如何製作一個簡單的遊戲 Cocos2d-x 2 0 4
步驟如下:
1.新建Cocos2d-win32工程,工程名為" SimpleGame",去除" Box2D"選項,勾選" Simple Audio Engine in Cocos Denshion
2.編譯執行,可以看到如下圖所示:
3.下載本遊戲所需的資源,將資源放置" Resources"目錄下;
4.遊戲需要一個白色的背景,最簡單的方法是使用CCLayerColor,將 HelloWorldScene.h檔案"HelloWorld"類改為如下:
1 | class HelloWorld : public cocos2d::CCLayerColor |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
bool HelloWorld::init()
{ bool bRet = false; do { CC_BREAK_IF(! CCLayerColor::initWithColor(ccc4( 255, 255, 255, 255))); CCSize winSize = CCDirector::sharedDirector()->getWinSize(); CCSprite *player = CCSprite::create( "player.png", CCRectMake( 0, 0, 27, 40)); player->setPosition(ccp(player->getContentSize().width / 2, winSize.height / 2)); this->addChild(player); bRet = true; } while ( 0); return bRet; } |
6.接下來新增怪物,並且讓怪物可以移動,我們在螢幕右邊建立怪物,建立動作讓它們向左移動,增加 addMonster方法,程式碼如下:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
void HelloWorld::addMonster()
{ CCSprite *monster = CCSprite::create( "monster.png"); CCSize winSize = CCDirector::sharedDirector()->getWinSize(); int minY = monster->getContentSize().height / 2; int maxY = winSize.height - monster->getContentSize().height / 2; int rangeY = maxY - minY; int actualY = (rand() % rangeY) + minY; monster->setPosition(ccp(winSize.width + monster->getContentSize().width / 2, actualY)); this->addChild(monster); int minDuration = 2. 0; int maxDuration = 4. 0; int rangeDuration = maxDuration - minDuration; int actualDuration = (rand() % rangeDuration) + minDuration; CCMoveTo *actionMove = CCMoveTo::create(actualDuration, ccp(-monster->getContentSize().width / 2, actualY)); CCCallFuncN *actionMoveDone = CCCallFuncN::create( this, callfuncN_selector(HelloWorld::spriteMoveFinished)); monster->runAction(CCSequence::create(actionMove, actionMoveDone, NULL)); } |
在右邊螢幕以隨機的位置新增怪物精靈,注意計算精靈的位置座標,預設描點在中心,不要讓怪物截斷了。然後再以2~4秒的隨機總時間,讓怪物從右邊移動到左邊,移動出邊界後,即回撥函式spriteMoveFinished,進行刪除精靈物件,增加的spriteMoveFinished方法如下:
1
2 3 4 5 |
void HelloWorld::spriteMoveFinished(CCNode *sender)
{ CCSprite *sprite = (CCSprite*)sender; this->removeChild(sprite, true); } |
1 | this->schedule(schedule_selector(HelloWorld::gameLogic), 1. 0); |
1
2 3 4 |
void HelloWorld::gameLogic(
float dt )
{ this->addMonster(); } |
8.接著讓玩家可以射擊子彈,當用戶在螢幕點選時,就讓玩家往點選的方向進行傳送子彈,使用者的螢幕點選點並不是子彈移動的最終地,借用原文的一張圖片來說明:
要讓層可以支援觸控,需要在 init方法,新增如下程式碼:
1 | this->setTouchEnabled( true); |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
void HelloWorld::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent)
{ CCTouch *touch = (CCTouch*)pTouches->anyObject(); CCPoint location = this->convertTouchToNodeSpace(touch); CCSize winSize = CCDirector::sharedDirector()->getWinSize(); CCSprite *projectile = CCSprite::create( "projectile.png"); projectile->setPosition(ccp( 20, winSize.height / 2)); CCPoint offset = ccpSub(location, projectile->getPosition()); if (offset.x <= 0) { return; } this->addChild(projectile); int realX = winSize.width + projectile->getContentSize().width / 2; float ratio = ( float)offset.y / ( float)offset.x; int realY = realX * ratio + projectile->getPosition().y; CCPoint realDest = ccp(realX, realY); int offRealX = realX - projectile->getPosition().x; int offRealY = realY - projectile->getPosition().y; float length = sqrtf(offRealX * offRealX + offRealY * offRealY); float velocity = 480 / 1; float realMoveDuration = length / velocity; projectile->runAction(CCSequence::create(CCMoveTo::create(realMoveDuration, realDest), CCCallFuncN::create( this, callfuncN_selector(HelloWorld::spriteMoveFinished)), NULL)); } |
首先,得到觸控點,然後建立子彈精靈,算出觸控點與子彈初始位置之差,若觸控點在初始位置的前方(即玩家前方),則新增子彈到層上。以同比例方法,計算出子彈飛向螢幕右邊的最終座標。然後再用勾股定理計算飛行長度,假定速度為每秒480畫素,則計算出飛行總時間。之後就是讓子彈執行給定的飛行動作,以及之後的刪除自身呼叫。
9.編譯執行,往螢幕點選,可以看到子彈發射出去,如下圖所示:
10.當子彈碰到怪物時,怪物被消滅,子彈消失,即碰撞檢測。需要在場景中跟蹤目標和子彈,在HelloWorldScene.h宣告如下:
1
2 |
cocos2d::CCArray *_monsters;
cocos2d::CCArray *_projectiles; |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
HelloWorld::HelloWorld()
{ _monsters = NULL; _projectiles = NULL; } HelloWorld::~HelloWorld() { if (_monsters) { _monsters->release(); _monsters = NULL; } if (_projectiles) { _projectiles->release(); _projectiles = NULL; } } |
然後在init函式中初始化這兩個陣列:
1
2 3 4 |
this->_monsters = CCArray::create();
this->_monsters->retain(); this->_projectiles = CCArray::create(); this->_projectiles->retain(); |
1
2 |
monster->setTag(
1);
_monsters->addObject(monster); |
1
2 |
projectile->setTag(
2);
_projectiles->addObject(projectile); |
1
2 3 4 5 6 7 8 |
if (sprite->getTag() ==
1)
{ _monsters->removeObject(sprite); } else if (sprite->getTag() == 2) { _projectiles->removeObject(sprite); } |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
void HelloWorld::update(
float dt)
{ CCArray *projectilesToDelete = CCArray::create(); CCObject *pObject = NULL; CCObject *pObject2 = NULL; CCARRAY_FOREACH(_projectiles, pObject) { CCSprite *projectile = (CCSprite*)pObject; CCArray *monstersToDelete = CCArray::create(); CCARRAY_FOREACH(_monsters, pObject2) { CCSprite *monster = (CCSprite*)pObject2; if (CCRect::CCRectIntersectsRect(projectile->boundingBox(), monster->boundingBox())) { monstersToDelete->addObject(monster); } } CCARRAY_FOREACH(monstersToDelete, pObject2) { CCSprite *monster = (CCSprite*)pObject2; _monsters->removeObject(monster); this->removeChild(monster, true); } if (monstersToDelete->count() > 0) { projectilesToDelete->addObject(projectile); } monstersToDelete->release(); } CCARRAY_FOREACH(projectilesToDelete, pObject) { CCSprite *projectile = (CCSprite*)pObject; _projectiles->removeObject(projectile); this->removeChild(projectile, true); } projectilesToDelete->release(); } |
遍歷子彈陣列,計算每一個子彈所可能遇到的怪物,用它們各自的邊界框進行交叉檢測,檢測到交叉,則將怪物物件放入ToDelete(待刪除)陣列,不能在遍歷的時候刪除一個物件。若是子彈遇到了怪物,也需要放入ToDelete(待刪除)陣列。然後從場景和陣列中移動掉。同樣,也在init函式,安裝定時器,程式碼如下:
1 | this->schedule(schedule_selector(HelloWorld::update)); |
12.新增音效,在 init函式新增背景音樂,程式碼如下:
1 | CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic( "background-music-aac.wav"); |
1 | CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect( "pew-pew-lei.wav"); |
GameOverLayer.h檔案程式碼為:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#pragma once
#include "cocos2d.h" class GameOverLayer : public cocos2d::CCLayerColor { public: GameOverLayer( void); ~GameOverLayer( void); bool initWithWon( bool won); static cocos2d::CCScene* sceneWithWon( bool won); static GameOverLayer* createWithWon( bool won); void gameOverDone(); }; |
GameOverLayer.cpp檔案程式碼為:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
#include
"GameOverLayer.h"
#include "HelloWorldScene.h" using namespace cocos2d; GameOverLayer::GameOverLayer( void) { } GameOverLayer::~GameOverLayer( void) { } GameOverLayer* GameOverLayer::createWithWon( bool won) { GameOverLayer *pRet = new GameOverLayer(); if (pRet && pRet->initWithWon(won)) { pRet->autorelease(); return pRet; } else { CC_SAFE_DELETE(pRet); return NULL; } } bool GameOverLayer::initWithWon( bool won) { bool bRet = false; do { CC_BREAK_IF(! CCLayerColor::initWithColor(ccc4( 255, 255, 255, 255))); char *message; if (won) { message = "You Won!"; } else { message = "You Lose :["; } CCSize winSize = CCDirector::sharedDirector()->getWinSize(); CCLabelTTF *label = CCLabelTTF::create(message, "Arial", 32); label->setColor(ccc3( 0, 0, 0)); label->setPosition(ccp(winSize.width / 2, winSize.height / 2)); this->addChild(label); this->runAction(CCSequence::create(CCDelayTime::create( 3), CCCallFunc::create( this, callfunc_selector(GameOverLayer::gameOverDone)), NULL)); bRet = true; } while ( 0); return bRet; } cocos2d::CCScene* GameOverLayer::sceneWithWon( bool won) { CCScene * scene = NULL; do { scene = CCScene::create(); CC_BREAK_IF(! scene); GameOverLayer *layer = GameOverLayer::createWithWon(won); CC_BREAK_IF(! layer); scene->addChild(layer); } while ( 0); return scene; } void GameOverLayer::gameOverDone() { CCDirector::sharedDirector()->replaceScene(HelloWorld::scene()); } |
遊戲結束時,切換到以上所建的場景,場景上的層顯示一個文字,在3秒之後返回到HelloWorld場景中。
14.最後,為遊戲新增一些遊戲邏輯。記錄玩家消滅怪物的數量,進而決定該玩家輸贏。在HelloWorldScene.h檔案中,新增如下:
1 | int _monstersDestroyed; |
1 | _monstersDestroyed = 0; |
1 | #include "GameOverLayer.h" |
1
2 3 4 5 6 |
_monstersDestroyed++;
if (_monstersDestroyed > 30) { CCScene *gameOverScene = GameOverLayer::sceneWithWon( true); CCDirector::sharedDirector()->replaceScene(gameOverScene); } |
1
2 |
CCScene *gameOverScene = GameOverLayer::sceneWithWon(
false);
CCDirector::sharedDirector()->replaceScene(gameOverScene); |
參考資料:
1.How To Make A Simple iPhone Game with Cocos2D 2.X Tutorial http://www.raywenderlich.com/25736/how-to-make-a-simple-iphone-game-with-cocos2d-2-x-tutorial
2.如何用Cocos2d來開發簡單的IPhone遊戲教程 http://www.cocoachina.com/bbs/read.php?tid-15554.html
3.Cocos2d Classic Tutorial Demo Revisit:(1) http://www.zilongshanren.com/cocos2d-classic-tutorial-demo-revisit-1/
非常感謝以上資料,本例子原始碼附加資源下載地址:http://download.csdn.net/detail/akof1314/4857315
如文章存在錯誤之處,歡迎指出,以便改正。
再分享一下我老師大神的人工智慧教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智慧的隊伍中來!https://www.cnblogs.com/captainbed