使用Cocos2d-x 3.0和物理引擎制作简单的platformer游戏
来源:互联网 发布:张民弢 知乎 编辑:程序博客网 时间:2024/06/13 20:18
前言
本教程建立在上一篇教程的基础之上,所以,在继续之前,建议你先看完《使用Cocos2d-x 3.0和物理引擎制作滚动背景》。
内容大纲
我将在本教程中覆盖下面的内容:
1. 简单的面向对象游戏设计
2. 用户输入和touch检测
3. 给游戏对象施加力,使之移动和跳跃
4. 碰撞检测
本教程建立在上一篇教程的基础之上,所以,在继续之前,建议你先看完《使用Cocos2d-x 3.0和物理引擎制作滚动背景》。
内容大纲
我将在本教程中覆盖下面的内容:
1. 简单的面向对象游戏设计
2. 用户输入和touch检测
3. 给游戏对象施加力,使之移动和跳跃
4. 碰撞检测
简单的面向对象设计
这个教程是个非常简单的平台游戏,只有一些简单的平台和一个圆形的主角。说明一下,我在这里使用的是上一个教程中的TileMap编辑器来制作游戏地图的,所以,你可以参照上一篇教程。本游戏示例中只有两种对象。一种是player对象,另一种是platform对象。这两种对象都继承至GameObject类。而GameObject类又继承至Sprite类,同时它包含一个type属性,用来区分不同的游戏对象。把游戏对象都继承至同一基类有一个好处,就是在做碰撞检测的时候,可以直接强制转换过来。下面是GameObject类的代码,它从Sprite类继承过来的。同时把它的type初始化为kGameObjectNone。(这是一个枚举类型,它定义在Constants.h中,本教程不会显示它的实现,但是大家可以在后面下载的源码中找到其实现)
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
// GameObject.h
#include "cocos2d.h"
#include "Constants.h"
USING_NS_CC;
class
GameObject :
public
Sprite
{
public
:
GameObjectType type;
virtual
bool
init();
CREATE_FUNC(GameObject);
};
////////////////////////////////////////////////////////
// GameObject.cpp
#include "GameObject.h"
bool
GameObject::init()
{
if
(!Node::init())
{
return
false
;
}
return
true
;
}
接下来是我们的Player类。
Player主要负责创建它自己的box2d世界中的body,当你调用createBox2dObject的时候,就会创建相应的body,同时把它加到world中去。同时,player类还包含使player往右移动和跳跃的方法,我们会在教程的后面讨论。
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
#include "cocos2d.h"
#include "GameObject.h"
USING_NS_CC;
class
Player :
public
GameObject
{
public
:
PhysicsBody* body;
void
createdObject();
void
jump();
void
moveRight();
virtual
bool
init();
CREATE_FUNC(Player);
};
///////////////////////////////////////////////////////
#include "Player.h"
#include "Constants.h"
bool
Player::init()
{
if
(!GameObject::init())
{
return
false
;
}
return
true
;
}
void
Player::createdObject()
{
body = PhysicsBody::createCircle(0.7f);
body->getShape(0)->setRestitution(1.0f);
body->getShape(0)->setFriction(1.0f);
body->getShape(0)->setDensity(1.0f);
body->setRotationEnable(
false
);
this
->setPhysicsBody(body);
}
void
Player::moveRight()
{
Vect impulse = Vect(50.0f, 0.0f);
body->applyImpulse(impulse);
}
void
Player::jump()
{
Vect impulse = Vect(0.0f, 100.0f);
body->applyImpulse(impulse);
}
下面几行行代码定义在GameScene的onEnter方法中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void
GameScene::onEnter()
{
Layer::onEnter();
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(
true
);
listener->onTouchBegan = CC_CALLBACK_2(GameScene::onTouchBegan,
this
);
auto contactListener = EventListenerPhysicsContact::create();
contactListener->onContactBegin = CC_CALLBACK_2(GameScene::onContactBegin,
this
);
auto dispatcher = Director::getInstance()->getEventDispatcher();
dispatcher->addEventListenerWithSceneGraphPriority(listener,
this
);
dispatcher->addEventListenerWithSceneGraphPriority(contactListener,
this
);
}
下面的方法是在你鼠标点击模拟器或者手触摸设备屏幕的时候被调用的,也就是touch事件。我们需要把touch坐标点转换成cocos2d的坐标点。然后,我们判断,当单击的点在右半屏幕的时候,就让player往右移动。当单击左半边屏幕的时候,就让player跳起来。可以跳到platfrom上哦,呵呵。如果在下面起跳,会撞到头。这可能不是我们想要的结果。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool
GameScene::onTouchBegan(Touch *touch, Event *event)
{
Point touchLocation =
this
->convertToWorldSpace(
this
->convertTouchToNodeSpace(touch));
if
(touchLocation.x >= screenSize.width / 2)
{
player->moveRight();
}
else
{
player->jump();
}
return
TRUE;
}
给游戏对象施加力,使之移动和跳跃
1
2
3
4
5
6
7
8
9
10
11
void
Player::moveRight()
{
Vect impulse = Vect(50.0f, 0.0f);
body->applyImpulse(impulse);
}
void
Player::jump()
{
Vect impulse = Vect(0.0f, 100.0f);
body->applyImpulse(impulse);
}
Wrap-up and Loose Ends
下面是GameScene类的实现。这里面使用的技术大家应该都接触过了,如果不清楚,可以参考我翻译的其它教程,或者在下方留言。可能需要指出来的是碰撞检测的代码,大家可以花点时间看看。
GameScene.h
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
#include "cocos2d.h"
#include "Player.h"
USING_NS_CC;
class
GameScene :
public
Layer
{
public
:
Size screenSize;
PhysicsWorld* m_world;
Player* player;
TMXTiledMap* tileMapNode;
void
setPhyWorld(PhysicsWorld* world){ m_world = world; };
void
makeBox2dObjAt(Point p, Size size,
bool
d,
float
r,
float
friction,
float
density,
float
restitution);
void
drawCollisionTiles();
void
addScrollingBackgroundWithTileMap();
void
virtual
update(
float
dt);
static
cocos2d::Scene* createScene();
virtual
bool
init();
virtual
void
onEnter();
bool
onTouchBegan(Touch *touch, Event *event);
bool
onContactBegin(EventCustom* event,
const
PhysicsContact& contact);
CREATE_FUNC(GameScene);
};
GameScene.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "GameScene.h"
Scene* GameScene::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::createWithPhysics();
//scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
/*Vect gravity(0.0f, -600.0f);
scene->getPhysicsWorld()->setGravity(gravity);*/
// 'layer' is an autorelease object
auto layer = GameScene::create();
layer->setPhyWorld(scene->getPhysicsWorld());
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return
scene;
}
bool
GameScene::init()
{
if
(!Layer::init())
{
return
false
;
}
// enable touches
screenSize = Director::getInstance()->getWinSize();
this
->addScrollingBackgroundWithTileMap();
this
->drawCollisionTiles();
player = (Player*)Sprite::create(
"Icon-Small.png"
);
player->retain();
player->setPosition(100.0f, 180.0f);
player->createdObject();
this
->addChild(player);
// Start main game loop
this
->scheduleUpdate();
return
true
;
}
void
GameScene::makeBox2dObjAt(Point p, Size size,
bool
d,
float
r,
float
friction,
float
density,
float
restitution)
{
auto sprite = Sprite::create();
auto body = PhysicsBody::createBox(size, PHYSICSBODY_MATERIAL_DEFAULT);
body->getShape(0)->setDensity(density);
body->getShape(0)->setFriction(friction);
body->getShape(0)->setRestitution(restitution);
body->setDynamic(d);
sprite->setPosition(p);
sprite->setPhysicsBody(body);
this
->addChild(sprite);
}
void
GameScene::drawCollisionTiles()
{
TMXObjectGroup *objects = tileMapNode->objectGroupNamed(
"Collision"
);
float
x, y, w, h;
ValueVector objectsPoint = objects->getObjects();
Value objPointMap;
for
each(objPointMap in objectsPoint)
{
ValueMap objPoint = objPointMap.asValueMap();
x = objPoint.at(
"x"
).asFloat();
y = objPoint.at(
"y"
).asFloat();
w = objPoint.at(
"width"
).asFloat();
h = objPoint.at(
"height"
).asFloat();
Point _point = Point(x + w / 2.0f, y + h / 2.0f);
Size _size = Size(w, h);
this
->makeBox2dObjAt(_point, _size,
false
, 0, 0.0f, 0.0f, 0);
}
}
void
GameScene::addScrollingBackgroundWithTileMap()
{
tileMapNode = TMXTiledMap::create(
"scroller.tmx"
);
tileMapNode->setAnchorPoint(Point(0, 0));
this
->addChild(tileMapNode);
}
void
GameScene::update(
float
dt)
{
Point pos = player->getPosition();
this
->setPosition(-1 * pos.x + 100,
this
->getPositionY());
}
void
GameScene::onEnter()
{
Layer::onEnter();
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(
true
);
listener->onTouchBegan = CC_CALLBACK_2(GameScene::onTouchBegan,
this
);
auto contactListener = EventListenerPhysicsContact::create();
contactListener->onContactBegin = CC_CALLBACK_2(GameScene::onContactBegin,
this
);
auto dispatcher = Director::getInstance()->getEventDispatcher();
dispatcher->addEventListenerWithSceneGraphPriority(listener,
this
);
dispatcher->addEventListenerWithSceneGraphPriority(contactListener,
this
);
}
bool
GameScene::onContactBegin(EventCustom* event,
const
PhysicsContact& contact)
{
return
true
;
}
bool
GameScene::onTouchBegan(Touch *touch, Event *event)
{
Point touchLocation =
this
->convertToWorldSpace(
this
->convertTouchToNodeSpace(touch));
if
(touchLocation.x >= screenSize.width / 2)
{
player->moveRight();
}
else
{
player->jump();
}
return
TRUE;
}
这里有本教程的完整源代码。
0 0
- 使用Cocos2d-x 3.0和物理引擎制作简单的platformer游戏
- 使用cocos2d-x3.0和物理引擎制作简单的platformer游戏
- Cocos2d-x物理引擎世界的使用
- 如何使用cocos2d-x3.0和物理引擎来制作一个Breakout游戏:第一部分
- 如何使用cocos2d-x3.0和物理引擎来制作一个Breakout游戏:第二部分
- Cocos2d-x 3.0 简捷的物理引擎
- 【Cocos2D游戏引擎教程】如何使用Cocos2D制作一款简单的iPhone游戏(第二部分)
- Cocos2d-x-3. X使用自带的物理引擎
- 使用cocos2d-x3.0和物理引擎制作滚动背景
- Cocos2d-x Lua引擎制作的游戏代码加密
- Box2D和Chipmunk的对比 Cocos2d-x物理引擎
- 在cocos2d-x 3.0中使用物理引擎
- 【Cocos2d-x】物理引擎使用入门
- cocos2d-x物理引擎
- cocos2d-x物理引擎
- cocos2d-x 物理引擎
- Cocos2d-x 3.0中的新物理引擎:Chipmunk和Box2d
- 怎样在cocos2d里面如何使用物理引擎box2d制作弹球游戏
- Factory Method - 工厂方法模式
- ci框架---调用非php文件作视图
- rails 数据验证
- java语言-下雪花的简单小程序
- SQL语句异常导致项目报错
- 使用Cocos2d-x 3.0和物理引擎制作简单的platformer游戏
- git push 小结
- Java Socekt 入门 一
- rails 参数传递
- 非归档模式下数据文件移动方法
- 应用层adcfgclone.pl报错,执行txkExecSetJaznCredentials.pl失败
- 并查集路径压缩
- VIM和Bash Shell的快捷键思维导图
- mysql控制台命令