安卓小游戏:小板弹球
安卓小游戏:小板弹球
前言
这个是通过自定义View实现小游戏的第三篇,是小时候玩的那种五块钱的游戏机上的,和俄罗斯方块很像,小时候觉得很有意思,就模仿了一下。
需求
这里的逻辑就是板能把球弹起来,球在碰撞的时候能把顶部的目标打掉,当板没有挡住球,掉到了屏幕下面,游戏就结束了。核心思想如下:
- 1,载入配置,读取游戏信息、配置及掩图
- 2,启动游戏控制逻辑,球体碰到东西有反弹效果
- 3,手势控制板的左右移动
效果图
效果图已经把游戏的逻辑玩出来了,大致就是这么个玩法,就是我感觉这不像一个游戏,因为小球的初始方向就决定了游戏结果,也许我应该把板的速度和球的方向结合起来,创造不一样。
代码
import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.drawable.Drawable
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.silencefly96.module_views.R
import java.lang.ref.WeakReference
import kotlin.math.*/*** 弹球游戏view** 1,载入配置,读取游戏信息、配置及掩图* 2,启动游戏控制逻辑,球体碰到东西有反弹效果* 3,手势控制板的左右移动** @author silence* @date 2023-02-08*/
class BombBallGameView @JvmOverloads constructor(context: Context,attrs: AttributeSet? = null,defStyleAttr: Int = 0
): View(context, attrs, defStyleAttr) {companion object {// 游戏更新间隔,一秒20次const val GAME_FLUSH_TIME = 50L// 目标移动距离const val TARGET_MOVE_DISTANCE = 20// 距离计算公式fun getDistance(x1: Int, y1: Int, x2: Int, y2: Int): Float {return sqrt(((x1 - x2).toDouble().pow(2.0)+ (y1 - y2).toDouble().pow(2.0)).toFloat())}// 两点连线角度计算, (x1, y1) 为起点fun getDegree(x1: Float, y1: Float, x2: Float, y2: Float): Double {// 弧度val radians = atan2(y1 - y2, x1 - x2).toDouble()// 从弧度转换成角度return Math.toDegrees(radians)}}// 板的长度private val mLength: Int// 行的数量、间距private val rowNumb: Intprivate var rowDelta = 0// 列的数量、间距private val colNumb: Intprivate var colDelta = 0// 球的掩图private val mBallMask: Bitmap?// 目标的掩图private val mTargetMask: Bitmap?// 目标的原始配置private val mTargetConfigList = ArrayList<Sprite>()// 目标的集合private val mTargetList = ArrayList<Sprite>()// 球private val mBall = Sprite(0, 0, 0f)// 板private val mBoard = Sprite(0, 0, 0f)// 游戏控制器private val mGameController = GameController(this)// 上一个触摸点X的坐标private var mLastX = 0f// 画笔private val mPaint = Paint().apply {color = Color.WHITEstrokeWidth = 10fstyle = Paint.Style.STROKEflags = Paint.ANTI_ALIAS_FLAGtextAlign = Paint.Align.CENTERtextSize = 30f}init {// 读取配置val typedArray = context.obtainStyledAttributes(attrs, R.styleable.BombBallGameView)mLength = typedArray.getInteger(R.styleable.BombBallGameView_length, 300)rowNumb = typedArray.getInteger(R.styleable.BombBallGameView_row, 30)colNumb = typedArray.getInteger(R.styleable.BombBallGameView_col, 20)// 球的掩图var drawable = typedArray.getDrawable(R.styleable.BombBallGameView_ballMask)mBallMask = if (drawable != null) drawableToBitmap(drawable) else null// 目标的掩图drawable = typedArray.getDrawable(R.styleable.BombBallGameView_targetMask)mTargetMask = if (drawable != null) drawableToBitmap(drawable) else null// 读取目标的布局配置val configId = typedArray.getResourceId(R.styleable.BombBallGameView_targetConfig, -1)if (configId != -1) {getTargetConfig(configId)}typedArray.recycle()}private fun drawableToBitmap(drawable: Drawable): Bitmap? {val w = drawable.intrinsicWidthval h = drawable.intrinsicHeightval config = Bitmap.Config.ARGB_8888val bitmap = Bitmap.createBitmap(w, h, config)//注意,下面三行代码要用到,否则在View或者SurfaceView里的canvas.drawBitmap会看不到图val canvas = Canvas(bitmap)drawable.setBounds(0, 0, w, h)drawable.draw(canvas)return bitmap}private fun getTargetConfig(configId: Int) {val array = resources.getStringArray(configId)try {for (str in array) {// 取出坐标val pos = str.substring(1, str.length - 1).split(",")val x = pos[0].trim().toInt()val y = pos[1].trim().toInt()mTargetConfigList.add(Sprite(x, y, 0f))}}catch (e : Exception) {e.printStackTrace()}// 填入游戏的listmTargetList.clear()mTargetList.addAll(mTargetConfigList)}override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {super.onSizeChanged(w, h, oldw, oldh)// 开始游戏load()}// 加载private fun load() {mGameController.removeMessages(0)// 设置网格rowDelta = height / rowNumbcolDelta = width / colNumb// 设置球,随机朝下的方向mBall.posX = width / 2mBall.posY = height / 2mBall.degree = (Math.random() * 180 + 180).toFloat()// 设置板mBoard.posX = width / 2mBoard.posY = height - 50// 将目标集合中的坐标改为实际坐标for (target in mTargetList) {val exactX = target.posY * colDelta + colDelta / 2val exactY = target.posX * rowDelta + rowDelta / 2target.posX = exactXtarget.posY = exactY}mGameController.sendEmptyMessageDelayed(0, GAME_FLUSH_TIME)}// 重新加载private fun reload() {mGameController.removeMessages(0)// 重置mTargetList.clear()mTargetList.addAll(mTargetConfigList)mGameController.isGameOver = false// 设置球,随机朝下的方向,注意:因为Y轴朝下应该是180度以内mBall.posX = width / 2mBall.posY = height / 2mBall.degree = (Math.random() * 180 + 180).toFloat()// 设置板mBoard.posX = width / 2mBoard.posY = height - 50// 由于mTargetConfigList内对象被load修改了,清空并不影响对象,不需要再转换了mGameController.sendEmptyMessageDelayed(0, GAME_FLUSH_TIME)}override fun onDraw(canvas: Canvas) {super.onDraw(canvas)// 绘制网格mPaint.strokeWidth = 1ffor (i in 0..rowNumb) {canvas.drawLine(0f, rowDelta * i.toFloat(),width.toFloat(), rowDelta * i.toFloat(), mPaint)}for (i in 0..colNumb) {canvas.drawLine(colDelta * i.toFloat(), 0f,colDelta * i.toFloat(), height.toFloat(), mPaint)}mPaint.strokeWidth = 10f// 绘制板canvas.drawLine(mBoard.posX - mLength / 2f, mBoard.posY.toFloat(),mBoard.posX + mLength / 2f, mBoard.posY.toFloat(), mPaint)// 绘制球canvas.drawBitmap(mBallMask!!, mBall.posX - mBallMask.width / 2f,mBall.posY - mBallMask.height / 2f, mPaint)// 绘制目标物for (target in mTargetList) {canvas.drawBitmap(mTargetMask!!, target.posX - mTargetMask.width / 2f,target.posY - mTargetMask.height / 2f, mPaint)}}@SuppressLint("ClickableViewAccessibility")override fun onTouchEvent(event: MotionEvent): Boolean {when(event.action) {MotionEvent.ACTION_DOWN -> {mLastX = event.x}MotionEvent.ACTION_MOVE -> {val len = event.x - mLastXval preX = mBoard.posX + lenif (preX > mLength / 2 && preX < (width - mLength / 2)) {mBoard.posX += len.toInt()invalidate()}mLastX = event.x}MotionEvent.ACTION_UP -> {}}return true}private fun gameOver() {AlertDialog.Builder(context).setTitle("继续游戏").setMessage("请点击确认继续游戏").setPositiveButton("确认") { _, _ -> reload() }.setNegativeButton("取消", null).create().show()}// kotlin自动编译为Java静态类,控件引用使用弱引用class GameController(view: BombBallGameView): Handler(Looper.getMainLooper()){// 控件引用private val mRef: WeakReference<BombBallGameView> = WeakReference(view)// 游戏结束标志internal var isGameOver = falseoverride fun handleMessage(msg: Message) {mRef.get()?.let { gameView ->// 移动球val radian = Math.toRadians(gameView.mBall.degree.toDouble())val deltaX = (TARGET_MOVE_DISTANCE * cos(radian)).toInt()val deltaY = (TARGET_MOVE_DISTANCE * sin(radian)).toInt()gameView.mBall.posX += deltaXgameView.mBall.posY += deltaY// 检查反弹碰撞checkRebound(gameView)// 球和目标的碰撞val iterator = gameView.mTargetList.iterator()while (iterator.hasNext()) {val target = iterator.next()if (checkCollision(gameView.mBall, target,gameView.mBallMask!!, gameView.mTargetMask!!)) {// 与目标碰撞,移除该目标并修改球的方向iterator.remove()collide(gameView.mBall, target)break}}// 循环发送消息,刷新页面gameView.invalidate()if (!isGameOver) {gameView.mGameController.sendEmptyMessageDelayed(0, GAME_FLUSH_TIME)}else {gameView.gameOver()}}}// 检测碰撞private fun checkCollision(s1: Sprite, s2: Sprite, mask1: Bitmap, mask2: Bitmap): Boolean {// 选较长边的一半作为碰撞半径val len1 = if(mask1.width > mask1.height) mask1.width / 2f else mask1.height / 2fval len2 = if(mask2.width > mask2.height) mask2.width / 2f else mask2.height / 2freturn getDistance(s1.posX, s1.posY, s2.posX, s2.posY) <= (len1 + len2)}// 击中目标时获取反弹角度,角度以两球圆心连线对称并加180度private fun collide(ball: Sprite, target: Sprite) {// 圆心连线角度,注意向量方向,球的方向向上,连线以球为起点val lineDegree = getDegree(ball.posX.toFloat(), ball.posY.toFloat(),target.posX.toFloat(), target.posY.toFloat())val deltaDegree = abs(lineDegree - ball.degree)ball.degree += if(lineDegree > ball.degree) {2 * deltaDegree.toFloat() + 180}else {-2 * deltaDegree.toFloat() + 180}}// 击中边缘或者板时反弹角度,反射角度和法线对称,方向相反private fun checkRebound(gameView: BombBallGameView) {val ball = gameView.mBallval board = gameView.mBoard// 左边边缘,法线取同向的180度if (ball.posX <= 0) {val deltaDegree = abs(180 - ball.degree)ball.degree += if (ball.degree < 180) {2 * deltaDegree - 180}else {-2 * deltaDegree - 180}// 右边边缘}else if (ball.posX >= gameView.width) {val deltaDegree: Floatball.degree += if (ball.degree < 180) {deltaDegree = ball.degree - 0-2 * deltaDegree + 180}else {deltaDegree = 360 - ball.degree2 * deltaDegree - 180}// 上边边缘}else if(ball.posY <= 0) {val deltaDegree = abs(90 - ball.degree)ball.degree += if (ball.degree < 90) {2 * deltaDegree + 180}else {-2 * deltaDegree + 180}// 和板碰撞,因为移动距离的关系y不能完全相等}else if (ball.posY + gameView.mBallMask!!.height / 2 >= board.posY) {// 板内if (abs(ball.posX - board.posX) <= gameView.mLength / 2){val deltaDegree = abs(270 - ball.degree)ball.degree += if (ball.degree < 270) {2 * deltaDegree - 180}else {-2 * deltaDegree - 180}}else {isGameOver = true}}}}// 圆心坐标,角度方向(degree,对应弧度radian)data class Sprite(var posX: Int, var posY: Int, var degree: Float)/*** 供外部回收资源*/fun recycle() {mBallMask?.recycle()mTargetMask?.recycle()mGameController.removeMessages(0)}
}
对应style配置,这里rowNunb不能用了,和上个贪吃蛇游戏冲突了,不能用一样的名称。游戏数据的数组我也写在这里了,实际应该分开写的,但是小游戏而已,就这样吧!
res -> values -> bomb_ball_game_view_style.xml
<?xml version="1.0" encoding="utf-8"?>
<resources><declare-styleable name="BombBallGameView"><attr name="length" format="integer"/><attr name="row" format="integer"/><attr name="col" format="integer"/><attr name="ballMask" format="reference"/><attr name="targetMask" format="reference"/><attr name="targetConfig" format="reference"/></declare-styleable><string-array name="BombBallGameConfig"><item>(0,5)</item><item>(0,6)</item><item>(0,7)</item><item>(0,8)</item><item>(0,9)</item><item>(0,10)</item><item>(0,11)</item><item>(0,12)</item><item>(0,13)</item><item>(0,14)</item><item>(1,3)</item><item>(1,5)</item><item>(1,7)</item><item>(1,9)</item><item>(1,11)</item><item>(1,13)</item><item>(1,15)</item></string-array>
</resources>
掩图也还是从Android Studio里面的vector image来的,我觉得还阔以。
res -> drawable -> ic_circle.xml
<vector android:height="24dp" android:tint="#6F6A6A"android:viewportHeight="24" android:viewportWidth="24"android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"><path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM17,13h-4v4h-2v-4L7,13v-2h4L11,7h2v4h4v2z"/>
</vector>
res -> drawable -> ic_target.xml
<vector android:height="24dp" android:tint="#6F6A6A"android:viewportHeight="24" android:viewportWidth="24"android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"><path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM17,13h-4v4h-2v-4L7,13v-2h4L11,7h2v4h4v2z"/>
</vector>
layout也说一下,前面都没写layout,这里用到了字符串数组,说下吧
<com.silencefly96.module_views.game.BombBallGameViewandroid:id="@+id/gamaView"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/black"app:ballMask="@drawable/ic_circle"app:targetMask="@drawable/ic_target"app:targetConfig="@array/BombBallGameConfig"/>
主要问题
下面简单讲讲吧,主要结构和前面游戏没什么变化,就是游戏逻辑变得复杂了很多。
资源加载
和前面一样,资源加载就是从styleable配置里面读取设置,这里需要额外说明的就是目标的配置文件了。
这里顶部目标是通过外部的配置文件来设置的,接受的是一个字符串数组的资源id,我这保存在下面:
res -> values -> bomb_ball_game_view_style.xml -> BombBallGameConfig
结构是一个坐标,需要注意的是要配合row和col使用(行数和列数),第一个数字表示第几行,第二个数字表示第几列。
<item>(0,5)</item>
读取的时候是把行标和列标读到了Sprite的posX和posY里面,这里是错误的,当时在init读取的时候无法获得控件的宽高,所以暂时先存放下,在onMeasuer -> onSizeChanged得到宽高之后,在load中对数据进行处理,mTargetList(游戏操作的列表)和mTargetConfigList(原始数据列表)都保存的是读取到的配置对象,即使mTargetList清空了,配置对象不变,依然保存在mTargetConfigList,这里要分清,不然reload的时候再处理就大错特错了。
板的移动
这里叫板,实际是通过paint画出来的线,只是设置的strokeWidth比较粗而已。移动的时候在onTouchEvent的ACTION_MOVE事件中更新板的坐标,在onDraw会以它的坐标和长度绘制成“板”。
球对四周的反弹
球的数据保存在Sprite对象里面,里面保存了三个变量,坐标以及方向。球在四个边的反弹(板实际就是下边),类似光的反射,找到反射面以及反射的法线,再以法线对称就得到反射路线了。实际操作上,先获取入射方向与法线夹角的绝对值,对称到法线另一边,再旋转180度掉头,就能得到出射方向了。
当然计算的时候要根据实际情况计算,尤其是0度和360度作为法线时。
球和目标的碰撞时的反射
球和目标的碰撞就不说了,很简单,计算下两个中心的距离就行了。这里说下碰撞后的反射问题,和上面在四周的反射类似,这里也是要通过反射面和法线来决定,实际上法线就是两个圆心的连线,而且小球和目标碰撞时,方向只会向上,所以取小球中心为起点,目标中心为中点,得到法线向量,再去计算角度就很简单了。
球的初始随机方向问题
球的初始随机方向我是想让它向上的,那应该生成哪个范围的角度呢?我们上学的时候X轴向右,Y轴向上,上半部分角度时[0, 180],那这时候U轴向下了,角度范围呢?答案很简单了,就是[180, 360],上面碰撞的代码实际是我以默认上半区为[0, 180]的时候写的,实际也无需修改,因为只是坐标轴对称了,逻辑并没对称。
相关文章:

安卓小游戏:小板弹球
安卓小游戏:小板弹球 前言 这个是通过自定义View实现小游戏的第三篇,是小时候玩的那种五块钱的游戏机上的,和俄罗斯方块很像,小时候觉得很有意思,就模仿了一下。 需求 这里的逻辑就是板能把球弹起来,球…...

7、单行函数
文章目录1 函数的理解1.1 什么是函数1.2 不同DBMS函数的差异1.3 MySQL的内置函数及分类2 数值函数2.1 基本函数2.2 角度与弧度互换函数2.3 三角函数2.4 指数与对数2.5 进制间的转换3 字符串函数4 日期和时间函数4.1 获取日期、时间4.2 日期与时间戳的转换4.3 获取月份、星期、星…...
华为机试题:HJ56 完全数计算(python)
文章目录博主精品专栏导航知识点详解1、input():获取控制台(任意形式)的输入。输出均为字符串类型。1.1、input() 与 list(input()) 的区别、及其相互转换方法2、print() :打印输出。3、整型int() :将指定进制…...

opencv——傅里叶变换、低通与高通滤波及直方图等操作
1、傅里叶变换a、傅里叶变换原理时域分析:以时间为参照进行分析。频域分析:相当于上帝视角一样,看事物层次更高,时域的运动在频域来看就是静止的。eg:投球——时域分析:第1分钟投了3分,第2分钟投…...

【NGINX入门指北】 进阶篇
nginx 进阶篇 文章目录nginx 进阶篇一、Nginx Proxy 服务器1、代理原理2、proxy代理3、proxy缓存一、Nginx Proxy 服务器 1、代理原理 正向代理 内网客户机通过代理访问互联网,通常要设置代理服务器地址和端口。 反向代理 外网用户通过代理访问内网服务器&…...

Python中关于@修饰符、yeild关键词、next()函数的基本功能简述
关于修饰符:其实就是将修饰符下面的函数当成参数传给它上面的函数。 def a(x):print(a)adef b():print(b) 其效果等价为: def a(x):print(a)def b():print(b)a(b())有个记忆诀窍,的下面哪个函数最近,谁就是儿子,谁就…...
结合Coverity扫描Spring Boot项目进行Path Manipulation漏洞修复
本篇介绍使用Coverity 扫描基于Spring Boot 项目中的Path Manipulation 漏洞, 进而解决风险,并且可以通过扫描。 什么样的代码会被扫描有路径操纵风险? 在Spring Boot 项目中, 实验了如下的场景: 1. Control 中 file path 作为参数传递的会被扫描,单纯服务方法不会 场…...

【FFMPEG源码分析】从ffplay源码摸清ffmpeg框架(一)
ffplay入口 ffmpeg\fftools\ffplay.c int main(int argc, char **argv) {/*******************start 动态库加载/网络初始化等**************/int flags;VideoState *is;init_dynload();av_log_set_flags(AV_LOG_SKIP_REPEATED);parse_loglevel(argc, argv, options);/* regis…...
C++蓝桥杯 基础练习,高精度加法,输入两个整数a和b,输出这两个整数的和。a和b都不超过100位。
C蓝桥杯 基础练习,高精度加法 问题描述 输入两个整数a和b,输出这两个整数的和。a和b都不超过100位。 算法描述 由于a和b都比较大,所以不能直接使用语言中的标准数据类型来存储。对于这种问题,一般使用数组来处理。 定义一…...

MySQL面试题:SQL语句的基本语法
MySQL目录一、数据库入门1. 数据管理技术的三个阶段2. 关系型数据库与非关系型数据库3. 四大非关系型数据库a. 基于列的数据库(column-oriented)b. 键值对存储(Key-Value Stores)c. 文档存储(Document Storesÿ…...

Fluid-数据编排能力原理解析
前言本文对Fluid基础功能-数据编排能力进行原理解析。其中涉及到Fluid架构和k8s csi driver相关知识。建议先了解相关概念,为了便于理解,本文使用JuiceFS作为后端runtime引擎。原理概述Fuild数据编排能力,主要是在云原生环境中,能…...

并发线程、锁、ThreadLocal
并发编程并发编程Java内存模型(JMM)并发编程核心问题—可见性、原子性、有序性volatile关键字原子性原子类CAS(Compare-And-Swap 比较并交换)ABA问题Java中的锁乐观锁和悲观锁可重入锁读写锁分段锁自旋锁共享锁/独占锁公平锁/非公平锁偏向锁/轻量级锁/重…...

CMMI-结项管理
结项管理(ProjectClosing Management, PCM)是指在项目开发工作结束后,对项目的有形资产和无形资产进行清算;对项目进行综合评估;总结经验教训等。结项管理过程域是SPP模型的重要组成部分。本规范阐述了结项管理的规程&…...

网络通信协议是什么?
网络通信基本模式 常见的通信模式有如下2种形式:Client-Server(CS) 、 Browser/Server(BS) 实现网络编程关键的三要素 IP地址:设备在网络中的地址,是唯一的标识。 端口:应用程序在设备中唯一的标识。 协议: 数据在网络中传输的…...
阶段5:Java分布式与微服务实战
目录 第33-34周 Spring Cloud电商实战 一、Eureka-server模块开发 1、引入依赖 2、配置文件 3、启动注解 一、Eureka-server模块开发 第33-34周 Spring Cloud电商实战 一、Eureka-server模块开发 1、引入依赖 父项目依赖:cloud-mall-practice springboot的…...

我的创作纪念日
目录 机缘 收获 日常 憧憬 机缘 其实本来从大一上学期后半段(2017)就开始谢谢零星的博客,只不过当时是自己用hexo搭建了一个小网站,还整了个域名:jiayoudangdang.top,虽然这个早就过期; 后来发现了CSDNÿ…...

Qml学习——动态加载控件
最近在学习Qml,但对Qml的各种用法都不太熟悉,总是会搞忘,所以写几篇文章对学习过程中的遇到的东西做一个记录。 学习参考视频:https://www.bilibili.com/video/BV1Ay4y1W7xd?p1&vd_source0b527ff208c63f0b1150450fd7023fd8 目…...

设计模式之职责链模式
什么是职责链模式 职责链模式是避免请求发送者与接受者耦合在一起,让多个对象都可以接受到请求,从而将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理为止。 职责链模式包含以下几个角色: …...
MySQL入门篇-MySQL 8.0 延迟复制
备注:测试数据库版本为MySQL 8.0 这个blog我们来聊聊MySQL 延迟复制 概述 MySQL的复制一般都很快,虽然有时候因为 网络原因、大事务等原因造成延迟,但是这个无法人为控制。 生产中可能会存在主库误操作,导致数据被删除了,Oracl…...

FPGA时序约束与分析 --- 实例教程(1)
注意: 时序约束辅助工具或者相关的TCL命令,都必须在 open synthesis design / open implemention design 后才能有效运行。 1、时序约束辅助工具 2、查看相关时序信息 3、一般的时序约束顺序 1、 时序约束辅助工具(1)时序约束编辑…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...

iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...