1、Box2D教程5碰撞检测大伦子de空间 转载来源:Coming X原文链接:Box2D教程5-碰撞检测之前我们已经了解了如何通过Box2D创建一个物理世界,给刚体添加复杂材质,鼠标交互。在游戏开发里面我们通常要判断两个物体相互碰撞了,然后进行相应的操作。比如“愤怒的小鸟”,当小鸟碰撞到箱子的时候,我们需要知道这两个物体碰撞了,然后判断碰撞的力度(后面的教程会讲),然后对箱子进行操作。这个教程就是用来处理Box2D的碰撞检测问题。这个教程仍然基于先前的教程,关于如何创建一个物理世界,这里就不解释了。为了要实现碰撞检测,需要使用到Box2D的B2ContactListener类。该类是一个抽象类,
2、不能直接被实例化,它包含四个方法:BeginContact, EndContact, PreSolve, PostSolve,我们必须先继承它创建自定义的ContactListener,然后override你需要的方法。这个教程主要检测两个物体产生碰撞以及碰撞结束。因此我们override BeginContact(开始碰撞)和EndContact(碰撞结束)方法。首先我们创建一个简单的物理世界,四个边框和三个球体,这在先前的教程有详细说明123456789101112131415161718192021222324252627282930313233343536373839404142434
3、445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
4、163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
5、263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292package import Box2D.Collision.Shapes.b2CircleShape; import Box2D.Collision.Shapes.b2PolygonShape; import Box2D.Collision.Shapes.b2Shape; import Box2D.Collision.b2AABB; import Box2D.Common.Math.b2Vec2; import B
6、ox2D.Dynamics.Joints.b2MouseJoint; import Box2D.Dynamics.Joints.b2MouseJointDef; import Box2D.Dynamics.b2Body; import Box2D.Dynamics.b2BodyDef; import Box2D.Dynamics.b2DebugDraw; import Box2D.Dynamics.b2Fixture; import Box2D.Dynamics.b2FixtureDef; import Box2D.Dynamics.b2World; import mon.Console; i
7、mport mon.CustomContactListener; import comingx.jingle.events.CollisionEvent; import comingx.jingle.userdata.BallUserData; import flash.display.GradientType; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Matrix; import flash.text.TextField;
8、 import flash.text.TextFieldAutoSize; import flash.text.TextFormat; SWF(width=500,height=300,frameRate=30) public class Box2DCheckCollision extends Sprite /屏幕像素单位转换成物理世界的距离单位 private const PIXEL_TO_METER:Number = 30; /物理世界 private var world:Box2D.Dynamics.b2World; private var _mouseXWorldPhys:Number
9、; private var _mouseYWorldPhys:Number; private var _mouseXWorld:Number; private var _mouseYWorld:Number; private var _mousePVec:b2Vec2 = new b2Vec2(); private var _groundBody:b2Body; private var _mouseJoint:b2MouseJoint; private var mouseDown:Boolean = false; private var console:Console; public func
10、tion Box2DCheckCollision() drawBackground(); createWorld(); createWall(); createBall(); createDebugDraw(); addEventListener(Event.ENTER_FRAME, handleEnterFrame); addEventListener(MouseEvent.MOUSE_DOWN,handleMouseDown); addEventListener(MouseEvent.MOUSE_UP,handleMouseUp); addEventListener(MouseEvent.
11、CLICK,handleMouseUp); addEventListener(Event.MOUSE_LEAVE,handleMouseUp); private function createWorld():void /重力向量 var gravity:b2Vec2 = new b2Vec2(0,9.0); /是否休眠 var doSleep:Boolean = true; world = new b2World(gravity,doSleep); world.SetWarmStarting(true); private function createWall():void /1.需要创建的墙
12、刚体 var leftWall:b2Body; /2.刚体定义 var leftWallBodyDef:b2BodyDef = new b2BodyDef(); /刚体类型和位置 leftWallBodyDef.type = b2Body.b2_staticBody; /注意刚体的注册中心都是在物体的中心位置 leftWallBodyDef.position.Set(10/PIXEL_TO_METER, stage.stageHeight/2/PIXEL_TO_METER); /工厂模式创建刚体 leftWall = world.CreateBody(leftWallBodyDef); /3.
13、刚体修饰物定义 var leftWallFixtureDef:b2FixtureDef = new b2FixtureDef(); /密度 leftWallFixtureDef.density = 1.0; /摩擦粗糙程度 leftWallFixtureDef.friction = 0.3; /力度返回程度(弹性) leftWallFixtureDef.restitution = 1.0; /4.创建墙形状 var leftWallShape:b2PolygonShape = new b2PolygonShape(); /此处参数为宽和高度的一半值 leftWallShape.SetAsBox
14、(10/PIXEL_TO_METER, stage.stageHeight/2/PIXEL_TO_METER); /将形状添加到刚体修饰物 leftWallFixtureDef.shape = leftWallShape; leftWall.CreateFixture(leftWallFixtureDef); /下面创建其他三面墙,共用leftwall的几个变量 leftWallBodyDef.position.Set(stage.stageWidth-10)/PIXEL_TO_METER, stage.stageHeight/2/PIXEL_TO_METER); var rightWall:
15、b2Body = world.CreateBody(leftWallBodyDef); rightWall.CreateFixture(leftWallFixtureDef); leftWallBodyDef.position.Set( stage.stageWidth/2/PIXEL_TO_METER, (stage.stageHeight-10)/PIXEL_TO_METER); var bottomWall:b2Body = world.CreateBody(leftWallBodyDef); leftWallShape.SetAsBox(stage.stageWidth/2/PIXEL
16、_TO_METER, 10/PIXEL_TO_METER); bottomWall.CreateFixture(leftWallFixtureDef); leftWallBodyDef.position.Set( stage.stageWidth/2/PIXEL_TO_METER, 10/PIXEL_TO_METER); var topWall:b2Body = world.CreateBody(leftWallBodyDef); topWall.CreateFixture(leftWallFixtureDef); private function createBall():void var
17、ballDef:b2BodyDef = new b2BodyDef(); ballDef.type = b2Body.b2_dynamicBody; ballDef.position.Set(50/PIXEL_TO_METER,30/PIXEL_TO_METER); var ballBig:b2Body = world.CreateBody(ballDef); var circleShape:b2CircleShape = new b2CircleShape(30/PIXEL_TO_METER); var ballFixtureDef:b2FixtureDef = new b2FixtureD
18、ef(); ballFixtureDef.shape = circleShape; ballFixtureDef.density = 1.0; ballFixtureDef.restitution = 0.5; ballBig.CreateFixture(ballFixtureDef); ballDef.position.Set(200/PIXEL_TO_METER, 30/PIXEL_TO_METER); var ballMedium:b2Body = world.CreateBody(ballDef); circleShape = new b2CircleShape(20/PIXEL_TO
19、_METER); ballFixtureDef.shape = circleShape; ballMedium.CreateFixture(ballFixtureDef); ballDef.position.Set(400/PIXEL_TO_METER, 30/PIXEL_TO_METER); var ballSmall:b2Body = world.CreateBody(ballDef); circleShape = new b2CircleShape(15/PIXEL_TO_METER); ballFixtureDef.shape = circleShape; ballSmall.Crea
20、teFixture(ballFixtureDef); private function createDebugDraw():void /创建一个sprite,可以将测试几何物体放入其中 var debugSprite:Sprite = new Sprite(); addChild(debugSprite); var debugDraw:b2DebugDraw = new b2DebugDraw(); debugDraw.SetSprite(debugSprite); /设置边框厚度 debugDraw.SetLineThickness(1.0); /边框透明度 debugDraw.SetAlp
21、ha(1.0); /填充透明度 debugDraw.SetFillAlpha(0.5); /设置显示对象 debugDraw.SetFlags(b2DebugDraw.e_shapeBit); /物理世界缩放 debugDraw.SetDrawScale(PIXEL_TO_METER); world.SetDebugDraw(debugDraw); private function handleEnterFrame(evt:Event):void UpdateMouseWorld(); mouseDrag(); var timeStep:Number = 1/30; var velocityI
22、nterations:int = 10; var positionIterations:int = 10; world.Step(timeStep,velocityInterations,positionIterations); /在2.1版本清除力,以提高效率 world.ClearForces(); /绘制 world.DrawDebugData(); private function drawBackground():void var bg:Sprite = new Sprite(); var matrix:Matrix = new Matrix(); matrix.translate(
23、100,100); bg.graphics.beginGradientFill(GradientType.RADIAL,0xffffff,0xffaa00,0.3,0.2,0,255,matrix); bg.graphics.drawRect(0,0,stage.stageWidth,stage.stage.stageHeight); bg.graphics.endFill(); addChild(bg); /tips var tf:TextField = new TextField(); tf.text = 拖动球产生碰撞; tf.autoSize = TextFieldAutoSize.L
24、EFT; var fomat:TextFormat = new TextFormat(Kai,华文楷体, 20, 0x555555); tf.setTextFormat(fomat); tf.x = tf.y = 30; addChild(tf); private function UpdateMouseWorld():void _mouseXWorldPhys = this.mouseX / PIXEL_TO_METER; _mouseYWorldPhys = this.mouseY / PIXEL_TO_METER; _mouseXWorld = this.mouseX; _mouseYW
25、orld = this.mouseY; private function getBodyAtMouse(includeStatic:Boolean = false):b2Body _mousePVec.Set(_mouseXWorldPhys,_mouseYWorldPhys); var aabb:b2AABB = new b2AABB(); aabb.lowerBound.Set(_mouseXWorldPhys - 0.001, _mouseYWorldPhys - 0.001); aabb.upperBound.Set(_mouseXWorldPhys + 0.001, _mouseYW
26、orldPhys + 0.001); var body:b2Body = null; var fixture:b2Fixture; function getBodyCallback(fixture:b2Fixture):Boolean var shape:b2Shape = fixture.GetShape(); if(fixture.GetBody().GetType() != b2Body.b2_staticBody | includeStatic) var inside:Boolean = shape.TestPoint(fixture.GetBody().GetTransform(),
27、 _mousePVec); if(inside) body = fixture.GetBody(); return false; return true; world.QueryAABB(getBodyCallback, aabb); return body; private function mouseDrag():void if(mouseDown & !_mouseJoint) var body:b2Body = getBodyAtMouse(); if(body) var md:b2MouseJointDef = new b2MouseJointDef(); md.bodyA = world.GetGroundBody(); md.bodyB = body; md.target.Set(_mouseXWorldPhys,_mouseYWorldPhys); md.collideConnected = true; md.maxForce = 300.0 * body.GetMass(); _mouseJoint =
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1