如何用 Kotlin + 动画 快速实现一款游戏,快速上手!这些日子利用闲暇时间使用Kotlin + 动画开发了一款小游
前言
前些日子开发过一款小游戏,kotlin快速实现一款小游戏,糖果雨来啦,但由于时间的原因,只开发完成了基础版。如今,我对它进行了升级,新增了进阶版与困难版,分享给大家。
成果展示
现在这款游戏包含三个版本,分别为:
基础版:糖果只会在屏幕最上方生成,然后从上往下掉落。 进阶版:糖果只会在屏幕中间生成,然后向四周发散 困难版:糖果会在屏幕四个角随机生成,然后向大致对角方向发散。 基础版进阶版困难版你可以通过点击糖果捕捉器apk 下载地址github进行下载安装apk来体验一下该游戏。
实现细节
这里关于引导动画的实现,糖果的生成、掉落与收集就不再次展开分析了,具体实现细节请参考上一篇文章kotlin快速实现一款小游戏,糖果雨来啦。
接下里将重点讲解一下进阶版与困难版的实现原理。
进阶版
具体实现主要分为两步:
动态生成一个View,居中展示。 生成随机坐标,计算平移距离。 利用属性动画将View向四周平移出屏幕。TextView(this).apply { //1. 设置为居中 layoutParams = ConstraintLayout.LayoutParams(tvWidth, tvHeight).apply { bottomToBottom = ConstraintSet.PARENT_ID topToTop = ConstraintSet.PARENT_ID startToStart = ConstraintSet.PARENT_ID endToEnd = ConstraintSet.PARENT_ID } //2. 设置糖果背景 background = ContextCompat.getDrawable(this@AdvancedActivity, generateRandomCandy()) //3. 添加到视图 viewBinding.root.addView(this) }
动态生成一个TextView,设置其属性让其居中,然后设置糖果的背景,并添加到视图中。
在对其添加属性动画前,我们需要为它确定一个随机坐标。这里我们利用获取到的屏幕宽高来随机生成一个屏幕内坐标。
fun generateRandomX(leftRange: Int = 0, rightRange: Int = getScreenWidth()): Int { return (leftRange..rightRange).random() } fun generateRandomY(leftRange: Int = 0, rightRange: Int = getScreenHeight()): Int { return (leftRange..rightRange).random() }
我们将屏幕分成四块,生成的随机坐标点随机分布在这四块区域中。
在确定了随机坐标后,接着我们就需要通过这个随机坐标来计算出需平移的距离。
我们以随机坐标点位于左上方区域来举例:
我们利用相似三角形来确定需要平移的距离,取两个相同大小的三角形来计算:
X轴平移的距离为:halfScreenWidth - x) * -2。 Y轴平移的距离为:(halfScreenHeight - y) * -2。除了左上区域,剩下的其他三个区域分别为:
右上区域左下区域右下区域将这四个区域合起来的总的计算方法为:
private fun calculatePosition(x: Int, y: Int): Pair<Int, Int> { //利用相似三角形来确定平移距离,现在是取一个相同大小的相似三角形。 return if (x <= halfScreenWidth) { if (y <= halfScreenHeight) { //left_top Pair((halfScreenWidth - x) * -2, (halfScreenHeight - y) * -2) } else { //left_bottom Pair((halfScreenWidth - x) * -2, (y - halfScreenHeight) * 2) } } else { if (y <= halfScreenHeight) { //right_top Pair((x - halfScreenWidth) * 2, (halfScreenHeight - y) * -2) } else { //right_bottom Pair(((x - halfScreenWidth) * 2).toInt(), (y - halfScreenHeight) * 2) } } }
问题
如上所述,我们利用两个相同的相似三角形来计算平移距离,看起来很美好,但实际调式过程中,发现很多时候糖果无法平移出手机屏幕,因为平移的距离不够。
像这种情况,即使我们用了两个相同的相似三角形来计算平移距离,平移距离还是不够,造成糖果无法平移出手机屏幕。
那怎么办呢?
这里我们采取一个递归算法,来保证我们计算出的平移距离能够支持糖果平移出屏幕。
/** * 取一个相同大小的三角形的话,还是有可能平移不出屏幕,应该避免这个情况 */ private fun checkTransitionXy(transitionXyPair: Pair<Int, Int>): Pair<Int, Int> { //递归的终止条件 if (transitionXyPair.first.absoluteValue > (halfScreenWidth + tvWidth) || transitionXyPair.second.absoluteValue > (halfScreenHeight + tvHeight) ) { return transitionXyPair } return checkTransitionXy( Pair( (transitionXyPair.first * 1.1).toInt(), (transitionXyPair.second * 1.1).toInt() ) ) }
递归的终止条件就是判断X轴的平移距离或者Y轴的平移距离能够平移出屏幕,不满足该终止条件则将平移距离不停的放大。
介绍完了进阶版的实现原理,接着我们来看看困难版的实现原理。
困难版
相对比基础版与进阶版,困难版的发球点增加到四个,分别位于屏幕的四周。糖果会随机从这四个点生成,然后向大致对角方向发散。
所以同样,我们将屏幕分成四块。
enum class Direction { LEFT_TOP, RIGHT_TOP, LEFT_BOTTOM, RIGHT_BOTTOM }
通过 Direction.values().random()来随机确定糖果的初始坐标位于哪一块区域中,然后通过设置LayoutParams属性来让其位于四个角中。
TextView(this).apply { //1.设置糖果背景 background = ContextCompat.getDrawable(this@DifficultActivity, generateRandomCandy()) //2.确定初始位置 tv.layoutParams = when (Direction.values().random()) { Direction.LEFT_TOP -> { ConstraintLayout.LayoutParams(tvWidth, tvHeight).apply { startToStart = ConstraintSet.PARENT_ID topToTop = ConstraintSet.PARENT_ID } } Direction.LEFT_BOTTOM -> { ConstraintLayout.LayoutParams(tvWidth, tvHeight).apply { startToStart = ConstraintSet.PARENT_ID bottomToBottom = ConstraintSet.PARENT_ID } } Direction.RIGHT_TOP -> { ConstraintLayout.LayoutParams(tvWidth, tvHeight).apply { endToEnd = ConstraintSet.PARENT_ID topToTop = ConstraintSet.PARENT_ID } } Direction.RIGHT_BOTTOM -> { ConstraintLayout.LayoutParams(tvWidth, tvHeight).apply { endToEnd = ConstraintSet.PARENT_ID bottomToBottom = ConstraintSet.PARENT_ID } } } //3.添加到视图中 viewBinding.root.addView(this) }
接着就是计算平移的距离了。
因为是向对角发散,所以随机坐标是生成在对角区域,也就是左上区域对右下区域,右上区域对左下区域。
我们还是以左上区域来举例:
这里我们简单点直接利用两个相似三角形来计算平移距离:
X轴平移距离为:x * 2。 Y轴平移距离为:y * 2。其它三个区域这边就不展开分析了,总的计算方法为:
/** * x, y 是指生成的随机坐标点的坐标 * * 移动的距离是两个相似三角形相加 */ private fun calculatePosition(x: Int, y: Int): Pair<Int, Int> { return if (x > halfScreenWidth) { if (y > halfScreenHeight) { //right_bottom Pair(x * 2, y * 2) } else { //right_top Pair(x * 2, -2 * (screenHeight - y)) } } else { if (y > halfScreenHeight) { //left_bottom Pair(-2 * (screenWidth - x), 2 * y) } else { //left_top Pair(-2 * (screenWidth - x), -2 * (screenHeight - y)) } } }
因为随机坐标点是在对角,所以两个三角形相加的平移距离就够支持糖果平移出屏幕了,当然你也可以参考进阶版采取递归算法来计算平移距离,那也会更加的精准。
总结
在完成了进阶版与困难版后,糖果捕捉器这款游戏也变得更加完整,当然后续还可以进行更多的升级,比如:让用户来定义糖果的生成速度,定义糖果的掉落速度,后续有时间的话,会对它进行再次升级。
如果你想查看游戏的所有代码,可以点击Github Candy-Catch进行查阅。如果可以,欢迎你给我点个小星星。
你可以通过点击糖果捕捉器apk 下载地址github进行下载安装该apk来进行体验一下该游戏。
到此本篇文章就结束啦,如果你有任何疑问或者不同的想法,欢迎在评论区留言与我一起探讨。
其实分享文章的最大目的正是等待着有人指出我的错误,如果你发现哪里有错误,请毫无保留的指出即可,虚心请教。
另外,如果你觉得文章不错,对你有所帮助,请帮我点个赞,就当鼓励,谢谢~
相关知识
Spine打造游戏2D动画的高效利器
如何快速上手一款新游戏——新手玩家的成长之路
安卓手机游戏编程学什么
如何用java编写手游
手机游戏都用什么语言编程
做手机游戏用什么编程
Android应用开发:基础小游戏开发
游戏动画设计师是干什么的,游戏中动画的设计师具体职责是什么?
动画游戏大全
安卓手机游戏编程用什么软件做的
推荐资讯
- 1老六爱找茬美女的烦恼怎么过- 4999
- 2博德之门3黄金雏龙法杖怎么得 4867
- 3《大侠立志传》剿灭摸金门任务 4312
- 4代号破晓官方正版角色介绍 4023
- 5赛马娘锻炼到底的伙伴支援卡事 3802
- 6闪烁之光11月兑换码大全20 3774
- 7原神原海异种刷怪路线-原神原 3547
- 8爆梗找茬王厕所特工怎么通关- 3542
- 9《我的世界》领地删除指令是什 3440
- 10原神开局星落湖怎么出去 原神 3426