cocos2d-x 3.2 之 2048 —— 第五篇,cocos2d-x2048
***************************************轉載請註明出處: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********************************************
剛下了cocos2d-x-32,在vs2013上編譯時間出現了下面一些問題,怎解決新手入門表示各種頭痛T_T
我也試過裝cocos2d-x,不過當時好像只支援到2012就放棄了,不過你這個因為cocos2d-x也只是提供了幾個庫而已,無法解析是因為你在編譯的時候沒有在VS裡將cocos2d-x的庫給串連進來,所以無法解析這些符號,具體的設定應該是“右鍵項目屬性 → C/C++ → 常規 ”裡面把庫檔案添加進來,百度上一大堆教你如何添加庫的教程
cocos2d-x32 WIN32移植到Android 編譯時間遇到的問題
我的部落格上有關於cocos2dx-3.2關於Android項目移植的問題。CSDN,windvix專欄。
參考:blog.csdn.net/windvix/article/details/38337003