注意:最新版本的代码我已经提交,加入了不少动画效果,优化了相关性能。
有特效版本:https://download.csdn.net/download/qq_20698983/10406847
无特效版本:https://download.csdn.net/download/qq_20698983/10383678

游戏效果图(今天更新成动图,但是看起来卡卡的,我程序很流畅的被弄成了这样):

当然你也可以在这个链接里面下载我的apk试玩
apk要求:Android version 6.0
链接:https://pan.baidu.com/s/1eTkO9mq 密码:w48l

##设计思路
一、实体类,封装一个动物头像。包含x,y坐标,图片(bitmap),一个id用于匹配,宽、高
二、布局方面一个Activity和一个自定义的View,主角当然是我们这个View。
三、在构造方法里面初始化游戏相关数据

public GameView(Context context, AttributeSet attr) {super(context, attr);screenHeight = DisplayUtil.getScreenHeight(context);screenWidth = DisplayUtil.getScreenWidth(context);// 音乐相关初始化bgMedia = MediaPlayer.create(this.getContext(), R.raw.bg_game);bgMedia.setOnCompletionListener(this);bgMedia.start();// swap = MediaPlayer.create(this.getContext(), R.raw.swap);// int ave = screenWidth / (row + 2); // 将屏幕宽度分为 row + 2 等份int ave = 0;int size = (screenWidth - ave * 2) / row; // 其它两分为:舞台距离屏幕左右边的像素ZooUtil.initZooData(size, size, this.getResources()); // 初始化动物头像数据// 背景图片background = BitmapFactory.decodeResource(this.getResources(), R.mipmap.game_bg);floorBg = BitmapFactory.decodeResource(this.getResources(), R.mipmap.floor_bg);/** 计算出舞台距离左边屏幕的距离* 计算方式为:*   (屏幕总宽度 - 人物头像的宽 * 总行数) / 2*/int leftSpan = (screenWidth - ZooUtil.getAnimalWidth() * row) / 2;int topSpan = (screenHeight - ZooUtil.getAnimalHeight() * col) / 3;// 将游戏舞台的坐标、高宽保存起来StageUtil.initStage(leftSpan, topSpan,leftSpan + ZooUtil.getAnimalWidth() * row,topSpan + ZooUtil.getAnimalHeight() * col);// 实例化画笔paint = new Paint();paint.setFlags(Paint.ANTI_ALIAS_FLAG);paint.setAntiAlias(true); // 消除锯齿initGamePoint();}/*** 生成游戏坐标*/private void initGamePoint() {currScore = 0; // 清空当前得分bitmaps = new FlashBitmap[row][col];// 生成背景图片的坐标(仅背景图片,后续可考虑将特效也加进来)for (int i = 0; i < row; ++i) {for (int j = 0; j < col; ++j) {do {// 计算头像坐标FlashBitmap bitmap = ZooUtil.getAnimal();bitmap.setX(StageUtil.getStage().getX() + i * ZooUtil.getAnimalWidth());bitmap.setY(StageUtil.getStage().getY() + j * ZooUtil.getAnimalHeight());transBitmap[i][j] = bitmap.clone();bitmap.setY(0); // 在顶部慢慢下落bitmaps[i][j] = bitmap;} while(StageUtil.checkClearPoint(bitmaps));}}}

四、重写该View的onDraw方法,在这个方法里面进行动物的绘制

@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 绘制背景图片Bitmap bgBitmap = DisplayUtil.resizeBitmap(background, screenWidth, screenHeight);canvas.drawBitmap(bgBitmap, 0, 0, paint);Bitmap floor = DisplayUtil.resizeBitmap(floorBg, ZooUtil.getAnimalWidth(), ZooUtil.getAnimalHeight());// 每一个小头像背后的背景for (int i = 0; i < row; ++i) {for (int j = 0; j < col; ++j) {if(transBitmap[i][j] != null){int x = (int) transBitmap[i][j].getX();int y = (int) transBitmap[i][j].getY();canvas.drawBitmap(floor, x, y, paint);}}}// 舞台中的所有动物头像FlashBitmap bitmap;for (int i = 0; i < row; ++i) {for (int j = 0; j < col; ++j) {bitmap = bitmaps[i][j];if(bitmap != null // 不为空并且坐标点要进入舞台&& StageUtil.inStage(bitmap.getX(), bitmap.getY() + bitmap.getHeight() / 2)){canvas.drawBitmap(bitmap.getBitmap(), bitmap.getX(), bitmap.getY(), paint);}}}// 是否需要加载消除synchronized (this){if (load) {pool.execute(new Runnable() {@Overridepublic void run() {clearBitmap();}});load = false;}}paint.setColor(Color.WHITE);paint.setTextSize(32);paint.setTypeface(Typeface.create(Typeface.DEFAULT_BOLD , Typeface.BOLD));canvas.drawText("当前关卡:" + level, 10, StageUtil.getStage().getHeight() + 70, paint);canvas.drawText("当前得分:" + currScore, 10, StageUtil.getStage().getHeight() + 120, paint);canvas.drawText("通关分数:" + accessScore[level - 1], 10, StageUtil.getStage().getHeight() + 170, paint);// 刷新屏幕的频率(理论上小于25,人就会感觉物体是在移动)postInvalidateDelayed(1);}

五、重写onTouchEvent方法监听该View的按下、抬起、移动等相关事件

@Overridepublic boolean onTouchEvent(MotionEvent event) {// 判断交换状态是否完毕if(swapState){return false;}// 如果正在做下落动画不允许操作if(loadAnimalState){return false;}// 获取当前触控位置float ex = event.getX();float ey = event.getY();switch (event.getAction()) {// 按下case MotionEvent.ACTION_DOWN:// 判断是否该点是按在舞台上if (!isDown && StageUtil.inStage(ex, ey)) {p1.setX(ex);p1.setY(ey);isDown = true;}break;// 移动case MotionEvent.ACTION_MOVE:// 判断是否该点是按在舞台上if (!isDown && StageUtil.inStage(ex, ey)) {p1.setX(ex);p1.setY(ey);isDown = true;}break;// 抬起case MotionEvent.ACTION_UP:if (isDown) {p2.setX(ex);p2.setY(ey);isDown = false;prepSwap(); // 预处理交换}break;}// 使系统响应事件,返回truereturn true;}

基本上到了这里,这个游戏的主体就已经完成了。
下面主要介绍交换和下落以及如何制作交换和下落的动画
##1:交换
我的整个游戏舞台都是用数组保存的,所以交换直接两个坐标交换一下就算完成了

    // 两个方块的交换状态private boolean swapState = false;// 载入动物头像动画是否结束状态private boolean loadAnimalState = false;// 是否要加载舞台消除动画(程序运行时立即加载)private boolean load = true;// 虚拟背景private FlashBitmap[][] transBitmap = new FlashBitmap[row][col];// 动物头像以及游戏坐标private FlashBitmap[][] bitmaps = new FlashBitmap[row][col];// 背景音乐private MediaPlayer bgMedia; // , clearMedia, swap;// 线程池ExecutorService pool = Executors.newFixedThreadPool(5);
//    private BlockingQueue queue = new LinkedBlockingQueue();
//    private ThreadPoolExecutor pool = new ThreadPoolExecutor(3,
//            10,
//            10,
//            TimeUnit.SECONDS,
//            queue);

###动画效果的思路如下:
1.1:定义两个线程,分别计算出两个头像要交换到的终点,这个终点是通过计算出来的
例如:a[0][0] -> a[0][1], 那么a[0][0]肯定是向右,a[0][1]肯定是向左,只要稍加判断就可以得出a[0][0]是x轴到达 a[0][1],这里大家不要误解,我的真实坐标是一个数组,但是画在地图上的坐标是这个数组所对应的x,y ,所以交换的时候先让真实数组交换,然后再根据真实数组的坐标,计算出x或y需要到达的位置.
a[0][1]所对应的 x 的真实坐标应为:0 * 动物宽度 + 舞台左边界距离(0是数组里面的)
a[0][1]所对应的 y 的真实坐标应为:1 * 动物高度 + 舞台上边界距离(1是数组里面的)
1.2:计算出这两个值,判断一下大小,然后定义两个线程同时启动就ok了,因为是两个线程不停的交互移动,所以肉眼是感觉不出来的
这是我的swap方法里面计算交换后x, y位置的代码

// 判断是横着交换还是竖的交换
final int px1 = (int) StageUtil.getStage().getX() + x1 * ZooUtil.getAnimalWidth();
final int py1 = (int) StageUtil.getStage().getY() + y1 * ZooUtil.getAnimalHeight();
final int px2 = (int) StageUtil.getStage().getX() + x2 * ZooUtil.getAnimalWidth();
final int py2 = (int) StageUtil.getStage().getY() + y2 * ZooUtil.getAnimalHeight();
// 取到交换后的两个坐标对象
final FlashBitmap one = bitmaps[x1][y1];
final FlashBitmap two = bitmaps[x2][y2];

##2:动物下落
下落我之前设想一个思路,是用多线程实现,但是大部分内存杀手估计就是像我这种的程序员吧,当然用多线程那肯定是方便多了,消除几个后,直接把每个要下落的动物都建立一个线程,慢慢的加这个动物的y轴,只要判断一下这个动物头像的最后落点在哪里(计算方式同swap里面的),当然要考虑一下动物头像的下落坐标,不要超过它的下面那个动物头像,因为线程,有的快,有的慢, 这个是没法保证的。
这种方案完成后,我找群里的人帮我测试了一下,大部分人都说反应慢,效果不好,动画不流畅。之后脑子里一直想着用一个线程处理掉这个下落的动画,而下落又是好多头像同时进行的,继而我又想起如何在每个动物之间快速切换,最后想了很久,想到了一种方案,两个for循环控制着所有的动物头像,每次循环只将一个动物的y轴加一步,然后就结束,在两个for之外再加一个while循环,这个while检测到所有的动物头像都到达终点后才退出,这样的话,用一个线程达到了我想要的效果。
代码片断:

// 移动其它头像
boolean updateFlag = false;
boolean canDoWhile;
int[] index = new int[col];
do {canDoWhile = false;// 开始进行下落处理for(int j = col - 1; j >= 0; --j){for(int i = 0; i < row; ++i){if(bitmaps[i][j] != null){if(!moveStageAnimal(i, j)){canDoWhile = true;}} else {// 只要检测到有任意一个空位就要进行更新updateFlag = true;// 如果是空,检测从当前位置往上是否还有其它动物头像boolean hasPoint = false;for(int k = j - 1; k >= 0; --k){// 如果检测到有一个点的话就不搞事情了if(bitmaps[i][k] != null){hasPoint = true;}}// 如果没有就直接生成一个新点在这个位置// 真实坐标是这个位置,但显示在地图上的坐标要给个到 (x, 0)if(!hasPoint) {FlashBitmap bitmap = ZooUtil.getAnimal();bitmap.setX(StageUtil.getStage().getX() + i * ZooUtil.getAnimalWidth());bitmap.setY(StageUtil.getStage().getY() - (index[i] + 1) * ZooUtil.getAnimalHeight());bitmaps[i][j] = bitmap;index[i]++;}}}}// 动画停留间隔DisplayUtil.sleep(time);
} while(canDoWhile);

最后再看一个下落的移动动物头像方法

/*** 移动舞台动物* @param x x* @param y y* @return 成功true 失败false*/
private boolean moveStageAnimal(int x, int y) {// 记录当前的点int j;float currY = bitmaps[x][y].getY();// 寻找最佳底部的空位for(j = col - 1; j >= 0; --j){// 不能小于以前的位置if(j <= y){break;}// 从底往上找,找到的第一个空位就为要到的位置if(bitmaps[x][j] == null){break;}}// 有最新点时才进行交换if(j != y){FlashBitmap temp = bitmaps[x][y];bitmaps[x][y] = null;bitmaps[x][j] = temp;}// 不允许在这之上的方块提前下落到下一个方块后面if(j < col - 1 && bitmaps[x][j + 1] != null){if(currY + ZooUtil.getAnimalHeight() >= bitmaps[x][j + 1].getY()){return true;}}// 到达指定高度停止if(currY >= j * ZooUtil.getAnimalHeight() + StageUtil.getStage().getY()){return true;}// 大于舞台高度直接停止if(currY + bitmaps[x][j].getHeight() >= StageUtil.getStage().getHeight()){return true;}// 自增currY += speed;bitmaps[x][j].setY(currY);return false;
}

做这个游戏大概花了两天半的时间,主要是为了更深刻的认识多线程,另外也是听说安卓6.0变动很大,所以用安卓做,其实安卓里面嵌入H5也比较合适的,我用h5做过坦克大战,基本不用考虑性能问题,嵌入到安卓里面就更完美了。

Android开发的消消乐游戏相关推荐

  1. 【思考一】Android程序员想做手机游戏开发

    之前觉得手游开发很有意思,很炫酷,本来以为Android程序员很容易就可以转行来做Android手游开发,后来一段时间苦苦在找资料学习,但是发现,一个纯粹的Android程序员只会用java语言,可能 ...

  2. python编程游戏手机版_利用Python开发手机同款游戏:开心消消乐

    手机上面的开心消消乐,我想大部分人都是玩过的吧,今天小编就教大家如何用python开发这款游戏 不过只有十个关卡,不像手机里面那么多的关卡!不过游戏的画面和bgm都是同款的哦~ 效果图 基本配置 wi ...

  3. Android开发入门 - 简易开心消消乐界面设计

    Android开发入门 - 简易开心消消乐界面设计 第一步,点击File->NEW->new module,进入以下界面,选择第一个,即运行在手机和平板电脑上.点击next. 第二步,在第 ...

  4. 视频教程-老司机讲前端之微信小程序开发成语消消乐游戏视频课程-微信开发

    老司机讲前端之微信小程序开发成语消消乐游戏视频课程 中国实战派HTML5培训第一人,微软技术讲师,曾任百合网技术总监,博看文思HTML5总监.陶国荣长期致力于HTML5.JavaScript.CSS3 ...

  5. 老司机讲前端之微信小程序开发成语消消乐游戏视频课程-陶国荣-专题视频课程...

    老司机讲前端之微信小程序开发成语消消乐游戏视频课程-102人已学习 课程介绍         本课通过一个完整.真实的游戏项目,带着学员手动开发代码,本课分项目介绍.界面效果.技术分析.代码实现.打包 ...

  6. 零基础cocos2dx游戏开发之【水果消消乐】

    cocos2dx零基础实战[水果消消乐]   前言:    大家好,我是Lampard!!!    好久没有更新实战的博文,今天给大家分享一款游戏[水果消消乐]    本游戏是基于刘克男老师在2019 ...

  7. 【图片消消乐】单机游戏-微信小程序项目开发入门

    这是一个微信小程序项目,是类似开心消消乐的休闲小游戏,老少皆宜,游戏互动里面的图片是用的任何图片素材,根据自己的需求更换图片即可.想要做游戏不知道怎么做,建议从这个小程序入手,花时间研究学习,很快就拥 ...

  8. 基于pygame的消消乐小游戏开发

    1 简介 今天向大家介绍一个帮助往届学生完成的毕业设计项目,基于pygame的消消乐小游戏开发. 计算机毕业生设计,课程设计需要帮助的可以找我 2 设计概要 21世纪是信息化时代,随着信息技术和网络技 ...

  9. 《七彩消消乐》开发中的一些经验分享和总结 - #游戏创业#

    最近游戏创业太累了, 弄了几个月搞出一个消消乐的游戏,太煎熬了,上线只是第一步,接下来的运营才是关键 给大家分享一下,游戏创业艰难险阻.如果你也想做游戏自主创业可以和我交流沟通 qq: 8416547 ...

  10. 利用Python开发手机同款游戏:开心消消乐

    手机上面的开心消消乐,我想大部分人都是玩过的吧,今天小编就教大家如何用Python开发这款游戏 不过只有十个关卡,不像手机里面那么多的关卡!不过游戏的画面和BGM都是同款的哦~ 效果图 基本配置 Wi ...

最新文章

  1. 分享一个高质量的 小程序UI框架
  2. 比尔.盖茨人生的四张面孔
  3. python OOP (1)
  4. 【ijkplayer】编译 Android 版本的 ijkplayer ④ ( 安装 make yasm 软件 | 执行 compile-ffmpeg.sh all 命令编译 ffmpeg )
  5. Linux与Windows中的UTC时间
  6. LAMP攻略: LAMP环境搭建,Linux下Apache,MySQL,PHP安装与配置
  7. php全套之一崭露头角(12天),PHP系列教程之一阶段崭露头角 (JS,bootstrap )
  8. java最长同值路径_力扣——最长同值路径
  9. IDEA 强大文件对比功能
  10. 树莓派开发笔记(七):GPIO口的SPI使用(BME280三合一传感器:测量温度、湿度、气压、海拔高度)
  11. 学完了C++语法之后该学什么??(网络基础篇)
  12. 代理服务是个什么东西?
  13. 十步会用IOCOMP–iplotx控件
  14. html5学生成绩表,学生成绩表excel
  15. erlang, 支付宝, 以及其他
  16. 2013百度之星月度冠军乔明达:小学五年级接触编程
  17. html双击回顶部,百度/微信小程序点击按钮回到顶部(scrollTop=0)/点击拨打电话...
  18. 遨博协作机器人插件开发-机械臂无线手柄遥控插件开发
  19. QA和QC到底是什么区别?
  20. FINTECH自建科技生态介绍

热门文章

  1. 朗威计算机保密检查取证工具,保密检查工具(中安兴坤、朗威、中孚)含国保测证书...
  2. 重装机兵3 完美攻略修正版
  3. 单片机编程软件很简单(16),Keil单片机编程软件建立工程项目
  4. VS2017的C++开发心得(一)VS的项目创建
  5. 解决office 2016公式编辑器空白,无法正常显示公式的问题
  6. qrcode生成带logo的二维码(插件,示例代码)
  7. 数据结构视频教程哪个好
  8. centos长ping输出日志的脚本
  9. java 读写acr122u_使用ACR122U 从NTAG203Chip 读取数据
  10. 基于 wke 的浏览器:如何实现 js 和 c++ 的互相调用