日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何用cocos2d-x来开发简单的Uphone游戏:(二) 移动的精灵

發布時間:2023/12/15 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何用cocos2d-x来开发简单的Uphone游戏:(二) 移动的精灵 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

三、添加一個精靈

?

我們先用個簡單的方式,把player, projectile, target三個PNG文件拷貝到 D:\Work7\NEWPLUS\TDA_DATA\UserData 目錄下,這使其可以在模擬器上直接通過文件路徑訪問到。Uphone有其資源打包的方式,圖片和音樂都可以打包到動態庫文件內,這個另外會有教程描述,我們這里先讓事情簡單化。

?? ? ? ??? ? ? ??


關于cocos2d坐標系統的規則,簡而言之就是左下角為原點,向上向右按像素遞增,這在Wenderlich的原文中有詳細描述,我們這里就不再贅述了。直接切入代碼

現在我們在HelloWorldScene.cpp里面,找到bool HelloWorld::init()函數,把它替換成下面代碼

?

bool?HelloWorld::init()
{
??
//
??//?1.?super?init?first
??if?(?!CCLayer::init()?)
??{
????
return?false;
??}

??
/////
??//?2.?add?a?menu?item?with?"X"?image,?which?is?clicked?to?quit?the?program
??
//????you?may?modify?it.

??
//?add?a?"close"?icon?to?exit?the?progress.?it's?an?autorelease?object
??CCMenuItemImage?*pCloseItem?=?CCMenuItemImage::itemFromNormalImage(?"CloseNormal.png",?
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
"CloseSelected.png",?
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
this,
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?menu_selector(HelloWorld::menuCloseCallback)?);
??pCloseItem->setPosition(?ccp(CCDirector::getSharedDirector()->getWinSize().width?-?20,?20)?);

??
//?create?menu,?it's?an?autorelease?object
??CCMenu*?pMenu?=?CCMenu::menuWithItems(pCloseItem,?NULL);
??pMenu->setPosition(?CGPointZero?);
??
this->addChild(pMenu);

??
/////
??//?3.?add?your?codes?below...

??CGSize?winSize?=?CCDirector::getSharedDirector()->getWinSize();
??CCSprite?*player?=?CCSprite::spriteWithFile("Player.png",?
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?CGRectMake(0,?0,?27,?40)?);
??player->setPosition(?ccp(player->getContentSize().width/2,?winSize.height/2)?);
??
this->addChild(player);

??
return?true;
}

?

其實我們只修改了 // 3. add your codes below 這段。

cocos2d-x和cocos2d-iphone的接口有細微的差別,不過你一旦習慣了這個差別,寫起代碼來就會很順手。

我們拋開添加"X"退出按鈕的一段,單純地看一下這兩段init函數的差異.

?

//?cpp with cocos2d-x
bool?HelloWorld::init()
{
??if?(?CCLayer::init()?)
??{
?? ?CGSize?winSize?=?CCDirector::getSharedDirector()->getWinSize();
?? ?CCSprite?*player?=?CCSprite::spriteWithFile("Player.png",?
??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? CGRectMake(0,?0,?27,?40)?);
?? ?player->setPosition(?ccp(player->getContentSize().width/2,?
??????????????????????????????winSize.height/2)?);
???this->addChild(player);
??}
??return?true;
}
//?objc with cocos2d-iphone
-(id)?init
{
??if(?(self=[super?init]?))?
??{
?? ?CGSize?winSize?=?[[CCDirector?sharedDirector]?winSize];
?? ?CCSprite?*player?=?[CCSprite?spriteWithFile:@"Player.png"
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?rect:CGRectMake(0,?0,?27,?40) ];
?? ?player.position?=?ccp(player.contentSize.width/2,?
?? ? ? ? ? ? ? ? ? ? ? ? ?winSize.height/2);
?? ?[self?addChild:player];
??}
??return?self;
}?

?

轉換要點

1. 雖然VC++中有super關鍵字,但linux下用gcc編譯時可不認。所以C++中不能用super::init(),而必須老老實實地指定是執行父類CCLayer::init()方法

?

2. 由于cpp里沒有property的概念,所以在objc里涉及property的地方,我們都用了get/set函數代替。于是,訪問CCDirector.SharedDirector屬性的代碼,就變成了CCDirector::getSharedDirector()函數調用,shared開頭小寫的s,也變成了大寫的S。同樣規則,取得winSize屬性的地方,則變成了getWinSize()函數調用。這段代碼中還有player->getContentSize()也受此影響。但訪問結構體中的變量,如winSize中的width和height則不需用getter封裝。

?

3. 設置類的屬性,如player.position = ,也改用setter實現,變成player->setPosition(...)


4. C++函數調用不需像OBJC那樣在每個參數前面說明這參數是干什么用的,比如rect:CGRectMake(...),只需直接輸入參數即可。另一方面, cocos2d-x仿照iOS實現了CGGeometry的一些函數,你可以在cocos2dx\include\CGGeometry.h里看到它們。除了CGRectMake,還有CGPointMake, CGSizeMake, CGPointZero, CGSizeZero, CGRectZero.


5. cocos2d-x所有的游戲元素, sprite,layer,scene,label,action等,都是new在heap上,并且用指針傳遞的,因此調用其成員函數一定是用->號,而不像objc里的點號


6. cpp里用this替代了objc的self關鍵字

?

7. cocos2d-x里的init函數改成返回bool類型了。由于cpp里沒有objc的"id"關鍵字,所以cocos2d-iphone里返回id的地方,都改成返回明確的類指針,或者bool型變量


好了,我們編譯運行一下,可以看到帶頭大哥一襲黑衣,很猥瑣地躲在黑色背景上,只露出一雙殺紅了的眼睛。為了游戲性,我們需要把背景顏色改成白的。只要簡單地修改,使HelloWorld不是繼承CCLayer,而是繼承CCColorLayer就行了。


在HelloWorldScene.h中,修改HelloWorld類聲明如下。

?(左邊為cpp代碼,也就是讀者現在應該使用的,右邊為Cocos2dSimpleGame原來使用cocos2d-iphone的objc代碼,用以對比參考。本系列后面的行文也都如此)

//?cpp with cocos2d-x
class?HelloWorld?:?public?cocos2d::CCColorLayer
//?objc with cocos2d-iphone
@interface?HelloWorld?:?CCColorLayer

?

然后在HelloWorld::init()函數實現中,修改剛開始的?

if?(?!CCLayer::init()?)
{
????
return?false;
}

變成

if?(?!CCColorLayer::initWithColor(?ccc4(255,255,255,255)?)?)
{
????
return?false;
}

這里小改了一下邏輯,原版objc里是如果super init成功,就BALA-BALA做后面的工作;我喜歡防御性編程,如果失敗則先做出錯處理、跳出,然后才繼續寫正確流程。這么做有兩個好處,一是不會寫到后面漏掉了錯誤處理,二是不用做太多層的if嵌套。這個是題外話了。拋開if的邏輯,我們來對比一下這句super init在cpp和objc的區別

//?cpp?with?cocos2d-x
if?(?CCColorLayer::initWithColor(?ccc4(255,255,255,255)?)
//?objc?with?cocos2d-iphone
if?(?self?=?[super?initWithColor:ccc4(255,255,255,255)]?)

?

轉換要點

1. 首先,cpp的繼承默認為private繼承,所以類聲明的繼承處public關鍵字不可少?

2. cocos2d-iphone的作者Ricardo Quesada建議我們采用C++的命名空間把cocos2d整個庫包起來。而我們在這里既不想直接到頭文件里using namespace cocos2d;感染了所有包含這個頭文件的CPP文件,也不想把class HelloWorld歸到cocos2d命名空間內,所以HelloWorldScene.h頭文件里只好在每個cocos2d類前面加上命名空間cocos2d::


編譯后運行,你就可以看到帶頭大哥孤獨地站在白色背景上了,寂寞得淚流滿面


?

?

四、移動目標


有了帶頭大哥后,我們就需要添加一些蝦兵蟹將讓大哥砍。英雄人物一般不喜歡砍木樁,所以我們就用void addTarget()方法在屏幕右邊創建一些跑龍套的小兵,讓他們以隨機速度向左移動。


先到HelloWorldScene.h里添加函數聲明 void addTarget(); 然后回到HelloWorldScene.cpp里實現函數

//?cpp?with?cocos2d-x
void?HelloWorld::addTarget()
{
??CCSprite?*target?=?CCSprite::spriteWithFile("Target.png",?
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?CGRectMake(0,0,27,40) );

??//?Determine?where?to?spawn?the?target?along?the?Y?axis
??CGSize?winSize?=?CCDirector::getSharedDirector()->getWinSize();
??int?minY?=?target->getContentSize().height/2;
??int?maxY?=?winSize.height?-??target->getContentSize().height/2;
??int?rangeY?=?maxY?-?minY;
??srand(?TimGetTicks()?);
??int?actualY?=?(?rand()?%?rangeY?)?+?minY;

??//?Create?the?target?slightly?off-screen?along?the?right?edge,
??//?and?along?a?random?position?along?the?Y?axis?as?calculated
??target->setPosition(?
?? ?ccp(winSize.width?+?(target->getContentSize().width/2),?
?? ?actualY)?);
??this->addChild(target);

??//?Determine?speed?of?the?target
??int?minDuration?=?(int)2.0;
??int?maxDuration?=?(int)4.0;
??int?rangeDuration?=?maxDuration?-?minDuration;
??srand(?TimGetTicks()?);
??int?actualDuration?=?(?rand()?%?rangeDuration?)?+?minDuration;

??//?Create?the?actions
??CCFiniteTimeAction*?actionMove?=?
?? ?CCMoveTo::actionWithDuration(?(ccTime)actualDuration,?
?? ? ? ?ccp(0?-?target->getContentSize().width/2,?actualY)?);
??CCFiniteTimeAction*?actionMoveDone?=?
?? ?CCCallFuncN::actionWithTarget(?this,?
?? ? ? ? ? ? ? ?callfuncN_selector(HelloWorld::spriteMoveFinished));
??target->runAction(?CCSequence::actions(actionMove,?
?? ? ? ? ? ? ? ? ? ? actionMoveDone,?NULL)?);
}
//?objc?with?cocos2d-iphone
-(void)addTarget?
{
??CCSprite?*target?=?[CCSprite?spriteWithFile:@"Target.png"
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?rect:CGRectMake(0,?0,?27,?40)];

??//?Determine?where?to?spawn?the?target?along?the?Y?axis
??CGSize?winSize?=?[[CCDirector?sharedDirector]?winSize];
??int?minY?=?target.contentSize.height/2;
??int?maxY?=?winSize.height?-?target.contentSize.height/2;
??int?rangeY?=?maxY?-?minY;

??int?actualY?=?(arc4random()?%?rangeY)?+?minY;

??//?Create?the?target?slightly?off-screen?along?the?right?edge,
??//?and?along?a?random?position?along?the?Y?axis?as?calculated
??target.position?=?
?? ?ccp(winSize.width?+?(target.contentSize.width/2),?
?? ?actualY);
??[self?addChild:target];

??//?Determine?speed?of?the?target
??int?minDuration?=?2.0;
??int?maxDuration?=?4.0;
??int?rangeDuration?=?maxDuration?-?minDuration;

??int?actualDuration?=?(arc4random()?%?rangeDuration)?+?minDuration;

??//?Create?the?actions
??id?actionMove?=?
?? ?[CCMoveTo?actionWithDuration:actualDuration
?? ? ? ? ?position:ccp(-target.contentSize.width/2,?actualY)];
??id?actionMoveDone?=?
?? ?[CCCallFuncN?actionWithTarget:self
?? ? ? ? ? ? ? ?selector:@selector(spriteMoveFinished:)];
??[target?runAction:[CCSequence?actions:actionMove,?
?? ? ? ? ? ? ? ? ? ?actionMoveDone,?nil]];?
}?

?

這里用callfuncN_selector(HelloWorld::spriteMoveFinished)回調了spriteMoveFinished方法,我們需要實現之。同樣別忘記在頭文件里加入聲明, 然后實現之

//?cpp?with?cocos2d-x
void?HelloWorld::spriteMoveFinished(CCNode*?sender)
{
??CCSprite?*sprite?=?(CCSprite?*)sender;
??this->removeChild(sprite,?true);
}
//?objc?with?cocos2d-iphone
-(void)spriteMoveFinished:(id)sender?
{
??CCSprite?*sprite?=?(CCSprite?*)sender;
??[self?removeChild:sprite?cleanup:YES];?
}?

?

轉換要點

1. 隨機函數。在iphone上可以用arc4random()直接生成隨機函數,而uphone上還是用傳統的方法,先獲取毫秒級時間(這個函數在uphone上是TimGetTickes()),用srand(int)塞進去作為random seed,然后再調用rand()生成隨機數。其中srand和rand是C標準庫函數

?

2. objc中的YES和NO,在cpp中變成true和false,這個容易理解

?

3. 回調函數.在objc中用 selector:@selector(spriteMoveFinished),在cpp中實現就比較復雜了,具體可以看cocos2dx\include\selector_protocol.h里面的聲明??傊糠N可能出現selector的地方,都有唯一的函數指針類型與之匹配。一共有5種回調函數類型

  • schedule_selector
  • callfunc_selector
  • callfuncN_selector
  • callfuncND_selector
  • menu_selector

具體使用時,可以看所用函數的變量類型定義來決定。比如使用CCTimer::initWithTarget方法,第二個參數是SEL_SCHEDULE類型,到selector_protocol.h里查一下,可以看到對應是schedule_selector(_SELECTOR)宏,所以調用時就需要在類里頭實現一個void MyClass::MyCallbackFuncName(ccTime)函數,然后把schedule_selector(MyClass::MyCallbackFuncName)作為CCTimer::initWithTarget的第二個參數傳入。

?

?

有了addTarget后,我們需要定時地調用它。所以在init函數返回前增加這個函數調用

//?cpp?with?cocos2d-x
//?Call?game?logic?about?every?second
this->schedule(?schedule_selector(HelloWorld::gameLogic),?1.0?);
//?objc?with?cocos2d-iphone
//?Call?game?logic?about?every?second
[self?schedule:@selector(gameLogic:)?interval:1.0];

?

然后實現gameLogic這個回調函數

//?cpp?with?cocos2d-x
void?HelloWorld::gameLogic(ccTime?dt)
{
?? ?this->addTarget();
}
//?objc?with?cocos2d-iphone
-(void)gameLogic:(ccTime)dt
{
?? ?[self?addTarget];
}

?

不要忘記在頭文件里增加函數聲明,并且應為public函數,否則回調是調用不到的。


編譯運行,現在你應該看到小嘍啰們張牙舞爪地向大哥撲過來。于是拯救世界、維護人類和平的重任就交給大哥了。



本文轉自Walzer博客園博客,原文鏈接:http://www.cnblogs.com/walzer/archive/2010/10/10/1847100.html,如需轉載請自行聯系原作者


?

總結

以上是生活随笔為你收集整理的如何用cocos2d-x来开发简单的Uphone游戏:(二) 移动的精灵的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。