cocos2d-x 3.2 之 2048 —— 第四篇 ★ 核心 ★

前端之家收集整理的这篇文章主要介绍了cocos2d-x 3.2 之 2048 —— 第四篇 ★ 核心 ★前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************



大家十一过得肿么样啊~

我现在的情况就是——每逢佳节 胖三斤 啊 ,胖三斤。。o(╯□╰)o。。


好了,继续做2048,

这是第四篇啦~


这篇的内容就是对触摸的处理哟~

就是,你上下左右滑动,相应移动~


我们先在 游戏的宏定义类 中,建立一个枚举方向变量:

GameDefine.h:

  1. <span style="font-family:Comic Sans MS;">enum class MOVE_DIR
  2. {
  3. UP,DOWN,LEFT,RIGHT
  4. };</span>

然后,我们可以在 游戏界面 进行屏幕触摸处理了:

GameScene.h:

  1. <span style="font-family:Comic Sans MS;">int m_x,m_y;
  2. bool m_startMove;</span>
  1. <span style="font-family:Comic Sans MS;">void moveAllTiled( MOVE_DIR dir );</span>

m_x和m_y 的作用是 记录屏幕开始触摸时的坐标,

m_startMove 判断是否开始触摸,并且在一个滑动结束前,不允许再次获取触摸

moveAllTiled 函数 作用 就是根据滑动的方向,对相应方向的数字块 进行合并或者移动


GameScene.cpp—— init函数

  1. <span style="font-family:Comic Sans MS;">// 屏幕触摸处理
  2.  
  3. // 创建触摸事件
  4. auto event = EventListenerTouchOneByOne::create();
  5. event -> onTouchBegan = [&](Touch *tou,Event *eve){
  6. // 记录触摸位置
  7. m_x = tou -> getLocation().x;
  8. m_y = tou -> getLocation().y;
  9. m_startMove = true;
  10. return true;
  11. };
  12. event -> onTouchMoved = [&](Touch *tou,Event *eve){
  13. // 记录触摸结束的位置
  14. int x = tou -> getLocation().x;
  15. int y = tou -> getLocation().y;
  16.  
  17. // 如果这个触摸事件开始,并且触摸位置相差有10像素,则开始进行移动合并
  18. if( m_startMove==true && ( abs( m_x - x ) > 10 || abs( m_y - y ) >10 ))
  19. {
  20. m_startMove = false;
  21. MOVE_DIR dir;
  22. // 根据起末坐标位置,判断向哪个方向移动
  23. if( abs(m_x - x) > abs(m_y - y) )
  24. {
  25. if( m_x < x )
  26. dir = MOVE_DIR::RIGHT;
  27. else
  28. dir = MOVE_DIR::LEFT;
  29. }
  30. else
  31. {
  32. if( m_y < y )
  33. dir = MOVE_DIR::UP;
  34. else
  35. dir = MOVE_DIR::DOWN;
  36. }
  37.  
  38. moveAllTiled(dir);
  39. }
  40. };
  41. // 当前场景添加监听器,就是可以获取当前场景的 触摸事件
  42. Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraPHPriority(
  43. event,this);</span><span style="font-family:Arial;">
  44. </span>

具体解释,都在代码中给出了,

然后进行对moveAllTiled函数设定:

  1. <span style="font-family:Comic Sans MS;">void GameScene::moveAllTiled( MOVE_DIR dir )
  2. {
  3. // 根据具体方向进行,相应方向的移动
  4. switch ( dir )
  5. {
  6. case MOVE_DIR::UP: moveUp();
  7. break;
  8. case MOVE_DIR::DOWN: moveDown();
  9. break;
  10. case MOVE_DIR::LEFT: moveLeft();
  11. break;
  12. case MOVE_DIR::RIGHT: moveRight();
  13. break;
  14. default:
  15. break;
  16. }
  17. // 移动完成,随机产生新块
  18. newNumberTiled();
  19. }</span>

这个函数,未来还要加很多东西,

比如判定是否游戏结束,判断是否可以向某个方向移动,

还有音效等等。。


在moveAllTiled函数中,用到了

moveUp、moveDown、moveLeft和moveRight四个函数,下面对这四个函数进行定义,

当然,首先要在GameScene.h中进行声明:

  1. void moveUp();
  2. void moveDown();
  3. void moveLeft();
  4. void moveRight();

然后,先对moveUp 进行定义:

  1. <span style="font-family:Comic Sans MS;font-size:14px;">void GameScene::moveUp( )
  2. {
  3. // 向上移动所有的块
  4. for( int col = 0 ; col < GAME_COLS ; ++col )
  5. {
  6. for( int row = GAME_ROWS - 1 ; row >= 0 ; --row )
  7. {
  8. if( map[row][col] > 0 )
  9. {
  10. for( int row1 = row ; row1 < GAME_ROWS - 1 ; ++row1 )
  11. {
  12. // 上方是空的 才会移动
  13. if( map[row1+1][col] == 0 )
  14. {
  15. map[row1+1][col] = map[row1][col];
  16. map[row1][col] = 0;
  17.  
  18. m_allTiled.at( map[row1+1][col] - 1 ) -> moveTo( row1+1,col );
  19. }
  20. else
  21. {
  22. // 判断, 是否可以消除
  23.  
  24. // 获取上面那格子的数字
  25. int numObj = m_allTiled.at( map[row1+1][col] - 1 ) -> m_number;
  26. // 获取当前格子的数字
  27. int numNow = m_allTiled.at( map[row1][col] - 1 ) -> m_number;
  28. // 两个格子数字相同
  29. if( numNow == numObj )
  30. {
  31. // 上面那一行数字X2
  32. m_allTiled.at( map[row1+1][col] - 1 ) -> doubleNumber();
  33. // 去除掉当前数字块
  34. m_allTiled.at( map[row1][col] - 1 ) -> removeFromParent();
  35. // 获取当前数字块编号
  36. int index = map[row1][col];
  37. m_allTiled.erase( map[row1][col] - 1 );
  38. // 纠正所有大于index号码的编号大小
  39. for( int r = 0 ; r < GAME_ROWS ; ++r )
  40. {
  41. for( int c = 0 ; c < GAME_COLS ; ++c )
  42. {
  43. if( map[r][c] > index )
  44. {
  45. --map[r][c];
  46. }
  47. }
  48. }
  49. // 将当前块编号设置为0
  50. map[row1][col] = 0;
  51. }
  52. break;
  53. }
  54. }
  55. }
  56. }
  57. }
  58. }</span>

详细解释,代码中也有注释。

但还是要说一下这个原理:( 应该属于2048的核心部分了~ )

就是从最下面一行最左面到 上面倒数第二行最右面,挨个遍历,

每个都要和自己上面一行相应列的数字块进行比较,

——如果本行的map值为0,则不管继续

——如果本行map值不为0,则从本行相应列一直遍历到倒数第二行的相应列

————如果上面那一行map值为0,则将本行与上面那一行互换(其实本行置0,上面那一行换成本行)

————否则,因为两行都不为0,判断两行数值是否相等

————————若相等,则上面那一行的数值翻倍,本行数字块移除,并对map内其他相应编号进行改变

————————若不等,则break

逻辑块由map和Vector共同处理控制,

map存储的是编号,就是这个块是本图内第几个产生的块,最先产生的块,map值为1,第二个为2,等等,

而Vector是存储这个数字块的类,包括这个数字块的位置,和数字块数字的值。


用这两个控制而不是仅仅单用Vector好处就是,我们不需要遇到判断,就要去Vector找,

而是先通过map可以判断当前位置有没有数字块,

而且在随机生成那里,也方便很多,程序效率会得到提高。


关于,核心原理部分已经说完,现在我们可以设置一下,关于对相应数字块的翻倍处理了:

在设置这个函数之前,要对之前的数字块进行些处理,

我们要在函数获取到 数字块背景颜色层 和 数字显示层,

所以,我们要对这两个设置个Tag:

  1. bk -> setTag( 101 );
  2.  
  3. label -> setTag( 102 );

别忘了,在头文件声明doubleNumber函数哟(我就不打出来了)

  1. <span style="font-family:Comic Sans MS;font-size:12px;">void NumberTiled::doubleNumber( )
  2. {
  3. // 将数字块的数字值翻倍
  4. this->m_number = this->m_number*2;
  5.  
  6. // 获取到背景层和数字层
  7. auto bk = this -> getChildByTag(101);
  8. Label *label = (Label *) bk -> getChildByTag(102);
  9. // 对数字层的数字,重新绘制
  10. label -> setString( StringUtils::format( "%d",m_number) );
  11.  
  12.  
  13. //根据值得大小,对背景层重绘颜色
  14. switch ( this -> m_number )
  15. {
  16. case 2: bk -> setColor(Color3B(230,220,210)); break;
  17. case 4: bk -> setColor(Color3B(230,210,190)); break;
  18. case 8: bk -> setColor(Color3B(230,150,100)); label -> setColor(Color3B(255,255,255)) ;break;
  19. case 16: bk -> setColor(Color3B(230,120,80)); label -> setColor(Color3B(255,255)) ;break;
  20. case 32: bk -> setColor(Color3B(230,100,90)); label -> setColor(Color3B(255,255)) ;break;
  21. case 64: bk -> setColor(Color3B(230,70,60)); label -> setColor(Color3B(255,255)) ;break;
  22. case 128: label -> setScale(0.7f); bk -> setColor(Color3B(230,190,60)); label -> setColor(Color3B(255,255)) ;break;
  23. case 256: label -> setScale(0.7f); bk -> setColor(Color3B(230,255)) ;break;
  24. case 512: label -> setScale(0.7f); bk -> setColor(Color3B(230,255)) ;break;
  25. case 1024:
  26. case 2048: label -> setScale(0.5f); bk -> setColor(Color3B(210,180,30)); label -> setColor(Color3B(255,255)) ;break;
  27. default: break;
  28. }
  29. }</span>

OK,来运行一下,看看效果



怎么样,还可以吧~

接下来,要对 下、左、右 剩下三个方向进行函数定义:

  1. <span style="font-family:Comic Sans MS;font-size:12px;">void GameScene::moveDown( )
  2. {
  3. // 向下移动所有的块
  4. for( int col = 0 ; col < GAME_COLS ; ++col )
  5. {
  6. for( int row = 0 ; row < GAME_ROWS ; ++row )
  7. {
  8. if( map[row][col] > 0 )
  9. {
  10. for( int row1 = row ; row1 > 0 ; --row1 )
  11. {
  12. if( map[row1-1][col] == 0 )
  13. {
  14. map[row1-1][col] = map[row1][col];
  15. map[row1][col] = 0;
  16. m_allTiled.at( map[row1-1][col] - 1 ) -> moveTo( row1-1,col );
  17. }
  18. else
  19. {
  20. int numObj = m_allTiled.at( map[row1-1][col] - 1 ) -> m_number;
  21. int numNow = m_allTiled.at( map[row1][col] - 1 ) -> m_number;
  22. if( numNow == numObj )
  23. {
  24. m_allTiled.at( map[row1-1][col] - 1 ) -> doubleNumber();
  25. m_allTiled.at( map[row1][col] - 1 ) -> removeFromParent();
  26.  
  27. int index = map[row1][col];
  28. m_allTiled.erase( map[row1][col] - 1 );
  29.  
  30. // 纠正块的编号
  31. for( int r = 0 ; r < GAME_ROWS ; ++r )
  32. {
  33. for( int c = 0 ; c < GAME_COLS ; ++c )
  34. {
  35. if( map[r][c] > index )
  36. {
  37. --map[r][c];
  38. }
  39. }
  40. }
  41. map[row1][col] = 0;
  42. }
  43. break;
  44. }
  45. }
  46. }
  47. }
  48. }
  49. }
  50.  
  51. void GameScene::moveLeft( )
  52. {
  53. // 向左移动所有的块
  54. for( int row = 0 ; row < GAME_ROWS ; ++row )
  55. {
  56. for( int col = 0 ; col < GAME_COLS ; ++col )
  57. {
  58. if( map[row][col] > 0 )
  59. {
  60. for( int col1 = col ; col1 > 0 ; --col1 )
  61. {
  62. if( map[row][col1-1] == 0 )
  63. {
  64. map[row][col1-1] = map[row][col1];
  65. map[row][col1] = 0;
  66.  
  67. m_allTiled.at( map[row][col1-1] - 1 ) -> moveTo( row,col1-1 );
  68. }
  69. else
  70. {
  71. int numObj = m_allTiled.at( map[row][col1-1] - 1 ) -> m_number;
  72. int numNow = m_allTiled.at( map[row][col1] - 1 ) -> m_number;
  73. if( numNow == numObj )
  74. {
  75. m_allTiled.at( map[row][col1-1] - 1 ) -> doubleNumber();
  76. m_allTiled.at( map[row][col1] - 1 ) -> removeFromParent();
  77. int index = map[row][col1];
  78. m_allTiled.erase( map[row][col1] - 1 );
  79. // 纠正块的编号
  80. for( int r = 0 ; r < GAME_ROWS ; ++r )
  81. {
  82. for( int c = 0 ; c < GAME_COLS ; ++c )
  83. {
  84. if( map[r][c] > index )
  85. {
  86. --map[r][c];
  87. }
  88. }
  89. }
  90. map[row][col1] = 0;
  91. }
  92. break;
  93. }
  94. }
  95. }
  96. }
  97. }
  98. }
  99.  
  100. void GameScene::moveRight( )
  101. {
  102. // 向右移动所有的块
  103. for( int row = 0 ; row < GAME_ROWS ; ++row )
  104. {
  105. for( int col = GAME_COLS - 1 ; col >= 0 ; --col )
  106. {
  107. if( map[row][col] > 0 )
  108. {
  109. for( int col1 = col ; col1 < GAME_COLS - 1 ; ++col1 )
  110. {
  111. if( map[row][col1+1] == 0 )
  112. {
  113. map[row][col1+1] = map[row][col1];
  114. map[row][col1] = 0;
  115.  
  116. m_allTiled.at( map[row][col1+1] - 1 ) -> moveTo( row,col1+1 );
  117. }
  118. else
  119. {
  120. int numObj = m_allTiled.at( map[row][col1+1] - 1 ) -> m_number;
  121. int numNow = m_allTiled.at( map[row][col1] - 1 ) -> m_number;
  122. if( numNow == numObj )
  123. {
  124. m_allTiled.at( map[row][col1+1] - 1 ) -> doubleNumber();
  125. m_allTiled.at( map[row][col1] - 1 ) -> removeFromParent();
  126. int index = map[row][col1];
  127. m_allTiled.erase( map[row][col1] - 1 );
  128.  
  129. for( int r = 0 ; r < GAME_ROWS ; ++r )
  130. {
  131. for( int c = 0 ; c < GAME_COLS ; ++c )
  132. {
  133. if( map[r][c] > index )
  134. {
  135. --map[r][c];
  136. }
  137. }
  138. }
  139. map[row][col1] = 0;
  140. }
  141. break;
  142. }
  143. }
  144. }
  145. }
  146. }
  147. }</span>


OK,完成,这次就到这里,

下次就是要对游戏相关功能进行完善,

比如:

——判断失败

——添加动画

——添加音效


不知不觉,这个2048就快要结束了~。~ 嘿嘿

下回见~



本篇文章代码下载:http://pan.baidu.com/s/1o6p1E4M





***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************

猜你在找的Cocos2d-x相关文章