發(fā)布時(shí)間:2023-11-30 12:48:16 瀏覽量:252次
游戲效果演示
游戲動(dòng)畫其實(shí)就是將圖片資源逐幀逐幀地播放,只是在這部游戲中我們并不打算用圖片文件而是用程序代碼手繪畫面,因?yàn)槭鞘掷L所以畫面簡(jiǎn)單了些。好了!照例先定義一個(gè)父類,然后再定義其它的動(dòng)畫類并繼承父類。
import android.graphics.Canvas
abstract class BaseEffect {
// 動(dòng)畫播放的中心坐標(biāo)
protected var x: Float = 0f
protected var y: Float = 0f
var free: Boolean = true
abstract fun draw(canvas: Canvas)
}
定義完父類后就可以定義實(shí)際的子類了,我們先定義子彈的彈痕類BulletEffect.kt
import android.graphics.*
import com.bamboo.boxspacegame.AppGobal
/**
* 子彈擊中物體時(shí)的特效
*/
class BulletEffect : BaseEffect() {
private var currentFrame = 0
companion object {
private const val FRAME_COUNT = 15 // 動(dòng)畫的總幀數(shù)
/**
* 初始化彈痕的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)
}
}
}
/**
* 根據(jù)當(dāng)前幀的編號(hào)繪制動(dòng)畫
*/
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
}
}
/**
* 播放動(dòng)畫并設(shè)置動(dòng)畫播放的坐標(biāo)
*/
fun play(x: Float, y: Float) {
free = false
this.x = x
this.y = y
this.currentFrame = 0
}
}
當(dāng)子彈擊中目標(biāo)或擊在屏幕邊界的時(shí)候就開始播放彈痕動(dòng)畫。接著定義開始爆炸動(dòng)畫類BombEffect.kt
import android.graphics.*
import com.bamboo.boxspacegame.AppGobal
/**
* 爆炸動(dòng)畫特效
*/
class BombEffect : BaseEffect() {
private val paint = Paint()
private var currentFrame = 1
private var onFinished: (() -> Unit)? = null // 動(dòng)畫播放完畢后的回調(diào)函數(shù)
companion object {
const val FRAME_COUNT = 20 // 動(dòng)畫的總幀數(shù)
}
/**
* 播放動(dòng)畫
* @param onFinished 動(dòng)畫播放完畢后的回調(diào)函數(shù),默認(rèn)可以不傳
*/
fun play(x: Float, y: Float, onFinished: (() -> Unit)? = null) {
this.free = false
this.x = x
this.y = y
this.currentFrame = 0
this.onFinished = onFinished
}
/**
* 直接在屏幕上繪制圖像,并不在游戲初始化時(shí)緩存
*/
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)
}
}
}
接著實(shí)現(xiàn)游戲的瞬移動(dòng)畫類FlashEffect.kt
import android.graphics.*
import com.bamboo.boxspacegame.AppGobal
/**
* 瞬移的動(dòng)畫特效
* 動(dòng)畫可以正序或倒序播放
*/
class FlashEffect : BaseEffect() {
private var isInvert: Boolean = false // 判斷動(dòng)畫是正序播放還是倒序播放
private var currentFrame = 0
private var onFinished: (() -> Unit)? = null // 動(dòng)畫播放完畢后的回調(diào)函數(shù)
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() }
}
}
}
/**
* 播放瞬移動(dòng)畫
* @param isInvert 是否倒置播放動(dòng)畫
* @param onFinished 動(dòng)畫播放完畢后響應(yīng)
*/
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
}
}
至此,游戲所需要的三個(gè)動(dòng)畫類就全部完成了?,F(xiàn)在我們要實(shí)現(xiàn)了個(gè)管理類,對(duì)這種特效類進(jìn)行統(tǒng)一管理。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()
}
}
下一篇我們就要實(shí)現(xiàn)游戲的關(guān)卡類了。
如果對(duì)我的文章感興趣或有疑問的話可以加我的公眾號(hào)或Q群聊:口袋里的安卓
熱門資訊
探討游戲引擎的文章,介紹了10款游戲引擎及其代表作品,涵蓋了RAGE Engine、Naughty Dog Game Engine、The Dead Engine、Cry Engine、Avalanche Engine、Anvil Engine、IW Engine、Frostbite Engine、Creation引擎、Unreal Engine等引擎。借此分析引出了游戲設(shè)計(jì)領(lǐng)域和數(shù)字藝術(shù)教育的重要性,歡迎點(diǎn)擊咨詢報(bào)名。
2. 手機(jī)游戲如何開發(fā)(如何制作傳奇手游,都需要準(zhǔn)備些什么?)
?如何制作傳奇手游,都需要準(zhǔn)備些什么?提到傳奇手游相信大家都不陌生,他是許多80、90后的回憶;從起初的端游到現(xiàn)在的手游,說明時(shí)代在進(jìn)步游戲在更新,更趨于方便化移動(dòng)化。而如果我們想要制作一款傳奇手游的
3. B站視頻剪輯軟件「必剪」:免費(fèi)、炫酷特效,小白必備工具
B站視頻剪輯軟件「必剪」,完全免費(fèi)、一鍵制作炫酷特效,適合新手小白??靵碓囋?!
4. Steam值得入手的武俠游戲盤點(diǎn),各具特色的快意江湖
游戲中玩家將面臨武俠人生的掙扎抉擇,戰(zhàn)或降?殺或放?每個(gè)抉定都將觸發(fā)更多愛恨糾葛的精彩奇遇?!短烀嬗肪哂卸嗑€劇情多結(jié)局,不限主線發(fā)展,高自由...
5. Bigtime加密游戲經(jīng)濟(jì)體系揭秘,不同玩家角色的經(jīng)濟(jì)活動(dòng)
Bigtime加密游戲經(jīng)濟(jì)模型分析,探討游戲經(jīng)濟(jì)特點(diǎn),幫助玩家更全面了解這款GameFi產(chǎn)品。
6. 3D動(dòng)畫軟件你知道幾個(gè)?3ds Max、Blender、Maya、Houdini大比拼
當(dāng)提到3D動(dòng)畫軟件或動(dòng)畫工具時(shí),指的是數(shù)字內(nèi)容創(chuàng)建工具。它是用于造型、建模以及繪制3D美術(shù)動(dòng)畫的軟件程序。但是,在3D動(dòng)畫軟件中還包含了其他類型的...
7. 3D動(dòng)漫建模全過程,不是一般人能學(xué)的會(huì)的,會(huì)的多不是人?
步驟01:面部,頸部,身體在一起這次我不準(zhǔn)備設(shè)計(jì)圖片,我從雕刻進(jìn)入。這一次,它將是一種純粹關(guān)注建模而非整體繪畫的形式。像往常一樣,我從Sphere創(chuàng)建它...
8. 如何自己開發(fā)一款游戲(游戲開發(fā)入門必看:五大獨(dú)立游戲開發(fā)技巧)
?游戲開發(fā)入門必看:五大獨(dú)立游戲開發(fā)技巧無論您是剛剛起步開發(fā)自己的第一款游戲,還是已經(jīng)制作了幾款游戲,本篇文章中的5大獨(dú)立游戲開發(fā)技巧都可以幫助您更好地設(shè)計(jì)下一款游戲。無論你對(duì)游戲有著什么樣的概念,都
?三昧動(dòng)漫對(duì)于著名ARPG游戲《巫師》系列,最近CD Projekt 的高層回應(yīng)并不會(huì)推出《巫師4》。因?yàn)椤段讕煛废盗性诓邉澋臅r(shí)候一直定位在“三部曲”的故事框架,所以在游戲的出品上不可能出現(xiàn)《巫師4》
10. 3D打印技巧揭秘!Cura設(shè)置讓你的模型更堅(jiān)固
想讓你的3D打印模型更堅(jiān)固?不妨嘗試一下Cura參數(shù)設(shè)置和設(shè)計(jì)技巧,讓你輕松掌握!
最新文章
同學(xué)您好!