欢迎光临散文网 会员登陆 & 注册

Egret-Box2d (一)

2020-10-28 23:37 作者:抑制住a  | 我要投稿

按照官方文档学习的记录,由于文档是英文的,所以本文中的截图都是经过百度翻译过的,box2d github地址:https://github.com/flyover/box2d.ts

首先要创建一个放置物体的地方,也就是box2dWorld,简称为b2World,其中x和y就是重力的大小和方向了,y:10也就是重力加速度。

 this.world = new b2World({ x: 0, y: 10 });

有了世界还需要有地面,这里就涉及到单位转换了,box2d使用的是MKS单位,也就是米、千克、秒,并不是我们常用的px(像素),由百度可知,1 米=30 像素。

let groundBodyDef = new b2BodyDef();

groundBodyDef.position.Set(0, 300 / 30);//此处就是把300像素转换成10米

groundBodyDef.type = b2BodyType.b2_staticBody;//地面是不会动的,所以设置为静态的

上面的只是对物体进行定义,然后开始创建一个物体

 let groundBody = this.world.CreateBody(groundBodyDef);

接下来是对物体的形状进行设置

 let groundBox = new b2PolygonShape();//这是个矩形

 groundBox.SetAsBox(500 / 2 / 30, 30 / 2 / 30);

//这里有个500 / 2 / 30,是不是感觉很诡异?

根据官方文档解释,SetAsBox的参数是半宽半高,所以要除以2,后面的除以30是单位转换

然后给物体添加上这个形状,后面的1是这个物体的密度,因为物体都是有密度的,所以不写的话可能会出现奇怪的bug,这个方法还有其他的重载,所以密度写在其他地方也可以

groundBody.CreateFixture(groundBox, 1);

然后地面就创建好了,不过运行起来还是什么都看不到的,因为box2d不自带渲染,然后我也找不到合适的b2debugdraw,我也不想自己写,就先用egret做个矩形吧

let rect = new egret.Sprite();

rect.graphics.beginFill(Math.random() * 0xffffff);

rect.graphics.drawRect(0, 0, 500, 30);

rect.graphics.endFill();

rect.anchorOffsetX = 500 / 2;

rect.anchorOffsetY = 30 / 2;

rect.x=0;

rect.y=300;

groundBodyDef.userData = rect;//这里的userData用于存一些东西

this.addChild(rect);

然后运行起来就能发现创建的地面了

然后我们来创建一个牛顿的苹果,还是上面的操作,只是把静态改成动态了。

let appleDef = new b2BodyDef();

appleDef.type = b2BodyType.b2_dynamicBody;//动态的

appleDef.position.Set(30 / 30, 30 / 30);

因为苹果可以受到力的影响,所以要给他添加一下材质(也叫夹具),就是密度、摩擦、形状等。

let fixDef = new b2FixtureDef();//这个就是材质

let appleShape = new b2PolygonShape();

appleShape.SetAsBox(50 / 2 / 30, 50 / 2 / 30);

fixDef.shape = appleShape;

fixDef.density = 1.0;//这个就是之前提到过的密度

fixDef.friction = 0.3;//这个是摩擦

fixDef.restitution = 0.2;//掉在地上弹起来的效果

this.world.CreateBody(appleDef).CreateFixture(fixDef);//添加到世界中

然后为了方便实用,把之前那个创建矩形(egret的那个)封装一下

createRect(x, y, width, height) {

        let rect = new egret.Sprite();

        rect.graphics.beginFill(Math.random() * 0xffffff);

        rect.graphics.drawRect(0, 0, width, height);

        rect.graphics.endFill();

        rect.anchorOffsetX = width / 2;

        rect.anchorOffsetY = height / 2;

        rect.x = x;

        rect.y = y;

        return rect;

    }

然后让苹果显示出来

appleDef.userData = this.createRect(30, 30, 50, 50);

this.addChild(appleDef.userData);

这是我们运行一下,会发现苹果是掉不下来的,因为我们还没有把box2d启动起来

//在合适的地方添加监听

this.addEventListener(egret.Event.ENTER_FRAME, this.loop, this);

//每帧调用这个方法

loop() {

        this.world.Step(1 / 60, 6, 2);

        for (var bodyIndex: b2Body = this.world.GetBodyList(); bodyIndex; bodyIndex = bodyIndex.GetNext()) {

            if (bodyIndex.m_userData != null) {

                bodyIndex.m_userData.x = bodyIndex.GetPosition().x * 30

                bodyIndex.m_userData.y = bodyIndex.GetPosition().y * 30

                bodyIndex.m_userData.rotation = bodyIndex.GetAngle() * 180 / Math.PI;

            }

        }

    }

上面的Step中的第一个参数是时间步长,1 / 60相当于六十分之一秒执行一次,也就是60hz,后边那两个参数为什么写6和2,就看官网的解释吧。


后面的for循环就是遍历每一个物体,并改变他的位置和角度,注意box2d用的是弧度制,不是角度值,而且还要进行单位的转换。


效果图

还可以添加多个

box2d 文档地址:https://box2d.org/documentation/md__d_1__git_hub_box2d_docs_hello.html



















Egret-Box2d (一)的评论 (共 条)

分享到微博请遵守国家法律