Box学习

Box2d源码分析(刚体)

2021-09-23  本文已影响0人  大旺旺的弟弟小旺旺

概述中知道了什么是世界,如何模拟世界重力,以及时间步和另外两个参数的使用,以及意义。世界的存在,有了物体才可以更加的完美。
刚体就是世界中的物体,可以仿真各种物体,对世界中物体的操作基本 就是对刚体的操作。
1.刚体定义
2.创建并加入到世界中
3.刚体的形状
4.显示出刚体的调试视图

刚体

a rigid Body,一般的看到的万物的形状都可以看作是刚体,刚体也是学习的核心,可以用来模拟所有的物体,它可以模拟出碰撞、反弹、运动轨迹等各种物体现象模拟和数据都是基于刚体实现的,所以属性比较多,位置、速度、质量、反弹系数等。

创建刚体

创建刚体,不仅仅是创建一个刚体,还需要创建bodyDef和fixtureDef,共同创建出来。

BodyDef bodyDef = new BodyDef();
bodyDef.type = this.type;
bodyDef.position.set(getX(Align.center),getY(Align.center));
this.body = Constant.world.createBody(bodyDef);
if (shape == null){
   PolygonShape polygonShape = new PolygonShape();
   polygonShape.setAsBox(getWidth()/2 , getHeight()/2);
   shape = polygonShape;
}
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
if (categoryBits != -1){
  fixtureDef.filter.categoryBits = categoryBits;
}
if (maskBits != -1) {
     fixtureDef.filter.maskBits = (short) maskBits;
}
fixtureDef.density = 100;
body.createFixture(fixtureDef);
shape.dispose();
body.setUserData(this);

源码分析世界创建body的过程。

long bodyAddr = 
        jniCreateBody(addr, 
                            def.type.getValue(),
                            def.position.x, 
                            def.position.y, 
                            def.angle, 
                            def.linearVelocity.x,
                            def.linearVelocity.y, 
                            def.angularVelocity, 
                            def.linearDamping, 
                            def.angularDamping, 
                            def.allowSleep, 
                            def.awake,
                            def.fixedRotation, 
                            def.bullet, 
                            def.active, 
                            def.gravityScale);
Body body = freeBodies.obtain();
body.reset(bodyAddr);
this.bodies.put(body.addr, body);
return body;

reset方法

protected void reset (long addr) {
    this.addr = addr;
    this.userData = null;
    for (int i = 0; i < fixtures.size; i++)
            this.world.freeFixtures.free(fixtures.get(i));
            fixtures.clear();
            this.joints.clear();
    }
}

创建body,body有fixturedef和joints以及userData.;将他们清掉。
这个创建和c++创建有一些区别,等下面补充的时候在加。

夹具

fixture的使用,夹具是一个固定设施,用来定义一些属性,材料本身的特性,比如摩擦力、密度、质量等。它可以设置刚体的形状,如果没有形状是不可以进行碰撞模拟的。
一般的常见图形有园和矩形,还有一些简单的 。对于fixtureDef只是短暂停的存储,它里面有属性fixture,我没让你创建的时候也是将数据在复制到fixture。并且fixtrue必须依附在刚体上才可以有作用,比如你的躯体脱离了你这个人,只是一个行尸走肉,并没有什么用户,一个刚体可以包含不止一个。
比如一个人,头部的硬度和肚子的硬度反弹系数不同,我们就需要创建两个。也就说刚体创建之后可以对其在增加fixture,实现形状的组合

FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.shape = shape;
        if (categoryBits != -1){
            fixtureDef.filter.categoryBits = categoryBits;
        }
        if (maskBits != -1) {
            fixtureDef.filter.maskBits = (short) maskBits;
        }
        fixtureDef.density = 100;
        body.createFixture(fixtureDef);
      

源码实现

 public final Fixture createFixture(FixtureDef def) {
    assert (m_world.isLocked() == false);

    if (m_world.isLocked() == true) {
      return null;
    }

    Fixture fixture = new Fixture();
    fixture.create(this, def);

    if ((m_flags & e_activeFlag) == e_activeFlag) {
      BroadPhase broadPhase = m_world.m_contactManager.m_broadPhase;
      fixture.createProxies(broadPhase, m_xf);
    }

    fixture.m_next = m_fixtureList;
    m_fixtureList = fixture;
    ++m_fixtureCount;

    fixture.m_body = this;

    // Adjust mass properties if needed.
    if (fixture.m_density > 0.0f) {
      resetMassData();
    }

    // Let the world know we have a new fixture. This will cause new contacts
    // to be created at the beginning of the next time step.
    m_world.m_flags |= World.NEW_FIXTURE;

    return fixture;
  }

创建一个 fixture,然后将创建好的fixtureDef传入 进行初始化,然后将其加入到清单中,最后将fixture设置给body对象,将fixture回传。这个时候图形就没有什么作用了,可以进行清楚操作。

如何理解bodydef和fixturedef

BodyDef:在创建之前将刚体的属性准备好, 创建的时候将属性值传递给内部的私有属性。数据传递之后,他就没有啥用处了,可以继续使用,重新修改,让下一个继续使用。所以无法使用bodydef来修改属性。需要修改可以通过下面的方法

body.setActive(xxx);
body.getTransform().setPosition();
image.png

bodyDef对应body中的属性修改。对于fixture也是一样的。


image.png

我们创建之后需要可以使用上面的方法对属性进行修改。

形状

刚体的形状,在世界模拟中,根据形状进行碰撞模拟。我们也了解到刚体的形状可以根据多个fixture进行组合而成,也就是说它们可以加入多个fixture.

圆形

圆形创建就很简单了,只有一个参数半径就可以了,默认值是0,这里创建的单位都是米,他和像素的转换关系为 30px = 1m;将创建的图形传给你夹具就是我们创建出刚体的形状。

矩形

创建矩形可以使用PolygonShape创建它是一个多边形的类,他没有什么构造函数,但是可以调用相应的函数来返回相应的形状。,比如矩形可使用setAsBox创建。
sexAsBox的使用以刚体的中心坐标位置为中心点的矩形,及就是宽和高都是i相对于刚体坐标位置对称的,需要传入两个参数宽和高。这里是半宽实际的宽和高是传入的二倍。并且像素和宽高的对应关系
需要进行转换,比如创建一个60x100的矩形,需要传入的参数是30/30 50/30;

回顾一下

创建def,创建body,创建fixture 创建图形 添加fixture.

看到效果

打开调试视图,box2d是一个引擎,我们并不可以看到,需要我们打开调试试图,否则就一无所有。
我们可以使用step进行模拟,在模拟之后调用调试视图得到显示的状态

上一篇下一篇

猜你喜欢

热点阅读