zoukankan      html  css  js  c++  java
  • Box2D教程1创建碰撞世界

    Box2D教程1-创建碰撞世界

    Box2D教程2-鼠标交互

    Box2D教程3-刚体绑定外观

    Box2D教程4-复杂刚体的复杂外观

    Box2D教程5-碰撞检测

    Box2D是一个比较优秀的二维物理引擎,由C++编写,后由Alchemy转换成AS3。这个教程主要介绍如何创建物理世界、刚体、及其基本形状,即Box2D的Hello world。
    Box2D的物理世界通常包括这样几个对象:
    world:一个物理世界,所有的刚体都将存在在这个世界里面,这个世界以米为距离单位。尽量贴近真实世界的度量。
    body:刚体,存在在物理世界的理想物体,比任何物体都硬,不会发生形变。body对应着一个bodyDef(刚体定义),刚体定义指定了刚体的类型(动态、静态、轨迹运动的)和刚体的位置,world通过刚体定义创建刚体。
    fixture:刚体修饰物,描述刚体的一些特征。fixture对应着fixtureDef(修饰物定义),它将形状绑定到刚体上,使刚体具有一些表现特征,如密度、摩擦系数、弹性等等。body通过fixtureDef创建fixture。
    shape:一个几何形状,比如圆和多边形。形状是修饰物fixture的一个属性,描述了刚体的碰撞边界。

    解释一下b2World, b2Body, b2BodyDef, b2Fixture, b2FixtureDef, shpae之间的关系
    1.b2World通过b2BodyDef创建b2Body,没有b2BodyDef,b2Body不知道是什么类型,放在世界什么位置。
    2.b2Body通过b2FixtureDef创建b2Fixture,没有b2Fixture,b2Body不知道是什么形状,摩擦、弹性、密度都不知道。shpae提供了碰撞检测的外边框。

    下面分析片段代码:

    public class Box2DTutorial extends Sprite
    {
    //屏幕像素单位转换成物理世界的距离单位
    private const PIXEL_TO_METER:Number = 30;

    //物理世界
    private var world:Box2D.Dynamics.b2World;
    public function Box2DTutorial()
    {
    drawBackground();
    createWorld();
    createWall();
    createBall();
    createDebugDraw();
    addEventListener(Event.ENTER_FRAME, handleEnterFrame);
    }

    PIXEL_TO_METER实现像素到物理世界米的转换,通常情况下1米等于30像素,即物理世界移动1米,屏幕移动30像素。
    这里我们自定义了是个方法createWorld(), createWall(), createBall(), createDebugDraw(), 分别创建世界,墙,球体,和调试绘制。

    private function createWorld():void
    {
    //重力向量
    var gravity:b2Vec2 = new b2Vec2(0,9.0);
    //是否休眠
    var doSleep:Boolean = true;
    world = new b2World(gravity,doSleep);
    world.SetWarmStarting(true);
    }

    创建一个世界,我们需要重力向量,我们可以通过(0,0)创建零重力环境,通过(-1,0)创建负重力环境。正常世界的重力为(0,9.8)。doSleep用来设置物体停止移动时是否休眠,节省运算量。SetWarmStarting false设置初始化时刚体不受重力影响,除非受到外力作用之后。

    private function createWall():void
    {
    //1.需要创建的墙刚体
    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.刚体修饰物定义
    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(10/PIXEL_TO_METER, stage.stageHeight/2/PIXEL_TO_METER);

    //将形状添加到刚体修饰物
    leftWallFixtureDef.shape = leftWallShape;

    leftWall.CreateFixture(leftWallFixtureDef);

    这里主要涉及到了b2Body, b2BodyDef, b2Fixture, b2FixtureDef, b2PolygonShape, 通过几个对象的关系创建一个刚体。

    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.SetAlpha(1.0);
    //填充透明度
    debugDraw.SetFillAlpha(0.5);
    //设置显示对象
    debugDraw.SetFlags(b2DebugDraw.e_shapeBit);
    //物理世界缩放
    debugDraw.SetDrawScale(PIXEL_TO_METER);
    world.SetDebugDraw(debugDraw);
    }

    此处主要是绘制调试显示对象,没有它,所有的上面创建的都是物理世界的概念,抽象无形,不会以物体的形式显示出来。如果以后你为每个刚体设置了自定义外观,此处就不需要调试显示对象了。

    最后handleEnterframe实现每帧更新计算。

    完整代码如下:

      1 package
    2 {
    3 import Box2D.Collision.Shapes.b2CircleShape;
    4 import Box2D.Collision.Shapes.b2PolygonShape;
    5 import Box2D.Common.Math.b2Vec2;
    6 import Box2D.Dynamics.b2Body;
    7 import Box2D.Dynamics.b2BodyDef;
    8 import Box2D.Dynamics.b2DebugDraw;
    9 import Box2D.Dynamics.b2FixtureDef;
    10 import Box2D.Dynamics.b2World;
    11
    12 import flash.display.GradientType;
    13 import flash.display.Sprite;
    14 import flash.events.Event;
    15 import flash.geom.Matrix;
    16
    17 [SWF(width="500",height="300",frameRate="30")]
    18 public class Box2DTutorial extends Sprite
    19 {
    20 //屏幕像素单位转换成物理世界的距离单位
    21 private const PIXEL_TO_METER:Number = 30;
    22
    23 //物理世界
    24 private var world:Box2D.Dynamics.b2World;
    25 public function Box2DTutorial()
    26 {
    27 drawBackground();
    28 createWorld();
    29 createWall();
    30 createBall();
    31 createDebugDraw();
    32 addEventListener(Event.ENTER_FRAME, handleEnterFrame);
    33 }
    34
    35 private function createWorld():void
    36 {
    37 //重力向量
    38 var gravity:b2Vec2 = new b2Vec2(0,9.0);
    39 //是否休眠
    40 var doSleep:Boolean = true;
    41 world = new b2World(gravity,doSleep);
    42 //false时初始刚体不受重力影响,除非受力
    43 world.SetWarmStarting(true);
    44 }
    45
    46 private function createWall():void
    47 {
    48 //1.需要创建的墙刚体
    49 var leftWall:b2Body;
    50 //2.刚体定义
    51 var leftWallBodyDef:b2BodyDef = new b2BodyDef();
    52 //刚体类型和位置
    53 leftWallBodyDef.type = b2Body.b2_staticBody;
    54 //注意刚体的注册中心都是在物体的中心位置
    55 leftWallBodyDef.position.Set(10/PIXEL_TO_METER, stage.stageHeight/2/PIXEL_TO_METER);
    56 //工厂模式创建刚体
    57 leftWall = world.CreateBody(leftWallBodyDef);
    58
    59 //3.刚体修饰物定义
    60 var leftWallFixtureDef:b2FixtureDef = new b2FixtureDef();
    61 //密度
    62 leftWallFixtureDef.density = 1.0;
    63 //摩擦粗糙程度
    64 leftWallFixtureDef.friction = 0.3;
    65 //力度返回程度(弹性)
    66 leftWallFixtureDef.restitution = 1.0;
    67
    68 //4.创建墙形状
    69 var leftWallShape:b2PolygonShape = new b2PolygonShape();
    70 //此处参数为宽和高度的一半值
    71 leftWallShape.SetAsBox(10/PIXEL_TO_METER, stage.stageHeight/2/PIXEL_TO_METER);
    72
    73 //将形状添加到刚体修饰物
    74 leftWallFixtureDef.shape = leftWallShape;
    75
    76 leftWall.CreateFixture(leftWallFixtureDef);
    77
    78 //下面创建其他三面墙,共用leftwall的几个变量
    79 leftWallBodyDef.position.Set((stage.stageWidth-10)/PIXEL_TO_METER, stage.stageHeight/2/PIXEL_TO_METER);
    80 var rightWall:b2Body = world.CreateBody(leftWallBodyDef);
    81 rightWall.CreateFixture(leftWallFixtureDef);
    82
    83 leftWallBodyDef.position.Set( stage.stageWidth/2/PIXEL_TO_METER, (stage.stageHeight-10)/PIXEL_TO_METER);
    84 var bottomWall:b2Body = world.CreateBody(leftWallBodyDef);
    85 leftWallShape.SetAsBox(stage.stageWidth/2/PIXEL_TO_METER, 10/PIXEL_TO_METER);
    86 bottomWall.CreateFixture(leftWallFixtureDef);
    87
    88
    89 leftWallBodyDef.position.Set( stage.stageWidth/2/PIXEL_TO_METER, 10/PIXEL_TO_METER);
    90 var topWall:b2Body = world.CreateBody(leftWallBodyDef);
    91 topWall.CreateFixture(leftWallFixtureDef);
    92 }
    93
    94 private function createBall():void
    95 {
    96 for(var i:int = 0; i < 10; i++)
    97 {
    98 var ballDef:b2BodyDef = new b2BodyDef();
    99 ballDef.type = b2Body.b2_dynamicBody;
    100
    101 var circleShape:b2CircleShape = new b2CircleShape((10+Math.random()*20)/PIXEL_TO_METER);
    102 var ballFixtureDef:b2FixtureDef = new b2FixtureDef();
    103 ballFixtureDef.shape = circleShape;
    104 ballFixtureDef.density = 1.0;
    105 ballFixtureDef.restitution = 1.0;
    106 ballDef.position.Set(stage.stageWidth/2/PIXEL_TO_METER,20/PIXEL_TO_METER);
    107 var ball:b2Body = world.CreateBody(ballDef);
    108 ball.CreateFixture(ballFixtureDef);
    109
    110 }
    111 }
    112
    113 private function createDebugDraw():void
    114 {
    115 //创建一个sprite,可以将测试几何物体放入其中
    116 var debugSprite:Sprite = new Sprite();
    117 addChild(debugSprite);
    118 var debugDraw:b2DebugDraw = new b2DebugDraw();
    119 debugDraw.SetSprite(debugSprite);
    120 //设置边框厚度
    121 debugDraw.SetLineThickness(1.0);
    122 //边框透明度
    123 debugDraw.SetAlpha(1.0);
    124 //填充透明度
    125 debugDraw.SetFillAlpha(0.5);
    126 //设置显示对象
    127 debugDraw.SetFlags(b2DebugDraw.e_shapeBit);
    128 //物理世界缩放
    129 debugDraw.SetDrawScale(PIXEL_TO_METER);
    130 world.SetDebugDraw(debugDraw);
    131 }
    132
    133 private function handleEnterFrame(evt:Event):void
    134 {
    135 var timeStep:Number = 1/30;
    136 var velocityInterations:int = 10;
    137 var positionIterations:int = 10;
    138
    139 world.Step(timeStep,velocityInterations,positionIterations);
    140 //在2.1版本清除力,以提高效率
    141 world.ClearForces();
    142 //绘制
    143 world.DrawDebugData();
    144 }
    145
    146 private function drawBackground():void
    147 {
    148 var bg:Sprite = new Sprite();
    149 var matrix:Matrix = new Matrix();
    150 matrix.translate(100,100);
    151 bg.graphics.beginGradientFill(GradientType.RADIAL,[0xffffff,0xffaa00],[0.3,0.2],[0,255],matrix);
    152 bg.graphics.drawRect(0,0,stage.stageWidth,stage.stage.stageHeight);
    153 bg.graphics.endFill();
    154 addChild(bg);
    155 }
    156 }
    157 }

    欢迎访问我的博客

  • 相关阅读:
    12-认识容量和升(四上)
    11 认识1-5(一上)
    10 圆柱的表面积(六下)
    009 单式折线统计图(五下)
    008 解决问题的策略 转化(苏教版 五下)
    007 分数的基本性质(五下)
    006 三位数乘两位数(四上)
    kafka,MQ消息队列
    005 圆的周长(六上)
    004 平行四边形的面积(五上)
  • 原文地址:https://www.cnblogs.com/jinglehit/p/2313115.html
Copyright © 2011-2022 走看看