您的位置:首页 > 移动开发 > Cocos引擎

cocos2d-x 2.2.1制作一个简单的游戏

2014-01-08 09:31 423 查看
一、用python创建一个cocos2d-x-2.2.1工程

打开cmd命令行cd 到cocos2d-x-2.2.1\tools\project-creator目录:

1 2 3
e:
cd
E:\cocos2d-x-2.2.1\tools\project-creator
python create_project.py -project MyDemo -package com.blogchen.mydemo -language cpp
解释下python create_project.py -project MyDemo -package com.blogchen.mydemo -language cpp这句代码的参数。

需要我们关注的只有两个,一个是MyDemo,这个MyDemo就是你们的工程名,随便取,然后是com.blogchen.mydemo学过android的一眼就知道com.blogchen.mydemo的作用—包名,这个其实也是随便取的,但是一般来说是域名的倒置,当然你取x.o.x.o也是可以的,但是这个有个要注意的是,要保证唯一性,也就是你确定别人不会用这个名字,因为这个当编译为android包时,就代表了android应用的唯一标识,如果你的这个名字和别人的包名字相重,那么你的apk将无法和别人的apk共存在手机里面,加上现在的应用市场都有验证机器,也就代表你的apk无法发布到应用市场去。

命令执行成功后的信息:

?
那么在cocos2d-x-2.2.1\projects目录下就能找到你的工程了。进入cocos2d-x-2.2.1\projects\MyDemo\proj.win32



双击MyDemo.sln:



这个就是我们的工程了,Ctrl+F5试试:



嗬嗬嗬嗬,完毕,果然新版本配置越来越方便了。

然而,有朋友可能会抱怨:每次命令行建立工程太麻烦了啊。懒惰使人进步,于是就用批处理来解决吧。代码如下:

?
运行效果如下:

?
大家自行建立xxx.cmd文件,然后把代码复制过去即可,路径根据自己的环境改变一下就可以。

二、游戏素材http://download.csdn.net/detail/akof1314/4857315在这个链接里可以下载到

三、游戏需要一个白色的背景,最简单的方法是使用CCLayerColor,将HelloWorldScene.h文件"HelloWorld"类改为如下:

1

class HelloWorld :
public cocos2d::CCLayerColor
首先添加玩家,让玩家位于左边屏幕中间,将HelloWorldScene.cpp文件的init函数,改为如下:

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);

}
接下去就是定时创建怪物,在init函数返回之前,安装定时器,每秒执行一次,代码如下:

1

this->schedule(schedule_selector(HelloWorld::gameLogic),1.0);
增加gameLogic方法,代码如下:

1

2

3

4

void HelloWorld::gameLogic(float dt )

{

this->addMonster();

}
7.编译运行,可以看到右边怪物定时增加,并且以不同的速度向左边移动,如下图所示:



8.接着让玩家可以射击子弹,当用户在屏幕点击时,就让玩家往点击的方向进行发送子弹,用户的屏幕点击点并不是子弹移动的最终地,借用原文的一张图片来说明:



要让层可以支持触摸,需要在init方法,添加如下代码:

1

this->setTouchEnabled(true);
然后重载ccTouchesEnded方法,代码如下:

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;
五、接下来添加怪物,并且让怪物可以移动,我们在屏幕右边创建怪物,建立动作让它们向左移动,增加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);

}
接下去就是定时创建怪物,在init函数返回之前,安装定时器,每秒执行一次,代码如下:

1

this->schedule(schedule_selector(HelloWorld::gameLogic),1.0);
增加gameLogic方法,代码如下:

1

2

3

4

void HelloWorld::gameLogic(float dt )

{

this->addMonster();

}
六、编译运行,可以看到右边怪物定时增加,并且以不同的速度向左边移动,如下图所示:



七、接着让玩家可以射击子弹,当用户在屏幕点击时,就让玩家往点击的方向进行发送子弹,用户的屏幕点击点并不是子弹移动的最终地,借用原文的一张图片来说明:



要让层可以支持触摸,需要在init方法,添加如下代码:

1

this->setTouchEnabled(true);
然后重载ccTouchesEnded方法,代码如下:
重载ccTouchesEnded方法可能会抛红,加一个USING_NS_CC;在头文件和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

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像素,则计算出飞行总时间。之后就是让子弹执行给定的飞行动作,以及之后的删除自身调用。

八、编译运行,往屏幕点击,可以看到子弹发射出去,如下图所示:



九、当子弹碰到怪物时,怪物被消灭,子弹消失,即碰撞检测。需要在场景中跟踪目标和子弹,在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();
修改addMonster函数,为怪物精灵添加标签,并加入到数组,代码如下:

1

2

monster->setTag(1);

_monsters->addObject(monster);
修改ccTouchesEnded函数,为子弹精灵添加标签,并加入到数组,代码如下:

1

2

projectile->setTag(2);

_projectiles->addObject(projectile);
然后修改spriteMoveFinished函数,增加如下代码:

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(projectile->boundingBox().intersectsRect(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));
十、编译运行,这时当子弹和怪物碰撞时,它们就会消失;

十一、添加音效,在init函数添加背景音乐,代码如下:

1

CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic("background-music-aac.wav");
ccTouchesEnded函数,添加子弹音效,代码如下:

1

CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect("pew-pew-lei.wav");
十二、接下来,创建一个新的场景,来指示"You Win"或者"You Lose"。右键 工程,"Add"→"Class..."→"C++"→"Add","Base class"为CCLayerColor,"Class name"为GameOverLayer,如下图所示:



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场景中。

十三、最后,为游戏添加一些游戏逻辑。记录玩家消灭怪物的数量,进而决定该玩家输赢。在HelloWorldScene.h文件中,添加如下:

1

int _monstersDestroyed;
HelloWorldScene.cpp文件,HelloWorld()构造函数,添加如下代码:

1

_monstersDestroyed = 0;
添加头文件引用:

1

#include
"GameOverLayer.h"
update定时函数中,monstersToDelete循环removeChild(monster, true)的后面添加被消灭怪物的计数,并判断胜利条件,代码如下:

1

2

3

4

5

6

_monstersDestroyed++;

if (_monstersDestroyed >
30)

{

CCScene *gameOverScene = GameOverLayer::sceneWithWon(true);

CCDirector::sharedDirector()->replaceScene(gameOverScene);

}
最后为玩家添加失败条件,规定只要有一只怪物跑到左边屏幕里,则玩家失败,在spriteMoveFinished函数里,sprite->getTag() == 1条件的后面,添加如下:

1

2

CCScene *gameOverScene = GameOverLayer::sceneWithWon(false);

CCDirector::sharedDirector()->replaceScene(gameOverScene);
十四、编译并运行,到此已完成了一个简单的游戏,包含音效,并带有胜利和失败的结束。游戏效果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: