Android Studio实现推箱子小游戏

一、项目概述

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

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

二、开发环境

在这里插入图片描述

三、详细设计

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实现推箱子小游戏


🚀这有你错过的精彩内容🚀
Android Studio实现五子棋小游戏
Android Studio实现知乎日报App
Android Studio实现贪吃蛇小游戏
Android Studio实现文艺阅读App
Android Studio实现多功能日记本
  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Android studio是一个Android应用程序开发工具,它提供了开发Android应用程序所需的各种工具和环境。Android studio是基于IntelliJ IDEA开发的,它提供了一个完整的集成开发环境,其中包括代码编辑器、编译器、调试器、代码分析工具和图形用户界面设计器等。 要在Android studio实现一个Android应用程序,您需要完成以下步骤: 1. 下载和安装Android studio:您可以从Android官方网站下载最新版本的Android studio,并根据安装向导安装。 2. 创建一个新项目:在Android studio中创建一个新项目,您需要为应用程序指定一个名称和包名,选择目标Android版本,选择要使用的语言和开发工具。 3. 设计用户界面:使用Android studio中的布局编辑器和设计器工具,设计应用程序的用户界面,并添加所需的控件和布局。 4. 编写代码:使用Java或Kotlin编写应用程序的逻辑代码,并将其与用户界面的控件和事件处理程序连接起来。 5. 调试和测试:使用Android studio中的调试器和测试工具,调试和测试应用程序的功能和性能。 6. 发布应用程序:完成应用程序的开发和测试后,您可以将其发布到Google Play商店或其他应用商店,以供用户下载和使用。 Android studio提供了丰富的开发工具和功能,使开发者能够轻松地创建高质量的Android应用程序。无论您是初学者还是经验丰富的开发者,Android studio都是一个强大的工具,可以帮助您快速、高效地开发Android应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

振华OPPO

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值