Cocos2d-x 物理引擎及碰撞

时间:2021-10-07 04:57:41

基础知识:



1
#ifndef __HELLOWORLD_SCENE_H__ 2 #define __HELLOWORLD_SCENE_H__
3
4 #include "cocos2d.h"
5
6 class HelloWorld : public cocos2d::Layer
7 {
8 private:
9 Size visibleSize;
10 public:
11 // there's no 'id' in cpp, so we recommend returning the class instance pointer
12 static cocos2d::Scene* createScene();
13
14 // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
15 virtual bool init();
16
17 // implement the "static create()" method manually
18 CREATE_FUNC(HelloWorld);
19
20 //物理引擎所需的入口
21 virtual void onEnter();
22
23 //物理引擎的物理边界
24 void addEdges();
25
26 //物理引擎添加物理元素 --- 方法重载1
27 void addBall(float postionX, float positionY);
28
29 //物理引擎动态添加物理元素 --- 方法重载2
30 void addBall(Vec2 position);
31 };
32
33 #endif // __HELLOWORLD_SCENE_H__
 1 #include "HelloWorldScene.h"
2 #include "cocostudio/CocoStudio.h"
3 #include "ui/CocosGUI.h"
4
5 USING_NS_CC;
6
7 using namespace cocostudio::timeline;
8
9 Scene* HelloWorld::createScene()
10 {
11 // 'scene' is an autorelease object
12 //auto scene = Scene::create();
13
14 /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
15
16 //34.Cocos2d - x v3物理引擎
17
18
19 //创建带有物理引擎的Scene
20 auto scene = Scene::createWithPhysics();
21 scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
22
23 // 'layer' is an autorelease object
24 auto layer = HelloWorld::create();
25
26 // add layer as a child to scene
27 scene->addChild(layer);
28
29 // return the scene
30 return scene;
31 }
32
33 // on "init" you need to initialize your instance
34 bool HelloWorld::init()
35 {
36 // 1. super init first
37 if ( !Layer::init() )
38 {
39 return false;
40 }
41
42 visibleSize = Director::getInstance()->getVisibleSize();
43
44 return true;
45 }
46
47 //物理引擎 应用程序入口
48 void HelloWorld::onEnter(){
49
50 //父类onEnter
51 Layer::onEnter();
52
53 //添加一个物理元素
54 addBall(visibleSize.width / 2, visibleSize.height / 2);
55
56 //添加物理边界
57 addEdges();
58
59 //动态添加物理元素
60 auto listener = EventListenerTouchOneByOne::create();
61 listener->onTouchBegan = [this](Touch *touch, Event *e){
62
63 this->addBall(touch->getLocation());
64
65 return false;
66 };
67 _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
68 }
69
70 //物理引擎的物理边界
71 void HelloWorld::addEdges(){
72
73 //创建边界框
74 auto body = PhysicsBody::createEdgeBox(visibleSize);
75 //auto body = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3);//边界框宽度 --- 可现实边界线
76
77 //用来承载边界框的图形
78 auto edgeShape = Node::create();
79 edgeShape->setPhysicsBody(body);
80 edgeShape->setPosition(visibleSize / 2);
81 addChild(edgeShape);
82 }
83
84 //物理引擎添加物理元素
85 void HelloWorld::addBall(float postionX, float positionY){
86 //创建一个Sprite对象
87 auto b = Sprite::create("ball.png");
88 b->setScale(0.2);
89 //设置物理Body
90 b->setPhysicsBody(PhysicsBody::createBox(b->getContentSize()));
91 b->cocos2d::Node::setPosition(postionX, positionY);
92 addChild(b);
93 }
94
95 //物理引擎添加物理元素 --- 方法重载
96 void HelloWorld::addBall(Vec2 position){
97 addBall(position.x, position.y);
98 }

 

碰撞测试:



1
#ifndef __HELLOWORLD_SCENE_H__ 2 #define __HELLOWORLD_SCENE_H__
3
4 #include "cocos2d.h"
5
6 class HelloWorld : public cocos2d::Layer
7 {
8 private:
9
10 Size visibleSize;
11
12 public:
13 // there's no 'id' in cpp, so we recommend returning the class instance pointer
14 static cocos2d::Scene* createScene();
15
16 // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
17 virtual bool init();
18
19 // implement the "static create()" method manually
20 CREATE_FUNC(HelloWorld);
21
22 //物理引擎入口
23 virtual void onEnter();
24
25 void addBox(Vec2 position);
26 };
27
28 #endif // __HELLOWORLD_SCENE_H__
  1 #include "HelloWorldScene.h"
2 #include "cocostudio/CocoStudio.h"
3 #include "ui/CocosGUI.h"
4
5 USING_NS_CC;
6
7 using namespace cocostudio::timeline;
8
9
10 #define RED_BIT_MASK 0x4
11 #define GREEN_BIT_MASK 0x2
12 #define BLUE_BIT_MASK 0x1
13 #define EDGE_BIT_MASK 0x8
14
15 Scene* HelloWorld::createScene()
16 {
17 //支持物理引擎的Scene
18 auto scene = Scene::createWithPhysics();
19 //显示物理引擎调试界面 --- 有红框
20 scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
21
22 //设置更大的重力加速度
23 scene->getPhysicsWorld()->setGravity(Vec2(0, -1000));
24
25 auto layer = HelloWorld::create();
26
27 scene->addChild(layer);
28
29 return scene;
30 }
31
32 bool HelloWorld::init()
33 {
34 if ( !Layer::init() )
35 {
36 return false;
37 }
38
39 visibleSize = Director::getInstance()->getVisibleSize();
40
41 //动态添加Box
42 auto listener = EventListenerTouchOneByOne::create();
43 listener->onTouchBegan = [this](Touch *touch, Event *e){
44
45 this->addBox(touch->getLocation());
46
47 return false;
48 };
49 _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
50
51 //碰撞监听
52 auto contactListener = EventListenerPhysicsContact::create();
53 contactListener->onContactBegin = [](PhysicsContact &contact){
54
55 switch (contact.getShapeA()->getBody()->getContactTestBitmask() |
56 contact.getShapeB()->getBody()->getContactTestBitmask())
57 {
58 case RED_BIT_MASK | BLUE_BIT_MASK:
59 log("red rect contact blue rect");
60 break;
61 case RED_BIT_MASK | GREEN_BIT_MASK:
62 log("red rect contact green rect");
63 break;
64 case GREEN_BIT_MASK | BLUE_BIT_MASK:
65 log("green rect contact blue rect");
66 break;
67 case RED_BIT_MASK | EDGE_BIT_MASK:
68 log("red rect hit edge");
69 break;
70 case GREEN_BIT_MASK | EDGE_BIT_MASK:
71 log("green rect hit edge");
72 break;
73 case BLUE_BIT_MASK | EDGE_BIT_MASK:
74 log("blue rect hit edge");
75 break;
76 case RED_BIT_MASK:
77 log("two red rect contact");
78 break;
79 case GREEN_BIT_MASK:
80 log("two green rect contact");
81 break;
82 case BLUE_BIT_MASK:
83 log("two blue rect contact");
84 break;
85 default:
86 break;
87 }
88 return true;
89 };
90 _eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);
91
92
93 return true;
94 }
95
96 //物理引擎入口实现
97 void HelloWorld::onEnter(){
98
99 Layer::onEnter();
100
101 //添加物理边界
102 auto bounds = Node::create();
103 bounds->setContentSize(visibleSize);
104 bounds->setPhysicsBody(PhysicsBody::createEdgeBox(bounds->getContentSize()));
105 //bounds->setPosition(visibleSize / 2);//Node锚点是(0,0)
106 bounds->getPhysicsBody()->setContactTestBitmask(EDGE_BIT_MASK);
107 addChild(bounds);
108
109 addBox(visibleSize / 2);
110 }
111
112 void HelloWorld::addBox(Vec2 position){
113 auto r = Sprite::create();
114 r->setTextureRect(Rect(0, 0, 50, 50));
115 r->setPhysicsBody(PhysicsBody::createBox(r->getContentSize()));
116 addChild(r);
117 r->setPosition(position);
118
119 //随机产生3种颜色的Box
120 switch (rand() % 3)
121 {
122 case 0:
123 r->setColor(Color3B(255, 0, 0));
124 r->getPhysicsBody()->setContactTestBitmask(RED_BIT_MASK);
125 break;
126 case 1:
127 r->setColor(Color3B(0, 255, 0));
128 r->getPhysicsBody()->setContactTestBitmask(GREEN_BIT_MASK);
129 break;
130 case 2:
131 r->setColor(Color3B(0, 0, 255));
132 r->getPhysicsBody()->setContactTestBitmask(BLUE_BIT_MASK);
133 break;
134 default:
135 break;
136 }
137 }