Android小游戏之推箱子(1.27更新)

关于推箱子(Sokoban)


From:Sokoban

Sokoban (倉庫番 sōkoban?, warehouse keeper) is a type of transport puzzle, in which the player pushes boxes or crates around in a warehouse, trying to get them to storage locations. The puzzle is usually implemented as a video game.
Sokoban was created in 1981 by Hiroyuki Imabayashi, and published in 1982 by Thinking Rabbit, a software house based in Takarazuka, Japan.

相信大家肯定都玩过推箱子这样的小游戏吧

推箱子

规则很简单:


  • 推到墙壁的箱子,玩家就不可以背对墙壁,把箱子推回到空处。即箱子只能以“被推”的方式被移动,不是以“被拉”的方式被移动。但如果玩家推至墙壁后,垂直墙壁的两侧没有阻碍物,则玩家可以朝这两个不同的方向推移箱子。

  • 一旦箱子被移动到角落,玩家没有任何方法再移动这个被推到角落的箱子。

  • 玩家不可同时推动两个或以上的箱子。假设工人面前有一个箱子,箱子的正前方又有一个箱子,则这两个箱子是不能被推动的。


初始思路


基本想法



  • 载入过程

  • 完善的菜单

  • 帮助引导


大体思路



  1. 利用布局控制菜单

  2. 通过算法来实现游戏逻辑

  3. 细节优化


游戏逻辑


大概思路


要想角色自如的移动不是太难的问题。但是如何想去判断他的行为,如遇到箱子可以继续前进,遇到墙壁无法前进等等,这才是需要着重考虑的事情。

因此,我们姑且将背景设置为一个二维的坐标系,通过坐标(x,y)来获得当前人物的具体位置。当然与之对应的就是在计算机中通过数组来表示。

但是难题出现了,若用二维数组表示坐标的话,能快速定位,但是具体的逻辑判断就很复杂。这样来说吧,若用上面的想法,对于墙,人,道路,箱子,每一个不同的物品我们就要分别使用不同的数组加以区分,更坏的是在逻辑判断的时候,我就得费很大的功夫去来调度控制它们,让诸如 人穿墙而不能推箱子 的事情不要发生。

换个思路


若我们将整个坐标简单话,比如原本的(2,3)变为(23),这样一来是不是咱们就将二维的数据换成一个一维的。同样是使用二维数组,那样咱们就可以空出一个位置来存放标志位了,标志位的作用嘛,大家都是懂的:

  • 0代表围墙

  • 1代表道路以及箱子的目的位置

  • 2代表箱子

  • 4代表人


不要问我3 哪里去了,我不是芒果台。

实施过程


人物移动判断处理


咱们将一个背景看作是一个二维坐标,在本例中我使用 8*12的坐标,假定其为一个二维的数组matirx[8][12],数组中保存的是一堆imageView的图片。关卡使用的是另一个数组,从@string/中读取关卡数据,就是一串字符串而已。游戏中,人的移动通过4个方向键控制移动的位置。例如

  • 上方向键,获取人所在的坐标peoplex,peopley

  • 通过判断矩阵matrix[peoplex - 1][peopley]的标志位是否为1或者matrix[peoplex - 1][peopley]为2时matrix[peoplex - 2][peopley]是否为1的方式控制人或箱子能否移动。

  • 移动之后将标记位交叉赋值,并重新设置imageView上的图片,达到移动效果,

  • 最后更新人物坐标peoplex peopley。


通过这个简单的过程,便能实现游戏人物和箱子逻辑的实现。

背景音乐及音效(1.27更新)

说起背景音乐,是一个让人头疼的问题,做过Android Mp3播放器的我,很是让它折磨。由于要有一定的线程知识,而我以前对于线程的理解很烂。所以到这个步骤,还是比较头疼。得解决如下的问题:

  • MediaPlayer调用很复杂,like this:
    MediaPlayer但背景音乐需要一直在后台播放,MediaPlayer每一次需要初始化,那样就能带来很多的问题,比如:

    • 在你退出游戏后,若忘记终止MediaPlayer,则音乐会一直在后台运行

    • 在游戏的主要逻辑上面需要插入大量的代码,影响后续的开发

    • 多个音频在一起的时候,需要书写的代码量就比较多

    • 按钮等特效音乐一般情况比较短暂且,用MediaPlayer很头疼等等



  • 利用SoundPool,可以将音乐放进一个大的音乐池,适合短暂的触发播放。这就是我们需要找的特效的音乐播放方式。


其实上面的MediaPlayer和SoundPool各有所长,所以我们要做的就是将他们mix up。
OK,接下来就是将他们封装起来,留出简单的调用API,实现我们的需求。

To Be Continue…


PS:最近刚刚放假回家,很奇怪不知道怎么的情况上火非常严重,每天鼻子会流血,牙齿会不定期出血,舌头疼,脸上非常缺水分。

想到了13年夏天,那个牙医再给我补那4颗牙的时候给我说的话:“等你这四个牙齿好了后,过来把你的那4个智齿拔了去,不然以后很影响我的生活。”现在是真心的体会到了,不要说熬夜了,晚上11点多睡觉,第二天牙齿还疼的厉害。So,我得想想办法下下火,解解肝热。

因此等我有所好转,就开始继续写Blog了,刚好趁着我在家,也好抽多点时间,帮老妈打扫家,老妈一年到头了,还那么幸苦,回家能帮点就帮点,洗完什么的早已经承包下来了,希望大家还是能多多尽一份自己的孝心,不要整天坐在电脑前面

1.27更新:

  • 随着过年越来越近,街道的人也达到了最多,出去买个饭都要等很久。小县城的好处就是过年的年味很足。

  • 今天是五九的第一天,五九来了春天还会远吗?送大家一个顺口溜

    • 一九二九不出手

    • 三九四 九河上走

    • 五九六九沿河望柳

    • 七九开河,八九雁来

    • 九九又一九,耕牛遍地走



  • 看完了《金蝉脱壳》,阿诺拿着51机枪扫射的时候,我想起了那天在夕阳下,我逝去的青春~(PS:考虑要不要在我的博客,里面开设一个电影分析和推荐的专题页,太爱电影)
    1
    I Will Be Back

  • 最后送上小弟不才的照片一张,期待万物复苏,花儿鲜艳,人儿美腻~
    2
    BTW:盗图可耻,转载说明出处

-------------The End-------------
请我喝一杯啤酒~