linux编译box2d,服务器端Box2D入门

本文介绍了如何在没有图形界面的Linux服务器上安装Box2D,这是一个用于游戏的2D刚体仿真库。通过修改CMakeCache.txt文件,禁用示例构建,然后使用cmake和make安装。接着,文章提供了一个基础的Box2D使用示例,创建了一个无重力的2D场景,包含两个动态物体并施加力,展示了物体的碰撞和运动。通过调整时间步长和迭代次数,实现了物理模拟的精确控制。
摘要由CSDN通过智能技术生成

Box2D是一个用于游戏的2D刚体仿真库。它的核心目的是为了模拟真实的2D环境,让物体运动更加真实,交互性更好。本文主要介绍一些使用Box2D的基础知识,并且记录如何在没有图形化界面的Linux服务器上使用它。(例子就是我使用的这台:D)。8e362a3c62e80effd3328cac5e64c5a6.gif

开始准备安装Box2D

$git clone https://github.com/erincatto/Box2D

完成之后因为没有图形化界面,去CMakeCache.txt中把BOX2D_BUILD_EXAMPLES设置从ON改成OFF

$cd Box2D/Box2D/Build/ && vim CMakeCache.txt

然后用cmake创建makefile,这里如果有库的缺失补全一下就可以了

$cmake ..

然后直接make会有一处编译错误,找到地方把”nullptr”改成”NULL”或者0

$make

$sudo make install

$locate Box2D

最后使用locate Box2D查看Box2D的安装情况,默认是在/usr/local/相关目录,至此安装完毕。

一些基础知识

世界(world)

虚拟化的物理时间,里面包含了各类刚体的演算。

刚体(rigid body)

最基础的单位,代表一个不会发生形变的实体,我们通常用body来指代刚体。

夹具(fixture)

个人喜欢叫它为材质,依附在刚体上,约束刚体的形状(shape),密度(density),摩擦(friction),恢复(restitution)等特性。

单位

使用米-千克-秒(MKS)单位制。

场景测试

一个无重力环境的2D场景,正方形40mx40m,正方形边是厚2m的静态围墙,正方形的中心是世界中心;

有bodyA(正方形2mx2m,坐标-10.0f, 10.0f)与bodyB(正方形2mx2m,坐标10.0f, 10.0f),对A施加一个向右的力,对B施加一个向左的力;

示意图:Box2D%E4%B8%80.png

详细的释义直接附加在代码里:

//file:myBox2D.cpp

#include ;

#include ;

#include ;

int32_t main()

{

//创建世界

b2Vec2 gravity(0.0f, -0.0f); //无重力,若要设置自然重力为(0.0f, -9.8f)

b2World world(gravity);

world.SetAllowSleeping(false); //静止的物理也会参与碰撞检测

//构建一个边长40m正方形

//创建下面围墙

b2BodyDef wall;

b2PolygonShape wallBox;

wall.type = b2_staticBody;

wall.position.Set(0.0f, -1.0f);

b2Body *wallDown = world.CreateBody(&wall);

//下面围墙的形状

wallBox.SetAsBox(20.0f, 1.0f);

//设置材质

wallDown->CreateFixture(&wallBox, 0.0f);

//创建上面围墙

wall.position.Set(0.0f, 21.0f);

b2Body *wallUp = world.CreateBody(&wall);

//上面围墙的形状

wallBox.SetAsBox(20.0f, 1.0f);

//设置材质

wallUp->CreateFixture(&wallBox, 0.0f);

//创建左面的围墙

wall.position.Set(-21.0f, 20.0f);

b2Body *wallLeft = world.CreateBody(&wall);

//左面围墙的形状

wallBox.SetAsBox(1.0f, 20.0f);

wallLeft->CreateFixture(&wallBox, 0.0f);

//创建右面的围墙

wall.position.Set(21.0f, 20.0f);

b2Body *wallRight = world.CreateBody(&wall);

//右面围墙的形状

wallBox.SetAsBox(1.0f, 20.0f);

wallRight->CreateFixture(&wallBox, 0.0f);

//创建二个动态的body

b2BodyDef bodyDefA;

bodyDefA.type = b2_dynamicBody;

bodyDefA.position.Set(-10.0f, 10.0f);

b2Body *bodyA = world.CreateBody(&bodyDefA);

b2BodyDef bodyDefB;

bodyDefB.type = b2_dynamicBody;

bodyDefB.position.Set(10.0f, 10.0f);

b2Body *bodyB = world.CreateBody(&bodyDefB);

//为这个动态bodyA设置形状

b2PolygonShape dynamicBox;

dynamicBox.SetAsBox(1.0f, 1.0f);

//为这个动态body设置材质

b2FixtureDef fixtureDef;

fixtureDef.shape = &dynamicBox;

fixtureDef.density = 1.0f; //密度

fixtureDef.friction = 0.3f; //摩擦系数

fixtureDef.restitution = 1.0f; //恢复系数

bodyA->CreateFixture(&fixtureDef);

bodyB->CreateFixture(&fixtureDef);

//施加一点力

bodyA->ApplyLinearImpulse(b2Vec2(10, 0), bodyA->GetWorldCenter(), true);

bodyB->ApplyLinearImpulse(b2Vec2(-10, 0), bodyB->GetWorldCenter(), true);

//迭代的时间间隔,这里是1秒60次

float32 timeStep = 1.0f / 60.0f;

int32 velocityIterations = 6; //碰撞时速度迭代

int32 positionIterations = 2; //碰撞时位置迭代

for (int32 i = 0; i < 600; ++i) {

world.Step(timeStep, velocityIterations, positionIterations);

b2Vec2 positionA = bodyA->GetPosition();

float32 angleA = bodyA->GetAngle();

printf("A %4.2f %4.2f %4.2f\n", positionA.x, positionA.y, angleA);

b2Vec2 positionB = bodyB->GetPosition();

float32 angleB = bodyB->GetAngle();

printf("B %4.2f %4.2f %4.2f\n", positionB.x, positionB.y, angleB);

for (b2Contact* c = world.GetContactList(); c; c = c->GetNext()) {

b2Body *A = c->GetFixtureA()->GetBody();

b2Body *B = c->GetFixtureB()->GetBody();

b2Vec2 positionA = A->GetPosition();

float32 angleA = A->GetAngle();

b2Vec2 positionB = B->GetPosition();

float32 angleB = B->GetAngle();

printf("b2Contact A:%4.2f %4.2f %4.2f|B:%4.2f %4.2f %4.2f\n",

positionA.x, positionA.y, angleA, positionB.x, positionB.y, angleB);

}

}

return 0;

}

编译后可查看效果

$g++ -o test myBox2D.cpp -lBox2D

$./test

关于代码的一些解释

b2BadyDef的type类型:

b2_staticBody:静态物理,质量无穷大,不会因为碰撞移动;不会和其它static或kinematic物体相互碰撞,例如上面样例的围墙;

b2_kinematicBody:可以行动的、质量无穷大的;

b2_dynamicBody:可以受力运动,也可以根据用户指令固定移动;拥有完整的fixtures各种特性;

关于fixtures:

形状(shape),密度(density),摩擦(friction)从字面意思就比较好理解了,说一下恢复(restitution):

官方文档给的释义:恢复可以使对象弹起。恢复的值通常设置在0到1之间。想象一个小球掉落到桌子上,值为0表示着小球不会弹起, 这称为非弹性碰撞。值为1表示小球的速度跟原来一样,只是方向相反,这称为完全弹性碰撞。

若2个均有restitution的刚体碰撞,那么取最大的restitution作为最终计算值。

关于施加力:

ApplyForce:增加力;

ApplyLinearImpulse:增加冲量;具体怎么换算为速度未知,同等单位下,相同时间比ApplyForce运动的更远;

ApplyTorque:角力矩;

ApplyAngularImpulse:角动量;

SetTransform:瞬移物体;

关于迭代:

时间迭代:可以抽象成帧的概念,比如我们需要一秒60帧那么就是float32 timeStep = 1.0f / 60.0f;

碰撞时速度、碰撞时位置迭代:核心是用来检测碰撞物体的相对位置,以及碰撞后的位移;如果值太小,会出现一个物理运动另外一个物理“内部”再碰撞;值越高就越接近真实物理,当然运算负载也越大;

个人觉得Box2D在接口设计上面非常合理,迭代逻辑与业务的主逻辑契合比较紧密(基于帧的概念),看后续有没有机会继续深入使用,若有使用还会更新进阶篇。

(全文结束)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值