android-使用compose写一个贪吃蛇游戏
关注公众号学习更多知识
灵感来源
前段时间看到了大佬fundroid使用compose编写俄罗斯方块的文章,深受启发,当时便决定也要把诺基亚的贪吃蛇搬到android上来,因此才有了这篇文章
本篇文章界面和思路参考于 fundroid的文章
fundroid俄罗斯方块传送: https://blog.csdn.net/vitaviva/article/details/115878190
最终效果
提前发一下效果,让读者有个心理预期,逻辑真不复杂,务必耐心看完
思路
我们的界面分为两部分,上半部分是游戏的动态显示区域,下半部分是操作区域
显示区域
显示区域也可以细分为两部分,
- 边框+黑线边框
- 屏幕动态显示区域
所以我们把这两部分分成两个组合@Composable BaseScreen
、@Composable GameScreen
BaseScreen
用于绘制边框和黑线边框,这部分只需要绘制一次即可,所以我们需要抽离出来
GameScreen
用于绘制动态区域,主要是绘制基础的浅色砖块矩阵,和蛇身深色砖块、游离蛇身深色砖块
操作区域
操作区域也有两部分,
- 开始重置按钮、恢复暂停按钮,这两个按钮用于操作游戏状态
- 方向键按钮,用于操纵蛇头方向
操作区域组合名称为@Composable OperateBody
。
其中操作状态按钮使用Row包裹两个@Composable GameButton
来实现
方向键按钮使用一个Box
来包裹四个@Composable DirectionButtom
来实现
逻辑
如何数据通信
使用StateFlow.collectAsState方法来获取Compose状态,从而在状态更改的时候刷新界面
如何刷新游戏状态
使用LauncherEffect
内部定义一个死循环来维护时钟,保证我们可以在自定义的时间间隔内更新游戏状态。
蛇身状态
我们使用一个数组来维护所有蛇身的砖块,然后就是蛇移动、蛇吃游离蛇身、蛇撞墙几个逻辑
蛇移动
蛇单纯移动的话,我们可以通过构建一个新数据的方式来实现,新数组的第一个元素就是蛇身下一个要移动到的砖块,然后将老的蛇身数组addAll到新的蛇身数组中,最后移除新蛇身数组的最后一个蛇身。刷新StateFlow状态
蛇吃游离蛇身
如果蛇下次要移动到的砖块位置刚好是游离蛇身的位置的话,那么我们直接将游离蛇身插入到数组的第一个元素位置,并且不移除蛇身数组最后位置的砖块
蛇撞墙
整个屏幕被我们栅格化为Width_Matrix * Height_Matrix
数组,如果蛇头的位置超出栅格数组那么蛇撞墙死,游戏结束。
代码分析
StateFlow声明和使用
声明StateFlow,这部分不需要引入任何依赖
private val _flow = MutableStateFlow(SnakeState(action = Action.GameTick))
val stateFlow = _flow.asStateFlow()
使用StateFlow获取状态
val model = viewModel<GameViewModel>()val state = model.stateFlow.collectAsState().value
这里的SnakeState
就是我们定义的状态实体,代码如下:
data class SnakeState(var action: Action,val direction: Direction = Direction.Bottom,val snakeBody: MutableList<SnakePart> = mutableListOf(SnakePart(10, 10)),val freeSnakePart: SnakePart = SnakePart(15, 15),var Width_Matrix: Int = 0,var Height_Matrix: Int = 0,var isRunning: Boolean = true
)
游戏状态时钟代码
使用LauncherEffect
维持死循环,300ms分发一次时钟
val model = viewModel<GameViewModel>()LaunchedEffect(key1 = Unit) {while (isActive) {delay(300)model.dispatch()}}
蛇移动、吃游离蛇身、撞墙代码
fun dispatch() {val state = stateFlow.valueif (state.action!=Action.GameTick){return}if (!state.isRunning) {//暂停状态不更新数据return}val firstPart = state.snakeBody.first()val newList = mutableListOf<SnakePart>()if (state.direction == Direction.Left || state.direction == Direction.Right) {val x = firstPart.x + state.direction.increaseif (x == state.freeSnakePart.x && firstPart.y == state.freeSnakePart.y) {//吃游离蛇身newList.add(state.freeSnakePart)newList.addAll(state.snakeBody)emit(state.copy(snakeBody = newList, freeSnakePart = newFreeSnakePart()))return}if (x > state.Width_Matrix || x < 0) {//撞墙emit(state.copy(action = Action.GameOver,))return} else {newList.add(SnakePart(x, firstPart.y))newList.addAll(state.snakeBody)newList.removeLast()//删除蛇身的最后一节}} else {val y = firstPart.y + state.direction.increaseif (y == state.freeSnakePart.y && firstPart.x == state.freeSnakePart.x) {//吃游离蛇身newList.add(state.freeSnakePart)newList.addAll(state.snakeBody)emit(state.copy(snakeBody = newList, freeSnakePart = newFreeSnakePart()))return}if (y > state.Height_Matrix || y < 0) {//撞墙emit(state.copy(action = Action.GameOver,))return} else {newList.add(SnakePart(firstPart.x, y))newList.addAll(state.snakeBody)newList.removeLast()//删除蛇身的最后一节}}emit(state.copy(snakeBody = newList))}fun emit(state: SnakeState) {_flow.value = state}
未实现部分
- 蛇撞自身蛇身逻辑
- 蛇撞墙后游戏结束的动画
这部分有兴趣的可以fork代码后自己实现一下,相信会有所收获。
代码:https://github.com/ananananzhuo-blog/HappySnake
android-使用compose写一个贪吃蛇游戏相关推荐
- python写一个游戏多少代码-使用Python写一个贪吃蛇游戏实例代码
我在程序中加入了分数显示,三种特殊食物,将贪吃蛇的游戏逻辑写到了SnakeGame的类中,而不是在Snake类中. 特殊食物: 1.绿色:普通,吃了增加体型 2.红色:吃了减少体型 3.金色:吃了回到 ...
- python游戏脚本实例-使用Python写一个贪吃蛇游戏实例代码
我在程序中加入了分数显示,三种特殊食物,将贪吃蛇的游戏逻辑写到了SnakeGame的类中,而不是在Snake类中. 特殊食物: 1.绿色:普通,吃了增加体型 2.红色:吃了减少体型 3.金色:吃了回到 ...
- 使用python game写一个贪吃蛇游戏
前言 最近在用python 做项目,也想对python有多一些了解,之前有用C语言和C++写过python游戏,刚好可以通过这个游戏来对python多一些了解. 文章内容翻译自以下链接 https:/ ...
- 手机java做贪吃蛇_如何用Java写一个贪吃蛇游戏
这是一位拓胜学员用Java写贪吃蛇游戏的心得:今天课程设计终于结束了自己学java没以前学C+那么用功了觉得我学习在哪里都是个开口向上的抛物线,现在应该在右半边吧,好了进入正题. 写java贪吃蛇也是 ...
- 用c语言写一个贪吃蛇游戏代码
首先,贪吃蛇是一个经典的游戏,主要通过控制一条蛇在地图上吃食物,不断长长身体,最终实现最高分数. 以下是使用C语言编写贪吃蛇游戏的示例代码: ``` #include<stdio.h> # ...
- 前端三小时用html和js写一个贪吃蛇游戏,非常简单带讲解,代码可直接用,功能完整
目录 游戏主体部分--普通模式 游戏主体部分--地狱模式 游戏主页入口 预览图 游戏入口代码 1.html 2.css 3.js 注册页面代码 游戏实现很简单,只写游戏主体的话只要三小时就够了. 话不 ...
- 贪吃蛇博弈算法python_算法应用实践:如何用Python写一个贪吃蛇AI
原标题:算法应用实践:如何用Python写一个贪吃蛇AI 前言 这两天在网上看到一张让人涨姿势的图片,图片中展示的是贪吃蛇游戏, 估计大部分人都玩过.但如果仅仅是贪吃蛇游戏,那么它就没有什么让人涨姿势 ...
- 好玩的c语言编程游戏,C语言写个贪吃蛇游戏
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 C语言写个贪吃蛇游戏 贪吃蛇是个非常经典的游戏,用C语言来实现也是一个好玩的事情.这个游戏我写完后放在知乎,竟然点赞的人数超级多.我觉得大家喜欢,一个方面 ...
- python游戏贪吃蛇_Python写的贪吃蛇游戏例子_python
这篇文章主要介绍了Python写的贪吃蛇游戏例子,练手作品,又好玩又可以学到东西,需要的朋友可以参考下 第一次用Python写这种比较实用且好玩的东西,权当练手吧 游戏说明: * P键控制" ...
最新文章
- svcagent32.exe,javaM.exe木马查杀解决方案 (转Ad0.cn)
- MyBatis常见面试题汇总
- 不仅能搜索还能查信息 带你了解LBS应用
- 结合JDK源码看设计模式——桥接模式
- 解决Ubuntu IDEA 不能输入中文
- [Java核心技术(卷I)] - Java中的参数能做什么和不能做什么
- spring 2.2 改进_Spring 4中@ControllerAdvice的改进
- c 连接mysql示例 源码_MySQL 连接
- MySQL 为什么用索引,为什么是 B+树,怎么用索引
- 腾讯云挂在和格式化数据盘
- HDU 6241 Color a Tree
- Fiddler抓包一键生成代码
- 90-0004Web颜色标准【中英文颜色对照】
- Linux指令部分(一)
- HTML如何返回上一页?
- android系统优化启动时间(Google官方推荐)
- 我的时间管理之一 ——做好规划
- 9个offer,12家公司
- CCNP350-401学习笔记(1-50题)
- 《Python+Kivy(App开发)从入门到实践》自学笔记:打包——Windwos打包