Android-贪吃蛇小游戏-分析与实现-Kotlin语言描述

2,142 阅读4分钟

Android-贪吃蛇小游戏-分析与实现-Kotlin语言描述

Overview

本章的主要的内容是贪吃蛇小游戏的分析和实现,关于实现的具体代码可以在,文章底部的github的链接中找到。

整个游戏通过通过在,View不断的绘制实现的。

先看看效果图

贪吃蛇小游戏

分析有哪些游戏对象

毫无疑问,不管Kotlin还是Java都是面向对象编程语言,那么我们要实现贪吃蛇游戏的第一步就是要分析游戏中有哪些对象,已有将对象都分析完全了,我们再能进行开发,从示意图中我们可以发现最少有两个对象。

  • 食物,贪吃蛇吃到食物后会增长
  • 贪吃蛇, 可以明显的看出来贪吃蛇是由一个个小方块组成的,那么其中每一个方块就是一个对象,将所有的方块对象放入一个集合中,这个集合就组成了贪吃蛇。集合的第一个元素就是 蛇头为了以示区别,将蛇头使用了不同的颜色跟身体区分出来。
  • 提取父类,不管是组成贪吃蛇的块还是食物对象,本质上都是游戏对象,那么我们可以将这两个对象提取取来一个公共的父类,在父类中定义通用的属性和方法。

Well,不管是贪吃和还是食物,都是需要绘制出来的,那么一提到绘制那么就不得不提到坐标了,坐标的计算是相当繁琐且容易出错的,那么我们得想办法将坐标给抽象一下。从游戏的示例图我们我们可以发现,所有的游戏对象都是可以通过一个行的索引,和一个类的索引来确定的二维的平面结构,那么我们就可以将本来的坐标抽象成行列结构。到这里公共父类的成员那就基本上就可以确定了,同时我们的类的结构也可以确定了。抽取出来的类的结构如下。

游戏对象的类的结构

/**
 * 贪吃蛇游戏中所有游戏的父类,所有的游戏对象都将会从此类继承
 * */
open class GameObject(var row: Int, var column: Int) {

    /**
     * 绘制游戏对象
     * @param canvas 画布对象
     * @param paint 画笔对象
     * */
    open fun draw(canvas: Canvas, x: Float, y: Float, paint: Paint) {
        canvas.drawRect(x, y, x + SnakeGameConfiguration.GRID_WIDTH, y + SnakeGameConfiguration.GRID_HEIGHT, paint)
    }
}
/**
 * 贪吃蛇吃的食物
 * */
class Food(row: Int, column: Int) : GameObject(row, column) {
    override fun draw(canvas: Canvas, x: Float, y: Float, paint: Paint) {
        val gw = SnakeGameConfiguration.GRID_WIDTH
        val gh = SnakeGameConfiguration.GRID_HEIGHT
        canvas.drawCircle(x + (gw / 2), y + (gh / 2), gw / 2, paint)
    }
}

/**
 * 因为蛇的组成是块状的,此对象就是组成蛇的块
 * */
class SnakeBlock(row: Int, column: Int, val isHead: Boolean) : GameObject(row, column) {

}

抽取游戏的配置参数

在贪吃蛇的游戏中,地图的长度是固定的(也就是 的数量是固定的),每一个游戏对象的宽度和高度是根据View的大小和行和列的数量来计算的。这些值我们都可以存储为全局的变量,方便以后修改和调用。

object SnakeGameConfiguration {
    var GRID_WIDTH = 0F
    var GRID_HEIGHT = 0F

    val GAME_COLUMN_COUNT = 20
    val GAME_ROW_COUNT = 20
}

贪吃蛇是如何移动的

这个逻辑在贪吃和游中算是个难点,因为贪吃蛇是可以多次拐弯的,移动蛇头的实现思路如下。

  1. 首先从蛇的尾部开始,向前一个组成蛇的块的对象的位置移动
  2. 然后倒数第二个想倒数第三个的位置移动,依次类图
  3. 到蛇头的位置以后,那么根据移动的方向移动蛇头

当移动了贪吃蛇的位置以后就可以进行碰撞检测了

碰撞检测

对于有序对象的碰撞检测分为三种情况, 至于如何碰撞检测只需要检测行和列是否超出游戏地图范围,或者是否是与其他的游戏对象重合即可。

  1. 贪吃蛇超出地图的边界-可以看做为撞墙
  2. 贪吃和吃到自己
  3. 贪吃蛇迟到食物,需要将贪吃蛇的长度+1,即在蛇的尾部在增加一个组成蛇的块

对于上面的三种情况我们可以提取出来两个回调函数

interface OnCrashListener {
    fun onCrash()
}

/**
 * 贪吃蛇吃到食物的回调
 * */
interface OnEatenFoodListener {
    fun onEaten()
}

源码下载

剩下一些比较简单的地方,也就没再文章中讲解,大家可以到我的Github上下载全部的源码。

贪吃蛇小游戏源码下载