https://blog.csdn.net/wwj_748/article/details/38168649
本篇博客給大家介紹如何快速開發2048這樣一款休閒遊戲,理解整個2048遊戲的開發流程,從本篇博客你將可以學習到以下內容:
這裏註明一下,本教程來自極客學院,小巫對其中代碼進行了解釋。
- 2048遊戲的邏輯
- Cocos2d-x中上下左右手勢的識別
- 遊戲中卡片類的創建
- 添加卡片到遊戲中
- 遊戲中的邏輯實現
- 遊戲中隨機卡片的生成
- 遊戲結束判斷
- 遊戲分數的添加
- 遊戲美化
理解2048遊戲邏輯
Cocos2d-x中上下左右手勢的識別
- // 加入手勢識別的事件
- virtual bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event);
- virtual void onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event);
- // 點擊的元素位置
- int firstX, firstY, endX, endY;
- // 加入手勢識別的事件
- bool HelloWorld::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event){
- // 觸摸點
- Point touchP0 = touch->getLocation();
- firstX = touchP0.x;
- firstY = touchP0.y;
- return true;
- }
- // 觸摸結束觸發
- void HelloWorld::onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event){
- // 獲取觸摸點位置
- Point touchP0 = touch->getLocation();
- // 獲取X軸和Y軸的移動距離
- endX = firstX - touchP0.x;
- endY = firstY - touchP0.y;
- // 判斷X軸和Y軸的移動距離,如果X軸的絕對值大於Y軸的絕對值就是左右否則是上下
- if (abs(endX) > abs(endY)){
- // 左右
- if (endX + 5 > 0) {
- // 左邊
- if(doLeft()) {
- autoCreateCardNumber();
- doCheckGameOver();
- }
- } else {
- // 右邊
- if(doRight()){
- autoCreateCardNumber();
- doCheckGameOver();
- }
- }
- } else {
- // 上下
- if (endY + 5 > 0) {
- // 下邊
- if(doDown()) {
- autoCreateCardNumber();
- doCheckGameOver();
- }
- } else {
- // 上邊
- if(doUp()) {
- autoCreateCardNumber();
- doCheckGameOver();
- };
- }
- }
- }
- // 創建手勢識別的事件監聽器
- auto touchListener = EventListenerTouchOneByOne::create();
- touchListener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
- touchListener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);
- // 添加事件監聽
- _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
上面中根據計算開始位置到結束位置X軸和Y軸的移動距離來判斷是向左、向右、向上還是向下的方向:
- // 上下左右的方法
- bool doLeft();
- bool doRight();
- bool doUp();
- bool doDown();
然後對其進行實現。這四個方法的邏輯實現放到後面進行講解。
遊戲中卡片類的創建
- //
- // CardSprite.h
- // 2048Game
- //
- // Created by mac on 14-7-16.
- //
- //
- #ifndef ___048Game__CardSprite__
- #define ___048Game__CardSprite__
- #include "cocos2d.h"
- class CardSprite:public cocos2d::Sprite {
- public:
- // 初始化遊戲卡片的方法
- static CardSprite *createCardSprite(int numbers, int width, int height, float CardSpriteX, float CardSpriteY);
- virtual bool init();
- CREATE_FUNC(CardSprite);
- // 設置數字
- void setNumber(int num);
- // 獲取數字
- int getNumber();
- private:
- // 顯示在界面的數字
- int number;
- void enemyInit(int numbers, int width, int height, float CardSpriteX, float CardSpriteY);
- // 定義顯示數字的控件
- cocos2d::LabelTTF *labTTFCardNumber;
- // 顯示的背景
- cocos2d::LayerColor *layerColorBG;
- };
- #endif /* defined(___048Game__CardSprite__) */
- //
- // CardSprite.cpp
- // 2048Game
- //
- // Created by wwj on 14-7-16.
- //
- //
- #include "CardSprite.h"
- USING_NS_CC;
- // 初始化遊戲卡片的方法
- CardSprite* CardSprite::createCardSprite(int numbers, int width, int height, float CardSpriteX, float CardSpriteY) {
- // new一個卡片精靈
- CardSprite *enemy = new CardSprite();
- if (enemy && enemy->init()) {
- enemy->autorelease();
- enemy->enemyInit(numbers, width, height, CardSpriteX, CardSpriteY);
- return enemy;
- }
- CC_SAFE_DELETE(enemy);
- return NULL;
- }
- // 卡片初始化方法
- bool CardSprite::init() {
- if (!Sprite::init()) {
- return false;
- }
- return true;
- }
- // 設置數字
- void CardSprite::setNumber(int num) {
- number = num;
- // 判斷數字的大小來調整字體的大小
- if (number >= 0) {
- labTTFCardNumber->setFontSize(80);
- }
- if (number >= 16) {
- labTTFCardNumber->setFontSize(60);
- }
- if (number >= 128) {
- labTTFCardNumber->setFontSize(40);
- }
- if (number >= 1024) {
- labTTFCardNumber->setFontSize(20);
- }
- // 判斷數組的大小調整顏色
- if (number == 0) {
- layerColorBG->setColor(cocos2d::Color3B(200, 190, 180));
- }
- if (number == 2) {
- layerColorBG->setColor(cocos2d::Color3B(240, 230, 220));
- }
- if (number == 4) {
- layerColorBG->setColor(cocos2d::Color3B(240, 220, 200));
- }
- if (number == 8) {
- layerColorBG->setColor(cocos2d::Color3B(240, 180, 120));
- }
- if (number == 16) {
- layerColorBG->setColor(cocos2d::Color3B(240, 140, 90));
- }
- if (number == 32) {
- layerColorBG->setColor(cocos2d::Color3B(240, 120, 90));
- }
- if (number == 64) {
- layerColorBG->setColor(cocos2d::Color3B(240, 90, 60));
- }
- if (number == 128) {
- layerColorBG->setColor(cocos2d::Color3B(240, 90, 60));
- }
- if (number == 256) {
- layerColorBG->setColor(cocos2d::Color3B(240, 200, 70));
- }
- if (number == 512) {
- layerColorBG->setColor(cocos2d::Color3B(240, 200, 70));
- }
- if (number == 1024) {
- layerColorBG->setColor(cocos2d::Color3B(0, 130, 0));
- }
- if (number == 2048) {
- layerColorBG->setColor(cocos2d::Color3B(0, 130, 0));
- }
- // 更新顯示的數字
- if (number > 0) {
- labTTFCardNumber->setString(__String::createWithFormat("%i", num)->getCString() );
- } else {
- labTTFCardNumber->setString("");
- }
- }
- // 獲取數字
- int CardSprite::getNumber() {
- return number;
- }
- //第1個參數爲數字,第2、3個參數爲卡片的寬高,第4、5個參數爲卡片的位置
- void CardSprite::enemyInit(int numbers, int width, int height, float CardSpriteX, float CardSpriteY) {
- // 初始化數字
- number = numbers;
- // 加入遊戲卡片的背景顏色
- layerColorBG = cocos2d::LayerColor::create(cocos2d::Color4B(200, 190, 180, 255), width - 15, height - 15);
- layerColorBG->setPosition(Point(CardSpriteX, CardSpriteY));
- // 判斷如果不等於0就顯示,否則爲空
- if (number > 0) {
- // 加入中間字體
- labTTFCardNumber = cocos2d::LabelTTF::create(__String::createWithFormat("%i", number)->getCString(), "HirakakuProN-W6", 100);
- // 顯示卡片數字的位置,這裏顯示在背景的中間
- labTTFCardNumber->setPosition(Point(layerColorBG->getContentSize().width/2, layerColorBG->getContentSize().height/2));
- // 添加卡片數字到背景中
- layerColorBG->addChild(labTTFCardNumber);
- } else {
- // 加入中間字體
- labTTFCardNumber = cocos2d::LabelTTF::create("", "HirakakuProN-w6", 80);
- labTTFCardNumber->setPosition(Point(layerColorBG->getContentSize().width/2, layerColorBG->getContentSize().height/2));
- layerColorBG->addChild(labTTFCardNumber);
- }
- // 將卡片添加到層
- this->addChild(layerColorBG);
- }
每張卡片都有相同的寬和高,但數字和位置不同,數字是顯示在背景中間的,所以我們需要5個參數來初始化卡片的位置。
添加卡片到遊戲中
- // 創建卡片
- void createCardSprite(cocos2d::Size size);
在HelloWorldScene.cpp中實現該方法:
- // 創建卡片,size爲屏幕大小
- void HelloWorld::createCardSprite(cocos2d::Size size) {
- // 求出單元格的寬度和高度,28爲左右距離
- int lon = (size.width - 28) / 4;
- // 4*4的單元格
- for (int j = 0; j < 4; j++) {
- for (int i = 0; i < 4; i++) {
- // 數字0,寬高相同爲lon,lon+j+20爲卡片X軸位置,如lon+0+20爲第一個卡片的位置,20是每張卡片的間隙,lon+i+20+size.height/6代表的意思是屏幕大小豎方向分了六份,我們這裏只放4個位置
- CardSprite *card = CardSprite::createCardSprite(0, lon, lon, lon * j + 10, lon * i + 10 + size.height / 6);
- addChild(card);
- // 添加卡片到二維數組中
- cardArr[j][i] = card;
- }
- }
- }
筆者對每張卡片顯示的位置在代碼中進行了說明,讀者也可以思考一下爲什麼要這麼做。
遊戲中的邏輯實現
- // 向左
- bool HelloWorld::doLeft(){
- log("doLeft");
- bool isdo = false;
- // 最外層循環爲4*4迭代
- for (int y = 0; y < 4; y++) {
- for (int x = 0; x < 4; x++) {
- // 這一層循環爲判斷卡片是合併還是清空
- for (int x1 = x + 1; x1 < 4; x1++) {
- if (cardArr[x1][y]->getNumber() > 0) {// 有數字
- if (cardArr[x][y]->getNumber() <= 0) { // 爲空
- // 設置爲右邊卡片的數值
- cardArr[x][y]->setNumber(cardArr[x1][y]->getNumber());
- cardArr[x1][y]->setNumber(0);
- x--;
- isdo = true;
- } else if(cardArr[x][y]->getNumber() == cardArr[x1][y]->getNumber()) {
- // 當前卡片的值與其比較卡片的值相等,設置爲其的2倍
- cardArr[x][y]->setNumber(cardArr[x][y]->getNumber()*2);
- cardArr[x1][y]->setNumber(0);
- // 設置分數
- score += cardArr[x][y]->getNumber();
- labelTTFCardNumber->setString(__String::createWithFormat("%i", score)->getCString());
- isdo = true;
- }
- break;// 跳出
- }
- }
- }
- }
- return isdo;
- }
- // 向右
- bool HelloWorld::doRight(){
- log("doRight");
- bool isdo = false;
- // 最外層循環爲4*4迭代
- for (int y = 0; y < 4; y++) {
- for (int x = 3; x >= 0; x--) {
- // 循環判斷左邊卡片往右是合併還是清空
- for (int x1 = x - 1; x1 >= 0; x1-- ) {
- if (cardArr[x1][y]->getNumber() > 0) {
- if (cardArr[x][y]->getNumber() <= 0) {
- cardArr[x][y]->setNumber(cardArr[x1][y]->getNumber());
- x++;
- isdo = true;
- }
- else if (cardArr[x][y]->getNumber() == cardArr[x1][y]->getNumber()) {
- cardArr[x][y]->setNumber(cardArr[x][y]->getNumber() * 2);
- cardArr[x1][y]->setNumber(0);
- // 設置分數
- score += cardArr[x][y]->getNumber();
- labelTTFCardNumber->setString(__String::createWithFormat("%i", score)->getCString());
- isdo = true;
- }
- break;
- }
- }
- }
- }
- return isdo;
- }
- // 向上
- bool HelloWorld::doUp(){
- log("doUp");
- bool isdo = false;
- // 最外層循環爲4*4迭代
- for (int x = 0; x < 4; x++) {
- for (int y = 3; y >= 0; y--) {
- // 這一層循環爲判斷卡片是合併還是清空
- for (int y1 = y - 1; y1 >= 0; y1--) {
- if (cardArr[x][y1]->getNumber() > 0) {// 有數字
- if (cardArr[x][y]->getNumber() <= 0) { // 爲空
- // 設置爲右邊卡片的數值
- cardArr[x][y]->setNumber(cardArr[x][y1]->getNumber());
- cardArr[x][y1]->setNumber(0);
- y++;
- isdo = true;
- } else if(cardArr[x][y]->getNumber() == cardArr[x][y1]->getNumber()) {
- // 當前卡片的值與其比較卡片的值相等,設置爲其的2倍
- cardArr[x][y]->setNumber(cardArr[x][y]->getNumber()*2);
- cardArr[x][y1]->setNumber(0);
- // 設置分數
- score += cardArr[x][y]->getNumber();
- labelTTFCardNumber->setString(__String::createWithFormat("%i", score)->getCString());
- isdo = true;
- }
- break;// 跳出
- }
- }
- }
- }
- return isdo;
- }
- // 向下
- bool HelloWorld::doDown(){
- log("doDown");
- bool isdo = false;
- // 最外層循環爲4*4迭代
- for (int x = 0; x < 4; x++) {
- for (int y = 0; y < 4; y++) {
- // 這一層循環爲判斷卡片是合併還是清空
- for (int y1 = y + 1; y1 < 4; y1++) {
- if (cardArr[x][y1]->getNumber() > 0) {// 有數字
- if (cardArr[x][y]->getNumber() <= 0) { // 爲空
- // 設置爲右邊卡片的數值
- cardArr[x][y]->setNumber(cardArr[x][y1]->getNumber());
- cardArr[x][y1]->setNumber(0);
- y--;
- isdo = true;
- } else if(cardArr[x][y]->getNumber() == cardArr[x][y1]->getNumber()) {
- // 當前卡片的值與其比較卡片的值相等,設置爲其的2倍
- cardArr[x][y]->setNumber(cardArr[x][y]->getNumber()*2);
- cardArr[x][y1]->setNumber(0);
- // 設置分數
- score += cardArr[x][y]->getNumber();
- labelTTFCardNumber->setString(__String::createWithFormat("%i", score)->getCString());
- isdo = true;
- }
- break;// 跳出
- }
- }
- }
- }
- return isdo;
- }
遊戲中隨機卡片的生成
- // 自動卡片生成
- void autoCreateCardNumber();
在HelloWorldScene.cpp實現該方法:
- // 自動生成卡片
- void HelloWorld::autoCreateCardNumber() {
- int i = CCRANDOM_0_1() * 4;
- int j = CCRANDOM_0_1() * 4;
- // 判斷是否已經存在的位置
- if (cardArr[i][j]->getNumber() > 0) {
- // 已存在,遞歸創建
- autoCreateCardNumber();
- } else {
- // 生成2和4的比例是1:9的概率
- cardArr[i][j]->setNumber(CCRANDOM_0_1() * 10 < 1 ? 4:2);
- }
- }
遊戲結束判斷
- // 判斷遊戲是否還能繼續運行下去
- void doCheckGameOver();
- // 遊戲是否還能繼續運行下去
- void HelloWorld::doCheckGameOver() {
- bool isGameOver = true;
- for (int y = 0; y < 4; y++) {
- for (int x = 0; x < 4; x++) {
- if (cardArr[x][y]->getNumber() == 0
- || (x>0 && (cardArr[x][y]->getNumber() == cardArr[x-1][y]->getNumber() ))
- || (x<3 && (cardArr[x][y]->getNumber() == cardArr[x+1][y]->getNumber()))
- || (y<0 && (cardArr[x][y]->getNumber() == cardArr[x][y-1]->getNumber()))
- || (x<3 && (cardArr[x][y]->getNumber() == cardArr[x][y+1]->getNumber()))) {
- isGameOver = false;
- }
- }
- }
- if (isGameOver) {
- // 結束遊戲
- Director::getInstance()->replaceScene(TransitionFade::create(1, HelloWorld::createScene()));
- }
- }
遊戲分數的添加
- // 整體遊戲的分數
- int score;
- // 定義顯示數據的控件
- cocos2d::LabelTTF *labelTTFCardNumber;
在HelloWorldScene.cpp中對分數初始化爲0,並顯示“分數”的文本:
- score = 0;
- // 獲得屏幕可視大小
- Size visibleSize = Director::getInstance()->getVisibleSize();
- // 加入遊戲的背景
- auto layerColorBG = cocos2d::LayerColor::create(cocos2d::Color4B(180,170,160, 255));
- this->addChild(layerColorBG);
- // 在上方加入遊戲的分數
- auto labelTTFCardNumberName = LabelTTF::create("分數:","HirakakuProN-W6", 80);
- labelTTFCardNumberName->setPosition(Point(visibleSize.width/5, visibleSize.height-100));
- addChild(labelTTFCardNumberName);
- labelTTFCardNumber = LabelTTF::create("0", "HirakakuProN-W6", 80);
- labelTTFCardNumber->setPosition(visibleSize.width/2+100, visibleSize.height - 100);
- addChild(labelTTFCardNumber
- );
遊戲美化
- // 設置數字
- void CardSprite::setNumber(int num) {
- number = num;
- // 判斷數字的大小來調整字體的大小
- if (number >= 0) {
- labTTFCardNumber->setFontSize(80);
- }
- if (number >= 16) {
- labTTFCardNumber->setFontSize(60);
- }
- if (number >= 128) {
- labTTFCardNumber->setFontSize(40);
- }
- if (number >= 1024) {
- labTTFCardNumber->setFontSize(20);
- }
- // 判斷數組的大小調整顏色
- if (number == 0) {
- layerColorBG->setColor(cocos2d::Color3B(200, 190, 180));
- }
- if (number == 2) {
- layerColorBG->setColor(cocos2d::Color3B(240, 230, 220));
- }
- if (number == 4) {
- layerColorBG->setColor(cocos2d::Color3B(240, 220, 200));
- }
- if (number == 8) {
- layerColorBG->setColor(cocos2d::Color3B(240, 180, 120));
- }
- if (number == 16) {
- layerColorBG->setColor(cocos2d::Color3B(240, 140, 90));
- }
- if (number == 32) {
- layerColorBG->setColor(cocos2d::Color3B(240, 120, 90));
- }
- if (number == 64) {
- layerColorBG->setColor(cocos2d::Color3B(240, 90, 60));
- }
- if (number == 128) {
- layerColorBG->setColor(cocos2d::Color3B(240, 90, 60));
- }
- if (number == 256) {
- layerColorBG->setColor(cocos2d::Color3B(240, 200, 70));
- }
- if (number == 512) {
- layerColorBG->setColor(cocos2d::Color3B(240, 200, 70));
- }
- if (number == 1024) {
- layerColorBG->setColor(cocos2d::Color3B(0, 130, 0));
- }
- if (number == 2048) {
- layerColorBG->setColor(cocos2d::Color3B(0, 130, 0));
- }
- // 更新顯示的數字
- if (number > 0) {
- labTTFCardNumber->setString(__String::createWithFormat("%i", num)->getCString() );
- } else {
- labTTFCardNumber->setString("");
- }
- }
- #ifndef _APP_DELEGATE_H_
- #define _APP_DELEGATE_H_
- #include "cocos2d.h"
- /**
- @brief The cocos2d Application.
- The reason for implement as private inheritance is to hide some interface call by Director.
- */
- class AppDelegate : private cocos2d::Application
- {
- public:
- AppDelegate();
- virtual ~AppDelegate();
- /**
- @brief Implement Director and Scene init code here.
- @return true Initialize success, app continue.
- @return false Initialize failed, app terminate.
- */
- virtual bool applicationDidFinishLaunching();
- /**
- @brief The function be called when the application enter background
- @param the pointer of the application
- */
- virtual void applicationDidEnterBackground();
- /**
- @brief The function be called when the application enter foreground
- @param the pointer of the application
- */
- virtual void applicationWillEnterForeground();
- };
- #endif // _APP_DELEGATE_H_
>>>AppDelegate.cpp
- #include "AppDelegate.h"
- #include "HelloWorldScene.h"
- USING_NS_CC;
- AppDelegate::AppDelegate() {
- }
- AppDelegate::~AppDelegate()
- {
- }
- bool AppDelegate::applicationDidFinishLaunching() {
- // initialize director
- auto director = Director::getInstance();
- auto glview = director->getOpenGLView();
- if(!glview) {
- glview = GLView::create("My Game");
- director->setOpenGLView(glview);
- }
- glview->setDesignResolutionSize(480, 800, ResolutionPolicy::SHOW_ALL);
- // turn on display FPS
- director->setDisplayStats(false);
- // set FPS. the default value is 1.0/60 if you don't call this
- director->setAnimationInterval(1.0 / 60);
- // create a scene. it's an autorelease object
- auto scene = HelloWorld::createScene();
- // run
- director->runWithScene(scene);
- return true;
- }
- // This function will be called when the app is inactive. When comes a phone call,it's be invoked too
- void AppDelegate::applicationDidEnterBackground() {
- Director::getInstance()->stopAnimation();
- // if you use SimpleAudioEngine, it must be pause
- // SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
- }
- // this function will be called when the app is active again
- void AppDelegate::applicationWillEnterForeground() {
- Director::getInstance()->startAnimation();
- // if you use SimpleAudioEngine, it must resume here
- // SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
- }
>>>HelloWorldScene.h
- #ifndef __HELLOWORLD_SCENE_H__
- #define __HELLOWORLD_SCENE_H__
- #include "cocos2d.h"
- #include "CardSprite.h"
- class HelloWorld : public cocos2d::Layer
- {
- public:
- static cocos2d::Scene* createScene();
- virtual bool init();
- void menuCloseCallback(cocos2d::Ref* pSender);
- CREATE_FUNC(HelloWorld);
- // 加入手勢識別的事件
- virtual bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event);
- virtual void onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event);
- // 上下左右的方法
- bool doLeft();
- bool doRight();
- bool doUp();
- bool doDown();
- // 自動卡片生成
- void autoCreateCardNumber();
- // 判斷遊戲是否還能繼續運行下去
- void doCheckGameOver();
- private:
- // 點擊的元素位置
- int firstX, firstY, endX, endY;
- // 定義一個二維數組
- CardSprite *cardArr[4][4];
- // 創建卡片
- void createCardSprite(cocos2d::Size size);
- // 整體遊戲的分數
- int score;
- // 定義顯示數據的控件
- cocos2d::LabelTTF *labelTTFCardNumber;
- };
- #endif // __HELLOWORLD_SCENE_H__
>>>HelloWorldScene.cpp
- #include "HelloWorldScene.h"
- #include "CardSprite.h"
- USING_NS_CC;
- Scene* HelloWorld::createScene()
- {
- // 'scene' is an autorelease object
- auto scene = Scene::create();
- // 'layer' is an autorelease object
- auto layer = HelloWorld::create();
- // add layer as a child to scene
- scene->addChild(layer);
- // return the scene
- return scene;
- }
- // on "init" you need to initialize your instance
- bool HelloWorld::init()
- {
- //////////////////////////////
- // 1. super init first
- if ( !Layer::init() )
- {
- return false;
- }
- score = 0;
- // 獲得屏幕可視大小
- Size visibleSize = Director::getInstance()->getVisibleSize();
- // 加入遊戲的背景
- auto layerColorBG = cocos2d::LayerColor::create(cocos2d::Color4B(180,170,160, 255));
- this->addChild(layerColorBG);
- // 在上方加入遊戲的分數
- auto labelTTFCardNumberName = LabelTTF::create("分數:","HirakakuProN-W6", 80);
- labelTTFCardNumberName->setPosition(Point(visibleSize.width/5, visibleSize.height-100));
- addChild(labelTTFCardNumberName);
- labelTTFCardNumber = LabelTTF::create("0", "HirakakuProN-W6", 80);
- labelTTFCardNumber->setPosition(visibleSize.width/2+100, visibleSize.height - 100);
- addChild(labelTTFCardNumber
- );
- // 創建手勢識別的事件監聽器
- auto touchListener = EventListenerTouchOneByOne::create();
- touchListener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
- touchListener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);
- // 添加事件監聽
- _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
- // 調用生成卡片的方法
- createCardSprite(visibleSize);
- // 調用生成隨機數
- autoCreateCardNumber();
- autoCreateCardNumber();
- return true;
- }
- // 遊戲是否還能繼續運行下去
- void HelloWorld::doCheckGameOver() {
- bool isGameOver = true;
- for (int y = 0; y < 4; y++) {
- for (int x = 0; x < 4; x++) {
- if (cardArr[x][y]->getNumber() == 0
- || (x>0 && (cardArr[x][y]->getNumber() == cardArr[x-1][y]->getNumber() ))
- || (x<3 && (cardArr[x][y]->getNumber() == cardArr[x+1][y]->getNumber()))
- || (y<0 && (cardArr[x][y]->getNumber() == cardArr[x][y-1]->getNumber()))
- || (x<3 && (cardArr[x][y]->getNumber() == cardArr[x][y+1]->getNumber()))) {
- isGameOver = false;
- }
- }
- }
- if (isGameOver) {
- // 結束遊戲
- Director::getInstance()->replaceScene(TransitionFade::create(1, HelloWorld::createScene()));
- }
- }
- // 自動生成卡片
- void HelloWorld::autoCreateCardNumber() {
- int i = CCRANDOM_0_1() * 4;
- int j = CCRANDOM_0_1() * 4;
- // 判斷是否已經存在的位置
- if (cardArr[i][j]->getNumber() > 0) {
- // 已存在,遞歸創建
- autoCreateCardNumber();
- } else {
- // 生成2和4的比例是1:9的概率
- cardArr[i][j]->setNumber(CCRANDOM_0_1() * 10 < 1 ? 4:2);
- }
- }
- // 創建卡片,size爲屏幕大小
- void HelloWorld::createCardSprite(cocos2d::Size size) {
- // 求出單元格的寬度和高度,28爲左右距離
- int lon = (size.width - 28) / 4;
- // 4*4的單元格
- for (int j = 0; j < 4; j++) {
- for (int i = 0; i < 4; i++) {
- // 數字0,寬高相同爲lon,lon+j+20爲卡片X軸位置,如lon+0+20爲第一個卡片的位置,20是每張卡片的間隙,lon+i+20+size.height/6代表的意思是屏幕大小豎方向分了六份,我們這裏只放4個位置
- CardSprite *card = CardSprite::createCardSprite(0, lon, lon, lon * j + 10, lon * i + 10 + size.height / 6);
- addChild(card);
- // 添加卡片到二維數組中
- cardArr[j][i] = card;
- }
- }
- }
- // 加入手勢識別的事件
- bool HelloWorld::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event){
- // 觸摸點
- Point touchP0 = touch->getLocation();
- firstX = touchP0.x;
- firstY = touchP0.y;
- return true;
- }
- // 觸摸結束觸發
- void HelloWorld::onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event){
- // 獲取觸摸點位置
- Point touchP0 = touch->getLocation();
- // 獲取X軸和Y軸的移動距離
- endX = firstX - touchP0.x;
- endY = firstY - touchP0.y;
- // 判斷X軸和Y軸的移動距離,如果X軸的絕對值大於Y軸的絕對值就是左右否則是上下
- if (abs(endX) > abs(endY)){
- // 左右
- if (endX + 5 > 0) {
- // 左邊
- if(doLeft()) {
- autoCreateCardNumber();
- doCheckGameOver();
- }
- } else {
- // 右邊
- if(doRight()){
- autoCreateCardNumber();
- doCheckGameOver();
- }
- }
- } else {
- // 上下
- if (endY + 5 > 0) {
- // 下邊
- if(doDown()) {
- autoCreateCardNumber();
- doCheckGameOver();
- }
- } else {
- // 上邊
- if(doUp()) {
- autoCreateCardNumber();
- doCheckGameOver();
- };
- }
- }
- }
- // 向左
- bool HelloWorld::doLeft(){
- log("doLeft");
- bool isdo = false;
- // 最外層循環爲4*4迭代
- for (int y = 0; y < 4; y++) {
- for (int x = 0; x < 4; x++) {
- // 這一層循環爲判斷卡片是合併還是清空
- for (int x1 = x + 1; x1 < 4; x1++) {
- if (cardArr[x1][y]->getNumber() > 0) {// 有數字
- if (cardArr[x][y]->getNumber() <= 0) { // 爲空
- // 設置爲右邊卡片的數值
- cardArr[x][y]->setNumber(cardArr[x1][y]->getNumber());
- cardArr[x1][y]->setNumber(0);
- x--;
- isdo = true;
- } else if(cardArr[x][y]->getNumber() == cardArr[x1][y]->getNumber()) {
- // 當前卡片的值與其比較卡片的值相等,設置爲其的2倍
- cardArr[x][y]->setNumber(cardArr[x][y]->getNumber()*2);
- cardArr[x1][y]->setNumber(0);
- // 設置分數
- score += cardArr[x][y]->getNumber();
- labelTTFCardNumber->setString(__String::createWithFormat("%i", score)->getCString());
- isdo = true;
- }
- break;// 跳出
- }
- }
- }
- }
- return isdo;
- }
- // 向右
- bool HelloWorld::doRight(){
- log("doRight");
- bool isdo = false;
- // 最外層循環爲4*4迭代
- for (int y = 0; y < 4; y++) {
- for (int x = 3; x >= 0; x--) {
- // 循環判斷左邊卡片往右是合併還是清空
- for (int x1 = x - 1; x1 >= 0; x1-- ) {
- if (cardArr[x1][y]->getNumber() > 0) {
- if (cardArr[x][y]->getNumber() <= 0) {
- cardArr[x][y]->setNumber(cardArr[x1][y]->getNumber());
- x++;
- isdo = true;
- }
- else if (cardArr[x][y]->getNumber() == cardArr[x1][y]->getNumber()) {
- cardArr[x][y]->setNumber(cardArr[x][y]->getNumber() * 2);
- cardArr[x1][y]->setNumber(0);
- // 設置分數
- score += cardArr[x][y]->getNumber();
- labelTTFCardNumber->setString(__String::createWithFormat("%i", score)->getCString());
- isdo = true;
- }
- break;
- }
- }
- }
- }
- return isdo;
- }
- // 向上
- bool HelloWorld::doUp(){
- log("doUp");
- bool isdo = false;
- // 最外層循環爲4*4迭代
- for (int x = 0; x < 4; x++) {
- for (int y = 3; y >= 0; y--) {
- // 這一層循環爲判斷卡片是合併還是清空
- for (int y1 = y - 1; y1 >= 0; y1--) {
- if (cardArr[x][y1]->getNumber() > 0) {// 有數字
- if (cardArr[x][y]->getNumber() <= 0) { // 爲空
- // 設置爲右邊卡片的數值
- cardArr[x][y]->setNumber(cardArr[x][y1]->getNumber());
- cardArr[x][y1]->setNumber(0);
- y++;
- isdo = true;
- } else if(cardArr[x][y]->getNumber() == cardArr[x][y1]->getNumber()) {
- // 當前卡片的值與其比較卡片的值相等,設置爲其的2倍
- cardArr[x][y]->setNumber(cardArr[x][y]->getNumber()*2);
- cardArr[x][y1]->setNumber(0);
- // 設置分數
- score += cardArr[x][y]->getNumber();
- labelTTFCardNumber->setString(__String::createWithFormat("%i", score)->getCString());
- isdo = true;
- }
- break;// 跳出
- }
- }
- }
- }
- return isdo;
- }
- // 向下
- bool HelloWorld::doDown(){
- log("doDown");
- bool isdo = false;
- // 最外層循環爲4*4迭代
- for (int x = 0; x < 4; x++) {
- for (int y = 0; y < 4; y++) {
- // 這一層循環爲判斷卡片是合併還是清空
- for (int y1 = y + 1; y1 < 4; y1++) {
- if (cardArr[x][y1]->getNumber() > 0) {// 有數字
- if (cardArr[x][y]->getNumber() <= 0) { // 爲空
- // 設置爲右邊卡片的數值
- cardArr[x][y]->setNumber(cardArr[x][y1]->getNumber());
- cardArr[x][y1]->setNumber(0);
- y--;
- isdo = true;
- } else if(cardArr[x][y]->getNumber() == cardArr[x][y1]->getNumber()) {
- // 當前卡片的值與其比較卡片的值相等,設置爲其的2倍
- cardArr[x][y]->setNumber(cardArr[x][y]->getNumber()*2);
- cardArr[x][y1]->setNumber(0);
- // 設置分數
- score += cardArr[x][y]->getNumber();
- labelTTFCardNumber->setString(__String::createWithFormat("%i", score)->getCString());
- isdo = true;
- }
- break;// 跳出
- }
- }
- }
- }
- return isdo;
- }
- void HelloWorld::menuCloseCallback(Ref* pSender)
- {
- #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
- MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
- return;
- #endif
- Director::getInstance()->end();
- #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
- exit(0);
- #endif
- }
>>>CardSprite.h
- //
- // CardSprite.h
- // 2048Game
- //
- // Created by mac on 14-7-16.
- //
- //
- #ifndef ___048Game__CardSprite__
- #define ___048Game__CardSprite__
- #include "cocos2d.h"
- class CardSprite:public cocos2d::Sprite {
- public:
- // 初始化遊戲卡片的方法
- static CardSprite *createCardSprite(int numbers, int width, int height, float CardSpriteX, float CardSpriteY);
- virtual bool init();
- CREATE_FUNC(CardSprite);
- // 設置數字
- void setNumber(int num);
- // 獲取數字
- int getNumber();
- private:
- // 顯示在界面的數字
- int number;
- void enemyInit(int numbers, int width, int height, float CardSpriteX, float CardSpriteY);
- // 定義顯示數字的控件
- cocos2d::LabelTTF *labTTFCardNumber;
- // 顯示的背景
- cocos2d::LayerColor *layerColorBG;
- };
- #endif /* defined(___048Game__CardSprite__) */
>>>CardSprite.cpp
- //
- // CardSprite.cpp
- // 2048Game
- //
- // Created by wwj on 14-7-16.
- //
- //
- #include "CardSprite.h"
- USING_NS_CC;
- // 初始化遊戲卡片的方法
- CardSprite* CardSprite::createCardSprite(int numbers, int width, int height, float CardSpriteX, float CardSpriteY) {
- // new一個卡片精靈
- CardSprite *enemy = new CardSprite();
- if (enemy && enemy->init()) {
- enemy->autorelease();
- enemy->enemyInit(numbers, width, height, CardSpriteX, CardSpriteY);
- return enemy;
- }
- CC_SAFE_DELETE(enemy);
- return NULL;
- }
- // 卡片初始化方法
- bool CardSprite::init() {
- if (!Sprite::init()) {
- return false;
- }
- return true;
- }
- // 設置數字
- void CardSprite::setNumber(int num) {
- number = num;
- // 判斷數字的大小來調整字體的大小
- if (number >= 0) {
- labTTFCardNumber->setFontSize(80);
- }
- if (number >= 16) {
- labTTFCardNumber->setFontSize(60);
- }
- if (number >= 128) {
- labTTFCardNumber->setFontSize(40);
- }
- if (number >= 1024) {
- labTTFCardNumber->setFontSize(20);
- }
- // 判斷數組的大小調整顏色
- if (number == 0) {
- layerColorBG->setColor(cocos2d::Color3B(200, 190, 180));
- }
- if (number == 2) {
- layerColorBG->setColor(cocos2d::Color3B(240, 230, 220));
- }
- if (number == 4) {
- layerColorBG->setColor(cocos2d::Color3B(240, 220, 200));
- }
- if (number == 8) {
- layerColorBG->setColor(cocos2d::Color3B(240, 180, 120));
- }
- if (number == 16) {
- layerColorBG->setColor(cocos2d::Color3B(240, 140, 90));
- }
- if (number == 32) {
- layerColorBG->setColor(cocos2d::Color3B(240, 120, 90));
- }
- if (number == 64) {
- layerColorBG->setColor(cocos2d::Color3B(240, 90, 60));
- }
- if (number == 128) {
- layerColorBG->setColor(cocos2d::Color3B(240, 90, 60));
- }
- if (number == 256) {
- layerColorBG->setColor(cocos2d::Color3B(240, 200, 70));
- }
- if (number == 512) {
- layerColorBG->setColor(cocos2d::Color3B(240, 200, 70));
- }
- if (number == 1024) {
- layerColorBG->setColor(cocos2d::Color3B(0, 130, 0));
- }
- if (number == 2048) {
- layerColorBG->setColor(cocos2d::Color3B(0, 130, 0));
- }
- // 更新顯示的數字
- if (number > 0) {
- labTTFCardNumber->setString(__String::createWithFormat("%i", num)->getCString() );
- } else {
- labTTFCardNumber->setString("");
- }
- }
- // 獲取數字
- int CardSprite::getNumber() {
- return number;
- }
- //第1個參數爲數字,第2、3個參數爲卡片的寬高,第4、5個參數爲卡片的位置
- void CardSprite::enemyInit(int numbers, int width, int height, float CardSpriteX, float CardSpriteY) {
- // 初始化數字
- number = numbers;
- // 加入遊戲卡片的背景顏色
- layerColorBG = cocos2d::LayerColor::create(cocos2d::Color4B(200, 190, 180, 255), width - 15, height - 15);
- layerColorBG->setPosition(Point(CardSpriteX, CardSpriteY));
- // 判斷如果不等於0就顯示,否則爲空
- if (number > 0) {
- // 加入中間字體
- labTTFCardNumber = cocos2d::LabelTTF::create(__String::createWithFormat("%i", number)->getCString(), "HirakakuProN-W6", 100);
- // 顯示卡片數字的位置,這裏顯示在背景的中間
- labTTFCardNumber->setPosition(Point(layerColorBG->getContentSize().width/2, layerColorBG->getContentSize().height/2));
- // 添加卡片數字到背景中
- layerColorBG->addChild(labTTFCardNumber);
- } else {
- // 加入中間字體
- labTTFCardNumber = cocos2d::LabelTTF::create("", "HirakakuProN-w6", 80);
- labTTFCardNumber->setPosition(Point(layerColorBG->getContentSize().width/2, layerColorBG->getContentSize().height/2));
- layerColorBG->addChild(labTTFCardNumber);
- }
- // 將卡片添加到層
- this->addChild(layerColorBG);
- }
最後,騷年們就不要向我要源碼了,所有的代碼在這裏均有實現,只要把這些代碼集成到你的項目中去就可以實現跟筆者一樣的效果,希望各位能好好體會2048開發的流程。