Cocos2d-x 3.x物理引擎概述(2)
上篇 碰撞 你是否经历过车祸?是否跟什么物体相撞过?就像车一样,物理刚体对象可以互相接触。当它们接触的时候,就发生了碰撞。当碰撞发生时,它可以被完全忽略,也可以引起一系列事件。 碰撞筛选 碰撞筛选允许你启用或者阻止形状之间碰撞的发生。物理引擎支持使用类型、组位掩码来筛选碰撞。 Cocos2d-x中支持32种碰撞类型。对于每个形状都可以指定其所属的类型。还可以指定有哪些类型可以与这个形状进行碰撞。这些是通过掩码来完成的。例如 auto sprite1 = addSpriteAtPosition(Vec2(s_centre.x - 150,s_centre.y)); sprite1->getPhysicsBody()->setCategoryBitmask(0x02);// 0010 sprite1->getPhysicsBody()->setCollisionBitmask(0x01);// 0001 sprite1 = addSpriteAtPosition(Vec2(s_centre.x - 150,s_centre.y + 100)); sprite1->getPhysicsBody()->setCollisionBitmask(0x01);// 0001 sprite2 = addSpriteAtPosition(Vec2(s_centre.x + 150,s_centre.y),1); sprite2->getPhysicsBody()->setCategoryBitmask(0x01);// 0001 sprite2->getPhysicsBody()->setCollisionBitmask(0x02);// 0010 sprite3 = addSpriteAtPosition(Vec2(s_centre.x + 150,s_centre.y + 100),2); sprite3->getPhysicsBody()->setCategoryBitmask(0x03);// 0011 sprite3->getPhysicsBody()->setCollisionBitmask(0x03);// 0011 可以通过检测、类型比较和碰撞掩码,来确定碰撞的发生: if((shapeA->getCategoryBitmask() & shapeB->getCollisionBitmask()) == 0 || (shapeB->getCategoryBitmask() & shapeA->getCollisionBitmask()) == 0) { // shapes can't collide ret = false; } 碰撞组允许你指定一个综合组的索引。你可以让具有同一组之索引的形状全都一直碰撞(正索引)或者永不碰撞(负索引或零索引)。组指数不同的形状间进行的碰撞,可以根据类型和掩码来进行筛选。换句话说,组筛选比类型筛选的优先级更高。 连接/关节 还记得之前的术语吗?关节是一种把接触点联结在一起的方式。没错,你可以把它类比为自己身体上的关节。每一个关节都有一个从PhysicsJoint对象获得的定义。在两个不同的刚体之间,所有的关节都是联结在一起的。刚体可以是静态的。你可以使用joint->setCollisionEnable(false)来避免相关联的刚体相互碰撞。很多关节的定义需要你提供一些几何数据。很多情况下,关节由锚点来定义。其余的关节定义数据取决于关节的类型。
碰撞检测 碰撞(Contacts)是一种由物理引擎创建的用以管理两个形状间碰撞的对象。Contact对象会自动创建,而非由用户创建。这里有几个与之相关联的术语。
你可以从一个碰撞中获取PhysicsShape。从中,你可以获取刚体。 boolonContactBegin(PhysicsContact& contact) bodyA = contact.getShapeA()->getBody(); bodyB = contact.getShapeB()->getBody(); returntrue; 你可以通过使用contact listener来访问碰撞。contact listener支持多种事件:begin,pre-solve,post-solve,以及separate。
也可以使用EventListenerPhysicsContactWithBodies,EventListenerPhysicsContactWithShapes,EventListenerPhysicsContactWithGroup来监听你感兴趣的刚体、形状和组的一些事件。除此之外,你还需要设定与物理接触相关的掩码,因为就算你创建了相关的EventListener,碰撞事件还是不会在默认状态下被接收。 例如: boolinit() //create a static PhysicsBody sprite = addSpriteAtPosition(s_centre,69);">sprite->setTag(10); sprite->getPhysicsBody()->setContactTestBitmask(0xFFFFFFFF); sprite->getPhysicsBody()->setDynamic(false); //adds contact event listener contactListener = EventListenerPhysicsContact::create(); contactListener->onContactBegin = CC_CALLBACK_1(PhysicsDemoCollisionProcessing::onContactBegin,this); _eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener,69);">schedule(CC_SCHEDULE_SELECTOR(PhysicsDemoCollisionProcessing::tick), 0.3f); returnfalse; voidtick(floatdt) sprite1 = addSpriteAtPosition(Vec2(s_centre.x + cocos2d::random(-300,300),69);">s_centre.y + cocos2d::random(-300,300))); physicsBody = sprite1->getPhysicsBody(); physicsBody->setVelocity(Vec2(cocos2d::random(-500,500),cocos2d::random(-500,500))); physicsBody->setContactTestBitmask(0xFFFFFFFF); nodeA = contact.getShapeA()->getBody()->getNode(); nodeB = contact.getShapeB()->getBody()->getNode(); if(nodeA && nodeB) if(nodeA->getTag() == 10) nodeB->removeFromParentAndCleanup(true); elseif (nodeB->getTag() == 10) nodeA->removeFromParentAndCleanup(true); //bodies can collide } 查询 你有没有过站在一个地方往四周看的经历?你能看到离你近的东西,也能看到离你远的东西。你能判断出它们离你有多远。物理引擎提供类似的空间查询功能。PhysicsWorld对象目前支持的查询包括点查询、射线查询和矩形查询。 点查询 当你碰到什么东西,比如说你的桌子的时候,你可以将此认为是一个点查询的例子。这使你能够检查在一个点周围的一定距离内是否有形状存在。对于鼠标拾取和简单的传感器来说,点查询是非常有用的。你还可以找到在一个形状上离某定点最近的点,或者找到离某个点最近的形状。 射线查询 当你四处看的时候,在你视线内的某些物体肯定会引起你的注意。像这样的时候,你基本上就算是执行了一次射线查询。你不停地扫描,直到有什么有趣的东西让你停下来。你可以使用对某个形状使用射线查询来获取第一个交叉点。例如: void tick(float dt) Vec2 d(300 * cosf(_angle),300 * sinf(_angle)); point2 = s_centre + d; if(_drawNode) removeChild(_drawNode); _drawNode = DrawNode::create(); points[5]; intnum = 0; func = [&points,&num](PhysicsWorld& world,69);">constPhysicsRayCastInfo& info,void* data)->bool if(num < 5) points[num++] = info.contact; }; s_currScene->getPhysicsWorld()->rayCast(func,69);">s_centre,point2,nullptr); _drawNode->drawSegment(s_centre,69);">point2,1,Color4F::RED); for(inti = 0; i < num; ++i) _drawNode->drawDot(points[i],69);">3,Color4F(1.0f,1.0f,1.0f)); addChild(_drawNode); _angle += 1.5f * (float)M_PI / 180.0f; 矩形查询 矩形查询提供了一个大致检查区域中存在的形状的一种快捷方式。它非常容易实现: auto func = [](PhysicsWorld& world,PhysicsShape& shape,69);">userData)->bool //Return true from the callback to continue rect queries scene->getPhysicsWorld()->queryRect(func,69);">Rect(0,200,200),69);">A few examples of using a Rect query while doing a logo smash: 这里是在制作撞击logo时使用矩形查询的几个例子: 禁用物理引擎 使用内置的物理引擎是个不错的想法。它又稳定又强大。然而,有时候你会想要使用一些其他的物理引擎。这时候你只需要在base/ccConfig.h中把CC_USE_PHYSICS禁用就好了。
上篇 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |