Stage.h
#ifdef WIN32#pragma execution_character_set("utf-8")#ifndef __STAGE_SCENE_H__#define __STAGE_SCENE_H__#include "ui\CocosGUI.h"#include "cocos2d.h"#include "cocos-ext.h"#include "SimpleAudioEngine.h"#include <iostream>#include <algorithm>#include "Block.h"using namespace std;using namespace CocosDenshion;USING_NS_CC_EXT;USING_NS_CC;class Stage : public cocos2d::Layer{public: int m = 7, n = 8;//七行八列 //typedef struct Sits //{ // int value; // int x; // int y; //}Sits; int offSet = 70; int swapx1, swapx2, swapy1, swapy2; virtual bool init(); static int tag[9][20]; //辅助标记每一个方块的tag Block* blocks[9][20]; //保存有对应的方块 bool ifReSwap = true; //是否要再换回来 bool isSwapping = false; //是否正在发生交换动画 bool ifSelected = false; //是否已经选中 Block* firstSelectedBlock; //第一个选中的方块 Block* secondSelectedBlock; //第二个选中的方块 int x1, y1; //用于判断第一个触摸的点 int x2, y2; //用于判断第二个触摸的点 //得分情况 static int score; //时间限制 static int Bartime; void initBlocks(); //初始化所有方块 bool initJudge(int index, int i, int j);//初始化判断,存在三连是返回true,不存在时返回false bool blockMarks(int blockClasses, int i, int j); //用于判断该方块周围有没有三连,并标记,有返回true,没有返回false bool blocksEraseJudge();//对整张图进行判断,是否存在能被消除的方块,存在标记并返回true,不存在返回false void selectFirst(int i, int j); void setSelectedBlock(Block* block,int index, bool flag); //设置第几个方块是否被选中 void removeSelectFirst(int i, int j); //void swap(int x1, int y1, int x2, int y2); bool swapBlocks(int x1, int y1, int x2, int y2); //返回值为,交换后有可以消除的,返回true,没有可以消除的返回false bool moveDownBlocks(); //将现有的方块落下补充空白 void initNewBlocks(); //补充新的方块 void initBlockFromPoint(int x, int y);//随机在某一个点生成一个方块 void updateInfo(int cnt); //更新游戏分数以及时间,传入参数为一次消除的方块数 bool removeBlocks(); //移除方块,返回值为true,若没有任何可以移除的方块,返回false CREATE_FUNC(Stage);};#endif // __STAGE_SCENE_H__#endif
Stage.cpp
#pragma once#if defined(_MSC_VER) && (_MSC_VER>=1900)#pragma execution_character_set("utf-8")#include "Stage.h"using namespace std;USING_NS_CC;int Stage::tag[9][20] = { 0 };//初始化int Stage::score = 0;int Stage::Bartime = 1800;static void problemLoading(const char* filename){ printf("Error while loading: %s\n", filename); printf("Depending on how you compiled you might have to add 'Resources/' in front of filenames in HardLevel.cpp\n");}bool Stage::init(){ if (!Layer::init()){ return false; } srand(unsigned int(time(0)));//利用时间做种子,让随机数更多,每次开始的场景不同; auto visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); initBlocks(); return true;}void Stage::updateInfo(int cnt) { int scoreMultiple = 1; int score = 10; switch (cnt) { case 3: scoreMultiple = 1; score = 10; break; case 4: case 5: case 6: scoreMultiple = 2; score = 15; break; default: scoreMultiple = 3; score = 30; break; } this->score += score * scoreMultiple * cnt; if(this->Bartime + cnt * scoreMultiple * 5 <= 1800) this->Bartime += cnt*scoreMultiple * 5;}void Stage::selectFirst(int i, int j) { blocks[i][j]->setOpacity(80);}void Stage::removeSelectFirst(int i, int j) { blocks[i][j]->setOpacity(255);}bool Stage::swapBlocks(int x1, int y1, int x2, int y2) { isSwapping = true; //表示正在发生交换 if (tag[x1][y1] < 0 || tag[x2][y2] < 0) return true; //支持任意两点的交换,可以方便后期补充各种用户自定义的道具 //log("准备交换(%d,%d)<->(%d,%d)", x1, y1, x2, y2); //释放选中状态 blocks[x1][y1]->setSelected(false); blocks[x2][y2]->setSelected(false); blocks[x1][y1]->moveByOffset(x2,y2); blocks[x2][y2]->moveByOffset(x1, y1); std::swap(blocks[x1][y1], blocks[x2][y2]); std::swap(tag[x1][y1], tag[x2][y2]); //交换后判断是否可以消除 if (blocksEraseJudge()) { return true; } else { this->x1 = x1; this->y1 = y1; this->x2 = x2; this->y2 = y2; return false; }}//创建默认的方块布局void Stage::initBlocks() { int index = 0; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (tag[i][j] == -1) //-1表示此处不能布置方块,包括边界或可以用于自己设置的固定空洞 continue; tag[i][j] = rand() % 5 + 1; if (initJudge(tag[i][j], i, j)) { //判断当前的tag放入后,能否满足不会自动消去,不满足的话,回退,重新随机 j--; continue; } switch (tag[i][j]){ case 1: blocks[i][j] = Block::create("item1.png", tag[i][j], i, j); break; case 2: blocks[i][j] = Block::create("item2.png", tag[i][j], i, j); break; case 3: blocks[i][j] = Block::create("item3.png", tag[i][j], i, j); break; case 4: blocks[i][j] = Block::create("item4.png", tag[i][j], i, j); break; case 5: blocks[i][j] = Block::create("item5.png", tag[i][j], i, j); break; default: break; } //排列各个方块 blocks[i][j]->setPosition(offSet*i, offSet*j); //blocks[i][j]->setPosition(offSet*i - 40, offSet*j + 150); this->addChild(blocks[i][j], 1); } }}//防止创建就是三连的bool Stage::initJudge(int index, int i, int j) { int ux1 = i - 1, uy1 = j, ux2 = i - 2, uy2 = j; int dx1 = i + 1, dy1 = j, dx2 = i + 2, dy2 = j; int lx1 = i, ly1 = j - 1, lx2 = i, ly2 = j - 2; int rx1 = i, ry1 = j + 1, rx2 = i, ry2 = j + 2; if (ux2 > 0 && (tag[i][j] == tag[ux1][uy1]) && (tag[i][j] == tag[ux2][uy2])) return true; if (dx2 <= m && (tag[i][j] == tag[dx1][dy1]) && (tag[i][j] == tag[dx2][dy2])) return true; if (lx2 >0 && (tag[i][j] == tag[lx1][ly1]) && (tag[i][j] == tag[lx2][ly2])) return true; if (rx2 <= n && (tag[i][j] == tag[rx1][ry1]) && (tag[i][j] == tag[rx2][ry2])) return true; return false;}//三连判断,只要保证都不满足三连情况,那么不满足四连也可以保证,所以不需要遍历整个图bool Stage::blockMarks(int blockClasses, int i, int j) { bool flag = false; int upX = i, upY = j + 1; //上方第一个点 int downX = i, downY = j - 1; //下方第一个点 int leftX = i - 1, leftY = j; //左边第一个点 int rightX = i + 1, rightY = j; //右边第一个点 //首先判断一横行有无三个 if (leftX > 0 && rightX <= n && (blockClasses == tag[leftX][leftY]) && (blockClasses == tag[rightX][rightY])) { blocks[leftX][leftY]->setDoesErase(true); blocks[i][j]->setDoesErase(true); blocks[rightX][rightY]->setDoesErase(true); log("当前被打上表示的为(%d,%d)", leftX, leftY); log("当前被打上表示的为(%d,%d)", i, j); log("当前被打上表示的为(%d,%d)", rightX, rightY); flag = true; } //再判断一竖列的三个 if (downY > 0 && upY <= m && (blockClasses == tag[upX][upY]) && (blockClasses == tag[downX][downY])) { blocks[upX][upY]->setDoesErase(true); blocks[i][j]->setDoesErase(true); blocks[downX][downY]->setDoesErase(true); log("当前被打上表示的为(%d,%d)", upX, upY); log("当前被打上表示的为(%d,%d)", i, j); log("当前被打上表示的为(%d,%d)", downX, downY); flag = true; } return flag;}//用于判断当前是否有能消除的方块,有则打上标记并返回true,否则返回falsebool Stage::blocksEraseJudge() { bool flag = false; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) if (blockMarks(blocks[i][j]->getClasses(), i, j)) { //log("当前被打上表示的为(%d,%d)", i, j); flag = true; } return flag;}bool Stage::removeBlocks() { bool flag = false; int cnt = 0; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) if (blocks[i][j]->getDoesErase()) { blocks[i][j]->blastAnimation(); tag[i][j] = 0; cnt++; flag = true; } updateInfo(cnt); return flag;}void Stage::setSelectedBlock(Block* block,int index, bool flag){ if(block!=nullptr) block->setSelected(flag); else return; if (index == 1) { this->firstSelectedBlock = block; } else if (index == 2) { this->secondSelectedBlock = block; }}//创建新的方块bool Stage::moveDownBlocks() { bool flag = false; //如果交换后仍能消除,返回true for (int i = 1; i <= n; i++) { //遍历从第一列开始 for (int j = 1; j <= 2*m; j++) { //从每一行的最底部开始,如果遇到空的,继续向这一行的上方遍历 if (tag[i][j] == 0) { //如果遇到空的位置 log("开始落下未消除方块"); int k = j + 1; for (; k <= 2*m; k++) //那么寻找这一列上方第一个不为空的方块,落下来 if (tag[i][k] > 0) break; log("当前k值为:%d", k); if (k > 2*m || tag[i][k] <= 0) continue; if (k <= 2*m) { //说明这一列的空缺处上方,还有没落下的方块 if (swapBlocks(i, k, i, j)) { //交换一个空缺和方块,继续遍历 flag = true; } } } } } return flag;}void Stage::initNewBlocks() { for (int i = 1; i <= n;i++){ int cnt = 0; //有多少个空,就在上方生成多少个 for (int j = 1; j <= m; j++) if (tag[i][j] == 0) cnt++; while (cnt--) initBlockFromPoint(i, m + cnt+1); }}void Stage::initBlockFromPoint(int x, int y) { tag[x][y] = rand() % 5 + 1; switch (tag[x][y]) { case 1: blocks[x][y] = Block::create("item1.png", tag[x][y], x, y); break; case 2: blocks[x][y] = Block::create("item2.png", tag[x][y], x, y); break; case 3: blocks[x][y] = Block::create("item3.png", tag[x][y], x, y); break; case 4: blocks[x][y] = Block::create("item4.png", tag[x][y], x, y); break; case 5: blocks[x][y] = Block::create("item5.png", tag[x][y], x, y); break; default: break; } blocks[x][y]->setPosition(offSet*x, offSet*y); //blocks[i][j]->setPosition(offSet*i - 40, offSet*j + 150); this->addChild(blocks[x][y], 1);}#endif