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的~
選擇一個自己喜歡的背景圖片,選擇圖片button神馬的,
包裝一下,就相當美麗啦~
但這些的前提是,要會怎麽做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********************************************
cocos2d-x 3.2 之 2048 —— 第五篇