在本文中,将探讨如何使用Box2D物理引擎在Mocrif中创建一个自行车模拟游戏。Box2D是一个广泛应用于2D游戏的物理引擎,它通过模拟物体之间的相互作用来实现逼真的物理效果。将通过一个简单的自行车模型来展示这一过程,最终实现一个可以运行的游戏草稿。
Box2D物理引擎由物体和连接它们的关节组成。这些关节允许物体之间有一定的运动,但同时也限制了它们的相对旋转。在本文的示例中,将使用棱柱关节和旋转关节。棱柱关节允许两个物体沿指定轴进行平移,而旋转关节则允许两个物体围绕锚点进行相对旋转。此外,一些关节如旋转关节和棱柱关节还支持限制(限制关节运动)和马达(强制关节运动)。
自行车模型由五个物体组成,它们通过关节连接在一起。自行车的主要部分是车架,其他部件都连接在车架上。车架用于施加角动量,从而实现自行车的旋转。自行车的位置也由车架的中心决定。车轮通过前减震器和后减震器连接到车架上。
在创建自行车模型时,首先需要定义自行车各个部件的多边形形状。然后,将使用Mocrif SDK中的函数来创建这些多边形物体。这些物体都是动态的,它们将完全被模拟并与其他静态物体(如地面和跳跃物)发生碰撞。
function create(scene, x, y) {
var shape = [
{x:-30, y:-82},
{x:100, y:-42},
{x:50, y:82},
{x:38, y:80},
{x:-98, y:46},
{x:-92, y:-76}
];
this._frame = scene.addPolygonBody(
this._images.frame, #dynamic,
1.0,
0.0,
0.0, shape);
this._frame.z = 2;
this._frame.setPosition(x, y);
// FRONT
this._frontDamper = scene.addPolygonBody(
this._images.frontDamper, #dynamic,
1.0,
0.0,
0.0,
this._images.frontDamper.width,
this._images.frontDamper.height);
this._frontDamper.z = 3;
this._frontDamper.setPosition(x + 96, y + 35);
this._frontWheel = scene.addCircleBody(
this._images.wheel, #dynamic,
1.2,
1.0,
0.0,
this._images.wheel.width / 2);
this._frontWheel.z = 2;
this._frontWheel.setPosition(x + 113, y + 73);
// BACK
this._backDamper = scene.addPolygonBody(
this._images.backDamper, #dynamic,
1.0,
0.0,
0.0,
this._images.backDamper.width,
this._images.backDamper.height);
this._backDamper.z = 3;
this._backDamper.setPosition(x - 80, y + 70);
this._backWheel = scene.addCircleBody(
this._images.wheel, #dynamic,
1.2,
1.0,
0.0,
this._images.wheel.width / 2);
this._backWheel.z = 2;
this._backWheel.setPosition(x - 120, y + 80);
}
现代自行车通常在两个轮子上都装有减震器,它们可以使骑行更加舒适和安全。为了使模拟更加逼真,模型也支持减震器。
前减震器的主要部分是一个棱柱关节,它连接车架和前减震器。这个棱柱关节有一个马达,它试图用一定的力将车架向上移动。然而,关节的上限限制了它的运动,这意味着车架只能移动到上限。如果前轮碰到障碍物,前减震器会受到力的影响,试图向上移动。这个力大于关节的最大力,导致前减震器向上移动,更接近车架。最后,当前轮越过障碍物时,前减震器上的力变小,关节可以将减震器移动到较低的位置。
后减震器使用旋转关节。旋转关节也支持限制和马达,但它们是通过角度而不是距离来定义的。后减震器围绕车架上的一个点旋转。限制限制了关节的旋转,而马达则强制其旋转。
// JOINTS
// connect front damper onto frame
var jointDef = {
lowerTranslation : -0.2,
upperTranslation : 0.0,
enableLimit : true,
enableMotor : true,
motorSpeed : 2.0,
maxMotorForce : this._frame.getMass() * 9.8,
}
this._joints.push(scene.createPrismaticJoint(
this._frontDamper,
this._frame, x + 96, y + 35,
-0.4,
1.0,
0.0, jointDef,
false));
// connect back damper onto frame
jointDef = {
enableMotor : true,
maxMotorTorque : 150,
motorSpeed : -0.9,
lowerAngle : 0.2,
upperAngle : 0.45,
enableLimit : true,
}
this._joints.push(scene.createRevoluteJoint(
this._backDamper,
this._frame, x - 50, y + 55,
jointDef,
false));
自行车通常由后轮驱动。两个车轮都通过旋转关节连接到减震器,没有限制。后轮通过带有马达的旋转关节连接,以加速或减速自行车。
/ front wheel - without motor
this._joints.push(scene.createRevoluteJoint(
this._frontDamper,
this._frontWheel, x + 113, y + 73,
null,
false));
// back wheel - with motor
jointDef = {
enableMotor : true,
maxMotorTorque : 1500000,
motorSpeed : -2.0,
}
this._motorJoint = scene.createRevoluteJoint(
this._backDamper,
this._backWheel, x - 120, y + 80,
jointDef,
false);
自行车还会定期施加角动量。角动量的施加允许在跳跃后创建翻转或稳定自行车。
// apply angular impulse in regular intervals. The angular damping allows to create flip or stabilize bike after jump
this._angularImpulse = 0.0;
var process = new Timer(50, true);
process.onTick = function() {
this.super._frame.applyAngularImpulse(this.super._angularImpulse);
}
process.start(50);
function pointerDragged (x, y, pointer) {
super.pointerDragged(x, y);
var maxSpeed = 33;
var maxPlayer = 1.4 * this._bike.getMass();
if (y < System.height / 2 - 150)
y = System.height / 2 - 150;
else if (y > System.height / 2 + 150)
y = System.height / 2 + 150;
if (x > 3 * System.width / 4) {
this._bike.player = (System.height / 2.0 - y) / 150 * maxPlayer;
this._anglePaint.shader = this._createAngleShader(y);
}
else if (x < System.width / 4){
this._bike.speed = -1 * (System.height / 2.0 - y) / 150 * maxSpeed;
this._speedPaint.shader = this._createSpeedShader(y);
}
}