转载自:http://gym202.blog.163.com/blog/static/95543274201011765141871/
demo : http://www.emanueleferonato.com/downloads/box2dplat3.swf
demo控制 左右键是左右移动 上方向键是起跳
下面是源码 :
box2d是的角色邹形 能跳 能移动 能发射东西
/* 知识补漏: world其本质也是个body, 即所有b2Body对象的parent 。CreateBody() 等一些Create , Create就相当于flash player里的 add , CreateBody() CreateShape() 就相当于flash player里的 addChild() ground_sensor.SetAsOrientedBox(10/pixels_in_a_meter,5/pixels_in_a_meter,new b2Vec2(0,27/pixels_in_a_meter), 0); 后面的坐标new b2Vec2(0,27/pixels_in_a_meter)其原点是body的中心(即以body的中心为原点),而不是以world中的原点为原点, (总结:以body的中心为原点,向右向下为xy轴的正方向) GetWorldCenter得到是整个body的中心,GetLocalCenter得到是SetAsBox() 这个组成的对象的中心 下面增加了b2ContactListene类进行了侦听 ,并对其进行了重写.. */ package { import flash.display.Sprite; import flash.events.Event; import Box2D.Dynamics.*; import Box2D.Collision.*; import Box2D.Collision.Shapes.*; import Box2D.Common.Math.*; import General.Input; import flash.events.MouseEvent; public class HelloWorld extends Sprite { public var m_world:b2World; public var pixels_in_a_meter:int=30; public var bodyDef:b2BodyDef; public var boxDef:b2PolygonDef; public var m_input:Input; public var xspeed:int=0; public var bazooka:zooka=new zooka(); public var bazooka_angle:Number; public var m_contactListener=new b2ContactListener(); var body:b2Body; public function HelloWorld() { addEventListener(Event.ENTER_FRAME, Update, false, 0, true); var worldAABB:b2AABB = new b2AABB(); worldAABB.lowerBound.Set(-100.0, -100.0); worldAABB.upperBound.Set(100.0, 100.0); var gravity:b2Vec2=new b2Vec2(0.0,10.0); var doSleep:Boolean=true; m_world=new b2World(worldAABB,gravity,doSleep); var m_sprite:Sprite; m_sprite = new Sprite(); addChild(m_sprite); var dbgDraw:b2DebugDraw = new b2DebugDraw(); var dbgSprite:Sprite = new Sprite(); m_sprite.addChild(dbgSprite); dbgDraw.m_sprite=m_sprite; dbgDraw.m_drawScale=30; dbgDraw.m_alpha=1; dbgDraw.m_fillAlpha=0.5; dbgDraw.m_lineThickness=1; dbgDraw.m_drawFlags=b2DebugDraw.e_shapeBit; m_world.SetDebugDraw(dbgDraw); var bodyDef:b2BodyDef; var boxDef:b2PolygonDef; var circleDef:b2CircleDef; square_tile(250,395,500,10); hero(100,370,20,40); // // adding the contact listener m_world.SetContactListener(m_contactListener); // // Box2D input class - why should I bother making my one? m_sprite = new Sprite(); addChild(m_sprite); // input m_input=new Input(m_sprite); addChild(bazooka); stage.addEventListener(MouseEvent.CLICK, shoot); } public function shoot(event:Event) { bodyDef = new b2BodyDef(); bodyDef.position.Set((bazooka.x+(bazooka.width+3)*Math.cos(bazooka_angle))/pixels_in_a_meter, (bazooka.y+(bazooka.width+3)*Math.sin(bazooka_angle))/pixels_in_a_meter); boxDef = new b2PolygonDef(); boxDef.SetAsBox(10/pixels_in_a_meter,10/pixels_in_a_meter); boxDef.friction=0.3; boxDef.density=1; body=m_world.CreateBody(bodyDef); body.CreateShape(boxDef); body.SetMassFromShapes(); body.ApplyImpulse(new b2Vec2(Math.cos(bazooka_angle)*4, Math.sin(bazooka_angle)*4),body.GetWorldCenter()); } public function square_tile(px:int,py:int,w:int,h:int) { bodyDef = new b2BodyDef(); bodyDef.position.Set(px/pixels_in_a_meter, py/pixels_in_a_meter); boxDef = new b2PolygonDef(); boxDef.SetAsBox(real_pixels(w), real_pixels(h)); boxDef.friction=0.3; boxDef.density=0; body=m_world.CreateBody(bodyDef); body.CreateShape(boxDef); body.SetMassFromShapes(); } public function hero(px:int, py:int, w:int, h:int) { bodyDef = new b2BodyDef(); bodyDef.position.Set(px/pixels_in_a_meter, py/pixels_in_a_meter); boxDef = new b2PolygonDef(); boxDef.SetAsBox(real_pixels(w), real_pixels(h)); boxDef.density=1.0; boxDef.friction=0.3; boxDef.restitution=0.2; bodyDef.userData = new Sprite(); bodyDef.userData.name="Player"; body=m_world.CreateBody(bodyDef); body.SetBullet(true); body.CreateShape(boxDef); // var ground_sensor:b2PolygonDef = new b2PolygonDef(); ground_sensor.isSensor=true; ground_sensor.userData="groundsensor"; ground_sensor.SetAsOrientedBox(10/pixels_in_a_meter,5/pixels_in_a_meter,new b2Vec2(0,27/pixels_in_a_meter), 0);//后面的坐标new b2Vec2(0,27/pixels_in_a_meter)其原点是body的中心(即以body的中心为原点),而不是以world中的原点为原点,(总结:以body的中心为原点,向右向下为xy轴的正方向) body.CreateShape(ground_sensor); // body.SetMassFromShapes(); } public function real_pixels(n:int) { return (n/pixels_in_a_meter/2); } public function Update(e:Event):void { m_world.Step(1/30, 10); xspeed=0; for (var bb:b2Body = m_world.m_bodyList; bb; bb = bb.m_next) { if (bb.GetUserData()!=null) { if (Input.isKeyDown(39)) { // right arrow xspeed=3; } else if (Input.isKeyDown(37)) { // left arrow xspeed=-3; } if (Input.isKeyDown(38)) {// up arrow if (m_contactListener.can_jump()) { // checking if the hero can jump bb.ApplyImpulse(new b2Vec2(0.0, -1.0), bb.GetWorldCenter());//这里用bb.GetWorldCenter(),而不用bb.GetLocalCenter()因为用GetLocalCenter容易引起bug } } if (xspeed) { bb.WakeUp(); bb.m_linearVelocity.x=xspeed; } bb.m_sweep.a=0; bazooka.x=bb.m_userData.x=bb.GetPosition().x*30; bazooka.y=bb.m_userData.y=bb.GetPosition().y*30; var dist_x=bazooka.x-mouseX; var dist_y=bazooka.y-mouseY; bazooka_angle=Math.atan2(- dist_y,- dist_x); bazooka.rotation=bazooka_angle*57.2957795; } } Input.update(); } } }
b2ContactListener类的重写:
/* * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ package Box2D.Dynamics{ import Box2D.Collision.*; import Box2D.Collision.Shapes.*; import Box2D.Dynamics.Contacts.*; import Box2D.Dynamics.*; import Box2D.Common.Math.*; import Box2D.Common.*; /// Implement this class to get collision results. You can use these results for /// things like sounds and game logic. You can also get contact results by /// traversing the contact lists after the time step. However, you might miss /// some contacts because continuous physics leads to sub-stepping. /// Additionally you may receive multiple callbacks for the same contact in a /// single time step. /// You should strive to make your callbacks efficient because there may be /// many callbacks per time step. /// @warning The contact separation is the last computed value. /// @warning You cannot create/destroy Box2D entities inside these callbacks. public class b2ContactListener { var canjump:Boolean=false; /// Called when a contact point is added. This includes the geometry /// and the forces. public function can_jump() { return (canjump); } public virtual function Add(point:b2ContactPoint):void {} /// Called when a contact point persists. This includes the geometry /// and the forces. //点持续接触时 public virtual function Persist(point:b2ContactPoint):void { if (point.shape1.GetUserData()=="groundsensor"||point.shape2.GetUserData()=="groundsensor") { canjump=true; } } /// Called when a contact point is removed. This includes the last /// computed geometry and forces. public virtual function Remove(point:b2ContactPoint):void { if (point.shape1.GetUserData()=="groundsensor"||point.shape2.GetUserData()=="groundsensor") { canjump=false; } } /// Called after a contact point is solved. public virtual function Result(point:b2ContactResult):void { } } }