当前位置: 首页 > news >正文

Android Studio贪吃蛇游戏完整开发教程 - 5关卡可调节速度

Android Studio贪吃蛇游戏完整开发教程 - 5关卡可调节速度

项目介绍

这是一个基于Android Studio开发的贪吃蛇游戏,具有5个难度关卡,随着关卡提升蛇的移动速度会逐渐加快。游戏采用按钮控制方式,适合移动设备操作。

功能特点

  • 🎮 经典的贪吃蛇游戏玩法
  • ⚡ 5个难度关卡,速度逐级提升
  • 🎯 直观的按钮方向控制
  • 🏆 分数系统和关卡进度显示
  • 🎨 不同关卡食物颜色不同
  • 🔄 游戏结束可重新开始

开发环境

  • 开发工具: Android Studio
  • 编程语言: Kotlin
  • 最低API级别: 21 (Android 5.0)
  • 目标API级别: 33 (Android 13)

项目结构

app/
├── src/main/
│   ├── java/com/example/myapplication/
│   │   ├── MainActivity.kt          # 主界面
│   │   ├── GameActivity.kt          # 游戏界面
│   │   ├── SnakeGameView.kt         # 游戏视图
│   │   └── models/
│   │       ├── Snake.kt             # 蛇模型
│   │       └── Food.kt              # 食物模型
│   └── res/
│       ├── layout/
│       │   ├── activity_main.xml    # 主界面布局
│       │   └── activity_game.xml    # 游戏界面布局
│       └── values/
│           ├── colors.xml           # 颜色资源
│           └── strings.xml          # 字符串资源

完整代码实现

1. 主界面 (MainActivity.kt)

package com.example.myapplicationimport android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Buttonclass MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val startButton: Button = findViewById(R.id.startButton)startButton.setOnClickListener {val intent = Intent(this, GameActivity::class.java)startActivity(intent)}}
}

2. 游戏界面 (GameActivity.kt)

package com.example.myapplicationimport android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.example.myapplication.models.Snakeclass GameActivity : AppCompatActivity() {private lateinit var gameView: SnakeGameViewprivate lateinit var scoreTextView: TextViewprivate lateinit var levelTextView: TextViewprivate lateinit var upButton: Buttonprivate lateinit var downButton: Buttonprivate lateinit var leftButton: Buttonprivate lateinit var rightButton: Buttonprivate lateinit var handler: Handler// 关卡设置private var currentLevel: Int = 1private val maxLevel: Int = 5private var score: Int = 0private var targetScore: Int = 50 // 第一关目标分数// 不同关卡的速度(毫秒)private val levelSpeeds = mapOf(1 to 300L, // 最慢2 to 250L,3 to 200L,4 to 150L,5 to 100L  // 最快)private var currentDelay: Long = levelSpeeds[1] ?: 300Loverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_game)initializeViews()setupButtonListeners()handler = Handler(Looper.getMainLooper())startGameLoop()updateUI()}private fun initializeViews() {gameView = findViewById(R.id.gameView)scoreTextView = findViewById(R.id.scoreTextView)levelTextView = findViewById(R.id.levelTextView)upButton = findViewById(R.id.upButton)downButton = findViewById(R.id.downButton)leftButton = findViewById(R.id.leftButton)rightButton = findViewById(R.id.rightButton)// 设置关卡监听器gameView.setOnScoreChangeListener { newScore ->score = newScorecheckLevelUp()updateUI()}}private fun setupButtonListeners() {upButton.setOnClickListener {if (gameView.snake.direction != Snake.Direction.DOWN) {gameView.snake.direction = Snake.Direction.UP}}downButton.setOnClickListener {if (gameView.snake.direction != Snake.Direction.UP) {gameView.snake.direction = Snake.Direction.DOWN}}leftButton.setOnClickListener {if (gameView.snake.direction != Snake.Direction.RIGHT) {gameView.snake.direction = Snake.Direction.LEFT}}rightButton.setOnClickListener {if (gameView.snake.direction != Snake.Direction.LEFT) {gameView.snake.direction = Snake.Direction.RIGHT}}}private fun checkLevelUp() {if (currentLevel < maxLevel && score >= targetScore) {currentLevel++targetScore = when (currentLevel) {2 -> 100  // 第二关目标3 -> 200  // 第三关目标4 -> 300  // 第四关目标5 -> 500  // 第五关目标else -> 500}currentDelay = levelSpeeds[currentLevel] ?: 100L// 重新开始游戏循环以应用新速度handler.removeCallbacksAndMessages(null)startGameLoop()// 重置游戏但保留关卡gameView.resetGameWithLevel(currentLevel)}}private fun updateUI() {scoreTextView.text = "得分: $score / $targetScore"levelTextView.text = "关卡: $currentLevel/$maxLevel (速度: ${getSpeedDescription()})"}private fun getSpeedDescription(): String {return when (currentLevel) {1 -> "很慢"2 -> "慢"3 -> "中等"4 -> "快"5 -> "很快"else -> "中等"}}private fun startGameLoop() {handler.postDelayed(object : Runnable {override fun run() {gameView.update()gameView.invalidate()handler.postDelayed(this, currentDelay)}}, currentDelay)}override fun onPause() {super.onPause()handler.removeCallbacksAndMessages(null)}override fun onResume() {super.onResume()startGameLoop()}
}

3. 游戏视图 (SnakeGameView.kt)

package com.example.myapplicationimport android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.example.myapplication.models.Snake
import com.example.myapplication.models.Food
import kotlin.random.Randomclass SnakeGameView @JvmOverloads constructor(context: Context,attrs: AttributeSet? = null,defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {lateinit var snake: Snakeprivate lateinit var food: Foodprivate var score: Int = 0private var gameOver: Boolean = falseprivate var currentLevel: Int = 1// 不同关卡的食物颜色private val levelFoodColors = mapOf(1 to Color.RED,2 to Color.YELLOW,3 to Color.CYAN,4 to Color.MAGENTA,5 to Color.rgb(255, 165, 0) // 橙色)// 画笔private val snakePaint = Paint().apply {color = Color.GREENstyle = Paint.Style.FILL}private val foodPaint = Paint().apply {color = Color.REDstyle = Paint.Style.FILL}private val gridPaint = Paint().apply {color = Color.GRAYstyle = Paint.Style.STROKEstrokeWidth = 1f}private val textPaint = Paint().apply {color = Color.WHITEtextSize = 50ftextAlign = Paint.Align.CENTER}private val levelTextPaint = Paint().apply {color = Color.WHITEtextSize = 30ftextAlign = Paint.Align.LEFT}// 游戏区域参数private var cellSize: Float = 0fprivate var gridWidth: Int = 20private var gridHeight: Int = 30private var onScoreChangeListener: ((Int) -> Unit)? = nullinit {initializeGame()}private fun initializeGame() {snake = Snake(gridWidth / 2, gridHeight / 2)food = generateFood()updateFoodColor()}private fun updateFoodColor() {foodPaint.color = levelFoodColors[currentLevel] ?: Color.RED}override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {super.onSizeChanged(w, h, oldw, oldh)cellSize = w.toFloat() / gridWidthgridHeight = (h / cellSize).toInt()initializeGame()}override fun onDraw(canvas: Canvas) {super.onDraw(canvas)// 绘制背景canvas.drawColor(Color.BLACK)// 绘制网格for (i in 0..gridWidth) {canvas.drawLine(i * cellSize, 0f, i * cellSize, height.toFloat(), gridPaint)}for (i in 0..gridHeight) {canvas.drawLine(0f, i * cellSize, width.toFloat(), i * cellSize, gridPaint)}// 绘制关卡信息canvas.drawText("关卡 $currentLevel", 20f, 50f, levelTextPaint)if (gameOver) {// 游戏结束显示canvas.drawText("游戏结束!", width / 2f, height / 2f - 80, textPaint)canvas.drawText("最终得分: $score", width / 2f, height / 2f - 20, textPaint)canvas.drawText("达到关卡: $currentLevel", width / 2f, height / 2f + 40, textPaint)canvas.drawText("点击重新开始", width / 2f, height / 2f + 120, textPaint)} else {// 绘制食物canvas.drawRect(food.x * cellSize,food.y * cellSize,(food.x + 1) * cellSize,(food.y + 1) * cellSize,foodPaint)// 绘制蛇for (segment in snake.body) {canvas.drawRect(segment.x * cellSize,segment.y * cellSize,(segment.x + 1) * cellSize,(segment.y + 1) * cellSize,snakePaint)}}}fun update() {if (gameOver) return// 移动蛇snake.move()// 检查是否吃到食物if (snake.body[0].x == food.x && snake.body[0].y == food.y) {snake.grow()food = generateFood()score += 10onScoreChangeListener?.invoke(score)}// 检查游戏结束条件if (checkCollision()) {gameOver = true}}private fun checkCollision(): Boolean {val head = snake.body[0]// 检查是否撞墙if (head.x < 0 || head.x >= gridWidth || head.y < 0 || head.y >= gridHeight) {return true}// 检查是否撞到自己for (i in 1 until snake.body.size) {if (head.x == snake.body[i].x && head.y == snake.body[i].y) {return true}}return false}private fun generateFood(): Food {var newFood: Fooddo {val x = Random.nextInt(0, gridWidth)val y = Random.nextInt(0, gridHeight)newFood = Food(x, y)} while (snake.body.any { segment -> segment.x == x && segment.y == y })return newFood}override fun onTouchEvent(event: MotionEvent): Boolean {if (event.action == MotionEvent.ACTION_DOWN) {if (gameOver) {// 重新开始游戏resetGame()return true}}return super.onTouchEvent(event)}private fun resetGame() {currentLevel = 1snake = Snake(gridWidth / 2, gridHeight / 2)food = generateFood()score = 0gameOver = falseupdateFoodColor()onScoreChangeListener?.invoke(score)invalidate()}fun resetGameWithLevel(level: Int) {currentLevel = levelsnake = Snake(gridWidth / 2, gridHeight / 2)food = generateFood()gameOver = falseupdateFoodColor()invalidate()}fun setOnScoreChangeListener(listener: (Int) -> Unit) {onScoreChangeListener = listener}
}

4. 数据模型

Snake.kt (在 models 包中):

package com.example.myapplication.modelsdata class Point(var x: Int, var y: Int)class Snake(startX: Int, startY: Int) {enum class Direction {UP, DOWN, LEFT, RIGHT}var direction = Direction.RIGHTvar body = mutableListOf<Point>()init {// 初始化蛇身,长度为3body.add(Point(startX, startY))body.add(Point(startX - 1, startY))body.add(Point(startX - 2, startY))}fun move() {// 移动蛇身for (i in body.size - 1 downTo 1) {body[i].x = body[i - 1].xbody[i].y = body[i - 1].y}// 移动蛇头when (direction) {Direction.UP -> body[0].y--Direction.DOWN -> body[0].y++Direction.LEFT -> body[0].x--Direction.RIGHT -> body[0].x++}}fun grow() {// 在蛇尾添加新的身体部分val tail = body.last()body.add(Point(tail.x, tail.y))}
}

Food.kt (在 models 包中):

package com.example.myapplication.modelsdata class Food(var x: Int, var y: Int)

5. 布局文件

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:gravity="center"android:background="@color/black"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="贪吃蛇游戏"android:textColor="@color/white"android:textSize="36sp"android:layout_marginBottom="50dp" /><Buttonandroid:id="@+id/startButton"android:layout_width="200dp"android:layout_height="wrap_content"android:text="开始游戏"android:textSize="24sp" /></LinearLayout>

activity_game.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:background="@color/black"><!-- 顶部信息栏 --><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:padding="10dp"android:gravity="center"><TextViewandroid:id="@+id/scoreTextView"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="得分: 0/50"android:textColor="@color/white"android:textSize="18sp"android:gravity="center" /><TextViewandroid:id="@+id/levelTextView"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="关卡: 1/5 (速度: 很慢)"android:textColor="@color/white"android:textSize="18sp"android:gravity="center" /></LinearLayout><com.example.myapplication.SnakeGameViewandroid:id="@+id/gameView"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1" /><!-- 方向控制按钮 --><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:gravity="center"android:padding="20dp"android:background="@color/purple_200"><!-- 上方向 --><Buttonandroid:id="@+id/upButton"android:layout_width="80dp"android:layout_height="60dp"android:text=""android:textSize="24sp"android:layout_marginBottom="10dp"android:backgroundTint="@color/teal_200" /><!-- 左右方向 --><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"><Buttonandroid:id="@+id/leftButton"android:layout_width="80dp"android:layout_height="60dp"android:text=""android:textSize="24sp"android:layout_marginEnd="20dp"android:backgroundTint="@color/teal_200" /><Buttonandroid:id="@+id/rightButton"android:layout_width="80dp"android:layout_height="60dp"android:text=""android:textSize="24sp"android:layout_marginStart="20dp"android:backgroundTint="@color/teal_200" /></LinearLayout><!-- 下方向 --><Buttonandroid:id="@+id/downButton"android:layout_width="80dp"android:layout_height="60dp"android:text=""android:textSize="24sp"android:layout_marginTop="10dp"android:backgroundTint="@color/teal_200" /></LinearLayout></LinearLayout>

6. 资源文件

colors.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources><color name="black">#FF000000</color><color name="white">#FFFFFFFF</color><color name="purple_200">#FFBB86FC</color><color name="purple_500">#FF6200EE</color><color name="purple_700">#FF3700B3</color><color name="teal_200">#FF03DAC5</color><color name="teal_700">#FF018786</color>
</resources>

strings.xml:

<resources><string name="app_name">贪吃蛇游戏</string>
</resources>

7. AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.myapplication"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:theme="@style/Theme.MyApplication"><activityandroid:name=".MainActivity"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activityandroid:name=".GameActivity"android:screenOrientation="portrait" /></application>
</manifest>

游戏特性说明

关卡系统

  • 第1关: 速度很慢 (300ms),目标50分
  • 第2关: 速度慢 (250ms),目标100分
  • 第3关: 速度中等 (200ms),目标200分
  • 第4关: 速度快 (150ms),目标300分
  • 第5关: 速度很快 (100ms),目标500分

控制方式

  • 使用屏幕底部的方向按钮控制蛇的移动
  • 防止直接反向移动导致游戏结束
  • 点击屏幕重新开始游戏

视觉效果

  • 不同关卡食物颜色不同
  • 网格背景便于定位
  • 实时显示分数和关卡信息

开发要点

  1. 自定义View: 使用 SnakeGameView 继承 View 实现游戏绘制
  2. 游戏循环: 使用 Handler 实现定时游戏更新
  3. 碰撞检测: 检测墙壁碰撞和自身碰撞
  4. 状态管理: 管理游戏状态(进行中/结束)
  5. 关卡逻辑: 实现分数累计和关卡升级机制

运行效果

游戏启动后进入主界面,点击"开始游戏"进入游戏界面。使用底部方向按钮控制蛇的移动,吃到食物增加分数,达到目标分数后进入下一关,速度逐渐加快。撞墙或撞到自身游戏结束,点击屏幕重新开始。
在这里插入图片描述

总结

这个贪吃蛇游戏项目展示了Android开发中的自定义View、游戏循环、触摸事件处理等关键技术。通过5个关卡的设置,增加了游戏的可玩性和挑战性。代码结构清晰,适合Android初学者学习和参考。

项目源码:贪吃蛇游戏源码 提取码:9999


欢迎在评论区交流学习心得,如有问题请随时提问!

http://www.dtcms.com/a/610638.html

相关文章:

  • k8s节点故障修复:v1.Secret观察失败解决方案
  • 中兴B862AV3.2M/B862AV3.1-M2-晨星MSO9385芯片-中兴STB3.0工具-开启ADB教程
  • 资源站 wordpress自建站怎么做
  • 外贸 静态网站 怎么做开通网站软件的会计科目怎么做
  • 企业部署求解器要考虑哪些因素?
  • 《电子政务电子认证服务业务规则规范》核心考点总览
  • 2025数维杯C题第一弹【透彻建模+无盲点解析】
  • css实现边框圆角的渐变色效果
  • 网站建设 思路长沙网站制
  • LeetCode hot100:002 两数相加(链表):逆序存储数字的加法运算
  • Transformer与MoE架构:原理、差异与应用全景
  • 使用 C# 实现 Excel 与 DataTable 相互转换
  • Meta DreamGym:用合成经验,重构智能体训练的“低成本革命”
  • 淮安建设网站制作权威发布的意思是什么
  • 数据库“Driver not loaded“错误,单例模式重构方案
  • 中山企业网站制作vi设计公司网站
  • 瀑布流网站有哪些百度大数据搜索引擎
  • Mysql官网下载Windows、Linux各个版本
  • Vue:“onMounted“ is defined but never used no-unused-vars
  • 网站建设中html5模板来源门户网站源码
  • 备案的网站可以攻击吗邵阳市建设工程造价管理站网站
  • 网站建设方案基本流程北京比较好的网络营销公司
  • redis批量删除namespace下的数据
  • Windows10专业版启动Docker启动不了问题排查解决
  • BC817-40,215 晶体管功率开关二极管 NXP安世 集成电路IC 芯片解析
  • 项目中基于redis实现缓存
  • SpringCloud-LoadBalancer负载均衡服务调用
  • 深圳网站建设选哪家好重庆景点排名前十
  • WordPress主题设置保存信誉好的镇江网站优化
  • 动态静态结合网站php网站开发小程序