发布时间:2023-11-30 12:48:16 浏览量:252次
游戏效果演示
游戏动画其实就是将图片资源逐帧逐帧地播放,只是在这部游戏中我们并不打算用图片文件而是用程序代码手绘画面,因为是手绘所以画面简单了些。好了!照例先定义一个父类,然后再定义其它的动画类并继承父类。
import android.graphics.Canvas
abstract class BaseEffect {
// 动画播放的中心坐标
protected var x: Float = 0f
protected var y: Float = 0f
var free: Boolean = true
abstract fun draw(canvas: Canvas)
}
定义完父类后就可以定义实际的子类了,我们先定义子弹的弹痕类BulletEffect.kt
import android.graphics.*
import com.bamboo.boxspacegame.AppGobal
/**
* 子弹击中物体时的特效
*/
class BulletEffect : BaseEffect() {
private var currentFrame = 0
companion object {
private const val FRAME_COUNT = 15 // 动画的总帧数
/**
* 初始化弹痕的Bitmap并缓存
*/
fun init() {
val paint = Paint()
paint.color = Color.WHITE
paint.style = Paint.Style.FILL
repeat(FRAME_COUNT) {
val bmp = Bitmap.createBitmap(
AppGobal.unitSize.toInt(),
AppGobal.unitSize.toInt(),
Bitmap.Config.ARGB_8888
)
Canvas(bmp).apply {
val unit = AppGobal.unitSize / 2f
paint.alpha = 255 - (255 / FRAME_COUNT * it)
paint.shader = RadialGradient(
unit, unit, unit + 0.1f,
intArrayOf(Color.WHITE, Color.TRANSPARENT), null,
Shader.TileMode.CLAMP
)
this.drawCircle(unit, unit, unit, paint)
}
AppGobal.bmpCache.put("bulletEffect_$it", bmp)
}
}
}
/**
* 根据当前帧的编号绘制动画
*/
override fun draw(canvas: Canvas) {
val bmp = AppGobal.bmpCache["bulletEffect_$currentFrame"]
val ex = x - AppGobal.unitSize / 2
val ey = y - AppGobal.unitSize / 2
canvas.drawBitmap(bmp, ex, ey, null)
currentFrame++
if (currentFrame >= FRAME_COUNT) {
currentFrame = 0
free = true
}
}
/**
* 播放动画并设置动画播放的坐标
*/
fun play(x: Float, y: Float) {
free = false
this.x = x
this.y = y
this.currentFrame = 0
}
}
当子弹击中目标或击在屏幕边界的时候就开始播放弹痕动画。接着定义开始爆炸动画类BombEffect.kt
import android.graphics.*
import com.bamboo.boxspacegame.AppGobal
/**
* 爆炸动画特效
*/
class BombEffect : BaseEffect() {
private val paint = Paint()
private var currentFrame = 1
private var onFinished: (() -> Unit)? = null // 动画播放完毕后的回调函数
companion object {
const val FRAME_COUNT = 20 // 动画的总帧数
}
/**
* 播放动画
* @param onFinished 动画播放完毕后的回调函数,默认可以不传
*/
fun play(x: Float, y: Float, onFinished: (() -> Unit)? = null) {
this.free = false
this.x = x
this.y = y
this.currentFrame = 0
this.onFinished = onFinished
}
/**
* 直接在屏幕上绘制图像,并不在游戏初始化时缓存
*/
override fun draw(canvas: Canvas) {
paint.color = Color.WHITE
paint.strokeWidth = 2f
val inc = AppGobal.unitSize / FRAME_COUNT
currentFrame++
if (currentFrame >= FRAME_COUNT) {
currentFrame = 0
free = true
onFinished?.let { it() }
} else {
paint.style = if (currentFrame >= FRAME_COUNT / 2) Paint.Style.STROKE
else Paint.Style.FILL
canvas.drawCircle(x, y, inc * currentFrame, paint)
}
}
}
接着实现游戏的瞬移动画类FlashEffect.kt
import android.graphics.*
import com.bamboo.boxspacegame.AppGobal
/**
* 瞬移的动画特效
* 动画可以正序或倒序播放
*/
class FlashEffect : BaseEffect() {
private var isInvert: Boolean = false // 判断动画是正序播放还是倒序播放
private var currentFrame = 0
private var onFinished: (() -> Unit)? = null // 动画播放完毕后的回调函数
companion object {
private const val FRAME_COUNT = 30
fun init() {
val unit = AppGobal.unitSize / 2
val paint = Paint()
paint.color = Color.WHITE
paint.style = Paint.Style.FILL_AND_STROKE
paint.strokeWidth = 1f
repeat(FRAME_COUNT) {
// 绘制瞬移的各帧图像
val bmp = Bitmap.createBitmap(
(AppGobal.unitSize * 2).toInt(),
(AppGobal.unitSize * 2).toInt(),
Bitmap.Config.ARGB_8888
)
Canvas(bmp).apply {
paint.shader = RadialGradient(
unit, unit, unit,
intArrayOf(
Color.parseColor("#33FFFFFF"),
Color.parseColor("#66FFFFFF"),
Color.WHITE,
), null,
Shader.TileMode.CLAMP
)
val step = (unit / FRAME_COUNT) * it
this.drawCircle(unit, unit, unit - step, paint)
paint.shader = RadialGradient(
unit, unit, unit,
intArrayOf(Color.WHITE, Color.parseColor("#33FFFFFF")), null,
Shader.TileMode.CLAMP
)
this.drawOval(
unit - (unit + step), unit - 2,
unit + (unit + step) - 1, unit + 2,
paint
)
this.drawOval(unit - 1, unit - 6, unit + 1, unit + 6, paint)
}
AppGobal.bmpCache.put(AppGobal.BMP_FLASH + "_$it", bmp)
}
}
}
override fun draw(canvas: Canvas) {
val bmp = AppGobal.bmpCache[AppGobal.BMP_FLASH + "_$currentFrame"]
canvas.drawBitmap(bmp, x, y, null)
if (isInvert) {
currentFrame--
if (currentFrame < 0) {
currentFrame = 15
free = true
onFinished?.let { it() }
}
} else {
currentFrame++
if (currentFrame >= FRAME_COUNT) {
currentFrame = 0
free = true
onFinished?.let { it() }
}
}
}
/**
* 播放瞬移动画
* @param isInvert 是否倒置播放动画
* @param onFinished 动画播放完毕后响应
*/
fun play(x: Float, y: Float, isInvert: Boolean = false, onFinished: (() -> Unit)? = null) {
this.x = x
this.y = y
this.free = false
this.currentFrame = if (isInvert) FRAME_COUNT - 1 else 0
this.isInvert = isInvert
this.onFinished = onFinished
}
}
至此,游戏所需要的三个动画类就全部完成了。现在我们要实现了个管理类,对这种特效类进行统一管理。EffectManager.kt
import android.graphics.Canvas
/**
* 特效管理类
*/
object EffectManager {
private val listEffect = mutableListOf<BaseEffect>()
@Synchronized
private inline fun <reified T : BaseEffect> obtain(t: T): BaseEffect {
val effect = listEffect.find {
it.free && (it is T)
}
return effect ?: t.apply { listEffect += this }
}
fun obtainBomb(): BombEffect {
return obtain(BombEffect()) as BombEffect
}
fun obtainFlash(): FlashEffect {
return obtain(FlashEffect()) as FlashEffect
}
fun obtainBullet(): BulletEffect {
return obtain(BulletEffect()) as BulletEffect
}
fun draw(canvas: Canvas) {
try {
listEffect.filter { !it.free }.forEach { it.draw(canvas) }
} catch (e: Exception) {
e.printStackTrace()
}
}
@Synchronized
fun release() {
listEffect.clear()
}
}
下一篇我们就要实现游戏的关卡类了。
如果对我的文章感兴趣或有疑问的话可以加我的公众号或Q群聊:口袋里的安卓
热门资讯
探讨游戏引擎的文章,介绍了10款游戏引擎及其代表作品,涵盖了RAGE Engine、Naughty Dog Game Engine、The Dead Engine、Cry Engine、Avalanche Engine、Anvil Engine、IW Engine、Frostbite Engine、Creation引擎、Unreal Engine等引擎。借此分析引出了游戏设计领域和数字艺术教育的重要性,欢迎点击咨询报名。
2. 手机游戏如何开发(如何制作传奇手游,都需要准备些什么?)
如何制作传奇手游,都需要准备些什么?提到传奇手游相信大家都不陌生,他是许多80、90后的回忆;从起初的端游到现在的手游,说明时代在进步游戏在更新,更趋于方便化移动化。而如果我们想要制作一款传奇手游的
3. B站视频剪辑软件「必剪」:免费、炫酷特效,小白必备工具
B站视频剪辑软件「必剪」,完全免费、一键制作炫酷特效,适合新手小白。快来试试!
游戏中玩家将面临武侠人生的挣扎抉择,战或降?杀或放?每个抉定都将触发更多爱恨纠葛的精彩奇遇。《天命奇御》具有多线剧情多结局,不限主线发展,高自由...
5. Bigtime加密游戏经济体系揭秘,不同玩家角色的经济活动
Bigtime加密游戏经济模型分析,探讨游戏经济特点,帮助玩家更全面了解这款GameFi产品。
6. 3D动画软件你知道几个?3ds Max、Blender、Maya、Houdini大比拼
当提到3D动画软件或动画工具时,指的是数字内容创建工具。它是用于造型、建模以及绘制3D美术动画的软件程序。但是,在3D动画软件中还包含了其他类型的...
7. 3D动漫建模全过程,不是一般人能学的会的,会的多不是人?
步骤01:面部,颈部,身体在一起这次我不准备设计图片,我从雕刻进入。这一次,它将是一种纯粹关注建模而非整体绘画的形式。像往常一样,我从Sphere创建它...
8. 如何自己开发一款游戏(游戏开发入门必看:五大独立游戏开发技巧)
游戏开发入门必看:五大独立游戏开发技巧无论您是刚刚起步开发自己的第一款游戏,还是已经制作了几款游戏,本篇文章中的5大独立游戏开发技巧都可以帮助您更好地设计下一款游戏。无论你对游戏有着什么样的概念,都
三昧动漫对于著名ARPG游戏《巫师》系列,最近CD Projekt 的高层回应并不会推出《巫师4》。因为《巫师》系列在策划的时候一直定位在“三部曲”的故事框架,所以在游戏的出品上不可能出现《巫师4》
想让你的3D打印模型更坚固?不妨尝试一下Cura参数设置和设计技巧,让你轻松掌握!
同学您好!