coco2d-x3.2使用物理引擎Physicals制作Breakout游戏

HelloWorldScene.h

 1 #ifndef __HELLOWORLD_SCENE_H__
 2 #define __HELLOWORLD_SCENE_H__
 3
 4 #include "cocos2d.h"
 5 #include "GameOverScene.h"
 6
 7 USING_NS_CC;
 8
 9 class HelloWorld : public cocos2d::Layer
10 {
11 public:
12     static cocos2d::Scene* createScene();
13     virtual void onEnter() override;
14     virtual bool init();
15
16     CREATE_FUNC(HelloWorld);
17
18     Sprite* ball;//弹射的球
19     Sprite* paddle;//玩家控制的可移动碰撞块
20     Sprite* edgeSp;//碰撞盒子
21
22     PhysicsWorld* m_world;
23
24     void setPhyWorld(PhysicsWorld* world){ m_world = world; };
25     void tick(float dt);
26
27     bool onTouchBegan(Touch* touch, Event* event);
28     void onTouchMoved(Touch* touch, Event* event);
29     void onTouchEnded(Touch* touch, Event* event);
30
31     bool onContactBegin(const PhysicsContact& contact);
32
33 };
34
35 #endif

HelloWorldScene.cpp

  1 #include "HelloWorldScene.h"
  2
  3 USING_NS_CC;
  4
  5 Scene* HelloWorld::createScene()
  6 {
  7     auto scene = Scene::createWithPhysics();
  8     //设置Debug模式,你会看到物体的表面被线条包围,主要为了在调试中更容易地观察
  9     scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
 10
 11     Vect gravity(0.0f, 0.0f);
 12     //设置重力
 13     scene->getPhysicsWorld()->setGravity(gravity);
 14
 15     auto layer = HelloWorld::create();
 16
 17     layer->setPhyWorld(scene->getPhysicsWorld());
 18
 19     scene->addChild(layer);
 20
 21     return scene;
 22
 23 }
 24
 25 /**
 26 PHYSICSBODY_MATERIAL_DEFAULT常量是默认材质,材质是由结构体PhysicsMaterial定义的,结构体PhysicsMaterial成员有:density(密度)、friction(磨擦系数)和restitution(弹性系数)。
 27 密度可以用来计算物体的质量,密度可以为零或者为正数。
 28 摩擦系数经常会设置在0.0~1.0之间,0.0表示没有摩擦力,1.0会产生强摩擦。
 29 弹性系数的值通常设置到0.0~1.0之间,0.0表示物体不会弹起,1.0表示物体会完全反弹,即称为弹性碰撞。
 30  **/
 31 bool HelloWorld::init()
 32 {
 33     if ( !Layer::init() )
 34     {
 35         return false;
 36     }
 37
 38     auto visibleSize = Director::getInstance()->getVisibleSize();
 39     auto origin = Director::getInstance()->getVisibleOrigin();
 40
 41     edgeSp = Sprite::create();
 42     //创建一个盒子,用来碰撞
 43     //矩形的大小、设置材质、设置边的宽度
 44     auto boundBody = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3);
 45     //设置物体的弹性 0表示完全不反弹。1完全反弹
 46     boundBody->getShape(0)->setRestitution(1.0f);
 47     //设置摩擦力
 48     boundBody->getShape(0)->setFriction(0.0f);
 49     //设置密度
 50     boundBody->getShape(0)->setDensity(1.0f);
 51     edgeSp->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));
 52     edgeSp->setPhysicsBody(boundBody);
 53     this->addChild(edgeSp);
 54     edgeSp->setTag(0);
 55
 56     //CategoryBitmask, 默认值为 0xFFFFFFFF
 57     //ContactTestBitmask, 默认值为 0x00000000
 58     //CollisionBitmask, 默认值为 0xFFFFFFFF
 59     //如果采用默认的数值,碰撞是可以检测的,但是碰撞事件是不会发出的,so我们的onContactBegin就被屏蔽了
 60     //果想我们的两个物体即发生碰撞又可以检测到,不让它们&的值不等于0就ok了
 61     edgeSp->getPhysicsBody()->setCategoryBitmask(0x01);
 62     edgeSp->getPhysicsBody()->setContactTestBitmask(0x01);
 63     edgeSp->getPhysicsBody()->setCollisionBitmask(0x01);
 64
 65     ball = Sprite::create("Ball.png", Rect(0, 0, 52, 52));
 66     ball->setPosition(100, 100);
 67     //创建物体,并且物体的形状为圆形,第一参数为半径,第二个参数为物体材质
 68     //第三个参数为边的厚度,就是在Debug模式下看到的物体外面线条的厚度,默认为0
 69     auto ballBody = PhysicsBody::createCircle(ball->getContentSize().width / 2.);
 70     ballBody->getShape(0)->setRestitution(1.0f);
 71     ballBody->getShape(0)->setFriction(0.0f);
 72     ballBody->getShape(0)->setDensity(1.0f);
 73     ballBody->setGravityEnable(false);
 74     Vect force = Vect(1000000.0f, 1000000.0f);
 75     //是对物体施加一个冲量
 76     ballBody->applyImpulse(force);
 77     ball->setPhysicsBody(ballBody);
 78     ball->setTag(1);
 79     this->addChild(ball);
 80
 81     ball->getPhysicsBody()->setCategoryBitmask(0x01);
 82     ball->getPhysicsBody()->setContactTestBitmask(0x01);
 83     ball->getPhysicsBody()->setCollisionBitmask(0x01);
 84
 85     paddle = Sprite::create("Paddle.png");
 86     //创建物体,并且物体的形状为矩形
 87     auto paddleBody = PhysicsBody::createBox(paddle->getContentSize(), PHYSICSBODY_MATERIAL_DEFAULT);
 88     paddleBody->getShape(0)->setRestitution(1.0f);
 89     paddleBody->getShape(0)->setFriction(0.0f);
 90     paddleBody->getShape(0)->setDensity(10.0f);
 91     paddleBody->setGravityEnable(false);
 92     paddleBody->setDynamic(false);
 93     paddle->setPosition(visibleSize.width / 2, 50);
 94     paddle->setPhysicsBody(paddleBody);
 95     paddle->setTag(2);
 96     this->addChild(paddle);
 97
 98     for (int i = 0; i < 4; i++) {
 99
100         static int padding = 100;
101
102         // 创建方块并添加到层中
103         auto block = Sprite::create("blocks.png");
104         auto blockBody = PhysicsBody::createBox(block->getContentSize(), PHYSICSBODY_MATERIAL_DEFAULT);
105         blockBody->getShape(0)->setDensity(10.0f);
106         blockBody->getShape(0)->setFriction(0.0f);
107         blockBody->getShape(0)->setRestitution(1.f);
108         blockBody->setDynamic(false);
109         int xOffset = padding + block->getContentSize().width / 2 +
110         ((block->getContentSize().width + padding)*i);
111         block->setPosition(xOffset, 450);
112         block->setPhysicsBody(blockBody);
113         block->setTag(3);
114         this->addChild(block);
115
116         block->getPhysicsBody()->setCategoryBitmask(0x01);
117         block->getPhysicsBody()->setContactTestBitmask(0x01);
118         block->getPhysicsBody()->setCollisionBitmask(0x01);
119     }
120
121     this->schedule(schedule_selector(HelloWorld::tick),0);
122
123     return true;
124 }
125
126 void HelloWorld::onTouchMoved(Touch* touch, Event* event)
127 {
128     Point touchLocation = this->convertToWorldSpace(this->convertTouchToNodeSpace(touch));
129     paddle->setPositionX(touchLocation.x);
130 }
131
132 bool HelloWorld::onTouchBegan(Touch* touch, Event* event)
133 {
134     return true;
135 }
136
137 void HelloWorld::onTouchEnded(Touch* touch, Event* event)
138 {
139
140 }
141
142 bool HelloWorld::onContactBegin(const PhysicsContact& contact)
143 {
144     if (ball->getPositionY() <= 50)
145     {
146         auto gameOverScene = GameOverScene::create();
147         gameOverScene->getLayer()->getLabel()->setString("You Lose!");
148         Director::getInstance()->replaceScene(gameOverScene);
149     }
150
151     auto spriteA = (Sprite*)contact.getShapeA()->getBody()->getNode();
152     auto spriteB = (Sprite*)contact.getShapeB()->getBody()->getNode();
153     int tagA = spriteA->getTag();
154     int tagB = spriteB->getTag();
155
156     if (tagA == 3)
157     {
158         spriteA->removeFromParentAndCleanup(true);
159     }
160
161     if (tagB == 3)
162     {
163         spriteB->removeFromParentAndCleanup(true);
164     }
165
166     return true;
167 }
168
169 void HelloWorld::tick(float dt)
170 {
171     bool isWin = true;
172     Vector<PhysicsBody*> bodies = m_world->getAllBodies();
173     Vector<PhysicsBody*>::iterator iter;
174     for (iter=bodies.begin();iter!=bodies.end();iter++) {
175         if ((*iter)->getNode()->getTag() == 3)
176         {
177             isWin = false;
178         }
179     }
180
181     if (isWin == true)
182     {
183         auto gameOverScene = GameOverScene::create();
184         gameOverScene->getLayer()->getLabel()->setString("You Win!");
185         Director::getInstance()->replaceScene(gameOverScene);
186     }
187 }
188
189 void HelloWorld::onEnter()
190 {
191     Layer::onEnter();
192
193     auto touchListener = EventListenerTouchOneByOne::create();
194     touchListener->setSwallowTouches(true);
195
196     touchListener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
197     touchListener->onTouchMoved = CC_CALLBACK_2(HelloWorld::onTouchMoved, this);
198     touchListener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);
199     _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
200
201     //添加监听器
202     auto contactListener = EventListenerPhysicsContact::create();
203     //设置监听器的碰撞开始函数
204     contactListener->onContactBegin = CC_CALLBACK_1(HelloWorld::onContactBegin, this);
205
206     //添加到事件分发器中
207     _eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);
208
209 }

GameOverScene.h

 1 #ifndef __SampleGame1__GameOverScene__
 2 #define __SampleGame1__GameOverScene__
 3
 4 #include "cocos2d.h"
 5
 6 class GameOverLayer : public cocos2d::LayerColor
 7 {
 8 public:
 9     GameOverLayer():_label(NULL) {};
10     virtual ~GameOverLayer();
11     bool init();
12     CREATE_FUNC(GameOverLayer);
13
14     void gameOverDone();
15
16     CC_SYNTHESIZE_READONLY(cocos2d::LabelTTF*, _label, Label);
17 };
18
19 class GameOverScene : public cocos2d::Scene
20 {
21 public:
22     GameOverScene():_layer(NULL) {};
23     ~GameOverScene();
24     bool init();
25     CREATE_FUNC(GameOverScene);
26
27     CC_SYNTHESIZE_READONLY(GameOverLayer*, _layer, Layer);
28 };
29
30 #endif

GameOverScene.cpp

 1 #include "GameOverScene.h"
 2 #include "HelloWorldScene.h"
 3 USING_NS_CC;
 4
 5
 6 bool GameOverScene::init()
 7 {
 8     if( Scene::init() )
 9     {
10         this->_layer = GameOverLayer::create();
11         this->_layer->retain();
12         this->addChild(_layer);
13
14         return true;
15     }
16     else
17     {
18         return false;
19     }
20 }
21
22 GameOverScene::~GameOverScene()
23 {
24     if (_layer)
25     {
26         _layer->release();
27         _layer = NULL;
28     }
29 }
30
31 bool GameOverLayer::init()
32 {
33     if ( LayerColor::initWithColor( Color4B(255,255,255,255) ) )
34     {
35         auto winSize = Director::getInstance()->getWinSize();
36         this->_label = LabelTTF::create("","Artial", 32);
37         _label->retain();
38         _label->setColor( Color3B(0, 0, 0) );
39         _label->setPosition( Point(winSize.width/2, winSize.height/2) );
40         this->addChild(_label);
41
42         this->runAction( Sequence::create(
43                                           DelayTime::create(3),
44                                           CallFunc::create(CC_CALLBACK_0(GameOverLayer::gameOverDone, this)),
45                                           NULL));
46
47         return true;
48     }
49     else
50     {
51         return false;
52     }
53 }
54
55 void GameOverLayer::gameOverDone()
56 {
57     Director::getInstance()->replaceScene( HelloWorld::createScene() );
58 }
59
60 GameOverLayer::~GameOverLayer()
61 {
62     if (_label)
63     {
64         _label->release();
65         _label = NULL;
66     }
67 }

游戏中图片:

游戏运行效果:

时间: 2024-10-31 18:52:23

coco2d-x3.2使用物理引擎Physicals制作Breakout游戏的相关文章

Cocos2d-js官方完整项目教程翻译:六、添加Chipmunk物理引擎在我们的游戏世界里

添加Chipmunk物理引擎在我们的游戏世界里         一.简介                   cocos2d JS能给我们力量来创造令人印象深刻的游戏世界.但缺乏某种现实.          虽然我们可以做复杂的计算,使游戏世界更真实的,但有另一个选择          它可以缓解我们的生活.答案是物理引擎.          物理引擎提供了重力,碰撞检测和物理模拟,可以使我们的游戏世界看起来更真实.          在本教程中,我们将介绍的ChipMunk的物理引擎进入我们的

制作简单的2D物理引擎(零)

最近发现了Github上的开源物理引擎项目Matter.js,对它很感兴趣,发现源码并不算长,算上注释大约1万行左右,值得剖析一番.Matter.js实现一个最小化的2D物理引擎,性能不错,故打算用C#重写并学习之. 由于JS是弱类型,而C#是强类型的,所以不得不还原相应的类型.在重写过程中,我也发现了源码中的一些问题,以及代码冗余,不过都无关紧要.在一万行之内实现一个简单的物理引擎本来就很令人激动了,这样可以以最小的工作量来熟悉物理引擎. 重写过程中,渲染用自带GDI实现,所以只需考虑物理引擎

使用P2物理引擎制作物理小球

今天分享的内容是:基于Egret使用P2物理引擎实现物理小球示例效果. 了解更多信息,您可以查看P2物理引擎GitHub地址或者是EgretP2物理系统文档. * 第三方库的引入 * 创建一个P2物理项目 一.第三方库的引入 1.首先新建一个项目. 2.在GitHub上下载包括P2物理引擎库的完整第三方库,解压后按照路径找到physics模块. 3.将physics模块放到新建项目根目录的同级目录. 4.修改egretProperties.json,modules数组里增加 {"name&quo

cocos2dx 3.2中的物理引擎初探(一)

cocos2dx在设计之初就集成了两套物理引擎,它们是box2d和chipmunk.我目前使用的是最新版的cocos2dx 3.2.引擎中默认使用的是chipmunk,如果想要改使用box2d的话,需要修改对应的android工程或者是ios工程的配置文件. 在2.x版本的cocos中,使用物理引擎的步骤十分繁琐.但在3.x版本中变得非常方便了.我这次的学习目标是制作一个打砖块的小游戏. 首先,现在的Scene类提供了一个静态工厂方法,用以创造一个集成物理引擎的场景. Scene::initWi

Verlet-js JavaScript 物理引擎

subprotocol最近在Github上开源了verlet-js.地址为https://github.com/subprotocol/verlet-js.verlet-js是一个集成Verlet的物理引擎,利用JavaScript编写.verlet-js支持粒子系统.距离限制.角度限制等.其Github声称基于这些基础,则可以帮助我们构建几乎任何我们所能想象到的东西. 其官网为我们提供了一下几个demo: Shapes (verlet-js Hello world) Fractal Trees

基于HT for Web 3D呈现Box2DJS物理引擎

上篇我们基于HT for Web呈现了A* Search Algorithm的3D寻路效果,这篇我们将采用HT for Web 3D来呈现Box2DJS物理引擎的碰撞效果,同上篇其实Box2DJS只是二维的平面碰撞物理引擎,但同样通过3D的呈现能让人更直观的体验到碰撞效果,先上张最终例子效果图: Box2D最早是Erin Catto在GDC大会上的一个展示例子,后来不断完善成C++的开源物理引擎库,这些年了衍生出Java.ActionScript以及JS等版本,被广泛应用在游戏领域.说其丰富的确

cocos2d_x_02_使用内置物理引擎

最终效果图: 一.新建工程 进入cocos2d-x的tools下的bin目录: /Users/beyond/Desktop/cocos2d-x/cocos2d-x-3.3beta0/tools/cocos2d-console/bin目录 打开终端,切换到上述bin目录 使用cocos命令,创建工程,格式如下: cocos new 工程名 -p 包名 -l 语言 -d 目标文件夹, 例如 : cocos new 01_cocos2d-x-p com.beyond-l cpp -d /Users/b

实例介绍Cocos2d-x物理引擎:HelloPhysicsWorld

我们通过一个实例介绍一下,在Cocos2d-x 3.x中使用物理引擎的开发过程,熟悉这些API的使用.这个实例的运行后的场景,当场景启动后,玩家可以触摸点击屏幕,每次触摸时候,就会在触摸点生成一个新的精灵,精灵的运行是自由落体运动. HelloPhysicsWorld实例 使用物理引擎的一般步骤,如下图所示. 这个过程与上帝创建世界的过程类似,上帝首先创建了世界,然后为世界指定了边界,否则万物就会掉到世界之外的混沌里去了,最后上帝创建了万物.当然这只是一个最基本的步骤,有的时候还需要碰撞检测和使

关于Unity中物理引擎的使用

物理引擎控制刚体,刚体上面贴上图片,所以看起来就是游戏运行起来的状态 物理世界计算刚体的运行状态,通过贴图显现出运算结果. 一.物理引擎 1:Unity 2D物理引擎基于Box2D封装而成;2: 物理引擎模拟物理运动和计算,物理引擎帮助我们计算物体运动; 3: 重力加速度;4: 碰撞器是物体的形状 + 碰撞的物理参数(物理材质);5: 刚体控制物体运动和受力; 二.步骤 1.创建一个Canvas 2.对Canvas进行初始化,记得把Game视图的分辨率调成和Canvas里面设置的一样的分辨率64