cocos2d-x for android:SimpleGame分析

cocos2d-x for android:SimpleGame分析html

做爲cocos2d-x的標配DEMO,SimpleGame可算是給入門學cocos2d-x的俺們這些新手門學習的對象了,那麼來分析分析,把幾個關鍵的代碼記錄下來。android

 

設置遊戲讀取資源的目錄數組

CCFileUtils::sharedFileUtils()->setResourceDirectory( " sd ");

默認路徑是Resource目錄iphone

 

設置遊戲的分辨率大小函數

CCEGLView::sharedOpenGLView()->setDesignResolutionSize(480, 320, kResolutionNoBorder);

也能夠不設置,自動去獲取post

 

建立精靈學習

複製代碼
CCSprite *player=CCSprite::create( " Player.png ",CCRectMake( 0, 0, 27, 40));
player->setPosition(ccp(
origin.x+player->getContentSize().width/ 2, //X軸爲:0+遊戲角色的寬度/2
winVisibleSize.height/ 2 + player->getContentSize().height/ 2) //y軸爲:指定的屏幕分辨率/2+遊戲角色的高/2
);
this->addChild(player);
複製代碼

若是你但願精靈在圖層初始化的時候就產生,那麼精靈的建立最好把它放在於圖層(CCLayer)的init函數中。this

建立精靈時,須要爲精靈指定位置(position),可接收的參數是CCPoint類型,CCPoint 是一個存放x、y軸數據的對象spa

 

使用時間選擇器刷新遊戲code

this->schedule(schedule_selector(HelloWorld::gameLogic), 1.0);

調用CCNodes的schedule(SEL_SCHEDULE selector, float interval)方法,這是一個自定義的時間選擇器,以秒爲單位。這裏以秒爲單位,每秒產生一個怪物

 

設置可接受觸摸(Touch)事件

在場景初始化時,設置可接受觸摸

this->setTouchEnabled(true);

而後,註冊一個觸摸事件的分發函數

void HelloWorld::registerWithTouchDispatcher(){
CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate( this, 0);
}

經過以上的作法,遊戲便可在ccTouchesEnded回調函數裏面獲得觸摸反饋。

 

移動精靈

上面每一秒鐘刷新遊戲,產生一個遊戲怪物,方法位於HelloWold::addTarget,移動精靈的代碼是

複製代碼
CCFiniteTimeAction* actionMove = CCMoveTo::create( ( float)actualDuration,
ccp( 0 - target->getContentSize().width/ 2, actualY) );
CCFiniteTimeAction* actionMoveDone = CCCallFuncN::create( this,
callfuncN_selector(HelloWorld::spriteMoveFinished));
target->runAction( CCSequence::create(actionMove, actionMoveDone, NULL) );
複製代碼

 

actionMove:設置精靈移動方向和移動速度

actionMoveDone:精靈移動完成後執行可執行的回調函數爲 spriteMoveFinished,當遊戲移動到屏幕邊界外,即回收該對象

而後經過精靈的runAction設置,精靈移動

 

上面代碼,怪物的產生位置定在x的最右邊,move方向從右到左到消息,須要設置x軸的最小值而且徹底能夠將怪物移動出屏幕便可,故x軸這裏設置移動代碼: (0 - target->getContentSize().width/2 ),y軸不變,隨機從出來那一刻起一直不變作橫向移動。

 

控制遊戲角色發射飛鏢

上面有提到設置圖層可授受觸摸 ,接下來咱們要經過觸摸讓遊戲主角發射飛鏢消滅不斷產生的怪物。代碼見下方

獲得觸摸點座標

CCTouch* touch = (CCTouch*)( touches->anyObject() );
CCPoint location = touch->getLocation();

每接受觸摸一次產生一個飛鏢

複製代碼

CCSize winSize = CCDirector::sharedDirector()->getVisibleSize();

CCSprite *projectile = CCSprite::create( " Projectile.png ", CCRectMake( 0, 0, 20, 20));
projectile->setPosition( ccp( 20, winSize.height/2+projectile->getContentSize().height/2) );//角色x軸爲0+角色的寬度,故飛鏢的x軸應和角色有交接,使用戶看起來飛鏢是從角色身上發出來的
複製代碼

飛鏢移動方向

複製代碼
float offX=location.x - projectile->getPosition().x;
float offY=location.y - projectile->getPosition().y;

if(offX <= 0) return;

this->addChild(projectile);

float realX=winSize.width+(projectile->getContentSize().width/ 2);//飛鏢的橫向方向跟遊戲怪物同樣,也是要移動出遊戲界面並回收的(若是碰到怪物也要回收)
float ratio = offY/offX;//偏移量
float realY=(realX*ratio)+projectile->getPosition().y;//飛鏢的豎向方向應是飛鏢的橫向方向*觸摸點的偏移量每幀偏移的數值+當前飛鏢所在位置的y軸
CCPoint realDest =ccp(realX,realY);
複製代碼

控制飛鏢移動

projectile->runAction(CCSequence::create(
CCMoveTo::create( 1.0,realDest),//參數1.移動速度。參數2.移動的x、y軸
CCCallFuncN::create( this,callfuncN_selector(HelloWorld::spriteMoveFinished)),//設置回調函數
NULL
));

 

飛鏢與怪物的碰撞檢測

這裏須要在圖層初始化的時候設置一個時間選擇器,監聽每幀的遊戲變化

this->schedule(schedule_selector(HelloWorld::updateGame));

這時委託函數updateGame就啓到每幀監聽的做用了,代碼以下

複製代碼
void HelloWorld::updateGame( float dt){
CCArray *projectileToDelete = new CCArray;
CCObject* it=NULL;
CCObject* jt = NULL;
CCARRAY_FOREACH(_projectiles,it){ //循環每個飛鏢
CCSprite *projectile=dynamic_cast<CCSprite*>(it);
CCRect projectileRect =CCRectMake(
projectile->getPosition().x - (projectile->getContentSize().width/ 2),
projectile->getPosition().y-(projectile->getContentSize().height/ 2),
projectile->getContentSize().width,
projectile->getContentSize().height);

CCArray* targetsToDelete= new CCArray;

CCARRAY_FOREACH(_targets, jt)//循環每個敵人
{
CCSprite *target = dynamic_cast<CCSprite*>(jt);

CCRect targetRect = CCRectMake(
target->getPosition().x - (target->getContentSize().width/ 2),
target->getPosition().y - (target->getContentSize().height/ 2),
target->getContentSize().width,
target->getContentSize().height);
if (projectileRect.intersectsRect(targetRect)) //這裏作矩形交集檢測,若是二者有產生交集則將須要刪除的敵人存放於數組裏面
{
targetsToDelete->addObject(target);
}
}

CCARRAY_FOREACH(targetsToDelete, jt)//循環須要刪除的敵人
{
CCSprite *target = dynamic_cast<CCSprite*>(jt);
_targets->removeObject(target); //將敵人從產生的敵人數組裏面刪除
this->removeChild(target, true);//從圖層刪除

_projectilesDestroyed++; //累積
if (_projectilesDestroyed >= 10) //當知足消滅必定數量的敵人時,則執行遊戲場景切換或者什麼的blablabla
{
///
}
}
if(targetsToDelete->count() > 0){ //若是有存在須要刪除的敵人,則同時將與敵人交集的飛鏢存入須要刪除的飛鏢數組
projectileToDelete->addObject(projectile);
}
targetsToDelete->release();
}

// remove projectile
CCARRAY_FOREACH(projectileToDelete,it){ //最後循環飛鏢將飛鏢刪除掉
CCSprite *projectile =dynamic_cast<CCSprite*>(it);
_projectiles->removeObject(projectile);
this->removeChild(projectile, true);
}
projectileToDelete->release();
// end
}
複製代碼

根據上面,邏輯並不複雜,注意一下當前飛鏢與敵人數組之間的關係便可。

 

播放遊戲音效

不管是遊戲背景音效也好,忍者發射飛鏢那一剎那時的聲音也好,好的遊戲都要加上特殊的音效效果才能使遊戲更加引人入勝。 cocos2d-x遊戲引擎固然也有相關的音樂播放接口。從網上找到的一段話:

cocos2d-iphone裏包含cocosDenshion庫,裏面從底到高提供三層接口:CDSoundEngine->CDAudioManager->SimpleAudioEngine,但整個庫徹底依賴於OpenAL來實現。關於OpenAL,它不是Khronos Group的標準,而是Creative公司的一個開源庫,能夠軟實現或硬件實現。目前硬件實現了OpenAL的好像就只有蘋果的產品,所以在其餘平臺上,咱們沒法提供cocosDenshion底層的支持,但咱們是支持頂層的,它是開發者最經常使用到的一層。

 

那麼如何添加音效呢?

添加背景音

CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic( " background-music-aac.wav ", true);//設置背景音循環

添加發射飛鏢音效

CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect( " pew-pew-lei.wav ", false);

這裏發射飛鏢音效須要注意一個問題就是,若是這樣寫在Touch裏面,第一次讓音效播放是無效的,緣由是播放音效須要預加載,否則第一次點擊是不會出聲音的,以後纔會。不知道這是引擎硬性要求的麼?解決辦法是在圖層初始化的時候讓音效預加載一次

CocosDenshion::SimpleAudioEngine::sharedEngine()->preloadEffect( " pew-pew-lei.wav ");

 

關於場景切換

以爲這方面沒什麼要說的,該說的網上都有,尤爲是nowpaper 這篇文章 ,講得很形象,能夠去看看。

SimpleGame裏面的場景切換類,對應是GameOverScene.cpp,該文件是判斷遊戲結束時,切換到該界面提示用戶失敗或者成功。這裏有一點須要特色注意的是

GameOverScene *gameOverScene=GameOverScene::create();

gameOverScene->getLayer()->getLabel()->setString( " you win!!! ");
CCDirector::sharedDirector()->replaceScene(gameOverScene);

 

上面紅色代碼這塊,比較難懂,這句話能夠這麼理解:經過GameOverScene頭文件中的CC_SYNTHESIZE_READONLY宏定義生成getLayer方法,該方法返回GameOverLayer類型,而後再經過CC_SYNTHESIZE_READONLY 宏定義生成getLabel方法,返回cocos2d::CCLabelTTF類型,最後調用CCLabelTTF成員裏面的setString ,該_label在初始化GameOverLayer的時候就己經this->addChild(_label) ,會不會這樣就至關於傳參數到另外一個CCScene呢?呵呵!

宏定義代碼以下:

#define CC_SYNTHESIZE_READONLY(varType, varName, funName)\
protected: varType varName;\

public: virtual varType get##funName(void) const { return varName; } //這裏組合獲得方法名和返回類型
來源:http://www.cnblogs.com/TerryBlog/archive/2012/10/30/2746150.html

相關文章
相關標籤/搜索