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,否则返回false
bool 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