本文翻譯自https://www.raywenderlich.com/網(wǎng)站上Guanghui Qu寫(xiě)的2015年4月30號(hào)的一篇博文Cocos2d-x Tutorial for Beginners,他使用的Cocos2d-x的版本是 version 3.5。另外,關(guān)于在Windows10下使用Cocos2d-x 3.17.2構(gòu)建項(xiàng)目的,可以參考我之前寫(xiě)的博客:Win10+Python2.7.14+cocos2d-x-3.17.2+VS2017環(huán)境搭建
Cocos2d-x初學(xué)者教程
在此Cocos2d-x教程中揣苏,學(xué)習(xí)如何使用C ++為iOS健芭,Android等創(chuàng)建基本的跨平臺(tái)游戲废睦!
Guanghui Qu
2015年4月30日·文章(30分鐘)·初學(xué)者
Cocos2d-x是一種快速坷虑,強(qiáng)大且易于使用的開(kāi)源2D游戲引擎。
它與Apple的Sprite Kit非常相似埂奈,但具有一個(gè)關(guān)鍵優(yōu)勢(shì)– Cocos2d-x是跨平臺(tái)的迄损。
這意味著您可以使用一組代碼來(lái)制作適用于iOS,Android账磺,Windows Phone芹敌,Mac OS X,Windows桌面和Linux的游戲垮抗。 對(duì)于獨(dú)立游戲開(kāi)發(fā)者來(lái)說(shuō)氏捞,這是意義巨大的!
在本教程中冒版,您將學(xué)習(xí)如何使用C ++在Cocos2d-x中創(chuàng)建一個(gè)簡(jiǎn)單的2D游戲液茎。 是的-會(huì)有忍者! :]
**注意:本教程假定您了解C ++開(kāi)發(fā)的基礎(chǔ)知識(shí)。 如果您不熟悉C ++捆等,請(qǐng)務(wù)必先閱讀有關(guān)該主題的書(shū)滞造。**
入門(mén)
在www.cocos2d-x.org/download下載最新版本的Cocos2d-x; 本教程使用3.5版栋烤。
將下載的文件放在您要存儲(chǔ)Cocos2d-x安裝的位置谒养,例如在主目錄中,然后將其解壓縮明郭。
打開(kāi)終端
并cd
到剛解壓縮的文件夾中买窟。 例如,如果將項(xiàng)目放置在主目錄中薯定,請(qǐng)運(yùn)行以下命令:
cd ~/cocos2d-x-3.5/
現(xiàn)在運(yùn)行以下命令:
python setup.py
這將設(shè)置必要的Shell環(huán)境變量始绍。 當(dāng)它提示您配置特定于Android的變量NDK_ROOT
,ANDROID_SDK_ROOT
和ANT_ROOT
時(shí)沉唠,只需按3次Enter
回車(chē)鍵即可完成配置疆虚。
注意:Cocos2D需要在您的機(jī)器上安裝Python 2.7+。 如果不確定所用的Python版本满葛,請(qǐng)?jiān)诿钚猩湘I入python
径簿,它將顯示該版本(然后按Ctrl-D退出)。 如果您使用的是Python的舊版本嘀韧,請(qǐng)?jiān)?a target="_blank">python.org上安裝最新版本的Python篇亭。
如下面的屏幕截圖所示,該腳本指示您執(zhí)行另一個(gè)命令以完成設(shè)置:
注意:根據(jù)您使用的shell锄贷,您可能會(huì)看到一些不同的輸出译蒂。 在上面的屏幕截圖中,安裝程序包提示輸入“ source / Users / rwenderlich / bash_profile”命令谊却,因?yàn)槲沂褂玫氖荁ash柔昼,但例如如果我一直使用Zsh,它會(huì)提示我運(yùn)行“ source /Users/rwenderlich/.zshrc”炎辨。
按照腳本的輸出說(shuō)明輸入命令捕透。 節(jié)省時(shí)間的秘訣:您可以使用代字號(hào)(?)代替/ Users / your_user_name
,因此要保存擊鍵碴萧,可以鍵入以下內(nèi)容:
source ~/.zshrc (or source ~/.bash_profile)
您輸入的命令只是重新處理您的shell配置乙嘀,并使其可以訪問(wèn)新變量。 現(xiàn)在破喻,您可以從任何目錄在終端中調(diào)用cocos命令虎谢。
運(yùn)行以下命令以創(chuàng)建一個(gè)名為SimpleGame的C ++游戲模板:
cocos new -l cpp -d ~/Cocos2d-x-Tutorial SimpleGame
這將在您的主目錄中創(chuàng)建一個(gè)名為Cocos2d-x-Tutorial
的目錄,并在其中創(chuàng)建一個(gè)名為SimpleGame
的子目錄曹质,其中包含您項(xiàng)目的文件婴噩。
注意:要了解可用的cocos
子命令擎场,請(qǐng)鍵入cocos --help
或cocos -h
。 您還可以通過(guò)添加“ --help”或“ -h”(例如cocos new -h
)來(lái)了解任何子命令的選項(xiàng)讳推,以查看new
命令的選項(xiàng)顶籽。
在Finder
中雙擊?/ Cocos2d-x-Tutorial / SimpleGame / proj.ios_mac / SimpleGame.xcodeproj
以在Xcode
中打開(kāi)項(xiàng)目。
一旦進(jìn)入Xcode
银觅,請(qǐng)確保SimpleGame Mac
是活動(dòng)方案礼饱,如下所示:
盡管Cocos2d-x
能夠?yàn)樵S多平臺(tái)構(gòu)建游戲,但在本教程中究驴,您將重點(diǎn)關(guān)注制作OS X
應(yīng)用程序镊绪。 將這個(gè)項(xiàng)目移植到其他平臺(tái)上是一件很簡(jiǎn)單的事情(是的,很簡(jiǎn)單H饔恰)蝴韭,這在本教程的結(jié)尾進(jìn)行了簡(jiǎn)要討論。
生成并運(yùn)行您的應(yīng)用熙侍,以全面了解模板項(xiàng)目:
分辨率設(shè)置
默認(rèn)情況下榄鉴,Cocos2d-x游戲的名稱(chēng)為“ MyGame”,分辨率為960×640蛉抓,但是這些細(xì)節(jié)很容易更改庆尘。
打開(kāi)AppDelegate.cpp并在其中找到以下行
AppDelegate::applicationDidFinishLaunching:
glview = GLViewImpl::create("My Game");
用以下代碼替換該行:
glview = GLViewImpl::createWithRect("SimpleGame", Rect(0,0, 480, 320), 1.0);
這會(huì)將應(yīng)用程序的名稱(chēng)更改為“ SimpleGame”,并將其分辨率設(shè)置為480×320巷送,以匹配模板隨附的背景圖片驶忌。
再次構(gòu)建并運(yùn)行您的應(yīng)用,以查看新的較小的游戲:
請(qǐng)注意笑跛,您傳遞給
createWithRect
的第三個(gè)參數(shù)-1.0
付魔。 此參數(shù)縮放幀,通常用于測(cè)試分辨率大于顯示器的幀飞蹂。 例如几苍,要在小于1920×1080的監(jiān)視器上測(cè)試1920×1080的分辨率,您可以傳遞0.5
以將窗口縮放到960×540陈哑。
雖然對(duì)createWithRect
的調(diào)用更改了臺(tái)式機(jī)上的游戲框架擦剑,但在iOS設(shè)備上這種方式無(wú)法正常工作; 而是游戲的分辨率與屏幕尺寸匹配芥颈。 這是在iPhone 6上的外觀:
那么,您如何處理多種分辨率呢赚抡? 在本教程中爬坑,您將基于960×640分辨率創(chuàng)建一組游戲資源,然后在運(yùn)行時(shí)根據(jù)需要簡(jiǎn)單地按比例放大或縮小資產(chǎn)涂臣。
要實(shí)現(xiàn)這一點(diǎn)盾计,請(qǐng)?jiān)趦?nèi)部添加以下代碼:
AppDelegate::applicationDidFinishLaunching
售担,位于在Director上
調(diào)用setDisplayStats
的行的上方:
// 1
Size designSize = Size(480,320);
Size resourceSize = Size(960,640);
// 2
director->setContentScaleFactor(resourceSize.height / designSize.height);
director->getOpenGLView()->setDesignResolutionSize(
designSize.width, designSize.height, ResolutionPolicy::FIXED_HEIGHT);
上面的代碼是這樣的:
- .在這里,您可以定義
designSize
(創(chuàng)建游戲邏輯時(shí)要使用的尺寸)和resourceSize
(您所有藝術(shù)資產(chǎn)所基于的尺寸)署辉。 - 2.這些行告訴您游戲的
Driector
根據(jù)您提供的設(shè)計(jì)和資源大小在必要時(shí)擴(kuò)展資產(chǎn)族铆。
有關(guān)Cocos2d-x
如何處理分辨率的詳細(xì)說(shuō)明,請(qǐng)參閱Cocos2d-x Wiki關(guān)于多分辨率適配的條目哭尝。
添加精靈
接下來(lái)哥攘,下載該項(xiàng)目的資源文件并將其解壓縮到方便的位置。
在剛剛提取的SimpleGameResources
文件夾中選擇所有文件材鹦,并將它們拖到``Xcode
項(xiàng)目的Resources
組中逝淹。 在出現(xiàn)的對(duì)話框中,請(qǐng)確保在單擊“完成”之前選中“復(fù)制項(xiàng)目”桶唐,SimpleGame iOS
和SimpleGame Mac
栅葡。
接下來(lái)打開(kāi)
HelloWorldScene.h
,在包含cocos2d.h
的行之后添加以下行:
using namespace cocos2d;
這指定您將使用cocos2d
命名空間尤泽; 這使您可以執(zhí)行諸如寫(xiě)Sprite *
而不是cocos2d :: Sprite *
的操作欣簇。 這不是絕對(duì)必要的,但肯定會(huì)使開(kāi)發(fā)更加愉快坯约。 :]
現(xiàn)在熊咽,您需要一個(gè)私有成員變量來(lái)指向您的player
精靈。 將以下代碼添加到HelloWorld
類(lèi)的聲明中:
private:
Sprite* _player;
接下來(lái)鬼店,打開(kāi)HelloWorldScene.cpp
并將HelloWorld::init
方法的內(nèi)容替換為以下內(nèi)容:
// 1
if ( !Layer::init() ) {
return false;
}
// 2
auto origin = Director::getInstance()->getVisibleOrigin();
auto winSize = Director::getInstance()->getVisibleSize();
// 3
auto background = DrawNode::create();
background->drawSolidRect(origin, winSize, Color4F(0.6,0.6,0.6,1.0));
this->addChild(background);
// 4
_player = Sprite::create("player.png");
_player->setPosition(Vec2(winSize.width * 0.1, winSize.height * 0.5));
this->addChild(_player);
return true;
這是此方法的逐步播放:
- 1.首先网棍,您調(diào)用父類(lèi)的
init
方法。 只有成功后妇智,您才能繼續(xù)進(jìn)行HelloWorldScene
的設(shè)置滥玷。 - 2.然后,您可以使用游戲的
Director
單例來(lái)獲取窗口的邊界巍棱。 - 3.然后惑畴,您創(chuàng)建一個(gè)
DrawNode
來(lái)繪制一個(gè)灰色矩形,該矩形將填充屏幕并將其添加到場(chǎng)景中航徙。 這是您游戲的背景如贷。 -
4.最后,您通過(guò)傳入圖片名稱(chēng)來(lái)創(chuàng)建player精靈到踏。 您將其從屏幕的左邊緣垂直居中放置10%杠袱,并將其添加到場(chǎng)景中。
生成并運(yùn)行您的應(yīng)用窝稿; 瞧楣富,女士們,先生們伴榔,忍者進(jìn)入了大樓纹蝴! :]
移動(dòng)怪物
忍者需要生活中的目標(biāo)庄萎,因此您需要在場(chǎng)景中添加一些怪物,忍者才能戰(zhàn)斗塘安。 為了讓事情變得更加有趣糠涛,您希望怪物們四處走動(dòng)-否則,這并不會(huì)帶來(lái)太大的挑戰(zhàn)兼犯! 您將在屏幕右側(cè)的右邊創(chuàng)建怪物忍捡,并為它們?cè)O(shè)置一個(gè)動(dòng)作,告訴它們向左移動(dòng)免都。
首先锉罐,打開(kāi)HelloWorldScene.h
并添加以下方法聲明:
void addMonster(float dt);
然后在HelloWorldScene.cpp
中添加以下方法實(shí)現(xiàn):
void HelloWorld::addMonster(float dt) {
auto monster = Sprite::create("monster.png");
// 1
auto monsterContentSize = monster->getContentSize();
auto selfContentSize = this->getContentSize();
int minY = monsterContentSize.height/2;
int maxY = selfContentSize.height - monsterContentSize.height/2;
int rangeY = maxY - minY;
int randomY = (rand() % rangeY) + minY;
monster->setPosition(Vec2(selfContentSize.width + monsterContentSize.width/2, randomY));
this->addChild(monster);
// 2
int minDuration = 2.0;
int maxDuration = 4.0;
int rangeDuration = maxDuration - minDuration;
int randomDuration = (rand() % rangeDuration) + minDuration;
// 3
auto actionMove = MoveTo::create(randomDuration, Vec2(-monsterContentSize.width/2, randomY));
auto actionRemove = RemoveSelf::create();
monster->runAction(Sequence::create(actionMove,actionRemove, nullptr));
}
它相對(duì)簡(jiǎn)單,但是上面的代碼是這樣的:
- 1.該方法的第一部分與您之前對(duì)player進(jìn)行的操作類(lèi)似:它會(huì)創(chuàng)建一個(gè)怪物(monster)精靈并將其放置在屏幕外的右側(cè)绕娘。 它將y位置設(shè)置為隨機(jī)值脓规,以保持有趣的狀態(tài)。
- 2.接下來(lái)险领,該方法會(huì)計(jì)算要添加到個(gè)怪物(monster)身上的動(dòng)作的隨機(jī)持續(xù)時(shí)間侨舆,介于2到4秒之間。 每個(gè)怪物(monster)都會(huì)在屏幕上移動(dòng)相同的距離绢陌,因此改變持續(xù)時(shí)間會(huì)導(dǎo)致怪物(monster)的速度隨機(jī)挨下。
- 3.最后,該方法創(chuàng)建一個(gè)動(dòng)作脐湾,該動(dòng)作使怪物(monster)從右到左在屏幕上移動(dòng)臭笆,并指示怪物(monster)運(yùn)行它。 下面將對(duì)此進(jìn)行詳細(xì)說(shuō)明秤掌。
Cocos2d-x提供了許多非常方便的內(nèi)置動(dòng)作愁铺,可幫助您隨時(shí)間輕松地更改精靈的狀態(tài),包括移動(dòng)動(dòng)作闻鉴,旋轉(zhuǎn)動(dòng)作茵乱,淡入淡出動(dòng)作,動(dòng)畫(huà)動(dòng)作等孟岛。 在這里瓶竭,您對(duì)怪物使用三個(gè)動(dòng)作:
-
MoveTo
:在特定的時(shí)間內(nèi)將對(duì)象從一個(gè)點(diǎn)移動(dòng)到另一點(diǎn)。 -
RemoveSelf
:從其父節(jié)點(diǎn)刪除節(jié)點(diǎn)渠羞,從而有效地將其從場(chǎng)景中“刪除”斤贰。 在這種情況下,您可以使用該操作將不再可見(jiàn)的怪物從場(chǎng)景中移除次询。 這很重要腋舌,因?yàn)榉駝t您將有無(wú)窮無(wú)盡的怪物供不應(yīng)求,并最終會(huì)消耗掉設(shè)備的所有資源渗蟹。 - Sequence:讓您一次執(zhí)行一系列其他操作块饺。 這意味著您可以讓怪物在場(chǎng)景中移動(dòng),并在到達(dá)目的地時(shí)將其從屏幕上移開(kāi)雌芽。
在讓忍者進(jìn)城之前授艰,還有最后一件事要做-您需要實(shí)際調(diào)用創(chuàng)建怪物的方法! 為了使事情變得有趣世落,您將創(chuàng)建不斷產(chǎn)生的怪物淮腾。
只需在return
語(yǔ)句之前,將以下代碼添加到HelloWorld:: init
的末尾:
srand((unsigned int)time(nullptr));
this->schedule(schedule_selector(HelloWorld::addMonster), 1.5);
srand((unsigned int)time(nullptr));
播種隨機(jī)數(shù)生成器屉佳。 如果您不這樣做谷朝,那么每次您運(yùn)行該應(yīng)用程序時(shí),您的隨機(jī)數(shù)都會(huì)相同武花。 感覺(jué)不會(huì)很隨意圆凰,是嗎? :]
然后体箕,將HelloWorld::addMonster
傳遞到schedule
方法中专钉,該方法每1.5
秒調(diào)用一次addMonster()
。
在這里累铅,Cocos2d-x
利用了C ++
指向成員函數(shù)的指針跃须。 如果您不了解其工作原理,請(qǐng)參閱ioscpp以獲取更多信息娃兽。
而已菇民! 建立并運(yùn)行您的項(xiàng)目; 您現(xiàn)在應(yīng)該可以看到妖怪在屏幕上快樂(lè)地(或憤怒地(視情況而定M洞ⅰ))移動(dòng):
射擊彈丸
您勇敢的小忍者需要一種保護(hù)自己的方法第练。 在游戲中實(shí)現(xiàn)火力的方法有很多,但是在此項(xiàng)目中轻要,您將讓用戶(hù)單擊或輕擊屏幕以沿單擊或輕擊的方向發(fā)射彈丸复旬。 ew! :]
為簡(jiǎn)化起見(jiàn)冲泥,您將通過(guò)MoveTo
操作實(shí)現(xiàn)這一點(diǎn)-但這意味著您需要做一些數(shù)學(xué)運(yùn)算驹碍。
MoveTo
操作需要射彈的目標(biāo)位置,但是您不能直接使用輸入位置凡恍,因?yàn)樵擖c(diǎn)僅代表相對(duì)于玩家的射擊方向志秃。 您想讓子彈一直移動(dòng)到該點(diǎn),直到子彈到達(dá)屏幕外的最終目的地嚼酝。
這是說(shuō)明問(wèn)題的圖片:
從原點(diǎn)到觸摸位置的x和y偏移會(huì)創(chuàng)建一個(gè)小三角形浮还; 您只需要制作一個(gè)具有相同比率的大三角形即可,并且您知道要使其中一個(gè)端點(diǎn)不在屏幕上闽巩。
利用Cocos2d-x
隨附的矢量數(shù)學(xué)例程钧舌,可以輕松執(zhí)行這些計(jì)算担汤。 但是,在計(jì)算移動(dòng)位置之前洼冻,您需要啟用輸入事件處理功能才能弄清楚用戶(hù)觸摸的位置崭歧!
將以下代碼添加到HelloWorld:: init
的末尾,就在return
語(yǔ)句的上方:
auto eventListener = EventListenerTouchOneByOne::create();
eventListener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(eventListener, _player);
Cocos2d-x版本3及更高版本使用EventDispatcher
來(lái)調(diào)度各種事件撞牢,例如觸摸率碾,加速計(jì)和鍵盤(pán)事件。
注意:在整個(gè)討論中屋彪,術(shù)語(yǔ)“觸摸”是指觸摸設(shè)備上的點(diǎn)擊以及桌面上的點(diǎn)擊所宰。 Cocos2d-x使用相同的方法來(lái)處理兩種類(lèi)型的事件。
為了從EventDispatcher
接收事件畜挥,您需要注冊(cè)一個(gè)EventListener
仔粥。 觸摸事件偵聽(tīng)器有兩種類(lèi)型:
-
EventListenerTouchOneByOne
:此類(lèi)型為每個(gè)觸摸事件調(diào)用一次您的回調(diào)方法。 -
EventListenerTouchAllAtOnce
:此類(lèi)型對(duì)所有觸摸事件調(diào)用一次您的回調(diào)方法砰嘁。
觸摸事件偵聽(tīng)器支持四個(gè)回調(diào)件炉,但是您只需要為您關(guān)心的事件綁定方法。
-
onTouchBegan
:在手指首次觸摸屏幕時(shí)調(diào)用矮湘。 如果使用的是EventListenerTouchOneByOne
斟冕,則必須返回true才能接收其他三個(gè)觸摸事件中的任何一個(gè)。 -
onTouchMoved
:當(dāng)您的手指已經(jīng)觸摸屏幕而沒(méi)有離開(kāi)屏幕而移動(dòng)時(shí)調(diào)用缅阳。 -
onTouchEnded
:當(dāng)手指離開(kāi)屏幕時(shí)調(diào)用磕蛇。 -
onTouchCancelled
:在某些情況下被調(diào)用以停止事件處理,例如當(dāng)您觸摸屏幕時(shí)十办,然后像電話之類(lèi)的中斷應(yīng)用程序秀撇。
在這個(gè)游戲中,您實(shí)際上只在乎何時(shí)發(fā)生觸摸向族。 聲明您的回調(diào)以在HelloWorldScene.h
中接收觸摸通知呵燕,如下所示:
bool onTouchBegan(Touch *touch, Event *unused_event);
然后在HelloWorldScene.cpp
中實(shí)現(xiàn)您的回調(diào):
bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event) {
// 1 - Just an example for how to get the _player object
//auto node = unused_event->getCurrentTarget();
// 2
Vec2 touchLocation = touch->getLocation();
Vec2 offset = touchLocation - _player->getPosition();
// 3
if (offset.x < 0) {
return true;
}
// 4
auto projectile = Sprite::create("projectile.png");
projectile->setPosition(_player->getPosition());
this->addChild(projectile);
// 5
offset.normalize();
auto shootAmount = offset * 1000;
// 6
auto realDest = shootAmount + projectile->getPosition();
// 7
auto actionMove = MoveTo::create(2.0f, realDest);
auto actionRemove = RemoveSelf::create();
projectile->runAction(Sequence::create(actionMove,actionRemove, nullptr));
return true;
}
上面的方法正在進(jìn)行很多工作,因此請(qǐng)花點(diǎn)時(shí)間逐步檢查一下件相。
- 1.第一行已被注釋掉再扭,但是它在那里向您展示了如何訪問(wèn)作為第二個(gè)參數(shù)傳遞給
addEventListenerWithSceneGraphPriority(eventListener, _player)
的_player
對(duì)象。 - 2.您可以在此處獲得場(chǎng)景坐標(biāo)系內(nèi)觸摸的坐標(biāo)夜矗,然后計(jì)算該點(diǎn)與播放器當(dāng)前位置的偏移量泛范。這是
Cocos2d-x
中向量數(shù)學(xué)的一個(gè)示例。 - 3.如果
offset
的x
值為負(fù)紊撕,則表示玩家正在嘗試向后射擊罢荡。在此游戲中不允許這樣做(真正的忍者永不回頭!),因此只需返回而無(wú)需發(fā)射彈丸区赵。 - 4.在玩家的位置上創(chuàng)建一個(gè)彈丸惭缰,并將其添加到場(chǎng)景中。
- 5.然后笼才,您調(diào)用
normalize()
將偏移量轉(zhuǎn)換為單位向量从媚,該向量是長(zhǎng)度為1的向量。將其乘以1000可得到長(zhǎng)度為1000的向量患整,該向量指向用戶(hù)點(diǎn)擊的方向。為什么是1000喷众?該長(zhǎng)度應(yīng)足以以該分辨率延伸超出屏幕邊緣:] - 6.將向量添加到彈丸的位置即可得到目標(biāo)位置各谚。
-
7.最后,創(chuàng)建一個(gè)動(dòng)作到千,將彈丸移至目標(biāo)位置超過(guò)兩秒鐘昌渤,然后將其從場(chǎng)景中移除。
生成并運(yùn)行您的應(yīng)用憔四;觸摸屏幕膀息,使您的忍者向即將來(lái)臨的部落射擊!
碰撞檢測(cè)與物理
現(xiàn)在您已經(jīng)擁有飛鏢飛來(lái)飛去的地方-但您的忍者真正想要做的就是放下一些零頭了赵。 因此潜支,您需要一些代碼來(lái)檢測(cè)彈丸何時(shí)與目標(biāo)相交。
關(guān)于Cocos2d-x
的一件好事是它內(nèi)置了一個(gè)物理引擎柿汛! 物理引擎不僅對(duì)于模擬逼真的運(yùn)動(dòng)非常有用冗酿,而且對(duì)于檢測(cè)碰撞也非常有用。 您將使用Cocos2d-x的物理引擎來(lái)確定怪物和投射物何時(shí)發(fā)生碰撞络断。
首先在HelloWorld::createScene
的實(shí)現(xiàn)上方裁替,向HelloWorldScene.cpp
添加以下代碼:
enum class PhysicsCategory {
None = 0,
Monster = (1 << 0), // 1
Projectile = (1 << 1), // 2
All = PhysicsCategory::Monster | PhysicsCategory::Projectile // 3
};
些位掩碼定義了您需要的物理類(lèi)別-并非雙關(guān)語(yǔ)! :]在這里貌笨,您已經(jīng)創(chuàng)建了兩種類(lèi)型弱判,Monster
和Projectile
,以及兩個(gè)特殊值锥惋,用于指定沒(méi)有類(lèi)型或所有類(lèi)型昌腰。 您將使用這些類(lèi)別為對(duì)象分配類(lèi)型,從而允許您指定允許哪些對(duì)象類(lèi)型相互碰撞净刮。
注意:您可能想知道這種奇特的語(yǔ)法是什么剥哑。 Cocos2d-x上的類(lèi)別只是一個(gè)32位整數(shù)。 此語(yǔ)法將整數(shù)中的特定位設(shè)置為代表不同的類(lèi)別淹父,最多給您32種可能的類(lèi)別株婴。 在這里,您將第一位設(shè)置為指示怪物,將下一位設(shè)置為代表彈丸困介,依此類(lèi)推大审。
接下來(lái),用以下代碼替換HelloWorld::createScene
的第一行:
auto scene = Scene::createWithPhysics();
scene->getPhysicsWorld()->setGravity(Vec2(0,0));
scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
這將創(chuàng)建一個(gè)啟用了物理的場(chǎng)景座哩。 Cocos2d-x
使用PhysicsWorld
來(lái)控制其物理模擬徒扶。 在這里,您可以在兩個(gè)方向上將世界的重力設(shè)置為零根穷,這實(shí)際上會(huì)禁用重力姜骡,并且可以啟用調(diào)試?yán)L圖以查看物理物體。 在對(duì)物理相互作用進(jìn)行原型設(shè)計(jì)時(shí)屿良,啟用調(diào)試?yán)L圖很有幫助圈澈,這樣可以確保事情正常進(jìn)行。
在HelloWorld::addMonster
中尘惧,在創(chuàng)建怪物精靈的第一行之后添加以下代碼:
// 1
auto monsterSize = monster->getContentSize();
auto physicsBody = PhysicsBody::createBox(Size(monsterSize.width , monsterSize.height),
PhysicsMaterial(0.1f, 1.0f, 0.0f));
// 2
physicsBody->setDynamic(true);
// 3
physicsBody->setCategoryBitmask((int)PhysicsCategory::Monster);
physicsBody->setCollisionBitmask((int)PhysicsCategory::None);
physicsBody->setContactTestBitmask((int)PhysicsCategory::Projectile);
monster->setPhysicsBody(physicsBody);
這是上面的代碼的作用:
- 1.為精靈創(chuàng)建一個(gè)
PhysicsBody
康栈。物理實(shí)體代表Cocos2d-x
物理仿真中的對(duì)象,您可以使用任何形狀來(lái)定義它們喷橙。在這種情況下啥么,可以使用與精靈大小相同的矩形作為怪獸的近似值。您可以使用更精確的形狀贰逾,但是更簡(jiǎn)單的形狀足以滿(mǎn)足大多數(shù)游戲和更高的性能要求悬荣。 - 2.將精靈設(shè)置為
動(dòng)態(tài)
。這意味著物理引擎不會(huì)向怪物施加力似踱。相反隅熙,您將直接通過(guò)之前創(chuàng)建的MoveTo
操作對(duì)其進(jìn)行控制。 - 3.在這里核芽,您可以設(shè)置類(lèi)別囚戚,碰撞和接觸測(cè)試位掩碼:
- 類(lèi)別:定義對(duì)象的類(lèi)型–
Monster
。 - 碰撞:定義在碰撞期間應(yīng)以何種類(lèi)型的對(duì)象物理影響該對(duì)象-在這種情況下為
None
轧简。因?yàn)榇藢?duì)象也是動(dòng)態(tài)的驰坊,所以此字段無(wú)效,但出于完整性考慮哮独,在此將其包括在內(nèi)拳芙。 - 接觸測(cè)試:定義碰撞應(yīng)通過(guò)其生成通知的對(duì)象類(lèi)型-
Projectile
。您將在本教程的稍后部分注冊(cè)并處理這些通知皮璧。 - 最后舟扎,將物理物體分配給怪物。
接下來(lái)悴务,將以下代碼添加到HelloWorld::onTouchBegan
中睹限,緊接設(shè)置彈丸位置的行之后:
- 類(lèi)別:定義對(duì)象的類(lèi)型–
auto projectileSize = projectile->getContentSize();
auto physicsBody = PhysicsBody::createCircle(projectileSize.width/2 );
physicsBody->setDynamic(true);
physicsBody->setCategoryBitmask((int)PhysicsCategory::Projectile);
physicsBody->setCollisionBitmask((int)PhysicsCategory::None);
physicsBody->setContactTestBitmask((int)PhysicsCategory::Monster);
projectile->setPhysicsBody(physicsBody);
這與您為怪物執(zhí)行的物理設(shè)置非常相似譬猫,不同的是它使用圓形而不是矩形來(lái)定義物理物體。 請(qǐng)注意羡疗,并不是絕對(duì)必要設(shè)置接觸測(cè)試位掩碼染服,因?yàn)楣治镆呀?jīng)在檢查與射彈的碰撞,但這有助于使代碼的意圖更加清晰叨恨。
立即構(gòu)建并運(yùn)行您的項(xiàng)目柳刮; 您會(huì)看到紅色形狀疊加在物理物體上,如下所示:
射彈被設(shè)置為可以擊中怪物痒钝,因此當(dāng)它們碰撞時(shí)秉颗,您需要將它們都移除岂昭。
還記得早先的物理學(xué)世界嗎蝎亚? 好吧,您可以在其上設(shè)置一個(gè)聯(lián)系人代表霎奢,以在兩個(gè)物理物體碰撞時(shí)得到通知益愈。 在那里,您將編寫(xiě)一些代碼來(lái)檢查對(duì)象的類(lèi)別夷家,如果它們是怪物和彈丸蒸其,則可以使其蓬勃發(fā)展!
首先库快,將以下方法聲明添加到HelloWorldScene.h
中:
bool onContactBegan(PhysicsContact &contact);
這是您注冊(cè)以接收聯(lián)系事件的方法摸袁。
接下來(lái),在HelloWorldScene.cpp
中實(shí)現(xiàn)以下方法:
bool HelloWorld::onContactBegan(PhysicsContact &contact) {
auto nodeA = contact.getShapeA()->getBody()->getNode();
auto nodeB = contact.getShapeB()->getBody()->getNode();
nodeA->removeFromParent();
nodeB->removeFromParent();
return true;
}
傳遞給此方法的PhysicsContact
包含有關(guān)碰撞的信息义屏。 在這個(gè)游戲中靠汁,您知道唯一會(huì)碰撞的對(duì)象是怪物和射彈。 因此闽铐,您將使節(jié)點(diǎn)參與碰撞并將其從場(chǎng)景中移除蝶怔。
最后,您需要注冊(cè)以接收聯(lián)系人通知兄墅。 在return
語(yǔ)句之前踢星,將以下行添加到HelloWorld ::init
的末尾:
auto contactListener = EventListenerPhysicsContact::create();
contactListener->onContactBegin = CC_CALLBACK_1(HelloWorld::onContactBegan, this);
this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(contactListener, this);
這將創(chuàng)建一個(gè)聯(lián)系人偵聽(tīng)器,注冊(cè)HelloWorld::onContactBegan
以接收事件并將偵聽(tīng)器添加到EventDispatcher
隙咸。 現(xiàn)在沐悦,只要兩個(gè)物理物體發(fā)生碰撞并且它們的類(lèi)別位掩碼與它們的接觸測(cè)試位掩碼匹配,EventDispatcher
就會(huì)調(diào)用onContactBegan
五督。
生成并運(yùn)行您的應(yīng)用藏否; 現(xiàn)在,當(dāng)您的彈丸與目標(biāo)相交時(shí)充包,它們應(yīng)該消失:
畫(huà)龍點(diǎn)睛
您現(xiàn)在已經(jīng)快要制作出一款可行(但非常簡(jiǎn)單)的游戲了副签。 您只需要添加一些聲音效果和音樂(lè)(因?yàn)槟姆N游戲都沒(méi)有聲音!)和一些簡(jiǎn)單的游戲邏輯即可。
Cocos2d-x
帶有一個(gè)稱(chēng)為CocosDenshion
的簡(jiǎn)單音頻引擎继薛,您將使用它來(lái)播放聲音修壕。
注意:Cocos2d-x還包括第二個(gè)音頻引擎,旨在代替簡(jiǎn)單的音頻引擎模塊遏考。 但是慈鸠,它仍處于試驗(yàn)階段,并且不適用于所有受支持的平臺(tái)灌具,因此您將不在此處使用它青团。
該項(xiàng)目已經(jīng)包含了一些很酷的背景音樂(lè)以及您之前導(dǎo)入的超贊的“ pew-pew”音效。 您只需要玩它們咖楣!
為此督笆,在其他#include
語(yǔ)句之后,將以下代碼添加到HelloWorldScene.cpp
的頂部:
using namespace CocosDenshion;
這將導(dǎo)入SimpleAudioEngine
模塊诱贿,并指定您將在此文件中使用CocosDenshion
命名空間娃肿。
接下來(lái),將以下定義添加到PhysicsCategory
枚舉上方的HelloWorldScene.cpp
:
#define PEW_PEW_SFX "pew-pew-lei.mp3"
在這里珠十,您定義了兩個(gè)字符串常量:BACKGROUND_MUSIC_SFX
和PEW_PEW_SFX
料扰。 這只是將文件名放在一個(gè)位置,這使得以后更容易更改它們焙蹭。 像這樣組織代碼(甚至使用完全獨(dú)立的文件甚至更好)晒杈,可以更輕松地支持特定于平臺(tái)的更改,例如在iPhone
上使用.mp3
文件孔厉,在Windows Phone
上使用.wav
文件拯钻。
現(xiàn)在,在return
語(yǔ)句之前撰豺,將以下行添加到HelloWorld::ini
t的末尾:
SimpleAudioEngine::getInstance()->playBackgroundMusic(BACKGROUND_MUSIC_SFX, true);
場(chǎng)景建立后粪般,即會(huì)開(kāi)始播放背景音樂(lè)。
至于聲音效果污桦,請(qǐng)將以下行添加到HelloWorld::onTouchBegan
的return
語(yǔ)句上方:
SimpleAudioEngine::getInstance()->playEffect(PEW_PEW_SFX);
每當(dāng)忍者發(fā)動(dòng)攻擊時(shí)刊驴,這都會(huì)起到很好的“ pew-pew”聲音效果。 很方便寡润,是嗎捆憎? 您僅需一行代碼即可播放聲音效果。
生成并運(yùn)行梭纹,并享受您的時(shí)髦音樂(lè)躲惰!
然后去哪兒?
這是上面教程中完成的示例游戲变抽。
希望您喜歡Cocos2d-x础拨,并從中獲得靈感來(lái)制作自己的游戲氮块! 要了解有關(guān)Cocos2d-x的更多信息,請(qǐng)訪問(wèn)Cocos2d-x網(wǎng)站以獲取大量學(xué)習(xí)資源诡宗。
如果對(duì)本教程有任何疑問(wèn)或意見(jiàn)滔蝉,請(qǐng)加入下面的討論!
關(guān)于本項(xiàng)目在其他系統(tǒng)如Windows上的移植
我使用的是Window7系統(tǒng)塔沃,Cocos2d-x的版本是3.17.2蝠引,Python是2.7.18
使用VS2017
打開(kāi)項(xiàng)目下的SimpleGame\proj.win32\文件夾下的SimpleGame.sln
,然后編譯運(yùn)行蛀柴,前提是需要配置好Cocos2d-x 3.17.2的開(kāi)發(fā)環(huán)境螃概,關(guān)于環(huán)境搭建可以參考我之前寫(xiě)的一篇博客:Win10+Python2.7.14+cocos2d-x-3.17.2+VS2017環(huán)境搭建,下面是我在VS2017中運(yùn)行本項(xiàng)目的截圖:
最終的項(xiàng)目源代碼我已經(jīng)托管到Github和Gitee上,需要的話執(zhí)行如下命令自雀爰病:
從github上獲取cocos2d-x-tutorial源代碼
git clone https://github.com/ccf19881030/Cocos2d-x-Tutorial.git
從gitee碼云上獲取cocos2d-x-tutorial源代碼
git clone https://gitee.com/havealex/cocos2d-x-tutorial.git