Cocos2d-x之物理世界(物体之间的碰撞)
在HelloWorldScene.h中添加如下内容,并让其继承public b2ContactListener
private:
b2Body *groundBody;//创建一个地板
public:
//继承的b2ContactListener实现
virtual void BeginContact(b2Contact* contact);
HelloWorldScene。cpp
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 //定义中间的比例为80(box2d和cocos2d的转换比例) 10 #define RATIO 80.0f 11 12 Scene* HelloWorld::createScene() 13 { 14 // 'scene' is an autorelease object 15 auto scene = Scene::create(); 16 17 // 'layer' is an autorelease object 18 auto layer = HelloWorld::create(); 19 20 // add layer as a child to scene 21 scene->addChild(layer); 22 23 // return the scene 24 return scene; 25 } 26 27 // on "init" you need to initialize your instance 28 bool HelloWorld::init() 29 { 30 ////////////////////////////// 31 // 1. super init first 32 if ( !Layer::init() ) 33 { 34 return false; 35 } 36 //创建一个世界,b2world(二维矢量类型的,指定世界的加速度的方向 37 //b2Vec2(加速度的方向,向下的,所以x轴没有为0,y轴为-10))这样才能往下落 38 world = new b2World(b2Vec2(0, -10)); 39 40 //设置链接的监听器 41 world->SetContactListener(this); 42 43 44 45 // //添加一个矩形,然后调用scheduleUpdate方法,实现矩形的下落,随着重力加速向下运动 46 // addRect(); 47 48 //添加一个地板 49 addGround(); 50 51 //复制矩形的代码后,他只是不受重力的影响 52 // //让矩形在x轴平移 53 // addRect(0, 5, b2_kinematicBody); 54 55 // //让矩形在y轴向上移动,然后向下加速运动 56 // addRect(8, 5, b2_dynamicBody); 57 58 //让矩形在y轴向上移动,然后向下加速运动 59 addRect(5, 3, b2_dynamicBody); 60 61 62 //调用update方法,实现每帧都改变物理世界中的物体 63 scheduleUpdate(); 64 65 return true; 66 } 67 68 69 //实现模拟物理世界的方法(当前一帧与上一帧的时间差) 70 void HelloWorld::update(float dt){ 71 72 //使用这个step方法来一步一步的模拟我们的物理世界 73 //(时间差(当前一步与最后一步的时间差,即当前一帧与上一帧的时间差), 74 //速度迭代,模拟物理世界的过程中难免会有误差,所以就用速度迭代的次数来避免误差,官方建议8次, 75 //位置的迭代,官方建议3次) 76 world->Step(dt, 8, 3); 77 78 //为了获取矩形,所以在这里定义一个Sprite 79 Sprite *s; 80 81 //获取移动的矩形 82 //在这里获取到所有的子集的对象 83 //遍历所有的子集对象, 84 for (b2Body *b = world->GetBodyList(); b; b = b->GetNext()) { 85 // //判断,因为只有一个动态的物体,所以可以这么判断,否则,要用别的方法 86 // if (b->GetType() == b2_dynamicBody) { 87 //让所有的类型都要刷新 88 //获取到移动的物体的y 位置 89 // log("%f",b->GetPosition().y); 90 91 if (b->GetUserData()) { 92 s = (Sprite*)b->GetUserData(); 93 94 //让Sprite与body同步 95 s->setPosition(b->GetPosition().x * RATIO, b->GetPosition().y * RATIO); 96 } 97 // } 98 } 99 } 100 101 102 103 //创建矩形,并且让其随着重力开始运动,有加速度的向下移动 104 void HelloWorld::addRect(){ 105 106 //config box2d 107 ///******************************************************************* 108 //定义一个b2BodyDef物体 109 b2BodyDef def; 110 111 // //指定def的初始化的position,x轴是0,y轴是10,代表着从10往下落 112 // def.position = b2Vec2(0, 10); 113 //定义完比例后开始修改位置,因为最高为6米,所以y轴定义为5,x轴最大为10米 114 def.position = b2Vec2(3, 5); 115 116 //配置物体的属性 117 //b2_dynamicBody是枚举类型的,代表运动的物体, 118 //还有b2_staticBody 代表静态的物体 119 //还有b2_kinematicBody 代表悬浮的物体 120 def.type = b2_dynamicBody;//此时这是个运动的物体 121 122 //创建一个物体(物体的相关的定义) 123 b2Body *body = world->CreateBody(&def); 124 125 ///******************************************************************* 126 127 128 129 130 //指定物体的fixture 131 ///******************************************************************* 132 133 b2PolygonShape shape; 134 shape.SetAsBox(0.5, 0.5);//设置一个一米的箱子 135 136 137 b2FixtureDef fixtureDef; 138 //指定fixtuer的属性 139 fixtureDef.density = 1;//密度 140 fixtureDef.friction = 0.3;//摩擦系数 141 fixtureDef.shape = &shape; 142 body->CreateFixture(&fixtureDef); 143 144 ///******************************************************************* 145 146 147 148 149 150 //config cocos shape 151 ///******************************************************************* 152 //定义一个图形 153 auto s = Sprite::create(); 154 // //指定他的Texture图形区域 155 // s->setTextureRect(Rect(0, 0, 80, 80)); 156 157 //指定加入fixture的图形的区域 158 s->setTextureRect(Rect(0, 0, 0.5 * 2 * RATIO, 0.5 * 2 * RATIO)); 159 160 //将其添加到层中 161 addChild(s); 162 163 //配置位置 164 //cocos2d的图形区域的位置是(800 x 600) 165 //box2d的范围单位是米,官方文档上的比较精确的范围是10米之内 166 //意味着800px的位置当成10米是比较合理的,所以中间的比例是80 167 168 // //因为每一帧都同步了,所以此处可以不要了, 169 // //因为update中的s->setPosition(b->GetPosition().x * RATIO, 170 // //b->GetPosition().y * RATIO);所以就不要了 171 // //配置s的位置 172 // s->setPosition(Point(def.position.x * RATIO, def.position.y * RATIO)); 173 174 //将图形和body相关起来 175 body->SetUserData(s);//这样就将图形和body绑定起来了 176 177 ///******************************************************************* 178 } 179 180 181 182 183 //直接复制上面的代码 184 //创建矩形,并且让其随着重力开始运动,有加速度的向下移动 185 void HelloWorld::addRect(float positionx, float positiony, b2BodyType type){ 186 187 //config box2d 188 ///******************************************************************* 189 //定义一个b2BodyDef物体 190 b2BodyDef def; 191 192 // //指定def的初始化的position,x轴是0,y轴是10,代表着从10往下落 193 // def.position = b2Vec2(0, 10); 194 //定义完比例后开始修改位置,因为最高为6米,所以y轴定义为5,x轴最大为10米 195 def.position = b2Vec2(positionx, positiony); 196 197 // //设置矩形的线性初速度,x轴平移 198 // def.linearVelocity = b2Vec2(1, 0); 199 200 //设置矩形的线性速度,y轴向上的速度 201 def.linearVelocity = b2Vec2(0, 10); 202 203 204 //配置物体的属性 205 //b2_dynamicBody是枚举类型的,代表运动的物体, 206 //还有b2_staticBody 代表静态的物体 207 //还有b2_kinematicBody 代表悬浮的物体 208 def.type = type;//此时这是个运动的物体 209 210 //创建一个物体(物体的相关的定义) 211 b2Body *body = world->CreateBody(&def); 212 213 ///******************************************************************* 214 215 216 217 218 //指定物体的fixture 219 ///******************************************************************* 220 221 b2PolygonShape shape; 222 shape.SetAsBox(0.5, 0.5);//设置一个一米的箱子 223 224 225 b2FixtureDef fixtureDef; 226 //指定fixtuer的属性 227 fixtureDef.density = 1;//密度 228 fixtureDef.friction = 0.3;//摩擦系数 229 fixtureDef.shape = &shape; 230 body->CreateFixture(&fixtureDef); 231 232 ///******************************************************************* 233 234 235 236 237 238 //config cocos shape 239 ///******************************************************************* 240 //定义一个图形 241 auto s = Sprite::create(); 242 // //指定他的Texture图形区域 243 // s->setTextureRect(Rect(0, 0, 80, 80)); 244 245 //指定加入fixture的图形的区域 246 s->setTextureRect(Rect(0, 0, 0.5 * 2 * RATIO, 0.5 * 2 * RATIO)); 247 248 //将其添加到层中 249 addChild(s); 250 251 //配置位置 252 //cocos2d的图形区域的位置是(800 x 600) 253 //box2d的范围单位是米,官方文档上的比较精确的范围是10米之内 254 //意味着800px的位置当成10米是比较合理的,所以中间的比例是80 255 256 // //因为每一帧都同步了,所以此处可以不要了, 257 // //因为update中的s->setPosition(b->GetPosition().x * RATIO, 258 // //b->GetPosition().y * RATIO);所以就不要了 259 // //配置s的位置 260 // s->setPosition(Point(def.position.x * RATIO, def.position.y * RATIO)); 261 262 //将图形和body相关起来 263 body->SetUserData(s);//这样就将图形和body绑定起来了 264 265 ///******************************************************************* 266 267 268 269 270 } 271 272 273 //添加一个地板 274 void HelloWorld::addGround(){ 275 276 //创建一个静态的物体 277 278 b2BodyDef def; 279 //指定位置 280 // def.position = b2Vec2(0, 0); 281 //为了让创建的地板铺满底部, 282 def.position = b2Vec2(400 / RATIO, 0); 283 //指定def的类型,静态的物体 284 def.type = b2_staticBody; 285 286 // b2Body *body = world->CreateBody(&def); 287 groundBody = world->CreateBody(&def); 288 289 290 b2PolygonShape groundShape; 291 //默认情况下指的是半宽和半高,单位为米 292 groundShape.SetAsBox(400 / RATIO, 0.5); 293 294 b2FixtureDef fixuredef; 295 //指定fixture的属性 296 fixuredef.density = 1;//密度 297 fixuredef.friction = 0.3;//摩擦系数 298 //为其指定一个图形区域,让其与其他图形有一个碰撞的作用 299 fixuredef.shape = &groundShape; 300 301 // body->CreateFixture(&fixuredef); 302 groundBody->CreateFixture(&fixuredef); 303 304 305 } 306 307 308 309 void HelloWorld::BeginContact(b2Contact *contact){ 310 311 //链接的两个对象的fixture 312 //不管怎么样,最终都要落到地板上 313 if (contact->GetFixtureA()->GetBody() == groundBody || contact->GetFixtureB()->GetBody() == groundBody) { 314 log("有物体落在地板上*——*"); 315 } 316 317 318 }