Android 连连看设计 (1)

1、绪论

1.1、 背景说明:

(1)休闲类游戏(Casual Game)可以包含任何游戏类型的游戏性要素,通常休闲游戏的游戏规则相对简单,无需特别的技巧,也不需要较长的时间就能完成游戏。休闲游戏经常出现在不同的平台上[8],包括家用游戏机、掌上游戏机和个人电脑上等等。休闲类游戏通常也适合于各种不同性别、地域和文化的玩家群体。 本文所涉及的游戏项目,是一款棋类休闲游戏,基于 Windows 平台,无需较长的时间就能完成一局的游戏,一局游戏一般在 5 到 20 分钟左右就能完成根据该局游戏玩家的游戏策略等因素,一局游戏的完成时间会有一定差别.(2) Android技术Android一词的本义指“机器人[29]”,同时也是Google于2007年11月5日宣布的基于Linux平台的开源手机操作系统的名称,该平台由操作系统、中间件、用户界面和应用软件组成,号称是首个为移动终端打造的真正开放和完整的移动软件。

Android作为软件平台标准,需有硬件提供各种运算能力才能形成完整系统。Android软件平台包含Java应用程序、Application Framework、Libraries、Runtime~Linux Os等层。每一层内含多个独立组件完成不同功能,Android在各组件与层之间订出标准界面。因此Android系统可以像积木堆栈一般,不同应用产品可以依功能需要加入软件或硬件组件整合成不同产品[31]

当今的人们忙于工作,很少有时间静下心来享受一些小游戏的乐趣,因此手机版一些小游戏 如:象棋、贪吃蛇、连连看。。。 等便受到人们的关注。

1.2、环境与平台

待开发软件系统的名称:基于Android系统的连连看游戏设计  

本项目的任务提出者:学校

开发者:游戏开发小组

用户:喜欢玩游戏的人

项目开发环境:my eclipse、Android系统平台

Android手机版 水果连连看 设计与实现

1.3、参考资料

Android开发指南》

《Android游戏开发》

网址:http://www.cnblogs.com/hellope/archive/2011/08/12/2136505.html

2、程序系统的结构

   连连看游戏结构如下:

本程序主要包含两大模块:即(1)表示层模块;(2)后台逻辑模块;(3)主要有6个大类:其中表示层模块可以理解为游戏的UI及一些游戏辅助效果,表示层模块中,重要的是实现游戏的布局地图,项目中实现中,游戏的布局将使用自定义View的方式,在屏幕上贴图实现。而菜单模块及选关的dialog,只是为用户提供一些常见的选择,如重玩,过关继续音效开关等等,为了有一个更好的用户交互环境,dialog的实现将通过自定义dialog的方式。而游戏音效是MediaPlayer在不同的状态场景下播放不同的游戏音效。而后台逻辑模块中,即时对于程序计算的实现与程序各种状态的监听,将是整个程序运行的基础。此模块中将实现对于游戏剩余时间限制和游戏状态的监听与处理。对于游戏剩余时间的监听,将开启单独的线程进行处理,从而不至于影响主程序逻辑的运行;游戏的状态的监控处理中,将会实现对于连通的两个图标的消除(即游戏界面的更新),游戏输赢的监听判断,游戏暂停与否等(暂停状态需要同时将剩余时间暂停,而时间监听线程需要知道所处状态,此二者紧密联系)。

class BoardView /表示层模块中的界面显示类

class GameView //用于处理游戏中的消息提示

class Listener //用于菜单的设计各模块监听

Class MyDialog //用于菜单中游戏难度的设定

Class SoundPlayer //用于音效播放的控制

Class WelcomActivity //时间及游戏状态监控与处理

3、表示层模块中的界面显示类设计说明

3.1、程序描述   

主要功能:用于为玩家提供操作提示,具有良好的可视化。

 

可扩展性:能够适应应用要求的变化和修改,具有灵活的可扩充性。

 

3.2、算法   

首先我们开发在表示层模块中的界面显示类,首先是BoardView类,在android平台下,采用继承自View类的方式,看此类的代码,代码中尽量添加了详细的注释:

   
   
   
   
  1. view sourceprint?
  2. package nate.llk.view;
  3. /*导入包种种再次略去*/
  4. view sourceprint?
  5. public class BoardView extends View {
  6. * xCount x轴方向的图标数+2
  7. protected static final int xCount = 10;
  8. * yCount y轴方向的图表数+2
  9. protected static final int yCount = 12;
  10. /* map 连连看游戏棋盘,map中添加的int型在程序中的意思是index,而不是屏幕坐标 */
  11. protected int[][] map = new int[xCount][yCount];
  12. protected int iconSize;
  13. protected int iconCounts=19;
  14. protected Bitmap[] icons = new Bitmap[iconCounts];
  15. private Point[] path = null;
  16. /**
  17. * selected 选中的图标
  18. */
  19. protected List<Point> selected = new ArrayList<Point>();
  20. /**
  21. 构造函数 * @param context
  22. * @param attrs */
  23. public BoardView(Context context, AttributeSet attrs) {
  24. super(context, attrs);
  25. calIconSize();
  26. Resources r = getResources();
  27. //载入连连看中的图标资源
  28. loadBitmaps(1, r.getDrawable(R.drawable.fruit_01));
  29. loadBitmaps(2, r.getDrawable(R.drawable.fruit_02));
  30. loadBitmaps(3, r.getDrawable(R.drawable.fruit_03));
  31. loadBitmaps(4, r.getDrawable(R.drawable.fruit_04));
  32. loadBitmaps(5, r.getDrawable(R.drawable.fruit_05));
  33. loadBitmaps(6, r.getDrawable(R.drawable.fruit_06));
  34. loadBitmaps(7, r.getDrawable(R.drawable.fruit_07));
  35. loadBitmaps(8, r.getDrawable(R.drawable.fruit_08));
  36. loadBitmaps(9, r.getDrawable(R.drawable.fruit_09));
  37. loadBitmaps(10, r.getDrawable(R.drawable.fruit_10));
  38. loadBitmaps(11, r.getDrawable(R.drawable.fruit_11));
  39. loadBitmaps(12, r.getDrawable(R.drawable.fruit_12));
  40. loadBitmaps(13, r.getDrawable(R.drawable.fruit_13));
  41. loadBitmaps(14, r.getDrawable(R.drawable.fruit_14));
  42. loadBitmaps(15, r.getDrawable(R.drawable.fruit_15));
  43. loadBitmaps(16, r.getDrawable(R.drawable.fruit_17));
  44. loadBitmaps(17, r.getDrawable(R.drawable.fruit_18));
  45. loadBitmaps(18, r.getDrawable(R.drawable.fruit_19));
  46. }
  47. /**
  48. * 计算图标的大小
  49. */
  50. private void calIconSize(){
  51. //取得屏幕的大小
  52. DisplayMetrics dm = new DisplayMetrics();
  53. ((Activity) this.getContext()).getWindowManager()
  54. .getDefaultDisplay().getMetrics(dm);
  55. iconSize = dm.widthPixels/( xCount );
  56. }
  57. /**
  58. * 函数目的在于载入图标资源,同时将一个key(特定的整数标识)与一个图标进行绑定
  59. */
  60. public void loadBitmaps(int key,Drawable d){
  61. Bitmapbitmap = Bitmap.createBitmap(iconSize,iconSize,Bitmap.Config.ARGB_8888);
  62. Canvas canvas = new Canvas(bitmap);
  63. d.setBounds(0, 0, iconSize, iconSize);
  64. d.draw(canvas);
  65. icons[key]=bitmap; //未用0 号index
  66. }
  67. /**
  68. * View自带的,但是在此方法中,有画路径(删除联通的两个图标),
  69. * 绘制棋盘的所有图标(也可理解为刷新,只要此map位置值>0)
  70. * 放大第一个选中的图标(selected.size() == 1)
  71. */
  72. protected void onDraw(Canvas canvas) {
  73. /**
  74. * 绘制连通路径,然后将路径以及两个图标清除
  75. */
  76. if(path != null && path.length >= 2){
  77. for(int i = 0; i < path.length - 1;++i){
  78. Paint paint = new Paint();
  79. paint.setColor(Color.BLUE);
  80. paint.setStrokeWidth(3);
  81. paint.setStyle(Paint.Style.STROKE);
  82. Point p1 = indexToScreen(path[i].x,path[i].y);
  83. Point p2 = indexToScreen(path[i + 1].x,path[i + 1].y);
  84. canvas.drawLine(p1.x + iconSize/2, p1.y + iconSize/2,
  85. p2.x + iconSize/2, p2.y + iconSize/2, paint);
  86. }
  87. map[path[0].x][path[0].y] = 0;
  88. map[path[path.length - 1].x][path[path.length -1].y] = 0;
  89. selected.clear();
  90. path = null;
  91. }
  92. for(int x = 1;x < xCount - 1; ++x){
  93. for(int y = 1; y < yCount -1; ++y){
  94. if(map[x][y]>0){
  95. Point p = indexToScreen(x, y);
  96. canvas.drawBitmap(icons[map[x][y]], p.x,p.y,null);
  97. }
  98. }
  99. }
  100. /**
  101. * 绘制选中图标,当选中时图标放大显示
  102. */
  103. //for(Point position:selected){
  104. if(selected.size() > 0){
  105. Point position = selected.get(0);
  106. Point p = indexToScreen(position.x, position.y);
  107. if(map[position.x][position.y] >= 1){
  108. canvas.drawBitmap(icons[map[position.x][position.y]],
  109. null,
  110. new Rect(p.x-5, p.y-5, p.x + iconSize + 5, p.y + iconSize + 5), null);
  111. }
  112. }
  113. super.onDraw(canvas);
  114. }
  115. /**
  116. * 工具方法
  117. * @param x 数组中的横坐标
  118. * @param y 数组中的纵坐标
  119. * @return 将图标在数组中的坐标转成在屏幕上的真实坐标
  120. */
  121. public Point indexToScreen(int x,int y){
  122. return new Point(x * iconSize,y * iconSize);
  123. }
  124. /**
  125. * 工具方法
  126. * @param x 屏幕中的横坐标
  127. * @param y 屏幕中的纵坐标
  128. * @return 将图标在屏幕中的坐标转成在数组上的虚拟坐标
  129. */
  130. public Point screenToIndex(int x,int y){
  131. int xindex = x / iconSize;
  132. int yindex = y / iconSize;
  133. if(xindex < xCount && yindex < yCount){
  134. return new Point(xindex,yindex);
  135. }else{
  136. return new Point(0,0);
  137. }
  138. }
  139. * 传进来path数据更新显示,也就是将能够连接的图标消除
  140. * @param path
  141. */
  142. public void drawLine(Point[] path) {
  143. this.path = path;
  144. this.invalidate();
  145. }

3.3、接口

1、API函数

   
   
   
   
  1. class RefreshTime implements Runnable{
  2. public void run() {
  3. if(isContinue){
  4. while(leftTime > 0 && !isStop){
  5. timerListener.onTimer(leftTime);
  6. leftTime --;
  7. try {
  8. } catch (InterruptedException e) {
  9. e.printStackTrace();
  10. }
  11. }
  12. }
  13. if(isStop && leftTime > 0){
  14. if(win())
  15. ;//setMode(WIN);
  16. else
  17. setMode(PAUSE);
  18. }
  19. //setMode(LOSE);
  20. else if(leftTime == 0){
  21. setMode(LOSE);
  22. } } }
  23. public void stopTimer(){
  24. isStop = true;
  25. isContinue = false;
  26. } /**
  27. * 设置继续
  28. */
  29. public void setContinue(){
  30. isContinue = true;
  31. isStop = false;
  32. refreshTime = new RefreshTime();
  33. Thread t = new Thread(refreshTime); //注意正确启动一个实现Runnable接口的线程
  34. t.start();
  35. }
  36. 2、上面已经提过,此线程用于控制游戏的时间
  37. 在此,再介绍自定义的几个接口,
  38. view sourceprint?
  39. public interface OnStateListener{
  40. public void OnStateChanged(int StateMode);
  41. }
  42. 只含有一个方法,主要对于游戏状态的变换的监听,比如pause,stop等等。
  43. view sourceprint?
  44. public interface OnTimerListener{
  45. public void onTimer(int leftTime);
  46. }

用于监听剩余时间,与上面线程不同的是,此方法中利用上面线程的leftTime的结果,主要用于更新游戏中用于提醒玩家的时间进度条。

view sourceprint?

public interface OnToolsChangeListener{

public void onRefreshChanged(int count);

public void onTipChanged(int count);

}

tool即是我们的游戏中提供给玩家的两个工具,一个是refresh一下游戏界面,即将现有的棋盘重新打乱(当然,现有图表数量不变),另一个是之前提过的hint的自动帮助功能,帮助玩家找到一组能够连通的图标。当然,这两种工具都有次数的限制。

 BoardView类及时间线程类的开发与介绍到此,后面我们将完整的实现游戏棋盘的绘制与touch事件的处理,以及游戏核心算法中连接算法、hint自动帮助算法与判断是否无解算法的实现。这些代码的处理都在继承自BoardView类的GameView类中。记录android小项目的经历,增加实战的能力,做个总结。

你可能感兴趣的:(android,设计,连连看)