package com.example.snake.activities;
import static com.example.snake.enums.State.GAMEOVER;
import static com.example.snake.enums.State.GAMEPAUSE;
import static com.example.snake.enums.State.GAMERUNNING;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.os.Bundle;
import android.os.Looper;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import com.example.snake.R;
import com.example.snake.components.OverDialog;
import com.example.snake.enums.Direction;
import com.example.snake.enums.State;
import com.example.snake.roles.Food;
import com.example.snake.roles.Snake;
import com.example.snake.sounds.PlaySound;
import com.example.snake.views.MainCanvasView;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
public class GameStart extends AppCompatActivity implements View.OnClickListener,View.OnTouchListener {
protected Button bt_up, bt_down, bt_left, bt_right, bt_begin, bt_pause, bt_leave,bt_speed;//添加控件
protected Snake snake;//添加蛇
protected ArrayList<Food> foods;//添加食物列表
protected TextView tv_score;//计分板
protected int score = 0;//分数
protected State state;//游戏状态,开始时为暂停
protected LinearLayout layout_main;//主游戏窗口主布局
//自定义View,游戏绘制核心,重新的onDraw方法可以将游戏内容绘制到该View中
protected MainCanvasView mainCanvasView;
PlaySound playSound;//音源播放类实例化
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_start);
init();//初始化一些控件
//设置计时器,死循环执行重绘和其他方法
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
//此处写需要循环的方法
if (state == GAMEOVER) this.cancel(); //如果游戏结束,则取消计时器
if (state == GAMERUNNING) gamerunning();
//重绘自定义View,这是动起来的核心
mainCanvasView.invalidate();
}
};
timer.schedule(timerTask, 0, 20);//参数:任务,延时开始时间,重复实现的时间间隔
}
@SuppressLint("ClickableViewAccessibility")
private void init() {
//初始化各个按钮和其他控件,与布局中相应元素绑定
bt_up = findViewById(R.id.bt_up);
bt_down = findViewById(R.id.bt_down);
bt_left = findViewById(R.id.bt_left);
bt_right = findViewById(R.id.bt_right);
bt_begin = findViewById(R.id.bt_begin);
bt_pause = findViewById(R.id.bt_pause);
bt_leave = findViewById(R.id.bt_leave);
bt_speed = findViewById(R.id.bt_speed);
tv_score = findViewById(R.id.tv_score);
layout_main = findViewById(R.id.layout_main);
//各个按钮添加监听器
bt_up.setOnClickListener(this);
bt_down.setOnClickListener(this);
bt_left.setOnClickListener(this);
bt_right.setOnClickListener(this);
bt_begin.setOnClickListener(this);
bt_pause.setOnClickListener(this);
bt_leave.setOnClickListener(this);
bt_speed.setOnTouchListener(this);
snake = new Snake(100, 100);//初始化蛇头
foods = new ArrayList<>();//初始化食物列表
state = State.GAMEPAUSE;//刚开始是暂停的,需要开始按钮激活
playSound = new PlaySound(GameStart.this);
mainCanvasView = new MainCanvasView(this);
layout_main.addView(mainCanvasView);
}
private void gamerunning(){
//保持食物和蛇和自定义View同步,然后才能在自定义View中画出来
mainCanvasView.snake = snake;//同步蛇
mainCanvasView.foods = foods;//同步食物列表
if (foods.isEmpty()) foods.add(new Food(mainCanvasView)) ; //判断条件,添加食物
snake.move();//蛇移动
// 检测蛇出界
if(snake.isOut(mainCanvasView)){
state = GAMEOVER;
playSound.overSound();
//多线程操作的时候会有一定的冲突问题,需要添加消息队列
Looper.prepare();
OverDialog overDialog = new OverDialog(this,R.style.OverDialog);
overDialog.setCancelable(false);
overDialog.setTitle("游戏结束!");
overDialog.setContent("您的得分为"+score);
overDialog.setPositiveMessage("返回主界面", new View.OnClickListener() {
@Override
public void onClick(View v) {
overDialog.dismiss();
finish();
}
});
overDialog.show();
Looper.loop();// 进入loop中的循环,查看消息队列
}
for (Food f : foods) {
if (snake.eat(f)) {
foods.remove(f);
score+=1;
tv_score.setText(String.valueOf(score));
playSound.eatSound();
}
}
}
/*
此处注解大概意思是:资源id在Android Gradle插件版本5.0中不是final,所以避免在switch case语句中使用它们。
原因是新版本中把final字段去掉了。而switch要的所有字段必须都是final加持的,所以要解决这个问题,需要在所在方法上
添加一个注解压制警告 @SuppressLint("NonConstantResourceId")。若无这个注解,则会有高亮提示
*/
@SuppressLint("NonConstantResourceId")
@Override
public void onClick(View v) {
playSound.clickSound();//点击按钮时播放点击音效
if (state==GAMERUNNING){
switch (v.getId()){
case R.id.bt_up: {
snake.direction = Direction.UP;
break;
}
case R.id.bt_down: {
snake.direction = Direction.DOWN;
break;
}
case R.id.bt_left: {
snake.direction = Direction.LEFT;
break;
}
case R.id.bt_right: {
snake.direction = Direction.RIGHT;
break;
}
}
}
switch (v.getId()) {
case R.id.bt_begin: {
if (state == GAMEPAUSE) state = GAMERUNNING;//开始游戏
break;
}
case R.id.bt_pause: {
if (state == GAMERUNNING) state = GAMEPAUSE;//暂停游戏
break;
}
case R.id.bt_leave: {
state = GAMEOVER;
finish();//销毁当前活动,返回上个活动
break;
}
default:
break;
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (v.getId()==R.id.bt_speed){
if (event.getAction()== MotionEvent.ACTION_DOWN){
snake.speed=8;
v.performClick();//解除同时监听点击事件和按下事件的影响
}
if (event.getAction()== MotionEvent.ACTION_UP){
snake.speed=3;
}
}
return false;
}
}
Android移动应用开发 贪吃蛇小游戏
需积分: 0 23 浏览量
更新于2023-01-16
14
收藏 513KB ZIP 举报
内容概要:
本资源是基于Android移动应用开发,用Android studio实现的期末作业,贪吃蛇小游戏。功能比较少,玩家可通过相应功能按键实现小游戏运行,碰到墙壁游戏结束
所使用配置:
1. Android studio 2022 Electric Eel(2022.1.1 RC 3)
2. SDK : API 22:Android 5.1(Lollipop)
3. JDK :jdk18
4. 语言:Java
如果配置不同导致不通过,可以直接复制粘贴main文件夹尝试使用,也可参照代码粘贴相应布局、Java代码和资源文件等进行使用。
适合人群:
初学Android 移动应用开发者
涉及知识点:
视图重绘,canvas,自定义对话框,布局等
建议和说明:
代码仅供初学者参考,对于有一定学习时长的入门者无参考价值,通过完整项目可体会到一些简单的应用开发思路和解决方法,涉及到一些简单的知识点,关于数据库,广播,内容接收者,服务,内容提供者等没有涉及。由于水平有限,可能存在一定问题,欢迎指正。

「已注销」
- 粉丝: 3
最新资源
- 网页制作中使用规范的HTML代码的几点(1).doc
- 互联网+餐饮连锁股份有限公司创业计划书2016.doc
- 微机接口课程设计报告(1).doc
- 2023年oracle相关分布式数据解决方案(1).doc
- 中央电大计算机应用基础网考试题大全及答案教学幻灯片.doc
- 【课件】UnitTheWorldWideWeb.ppt
- 数据库概论第1-3章习题参考答案.doc
- 一部分软件质量与质量保障培训课件.ppt
- XX中小企业信息化云服务平台—运营方案资料讲解.doc
- 物联网与短距离无线通信技术-第五章 PPT.ppt
- 电子商务岗位说明书(1).doc
- php-mysql网上购物系统毕业设计.doc
- 企业网站推广方案(网络营销作业)(1).doc
- 软件度量整理ppt教案资料.ppt
- C语言第1章概述.ppt
- MATLAB第一次实验.doc