关于推箱子(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:盗图可耻,转载说明出处