Android Studio实现推箱子小游戏

news2024/11/13 23:00:52

项目目录

  • 一、项目概述
  • 二、开发环境
  • 三、详细设计
  • 四、运行演示
  • 五、项目总结

一、项目概述

推箱子是一款非常受欢迎的益智游戏,游戏的玩法简单,但是需要玩家具备一定的逻辑思维能力和空间感知能力,因此深受广大玩家的喜爱。在游戏中,玩家需要将箱子推到指定位置,每一关都有一个特定的目标,比如推动所有的箱子到指定位置,或者在规定的时间内完成任务等等。随着关卡的逐渐升级,游戏的难度也会逐渐增加,需要玩家更加灵活地运用头脑和策略,才能完成更高难度的挑战。

本次推箱子不仅可以锻炼玩家的逻辑思维和空间想象力,同时也能带来愉悦的游戏体验和编程乐趣。

二、开发环境

在这里插入图片描述

三、详细设计

MainActivity包含游戏介绍、游戏开始和退出。菜单栏和底部导航栏逻辑相同。

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case R.id.itm_start:
                Intent xgq = new Intent(MainActivity.this, GameLevelActivity.class);
                startActivity(xgq);
                break;
            case R.id.itm_intro:
                Intent i = new Intent(MainActivity.this, GameIntroActivity.class);
                startActivity(i);
                break;
            case R.id.itm_exit:
                finish();
                break;
        }
        return super.onOptionsItemSelected(item);
    }

定义游戏视图GameView,mManRect为搬运工所在的位置,getManRect()设置搬运工的位置,goToLevel()选择关卡,resetGame()开始新游戏,gotoNextLevel()进入下一关,gotoPrvLevel()进入上一关,onDraw()绘制游戏区域,绘制音效开关的图标。drawGameBoard()绘制游戏网格,drawSoundSwitch()绘制音效开关,drawDoneLabel()绘制完成标志,onTouchEvent()根据用户通过在游戏区域触摸来控制搬运工的行进。

private void drawGameBoard(Canvas canvas) {
        Rect destRect = new Rect();
        for (int r = 0; r < mGameData.getBoardRowNum(); r++ )
            for (int c = 0; c < mGameData.getBoardColumnNum(); c++){
                int topleft_x = (int)(mTopLeft_x + c * mColumnWidth);
                int topleft_y = (int)(mTopLeft_y + r * mRowHeight);
                destRect.set(topleft_x, topleft_y,(int)(topleft_x + mColumnWidth) + 2, (int)(topleft_y + mRowHeight) + 2);//+2是为了去除墙体之间的缝隙
                if (mGameData.hasFlag(r, c))
                    canvas.drawBitmap(GameBitmaps.mFlagBitmap, null, destRect, null);
                StringBuffer []gameState = mGameData.getGameState();
                //根据网格的状态绘制:盒子、旗子、空闲、人、墙、盒子旗子、人旗子
                switch (gameState[r].charAt(c)){
                    case GameInitialData.BOX:
                        canvas.drawBitmap(GameBitmaps.mBoxBitmap, null, destRect, null);
                        break;
                    case GameInitialData.FLAG:
                        canvas.drawBitmap(GameBitmaps.mFlagBitmap, null, destRect, null);
                        break;
                    case GameInitialData.NOTHING:
                        break;
                    case GameInitialData.MAN:
                        canvas.drawBitmap(GameBitmaps.mManBitmap, null, destRect, null);
                        break;
                    case GameInitialData.WALL:
//                        destRect.set(destRect.left, destRect.top, destRect.right+2, destRect.bottom + 2);  //+2是为了去除墙体之间的缝隙
                        canvas.drawBitmap(GameBitmaps.mWallBitmap, null, destRect, null);
                        break;
                    case GameInitialData.BOX_FLAG:
                        canvas.drawBitmap(GameBitmaps.mFlagBitmap, null, destRect, null);
                        canvas.drawBitmap(GameBitmaps.mBoxBitmap, null, destRect, null);
                        break;
                    case GameInitialData.MAN_FLAG:
                        canvas.drawBitmap(GameBitmaps.mFlagBitmap, null, destRect, null);
                        canvas.drawBitmap(GameBitmaps.mManBitmap, null, destRect, null);
                        break;
                }
            }
    }

GameData类为所有关卡的数据,游戏区域不足11列,左右两边加上若干空白列凑足11列,行数不足11行,使得墙体图片看起来偏大也添加若干空行,go()方法为搬运工从(srcRow, srcColumn)移动到(destRow, destColumn),recordMoveInfo()记录移动的信息,方便重新绘制,isGameOver()判断所有箱子是否到达目的地。

public boolean undoMove(){
        if (mGameSteps.isEmpty())
            return false;
        GameStepData step = mGameSteps.remove(mGameSteps.size() - 1);
//        logUndoOneStep(step);
        assert(mManPostion.isEqualTo(step.getManCurrentPosition()));
        restoreInitialState(step.getManCurrentPosition().row, step.getManCurrentPosition().column);
        int manRow = step.getManPrvPosition().row;
        int manColumn = step.getManPrvPosition().column;
        mManPostion.set(manRow, manColumn);
        mGameState[manRow].setCharAt(manColumn, 'M');
        TCell boxPrvPos = step.getBoxPrvPosition();
        TCell boxCurPos = step.getBoxCurrentPosition();
        if (boxPrvPos != null && boxCurPos != null){
            //assert mGameState[boxCurPos.row].charAt(boxCurPos.column) == 'B';
            restoreInitialState(boxCurPos.row, boxCurPos.column);
            mGameState[boxPrvPos.row].setCharAt(boxPrvPos.column, 'B');
        }
        return true;
    }

GameBitmaps为游戏中每种状态的位图,loadBitmaps()加载位图,releaseBitmaps()释放所有位图资源。

public static void releaseBitmaps(){
        //game board
        releaseBmp(mBoxBitmap);
        releaseBmp(mManBitmap);
        releaseBmp(mWallBitmap);
        releaseBmp(mFlagBitmap);
        releaseBmp(mDoneBitmap);
        releaseBmp(mSoundOpenBitmap);
        releaseBmp(mSoundCloseBitmap);
    }

GameInitialData类为游戏初始化数据,先定义final char静态常量,说明游戏区域单元格放一个,给了第一关和第二关的默认图案。readConfig()方法读取assets文件夹下的test_level_list.txt,是所有关卡的样式。
在这里插入图片描述

    public static final char NOTHING = ' ';         //该单元格啥也没有
    public static final char BOX = 'B';             //该单元格放的是箱子
    public static final char FLAG = 'F';            //红旗,表示箱子的目的地
    public static final char MAN = 'M';              //搬运工
    public static final char WALL = 'W';             //墙
    public static final char MAN_FLAG = 'R';        //搬运工 + 红旗
    public static final char BOX_FLAG = 'X';        //箱子 + 红旗

GameSound类定义游戏音效,mOneSetpMusicId为移动一步的music,mMoveBoxMusicId为移动箱子的music,mGameOverMusicId为游戏结束的音效,mSoundAllowed表示是否允许音效。

    //关闭音效
    public static void releaseSound(){
        if (mSoundPool == null) return;
        mSoundPool.unload(mOneSetpMusicId);
        mSoundPool.unload(mMoveBoxMusicId);
        mSoundPool.unload(mGameOverMusicId);
        mSoundPool.release();
    }

LevelInitialData类为每关的单元格数据,TCell类为单元格坐标,PrfsManager类存储过关难度。

    public static void setPassedLevel(Context context, int level){
        mPassedLevels = context.getSharedPreferences(PRFS_PASSED_LEVEL_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = mPassedLevels.edit();
        editor.putBoolean(KEY_PASSED_LEVEL_PREFIX + level, true);
        editor.commit();
    }

    public static boolean getPassedLevel(Context context, int level){
        mPassedLevels = context.getSharedPreferences(PRFS_PASSED_LEVEL_NAME, Context.MODE_PRIVATE);
        return  mPassedLevels.getBoolean(KEY_PASSED_LEVEL_PREFIX + level, false);  //false是默认值,没有关卡level的首选项值时返回false
    }

四、运行演示

Android Studio实现推箱子小游戏

五、项目总结

推箱子小游戏是一款非常经典的益智游戏。在Android上实现推箱子小游戏可以锻炼学生的逻辑思维能力和Android开发技能。需要注意的是,推箱子小游戏的实现需要涉及到一些算法和逻辑处理,因此需要具备一定的编程经验和逻辑思维能力。下面总结下游戏的实现步骤:

  1. 创建一个Android项目,并在布局文件中添加一个二维数组的格子布局,用于展示游戏地图。

  2. 在代码中定义游戏地图的二维数组,并初始化地图数据。

  3. 实现游戏角色的移动功能:根据用户的操作,判断游戏角色是否可以向前移动,如果可以移动,更新地图数据和角色位置,刷新游戏地图。

  4. 实现游戏的胜利判定:判断地图上的目标点是否都被箱子占据,如果是,则游戏胜利。

  5. 实现游戏的失败判定:判断箱子是否被挤到了角落,如果是,则游戏失败。

  6. 在布局文件中添加游戏控制按钮,用于控制游戏角色的移动。

  7. 实现游戏控制按钮的点击事件,根据用户的操作调用游戏角色移动函数。

  8. 在游戏结束时,弹出游戏结束提示框,询问用户是否重新开始游戏。

完成以上步骤后,就可以实现一个简单的推箱子小游戏了。可以根据需要添加一些额外的功能,例如计分系统、关卡系统等。


🚀这有你错过的精彩内容🚀
Android Studio实现文艺阅读App
Android Studio实现多功能日记本
Android Studio实现志愿者系统
Android Studio实现记单词App
Android Studio实现记账本

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/673579.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

正点原子F4HAL库串口中断再解读

七步走&#xff0c;参考usart.c文件 void HAL_UART_MspInit(UART_HandleTypeDef *huart) 这个函数进行了&#xff08;1&#xff09;、&#xff08;2&#xff09;、&#xff08;3&#xff09;、&#xff08;5&#xff09;中的使能中断 void uart_init(u32 bound)函数进行了&…

『手撕 Mybatis 源码』07 - Proxy 对象创建

Proxy 对象创建 问题 sqlSession.getMapper(UserMapper.class) 是如何生成的代理对象&#xff1f; Mapper 代理方式初始化完成后&#xff0c;下一步进行获取代理对象来执行 public class MybatisTest {/*** 问题2&#xff1a;sqlSession.getMapper(UserMapper.class); 是如…

EMC学习笔记(五)传输线模型及反射、串扰

1.概述 在高速数字电路PCB设计中&#xff0c;当布线长度大于20分之一波长或信号延时超过6分之一信号上升沿时&#xff0c;PCB布线可被视为传输线。传输线有两种类型:微带线和带状线。与EMC设计有关的传输线特性包括:特征阻抗、传输延迟、固有电容和固有电感。反射与串扰会影响…

2023年第1季社区Task挑战赛贡献者榜单

基于数字身份凭证的业务逻辑设计&#xff0c;贡献了发放数字身份凭证的参考实现&#xff1b;提供企业碳排放、慈善公益等智能合约库业务场景案例&#xff1b;体验最新发布的WeCross-BCOS3-Stub&#xff0c;跟社区核心开发者碰撞想法并给出自己的见解……这些精彩贡献展现出社区…

<C++项目>高并发内存池

项目介绍&#xff1a; 原型是goole的开源项目tcmalloc(全称:Thread-Caching Malloc),用于替代系统的内存分配相关的函数(malloc, free).知名度非常高。 项目要求知识储备和难度&#xff1a; 会用到C/C、数据结构(链表、哈希桶)、操作系统内存管理、单例模式、多线程、互斥锁等等…

设计模式—“行为变化”

在组件构建过程中,组件行为的变化经常导致组件本身剧烈的变化。“行为变化”模式将组件的行为和组件本身进行解耦,从而支持组件行为的变化,实现两者之间的松耦合。 典型模式有:Command、Visitor 一、Command 动机 在软件构建过程中,"行为请求者"与“行为实现…

看完这篇,立马看懂理想首款纯电MEGA

作者 | 马波编辑 | 德新 6月17日&#xff0c;理想召开了首届家庭科技日活动。 这场打着家庭幌子的科技发布会&#xff0c;信息密度高到有些超出预期。但是看完这场发布会&#xff0c;理想超级旗舰车型 W01&#xff0c;也就是同时在本场发布会公布名称的理想MEGA&#xff0c;它…

硅谷之火重燃武大

关注、星标公众号&#xff0c;直达精彩内容 来源&#xff1a;技术让梦想更伟大 作者&#xff1a;李肖遥 昨天看到雷军雷总在武汉大学的毕业典礼上&#xff0c;朴实的演讲&#xff0c;看似吹牛&#xff0c;实则也是一种勉励。 雷军大学一年级时&#xff0c;在武大图书馆看到一本…

基于java,springboot的音乐分享平台

背景 音乐网站与分享平台的主要使用者分为管理员和用户&#xff0c;实现功能包括管理员&#xff1a;首页、个人中心、用户管理、音乐资讯管理、音乐翻唱管理、在线听歌管理、留言板管理、系统管理&#xff0c;用户&#xff1a;首页、个人中心、音乐翻唱管理、我的收藏管理&…

MySQL - 单表数据量大表优化方案

一. 前言 当MySQL单表记录数过大时&#xff0c;增删改查性能都会急剧下降&#xff0c;可以参考以下步骤来优化。 二. 单表优化 除非单表数据未来会一直不断上涨&#xff0c;否则不要一开始就考虑拆分&#xff0c;拆分会带来逻辑、部署、运维的各种复杂度&#xff0c;一般以整…

软考:软件工程:软件开发与测试,黑盒测试,白盒测试

软考&#xff1a;软件工程: 提示&#xff1a;系列被面试官问的问题&#xff0c;我自己当时不会&#xff0c;所以下来自己复盘一下&#xff0c;认真学习和总结&#xff0c;以应对未来更多的可能性 关于互联网大厂的笔试面试&#xff0c;都是需要细心准备的 &#xff08;1&#…

年轻人的储蓄困境:愿望与现实的交锋(原因及解决之道)

年轻人存款难吗&#xff1f;探讨年轻人存款问题是目前社会热议的话题之一。最近的一项调查称&#xff0c;大约五分之一的年轻人存款在一万元以内&#xff0c;而存款超过10万元的年轻人只占总人数的53.7%。这一数据引发了广泛的关注和讨论&#xff0c;究竟是什么原因导致了年轻人…

基于开源项目二次开发KKPrinter实现打印机共享,远程跨网络实现不同网络打印机共享,客户端利用虚拟打印机截取打印文件转发至物理打印机(附源码)

基于开源项目二次开发KKPrinter实现打印机共享&#xff0c;远程跨网络实现不同网络打印机共享&#xff0c;客户端利用虚拟打印机截取打印文件转发至物理打印机&#xff08;附源码&#xff09;。实现方案有很多种&#xff0c;这里主要介绍 2 种&#xff0c;并附详细的实现过程和…

MySQL学习笔记之索引优化与查询优化

文章目录 前言数据准备建表创建函数插入数据创建删除索引函数 索引失效案例全值匹配最佳左前缀法则主键插入顺序计算、函数导致列索引失效函数导致索引失效计算导致索引失效 类型转换导致列索引失效范围条件右边的列索引失效不等于导致列索引失效is not null不能使用索引like以…

探索“AI+算力”:加速创新与增长的无限潜力

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;技术正成为各行各业的关注焦点。在这个充满激情和创新的时代&#xff0c;"AI算力"的结合应用成为科技行业的热门话题&#xff0c;甚至引发出"AI算力最强龙头"的网络热门等式。本文将探讨…

数据结构-哈希-哈希表实现

哈希表实现 一&#xff0c;哈希概念哈希概念常见哈希函数哈希冲突哈希冲突的解决 二&#xff0c;闭散列实现闭散列的结构插入查找删除闭散列总结 三&#xff0c;哈希桶实现哈希桶的结构插入查找删除析构拷贝构造赋值运算符重载 四&#xff0c;哈希表总结开散列与闭散列的比较哈…

设备虚拟化基础 - PCI

目录 1. 配置空间概念和作用 2. 通过配置空间发现设备 3. Linux读取PCI配置空间接口 4. 内核中具体读取配置空间实例 5. Virtion设备自定义空间 6. Linux读取Capabilities List代码解析 1. 配置空间概念和作用 详细的定义可以参考PCI Spec的第六章《Configuration Space…

嵌入式操作系统(嵌入式学习)

嵌入式操作系统 嵌入式操作系统是什么&#xff1f;嵌入式操作系统有哪些&#xff1f;常用的嵌入式操作系统及其特点对初学者的建议 嵌入式操作系统是什么&#xff1f; 嵌入式操作系统是一种专门设计和优化用于嵌入式系统的操作系统。它是在资源受限的嵌入式设备上运行的操作系…

No CMAKE_Swift_COMPILER could be found问题解决

编译OpenCV的IOS平台包,出错: CMake Error at CMakeLists.txt:20 (enable_language): No CMAKE_Swift_COMPILER could be found. 出错定位,原因是启用Swift语言时没有找到CMAKE_Swift_COMPILER变量 CMAKE官方文档说明启用Swift语言方法 cmake 3.15开始支持swift 查找swift …

简单介绍html/javascript、ajax应用

文章目录 前言1、html1.1.、html实例1.2、HTML文档的后缀名1.3、HTML 编辑器1.4、HTML 标题1.5、HTML 段落1.6、HTML 链接1.7、HTML 图像1.8、HTML 表格1.8.1、HTML 表格实例1.8.2、HTML 表格和边框1.8.3、HTML 表格表头 1.9、HTML <input> 标签1.10、Bootstrap 教程1.10…