#include "GameScene.h"
GameScene::GameScene()
{
};
GameScene::~GameScene()
{
}
// 游戏初始化
bool GameScene::init()
{
if (!Layer::init())
{
return false;
}
auto size = Director::getInstance()->getVisibleSize();
// 显示分数
m_score = 0;
TTFConfig config("fonts/Marker Felt.ttf",25);
auto labelScore = Label::createWithTTF(config,"Scord: 0",TextHAlignment::LEFT);
labelScore->setTag(COMPONTLABSCORDTAG);
if(labelScore) {
labelScore->setPosition(Point(size.width - 180, size.height - 50));
this->addChild(labelScore);
}
// 这里要居中显示游戏的地图所以要计数下地图所显示的位置
int mapr = GAMEMAPROWCOLCOUNT * GAMECARDWIDTHHEIGHT;
this->m_mapTop = (size.height - mapr) / 2; // 得到地图显示 与屏幕 的上下 间距
this->m_mapLeft = (size.width - mapr) / 2;// 得到地图 显示与 屏幕的 左的 间距
// 画出网格
auto draw = DrawNode::create(); // 创建画图的对象
draw->setAnchorPoint(Point::ZERO);//设置画的锚点
draw->setPosition(Point(this->m_mapLeft, this->m_mapTop));// 设置画线的起始位置
this->addChild(draw);// 添加画图的对象对当前的图层
// 画出地图也就是蛇运动的方格 这里先画出行列
for (int i = 0; i< GAMEMAPROWCOLCOUNT+1; i++)
{
draw->drawSegment(Point(0, GAMECARDWIDTHHEIGHT * i), Point(mapr, GAMECARDWIDTHHEIGHT * i), 1, Color4F(1,1,1,1));
draw->drawSegment(Point(GAMECARDWIDTHHEIGHT * i, 0), Point(GAMECARDWIDTHHEIGHT * i, mapr), 1, Color4F(1,1,1,1));
}
// 显示出小图片
//添加游戏地图 显示出游元素,现设置位置 在屏幕的中心
int r = 0;
int c = 0;
for (r = 0; r < GAMEMAPROWCOLCOUNT; r++)
{
for(c = 0; c < GAMEMAPROWCOLCOUNT; c++)
{
m_map[r][c]=Card::createCard(rand() % CARDIMGIDXMAX + 1, r, c, this->m_mapLeft, this->m_mapTop);
this->addChild(m_map[r][c]);
}
}
// 添加单点屏幕触摸侦听 CC_CALLBACK_2这个表示有两个参数传递
auto listener=EventListenerTouchOneByOne::create();// 创建单点触摸对象
// 添加触摸对象的事件
listener->onTouchBegan=CC_CALLBACK_2(GameScene::onTouchBegan, this);
listener->onTouchMoved=CC_CALLBACK_2(GameScene::onTouchMoved, this);
listener->onTouchEnded=CC_CALLBACK_2(GameScene::onTouchEnded, this);
// 注册触摸事件
Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
this->m_curLogicType = GAMELOGICTYPE::LOGIC_NORMAL;
startTimer();
return true;
}
// 定时器操作 开始定时器
void GameScene::startTimer()
{
// 移动启动定时器 执行游戏逻辑
this->schedule(schedule_selector(GameScene::gameLogic), 0.2f);
}
void GameScene::stopTimer()
{
this->unschedule(schedule_selector(GameScene::gameLogic));
}
// 判断游戏逻辑
void GameScene::checkGameLogic()
{
// 判断每一个方块,是否有可消除的列或是列
checkHasDel();
if (getDelArrayValue() > 0)
{
// 表示有可消除的行或是列
this->m_curLogicType = GAMELOGICTYPE::LOGIC_DEL;
}
startTimer();
}
int GameScene::getScoreFrmCount(int c)
{
int v = 10;
int tem = 10;
for (int i = 0; i < c; i ++)
{
v += tem * 2;
}
return v;
}
void GameScene::setCurScore()
{
this->m_score += getScoreFrmCount(this->m_delCount);
Label *lab = (Label *)this->getChildByTag(COMPONTLABSCORDTAG);
lab->setString(StringUtils::format("Scord: %d",this->m_score));
}
// 处理游戏逻辑
void GameScene::gameLogic(float t)
{
stopTimer();
switch (this->m_curLogicType)
{
case GAMELOGICTYPE::LOGIC_NORMAL:
startTimer();// 重新开始定时器
// 什么也不做
break;
case GAMELOGICTYPE::LOGIC_DEL:
this->m_delCount = getArrayDelCount();
// 显示出分数
setCurScore();
// 消除行
delCardFrmArray();
break;
case GAMELOGICTYPE::LOGIC_MOVE:
down();
this->m_curLogicType = GAMELOGICTYPE::LOGIC_NEW;
startTimer();
break;
case GAMELOGICTYPE::LOGIC_NEW:
autoDownCard();
// 再判断一次
// 初始化消除数组
initDelArray();
checkGameLogic();
if (getDelArrayValue() > 0)
{
this->m_curLogicType = GAMELOGICTYPE::LOGIC_DEL;
}
else
{
this->m_curLogicType = GAMELOGICTYPE::LOGIC_NORMAL;
}
startTimer();
break;
default:
break;
}
}
// 创建游戏的场景
Scene* GameScene::CreateScene()
{
// 创建游戏界面
auto scene = Scene::create();
// 创建自己的层
auto layer = GameScene::create();
// 添加自己到场景里
scene->addChild(layer);
// 返回当前创建的场景
return scene;
}
// 触摸事件
bool GameScene::onTouchBegan(Touch *touch, Event *unused_event)
{
// 触摸开始
this->m_startX = touch->getLocation().x;// 得到触摸的坐标 X
this->m_startY = touch->getLocation().y;// 得到触摸的坐标 Y
// 这里一定要返回 true
return true;
}
void GameScene::onTouchMoved(Touch *touch, Event *unused_event)
{
// 不做处理
}
void GameScene::onTouchEnded(Touch *touch, Event *unused_event)
{
// 触摸结束
if (this->m_curLogicType != GAMELOGICTYPE::LOGIC_NORMAL)
{
return;
}
// 这里得到 触摸结束与 开始 时的 偏移
int w = abs(touch->getLocation().x - this->m_startX);
int h = abs(touch->getLocation().y - this->m_startY);
// 判断触摸的偏移,如果太小 (w < 5) && (h < 5)
// 或是不在网格内 那么不做处理 (this->m_startX > mapr) || (this->m_startY > mapr)
if ((w < 5) && (h < 5))
{
return;
}
int mapr = GAMEMAPROWCOLCOUNT * GAMECARDWIDTHHEIGHT;
// 或是不在网格内 那么不做处理 判断左右
if ((this->m_startX < this->m_mapLeft) && (this->m_startX > this->m_mapLeft + mapr))
{
return;
}
// 判断上下
if ((this->m_startY < this->m_mapTop) && (this->m_startX > this->m_mapTop + mapr))
{
return;
}
// 这里按偏移得到 触摸的格子
// 因为格子在屏幕的中小,所以这里要做 偏移
int nowrow = (this->m_startY - this->m_mapTop) / GAMECARDWIDTHHEIGHT;
int nowcol = (this->m_startX - this->m_mapLeft) / GAMECARDWIDTHHEIGHT;
// 如果 w > h 那么表示 左右 移动
if (w > h)
{
// 如果结果的位置大于 开始的位置,那么表示向右移动
if (touch->getLocation().x > this->m_startX)
{
moveCard(GAMEDIR::DIR_RIGHT, nowrow, nowcol);
}
else
{
// 向右移动
moveCard(GAMEDIR::DIR_LEFT, nowrow, nowcol);
}
}
else
{
// 上下移动
if (touch->getLocation().y > this->m_startY)
{
// 向上
moveCard(GAMEDIR::DIR_UP, nowrow, nowcol);
}
else
{
// 向下
moveCard(GAMEDIR::DIR_DOWN, nowrow, nowcol);
}
}
// 初始化消除数组
initDelArray();
checkGameLogic();
}
// 移动图片
void GameScene::moveCard(GAMEDIR d,int r,int c)
{
// 移动网格内 不小图片
// 按方向分开
switch (d)
{
case GAMEDIR::DIR_UP:
{
// 向上移动,先判断如果向上移动是否会移出网格
if (c + 1 < GAMEMAPROWCOLCOUNT)
{
// 移动网格小图片
m_map[r][c]->moveTo(r+1, c);
m_map[r + 1][c]->moveTo(r, c);
// 修改对象数组
Card *tmp = m_map[r][c];
m_map[r][c] = m_map[r + 1][c];
m_map[r + 1][c] = tmp;
}
break;
}
case GAMEDIR::DIR_LEFT:
{
if (c - 1 >= 0)
{
m_map[r][c]->moveTo(r, c - 1);
m_map[r][c - 1]->moveTo(r, c);
Card *tmp = m_map[r][c];
m_map[r][c] = m_map[r][c - 1];
m_map[r][c - 1] = tmp;
}
break;
}
case GAMEDIR::DIR_RIGHT:
{
if (c + 1 < 7)
{
m_map[r][c]->moveTo(r, c + 1);
m_map[r][c + 1]->moveTo(r, c);
Card *tmp = m_map[r][c];
m_map[r][c] = m_map[r][c + 1];
m_map[r][c + 1] = tmp;
}
break;
}
case GAMEDIR::DIR_DOWN:
{
if (c - 1 >= 0)
{
m_map[r][c]->moveTo(r - 1, c);
m_map[r - 1][c]->moveTo(r, c);
Card *tmp = m_map[r][c];
m_map[r][c] = m_map[r - 1][c];
m_map[r - 1][c] = tmp;
}
break;
}
default:
break;
}
}
// 初始化消除数组
void GameScene::initDelArray()
{
int r = 0;
int c = 0;
for (r = 0; r < GAMEMAPROWCOLCOUNT; r ++)
{
for (c = 0; c < GAMEMAPROWCOLCOUNT; c++)
{
m_delArray[r][c] = 0;
}
}
}
// 判断是否有可消除
int GameScene::getDelArrayValue()
{
int r = 0;
int c = 0;
int re = 0;
for (r = 0; r < GAMEMAPROWCOLCOUNT; r ++)
{
for (c = 0; c < GAMEMAPROWCOLCOUNT; c++)
{
re += m_delArray[r][c];
}
}
return