完成了前面的任务,接下来我们需要给游戏添加时间与分数。

1. 添加时间

一般消除类游戏,要么关卡,要么限制时间,但是关卡的设计很麻烦,个体创作,没有那么多精力,

所以只能通过限制时间来使游戏有些可玩性,但这种可玩性极低啊,反复挑战同样的东西,很容易疲劳的。

在程序中加时间,如何操作呢?

当然,先要有个时间的全局变量,在初始化游戏界面的时候,显示在屏幕上:

// 加载ttf字体

TTFConfig config("fonts/haibaoti.ttf",30);

// 游戏时间的显示

auto labelTime = Label::createWithTTF(config,StringUtils::format("Time: %d ",m_time));

labelTime -> setPosition(Vec2( labelTime->getContentSize().width , GAME_SCREEN_HEIGHT - labelTime->getContentSize().height ));

labelTime -> setTag(11);

this ->addChild(labelTime);

然后还要有个函数,让它每秒都会减少

void GameScene::myClock( float dt )

{

// 时间变化

--m_time;

// 如果时间归0,那么执行游戏结束动画,并跳到游戏结束界面

if( m_time == 0 )

{

Label *labelTime = (Label *)this -> getChildByTag(11);

labelTime->setScale(0);

// 游戏结束 动画

auto gmov = Sprite::create("pic_gameover.png");

gmov->setPosition(Point(GAME_SCREEN_WIDTH/2,GAME_SCREEN_HEIGHT*1.5));

this->addChild(gmov);

auto action = MoveTo::create(3.0f, Point(GAME_SCREEN_WIDTH/2, GAME_SCREEN_HEIGHT/2));

gmov -> runAction( action );

// 跳转到游戏结束界面

return;

}

// 如果还有时间,那么时间减少

if( m_time > 0 ) {

Label *labelTime = (Label *)this -> getChildByTag(11);

labelTime -> setString( StringUtils::format("Time: %d ",m_time));

}

}

但是,别忘了最重要的一步,要将这个倒计时函数加入到计划任务中,就像之前我们用的检查精灵。

之前检查精灵用的是 scheduleUpdate,每一帧都要执行,

而这次,我们用 schedule 就可以,自己指定函数,并且设定间隔时间。

就放在 scheduleUpdate 下面就可以啦。

1schedule(schedule_selector(GameScene::myClock),1.0f );

然后运行一下,就可以看到倒计时的实现啦。

然后,我们再建立 游戏结束界面,界面里放返回游戏,返回主界面和退出三个按钮,就可以啦。

代码就不贴出,具体的可以看文章末尾给出的源码。

2. 添加分数

光有时间倒计时可不行,要有分数才有意思!

和时间一样,也要初始化界面中将分数在游戏界面显示出来

// 分数显示

auto labelScore = Label::createWithTTF(config,StringUtils::format("Score: %d ",m_score) );

labelScore -> setPosition(Vec2( GAME_SCREEN_WIDTH/2 , GAME_SCREEN_HEIGHT - labelScore->getContentSize().height*2.6 ));

labelScore -> setTag(10);

this->addChild(labelScore);

但是 分数 就不需要像时间那样,单独弄一个函数,分数是时时刷新的,所以跟随每帧刷新即可,就是在update函数内加上分数的显示

// GameScene.cpp update()函数

// 分数变化

Label *labelScore = (Label *)this -> getChildByTag(10);

labelScore -> setString( StringUtils::format("Score: %d ",m_score));

然后在相应位置,进行分数的加,

我是在 精灵下落处,每消除一个精灵加30分

// GameScene.cpp 修改后的 fillSprite

// 填补空缺位置

void GameScene::fillSprite() {

// 下落精灵总个数(方便后面分数的计算)

int sum = 0;

// 重置移动方向标志

isAction = true;

int *colEmptyInfo = (int *)malloc(sizeof(int) * COLS);

memset((void *)colEmptyInfo, 0, sizeof(int) * COLS);

// 将存在的精灵降落下来

SpriteShape *spr = NULL;

for (int c = 0; c < COLS; c++) {

int removedSpriteOfCol = 0;

// 自底向上

for (int r = 0; r < ROWS; r++ ) {

spr = map[r][c];

if ( spr == NULL ) {

++removedSpriteOfCol;

} else {

if ( removedSpriteOfCol > 0) {

int newRow = r - removedSpriteOfCol;

map[newRow][c] = spr;

map[r][c] = NULL;

Point startPosition = spr->getPosition();

Point endPosition = positionOfItem(newRow, c);

float speed = (startPosition.y - endPosition.y) / GAME_SCREEN_HEIGHT*3;

spr->stopAllActions();

spr->runAction(CCMoveTo::create(speed, endPosition));

spr->setRow(newRow);

}

}

}

// 记录相应列数移除的数量

colEmptyInfo[c] = removedSpriteOfCol;

sum+=removedSpriteOfCol;

}

// 新建新的精灵,并降落

for (int c = 0; c < COLS; ++c ) {

for (int r = ROWS - colEmptyInfo[c]; r < ROWS ; ++r ) {

createSprite(r,c);

}

}

m_score += sum*30;

free(colEmptyInfo);

}

接下里,就是在游戏结束界面,将自己的分数传递过去。

如果看源码,会发现, 在时间到0时,我用的 scheduleOnce ( 有个动画,要delay一下)

然后跳转到一个游戏结束函数,就是在这个函数,进行了分数的传递。

当然,相应的 GameOverScene中,也要设置相应的函数来接受分数。

// GameScene.cpp

// 游戏结束函数

void GameScene::gameOver(float dt)

{

auto scene = Scene::create();

auto layer = GameOver::create();

// 传递当前游戏获得的分数

layer -> setScore( m_score );

scene -> addChild( layer );

CCTransitionScene* reScene= CCTransitionFadeUp::create(1.0f, scene);

CCDirector::sharedDirector()->replaceScene(reScene);

}

// GameOverScene.cpp

void GameOver::setScore( int sc )

{

auto labelScore = (Label *)this -> getChildByTag(13);

labelScore -> setString( StringUtils::format(" %d ",sc));

}

Ok啦,现在可以运行爽爽啦

现在做的东东已经有基本雏形了,

剩下的就属于额外的东西,往上添加就行了。

后面的文章将会对本游戏进行修饰,比如:

—— 消除的特效

—— 消除4个,产生消除一列 或者 一行的东东

—— 音乐、音效的添加

—— 最高分的记录

等等~