Stage.h

  1. #ifdef WIN32
  2. #pragma execution_character_set("utf-8")
  3. #ifndef __STAGE_SCENE_H__
  4. #define __STAGE_SCENE_H__
  5. #include "ui\CocosGUI.h"
  6. #include "cocos2d.h"
  7. #include "cocos-ext.h"
  8. #include "SimpleAudioEngine.h"
  9. #include <iostream>
  10. #include <algorithm>
  11. #include "Block.h"
  12. using namespace std;
  13. using namespace CocosDenshion;
  14. USING_NS_CC_EXT;
  15. USING_NS_CC;
  16. class Stage : public cocos2d::Layer
  17. {
  18. public:
  19. int m = 7, n = 8;//七行八列
  20. //typedef struct Sits
  21. //{
  22. // int value;
  23. // int x;
  24. // int y;
  25. //}Sits;
  26. int offSet = 70;
  27. int swapx1, swapx2, swapy1, swapy2;
  28. virtual bool init();
  29. static int tag[9][20]; //辅助标记每一个方块的tag
  30. Block* blocks[9][20]; //保存有对应的方块
  31. bool ifReSwap = true; //是否要再换回来
  32. bool isSwapping = false; //是否正在发生交换动画
  33. bool ifSelected = false; //是否已经选中
  34. Block* firstSelectedBlock; //第一个选中的方块
  35. Block* secondSelectedBlock; //第二个选中的方块
  36. int x1, y1; //用于判断第一个触摸的点
  37. int x2, y2; //用于判断第二个触摸的点
  38. //得分情况
  39. static int score;
  40. //时间限制
  41. static int Bartime;
  42. void initBlocks(); //初始化所有方块
  43. bool initJudge(int index, int i, int j);//初始化判断,存在三连是返回true,不存在时返回false
  44. bool blockMarks(int blockClasses, int i, int j); //用于判断该方块周围有没有三连,并标记,有返回true,没有返回false
  45. bool blocksEraseJudge();//对整张图进行判断,是否存在能被消除的方块,存在标记并返回true,不存在返回false
  46. void selectFirst(int i, int j);
  47. void setSelectedBlock(Block* block,int index, bool flag); //设置第几个方块是否被选中
  48. void removeSelectFirst(int i, int j);
  49. //void swap(int x1, int y1, int x2, int y2);
  50. bool swapBlocks(int x1, int y1, int x2, int y2); //返回值为,交换后有可以消除的,返回true,没有可以消除的返回false
  51. bool moveDownBlocks(); //将现有的方块落下补充空白
  52. void initNewBlocks(); //补充新的方块
  53. void initBlockFromPoint(int x, int y);//随机在某一个点生成一个方块
  54. void updateInfo(int cnt); //更新游戏分数以及时间,传入参数为一次消除的方块数
  55. bool removeBlocks(); //移除方块,返回值为true,若没有任何可以移除的方块,返回false
  56. CREATE_FUNC(Stage);
  57. };
  58. #endif // __STAGE_SCENE_H__
  59. #endif


Stage.cpp

  1. #pragma once
  2. #if defined(_MSC_VER) && (_MSC_VER>=1900)
  3. #pragma execution_character_set("utf-8")
  4. #include "Stage.h"
  5. using namespace std;
  6. USING_NS_CC;
  7. int Stage::tag[9][20] = { 0 };//初始化
  8. int Stage::score = 0;
  9. int Stage::Bartime = 1800;
  10. static void problemLoading(const char* filename)
  11. {
  12. printf("Error while loading: %s\n", filename);
  13. printf("Depending on how you compiled you might have to add 'Resources/' in front of filenames in HardLevel.cpp\n");
  14. }
  15. bool Stage::init(){
  16. if (!Layer::init()){
  17. return false;
  18. }
  19. srand(unsigned int(time(0)));//利用时间做种子,让随机数更多,每次开始的场景不同;
  20. auto visibleSize = Director::getInstance()->getVisibleSize();
  21. Vec2 origin = Director::getInstance()->getVisibleOrigin();
  22. initBlocks();
  23. return true;
  24. }
  25. void Stage::updateInfo(int cnt) {
  26. int scoreMultiple = 1;
  27. int score = 10;
  28. switch (cnt) {
  29. case 3:
  30. scoreMultiple = 1; score = 10; break;
  31. case 4:
  32. case 5:
  33. case 6:
  34. scoreMultiple = 2; score = 15; break;
  35. default:
  36. scoreMultiple = 3; score = 30; break;
  37. }
  38. this->score += score * scoreMultiple * cnt;
  39. if(this->Bartime + cnt * scoreMultiple * 5 <= 1800)
  40. this->Bartime += cnt*scoreMultiple * 5;
  41. }
  42. void Stage::selectFirst(int i, int j) {
  43. blocks[i][j]->setOpacity(80);
  44. }
  45. void Stage::removeSelectFirst(int i, int j) {
  46. blocks[i][j]->setOpacity(255);
  47. }
  48. bool Stage::swapBlocks(int x1, int y1, int x2, int y2) {
  49. isSwapping = true; //表示正在发生交换
  50. if (tag[x1][y1] < 0 || tag[x2][y2] < 0)
  51. return true;
  52. //支持任意两点的交换,可以方便后期补充各种用户自定义的道具
  53. //log("准备交换(%d,%d)<->(%d,%d)", x1, y1, x2, y2);
  54. //释放选中状态
  55. blocks[x1][y1]->setSelected(false);
  56. blocks[x2][y2]->setSelected(false);
  57. blocks[x1][y1]->moveByOffset(x2,y2);
  58. blocks[x2][y2]->moveByOffset(x1, y1);
  59. std::swap(blocks[x1][y1], blocks[x2][y2]);
  60. std::swap(tag[x1][y1], tag[x2][y2]);
  61. //交换后判断是否可以消除
  62. if (blocksEraseJudge()) {
  63. return true;
  64. }
  65. else {
  66. this->x1 = x1;
  67. this->y1 = y1;
  68. this->x2 = x2;
  69. this->y2 = y2;
  70. return false;
  71. }
  72. }
  73. //创建默认的方块布局
  74. void Stage::initBlocks() {
  75. int index = 0;
  76. for (int i = 1; i <= n; i++) {
  77. for (int j = 1; j <= m; j++) {
  78. if (tag[i][j] == -1) //-1表示此处不能布置方块,包括边界或可以用于自己设置的固定空洞
  79. continue;
  80. tag[i][j] = rand() % 5 + 1;
  81. if (initJudge(tag[i][j], i, j)) { //判断当前的tag放入后,能否满足不会自动消去,不满足的话,回退,重新随机
  82. j--;
  83. continue;
  84. }
  85. switch (tag[i][j]){
  86. case 1:
  87. blocks[i][j] = Block::create("item1.png", tag[i][j], i, j); break;
  88. case 2:
  89. blocks[i][j] = Block::create("item2.png", tag[i][j], i, j); break;
  90. case 3:
  91. blocks[i][j] = Block::create("item3.png", tag[i][j], i, j); break;
  92. case 4:
  93. blocks[i][j] = Block::create("item4.png", tag[i][j], i, j); break;
  94. case 5:
  95. blocks[i][j] = Block::create("item5.png", tag[i][j], i, j); break;
  96. default:
  97. break;
  98. }
  99. //排列各个方块
  100. blocks[i][j]->setPosition(offSet*i, offSet*j);
  101. //blocks[i][j]->setPosition(offSet*i - 40, offSet*j + 150);
  102. this->addChild(blocks[i][j], 1);
  103. }
  104. }
  105. }
  106. //防止创建就是三连的
  107. bool Stage::initJudge(int index, int i, int j) {
  108. int ux1 = i - 1, uy1 = j, ux2 = i - 2, uy2 = j;
  109. int dx1 = i + 1, dy1 = j, dx2 = i + 2, dy2 = j;
  110. int lx1 = i, ly1 = j - 1, lx2 = i, ly2 = j - 2;
  111. int rx1 = i, ry1 = j + 1, rx2 = i, ry2 = j + 2;
  112. if (ux2 > 0 && (tag[i][j] == tag[ux1][uy1]) && (tag[i][j] == tag[ux2][uy2]))
  113. return true;
  114. if (dx2 <= m && (tag[i][j] == tag[dx1][dy1]) && (tag[i][j] == tag[dx2][dy2]))
  115. return true;
  116. if (lx2 >0 && (tag[i][j] == tag[lx1][ly1]) && (tag[i][j] == tag[lx2][ly2]))
  117. return true;
  118. if (rx2 <= n && (tag[i][j] == tag[rx1][ry1]) && (tag[i][j] == tag[rx2][ry2]))
  119. return true;
  120. return false;
  121. }
  122. //三连判断,只要保证都不满足三连情况,那么不满足四连也可以保证,所以不需要遍历整个图
  123. bool Stage::blockMarks(int blockClasses, int i, int j) {
  124. bool flag = false;
  125. int upX = i, upY = j + 1; //上方第一个点
  126. int downX = i, downY = j - 1; //下方第一个点
  127. int leftX = i - 1, leftY = j; //左边第一个点
  128. int rightX = i + 1, rightY = j; //右边第一个点
  129. //首先判断一横行有无三个
  130. if (leftX > 0 && rightX <= n && (blockClasses == tag[leftX][leftY]) && (blockClasses == tag[rightX][rightY])) {
  131. blocks[leftX][leftY]->setDoesErase(true);
  132. blocks[i][j]->setDoesErase(true);
  133. blocks[rightX][rightY]->setDoesErase(true);
  134. log("当前被打上表示的为(%d,%d)", leftX, leftY);
  135. log("当前被打上表示的为(%d,%d)", i, j);
  136. log("当前被打上表示的为(%d,%d)", rightX, rightY);
  137. flag = true;
  138. }
  139. //再判断一竖列的三个
  140. if (downY > 0 && upY <= m && (blockClasses == tag[upX][upY]) && (blockClasses == tag[downX][downY])) {
  141. blocks[upX][upY]->setDoesErase(true);
  142. blocks[i][j]->setDoesErase(true);
  143. blocks[downX][downY]->setDoesErase(true);
  144. log("当前被打上表示的为(%d,%d)", upX, upY);
  145. log("当前被打上表示的为(%d,%d)", i, j);
  146. log("当前被打上表示的为(%d,%d)", downX, downY);
  147. flag = true;
  148. }
  149. return flag;
  150. }
  151. //用于判断当前是否有能消除的方块,有则打上标记并返回true,否则返回false
  152. bool Stage::blocksEraseJudge() {
  153. bool flag = false;
  154. for (int i = 1; i <= n; i++)
  155. for (int j = 1; j <= m; j++)
  156. if (blockMarks(blocks[i][j]->getClasses(), i, j)) {
  157. //log("当前被打上表示的为(%d,%d)", i, j);
  158. flag = true;
  159. }
  160. return flag;
  161. }
  162. bool Stage::removeBlocks() {
  163. bool flag = false;
  164. int cnt = 0;
  165. for (int i = 1; i <= n; i++)
  166. for (int j = 1; j <= m; j++)
  167. if (blocks[i][j]->getDoesErase()) {
  168. blocks[i][j]->blastAnimation();
  169. tag[i][j] = 0;
  170. cnt++;
  171. flag = true;
  172. }
  173. updateInfo(cnt);
  174. return flag;
  175. }
  176. void Stage::setSelectedBlock(Block* block,int index, bool flag){
  177. if(block!=nullptr)
  178. block->setSelected(flag);
  179. else return;
  180. if (index == 1) {
  181. this->firstSelectedBlock = block;
  182. }
  183. else if (index == 2) {
  184. this->secondSelectedBlock = block;
  185. }
  186. }
  187. //创建新的方块
  188. bool Stage::moveDownBlocks() {
  189. bool flag = false; //如果交换后仍能消除,返回true
  190. for (int i = 1; i <= n; i++) { //遍历从第一列开始
  191. for (int j = 1; j <= 2*m; j++) { //从每一行的最底部开始,如果遇到空的,继续向这一行的上方遍历
  192. if (tag[i][j] == 0) { //如果遇到空的位置
  193. log("开始落下未消除方块");
  194. int k = j + 1;
  195. for (; k <= 2*m; k++) //那么寻找这一列上方第一个不为空的方块,落下来
  196. if (tag[i][k] > 0)
  197. break;
  198. log("当前k值为:%d", k);
  199. if (k > 2*m || tag[i][k] <= 0)
  200. continue;
  201. if (k <= 2*m) { //说明这一列的空缺处上方,还有没落下的方块
  202. if (swapBlocks(i, k, i, j)) { //交换一个空缺和方块,继续遍历
  203. flag = true;
  204. }
  205. }
  206. }
  207. }
  208. }
  209. return flag;
  210. }
  211. void Stage::initNewBlocks() {
  212. for (int i = 1; i <= n;i++){
  213. int cnt = 0; //有多少个空,就在上方生成多少个
  214. for (int j = 1; j <= m; j++)
  215. if (tag[i][j] == 0)
  216. cnt++;
  217. while (cnt--)
  218. initBlockFromPoint(i, m + cnt+1);
  219. }
  220. }
  221. void Stage::initBlockFromPoint(int x, int y) {
  222. tag[x][y] = rand() % 5 + 1;
  223. switch (tag[x][y])
  224. {
  225. case 1:
  226. blocks[x][y] = Block::create("item1.png", tag[x][y], x, y); break;
  227. case 2:
  228. blocks[x][y] = Block::create("item2.png", tag[x][y], x, y); break;
  229. case 3:
  230. blocks[x][y] = Block::create("item3.png", tag[x][y], x, y); break;
  231. case 4:
  232. blocks[x][y] = Block::create("item4.png", tag[x][y], x, y); break;
  233. case 5:
  234. blocks[x][y] = Block::create("item5.png", tag[x][y], x, y); break;
  235. default:
  236. break;
  237. }
  238. blocks[x][y]->setPosition(offSet*x, offSet*y);
  239. //blocks[i][j]->setPosition(offSet*i - 40, offSet*j + 150);
  240. this->addChild(blocks[x][y], 1);
  241. }
  242. #endif