cocos2d-x 3.2 之 2048 —— 第五篇
***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************
不知不觉,都10月5号了, 十一大假期快结束了 不开心啊, 有木有!!!
算了,接着发 2048 吧,这是第五篇了, 也很快了呀,2048系列,马上就要结束了。 这篇文章主要讲述: —— 对于游戏相关移动和游戏结束的判定 —— 游戏音效的添加 —— 游戏分数的添加
直接正文: 1. 游戏方向能否移动 和 游戏结束的判定 这俩为什么放一块呢? 我的方法是在.h建立4个bool变量:能否向上移动、能否向下移动、。。。 这样,如果四个方向都不能移动,即为游戏结束了。
为这个判定,单独建立一个函数: <span style="font-family:Comic Sans MS;">void GameScene::judgeMove() { int r,c; isMoveUp = false; isMoveDown = false; isMoveRight = false; isMoveLeft = false; // 向上能否移动 for( r = 0 ; r < GAME_ROWS - 1 ; ++r ) { for( c = 0 ; c < GAME_COLS ; ++c ) { if( map[r+1][c] == 0 ) { if( map[r][c] != 0 ) { isMoveUp = true; break; } } else { if( map[r][c] != 0 ) { if( m_allTiled.at( map[r][c] - 1 ) -> m_number == m_allTiled.at( map[r+1][c] - 1 ) -> m_number ) { isMoveUp = true; break; } } } } if( isMoveUp == true ) break; } // 向下是否能移动 for( r = GAME_ROWS-1 ; r > 0 ; --r ) { for( c = 0 ; c < GAME_COLS ; ++c ) { if( map[r-1][c] == 0 ) { if( map[r][c] != 0 ) { isMoveDown = true; break; } } else { if( map[r][c] != 0 ) { if( m_allTiled.at( map[r][c] - 1 ) -> m_number == m_allTiled.at( map[r-1][c] - 1 ) -> m_number ) { isMoveDown = true; break; } } } } if( isMoveDown == true ) break; } // 向左是否能移动 for( c = 0 ; c < GAME_COLS-1 ; ++c ) { for( r = 0 ; r < GAME_ROWS ; ++r ) { if( map[r][c+1] == 0 ) { if( map[r][c] != 0 ) { isMoveRight = true; break; } } else { if( map[r][c] != 0 ) { if( m_allTiled.at( map[r][c] - 1 ) -> m_number == m_allTiled.at( map[r][c+1] - 1 ) -> m_number ) { isMoveRight = true; break; } } } } if( isMoveRight == true ) break; } // 向右是否能移动 for( c = GAME_COLS-1 ; c > 0 ; --c ) { for( r = 0 ; r < GAME_ROWS ; ++r ) { if( map[r][c-1] == 0 ) { if( map[r][c] != 0 ) { isMoveLeft = true; break; } } else { if( map[r][c] != 0 ) { if( m_allTiled.at( map[r][c] - 1 ) -> m_number == m_allTiled.at( map[r][c-1] - 1 ) -> m_number ) { isMoveLeft = true; break; } } } } if( isMoveLeft == true ) break; } }</span> 以能否向上移动来解析一下这个方法: 从最下面一行第一列到倒数第二行最后一列,进行两层循环: ——首先判断同列的上面那一行,是否为0(即是否是空的格子,没有数字块) ————如果为空,判断这一行是否为空 ——————不为空,则可以向上移动 ——————为空,则不能移动 ————如果不为空,判断本行相应列是否为空 ——————为空,则不能移动 ——————不为空,判断本行与上一行同列的是否相同 ————————相同,则可以移动 ————————不同,不能移动 根据前面“——”长短,可以看出,判断等级。
然后,建立游戏结束界面的类~GameOverScene:
<span style="font-family:Comic Sans MS;font-size:12px;">#ifndef __test2048_GameOverScene_H__ #define __test2048_GameOverScene_H__ #include "cocos2d.h" USING_NS_CC; class GameOver: public Layer { public: virtual bool init(); static Scene * createScene(); CREATE_FUNC(GameOver); // 重新开始游戏 的回调函数 void menuRestartCallback( Ref * pObject ); // 退出 的回调函数 void menuExitCallback( Ref * pObject ); }; #endif</span> .cpp:
<span style="font-family:Comic Sans MS;font-size:14px;">#include "GameOverScene.h" #include "GameDefine.h" #include "GameScene.h" Scene * GameOver::createScene() { auto scene = Scene::create(); auto * layer = GameOver::create(); scene -> addChild( layer ); return scene; } bool GameOver::init() { if( !Layer::init() ) { return false; } // 重新开始游戏 auto restartItem = MenuItemFont::create(" Restart ",CC_CALLBACK_1(GameOver::menuRestartCallback,this)); restartItem -> setPosition( Point( GAME_SCREEN_WIDTH/2,GAME_SCREEN_HEIGHT/2)); // 退出游戏 auto exit = MenuItemFont::create(" Exit ",CC_CALLBACK_1(GameOver::menuExitCallback,this)); exit -> setPosition( Point( GAME_SCREEN_WIDTH/2,GAME_SCREEN_HEIGHT/3 )); auto menu = Menu::create(restartItem,exit,NULL); menu -> setPosition(Point::ZERO); this -> addChild(menu); return true; } void GameOver::menuRestartCallback(Ref * pObject) { auto scene = GameScene::createScene(); Director::getInstance() -> replaceScene(CCTransitionProgressRadialCCW::create(1,scene)); } void GameOver::menuExitCallback(Ref * pObject) { Director::getInstance()->end(); }</span><span style="font-size:18px;"> </span> Ok,游戏结束界面已经搞定,可以改一下AppDelegate.cpp ,让游戏直接进入 GameOver界面,看看什么样子:
游戏结束界面,就是这样子的~ 做到这里,你们会不会 很嫌弃,卧XXXX,这么丑, 好吧,是很丑, 但是,这系列教程主要是,说明如何开发一款 2048 , 具体自己做的东东,可以自己DIY的~ 选择一个自己喜欢的背景图片,选择图片按钮神马的, 包装一下,就相当漂亮啦~ 但这些的前提是,要会怎么做2048,要知道 ,我想加入什么,应该在哪里改变什么,加什么。 而这系列教程,就是在说明,2048的制作及解析~
废话不多说,继续下去,要将GameScene中 moveAllTiled函数改变一下啦~:
<span style="font-family:Comic Sans MS;font-size:14px;">void GameScene::moveAllTiled( MOVE_DIR dir ) { // 判断 并 移动所有块 消除 judgeMove(); // 如果上下左右都不能移动,则游戏结束~ if( !isMoveLeft && !isMoveRight && !isMoveUp && !isMoveDown ) { auto * scene = Scene::create(); GameOver * layer = GameOver::create(); scene -> addChild( layer ); Director::sharedDirector() -> replaceScene(CCTransitionFadeDown::create(1.5f,scene)); } // 根据方向移动,但是要先判断是否可以向那个方向移动 switch ( dir ) { case MOVE_DIR::UP: if( !isMoveUp ) return; moveUp(); break; case MOVE_DIR::DOWN: if( !isMoveDown ) return; moveDown(); break; case MOVE_DIR::LEFT: if( !isMoveLeft ) return; moveLeft(); break; case MOVE_DIR::RIGHT: if( !isMoveRight ) return; moveRight(); break; default: break; } // 产生新块 newNumberTiled(); }</span> 对于,游戏结束方面,到这里就结束啦~
2.添加音效 对于2048,我觉得还是不要添加背景音乐了,很突兀的感觉的说, 我只是简单加了两个音效,如果有数字合并,一个成功的小音效, 如果没有数字合并,则是滑动的音效, 当然,先把相应文件放到Resource文件夹下,并在VS2012中添加现有项,添加进来,
然后在程序中,也需要进行加载, 我选择是在主界面跳到游戏界面之前,进行加载:
<span style="font-family:Comic Sans MS;font-size:14px;">// 加载音效 SimpleAudioEngine::getInstance() -> preloadEffect("move.wav"); SimpleAudioEngine::getInstance() -> preloadEffect("move1.wav");</span> 当然,之前要添加音效的头文件:
<span style="font-family:Comic Sans MS;font-size:14px;">#include "SimpleAudioEngine.h" using namespace CocosDenshion;</span> 然后,在游戏移动所有块函数中,添加声音播放: 现在,头文件添加两个bool变量:
<span style="font-family:Comic Sans MS;font-size:14px;"> // 播放哪个音乐 bool m_sound_clear;</span> GameScene.cpp——moveAllTiled:
<span style="font-family:Comic Sans MS;font-size:12px;">void GameScene::moveAllTiled( MOVE_DIR dir ) { // 判断 并 移动所有块 消除 judgeMove(); // 如果上下左右都不能移动,则游戏结束~ if( !isMoveLeft && !isMoveRight && !isMoveUp && !isMoveDown ) { auto * scene = Scene::create(); GameOver * layer = GameOver::create(); scene -> addChild( layer ); Director::sharedDirector() -> replaceScene(CCTransitionFadeDown::create(1.5f,scene)); } </span> <span style="font-family:Comic Sans MS;font-size:12px;"><span style="white-space:pre"> </span>m_sound_clear = false;</span> <span style="font-family:Comic Sans MS;font-size:12px;"> // 根据方向移动,但是要先判断是否可以向那个方向移动 switch ( dir ) { case MOVE_DIR::UP: if( !isMoveUp ) return; moveUp(); break; case MOVE_DIR::DOWN: if( !isMoveDown ) return; moveDown(); break; case MOVE_DIR::LEFT: if( !isMoveLeft ) return; moveLeft(); break; case MOVE_DIR::RIGHT: if( !isMoveRight ) return; moveRight(); break; default: break; } // 播放音乐 if( m_sound_clear ) { SimpleAudioEngine::getInstance() -> playEffect("move.wav"); } else { SimpleAudioEngine::getInstance() -> playEffect("move1.wav"); } // 产生新块 newNumberTiled(); }</span> 然后,在相应移动函数中,要设置m_sound_clear的值: 就是在moveUp,moveDown,moveLeft,moveRight相应位置,进行设置 在数字合并的判断语句下(判断numNow==numObj处),进行:
m_sound_clear = true; Ok,我们可以运行,感受一下啦~ 如果对于,音效,还有什么疑问,可以看我之前写的文章,专门说音效的博文:戳我~
接下来,就是关于分数的设置啦~
3.分数的添加 首先,在游戏界面,头文件设置,整型的分数变量 然后在初始化函数设定分数的位置: GameScene.cpp——init: <span style="font-family:Comic Sans MS;font-size:12px;"> TTFConfig config("HelloKitty.ttf",40); // 分数 score = 0; auto labelScore = Label::createWithTTF(config,"Score : 0 "); labelScore -> setPosition( Point(GAME_SCREEN_WIDTH/2,GAME_SCREEN_HEIGHT - 1.5*labelScore->getContentSize().height)); this->addChild(labelScore); labelScore -> setTag(105);</span> 我们分数的增加是,每合成一个新数字,加上所生成的数字, 比如两个2生成了一个4,则分数+4, 两个512 生成了一个 1024,则分数+1024, 所以,分数改变的位置 和 设置音乐的位置一样, 因为只有合成成功的时候,分数才会增加: <span style="font-family:Comic Sans MS;font-size:14px;">if( numNow == numObj ) { m_sound_clear = true; score += numObj * 2;</span> 然后,还要在移动所有块以后,更新分数: GameScene.cpp——moveAllTiled: <span style="font-family:Comic Sans MS;font-size:14px;">// 分数更新 Label *labelScore = (Label *)this -> getChildByTag(105); labelScore -> setString( StringUtils::format(" Score : %d ",score));</span> 好的啦~,~ 分数也更新完了。 运行一下,看看效果~
正常运行哟~ 嘿嘿,第五篇就到这里了, 下一篇就是最终章了 安卓平台移植~ 这系列真的要结束了呢
第五篇代码:http://pan.baidu.com/s/1mgHWcyO
***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |