Skip to content

Commit

Permalink
feat!: allow modifying gravity in the x-axis and y-axis (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
alestiago committed Apr 6, 2022
1 parent e943a56 commit c14b424
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 7 deletions.
9 changes: 7 additions & 2 deletions packages/forge2d/lib/src/dynamics/body.dart
Expand Up @@ -57,7 +57,12 @@ class Body {

double linearDamping = 0.0;
double angularDamping = 0.0;
double gravityScale = 0.0;

/// {@macro dynamics.body_def.gravity_override}
Vector2? gravityOverride;

/// {@macro dynamics.body_def.gravity_scale}
Vector2? gravityScale;

double sleepTime = 0.0;

Expand All @@ -67,7 +72,6 @@ class Body {
Body(final BodyDef bd, this.world)
: assert(!bd.position.isInfinite && !bd.position.isNaN),
assert(!bd.linearVelocity.isInfinite && !bd.linearVelocity.isNaN),
assert(bd.gravityScale >= 0.0),
assert(bd.angularDamping >= 0.0),
assert(bd.linearDamping >= 0.0) {
flags = 0;
Expand Down Expand Up @@ -103,6 +107,7 @@ class Body {

linearDamping = bd.linearDamping;
angularDamping = bd.angularDamping;
gravityOverride = bd.gravityOverride;
gravityScale = bd.gravityScale;

force.setZero();
Expand Down
24 changes: 21 additions & 3 deletions packages/forge2d/lib/src/dynamics/body_def.dart
Expand Up @@ -21,7 +21,8 @@ class BodyDef {
this.fixedRotation = false,
this.bullet = false,
this.active = true,
this.gravityScale = 1.0,
this.gravityOverride,
this.gravityScale,
}) : position = position ?? Vector2.zero(),
linearVelocity = linearVelocity ?? Vector2.zero();

Expand Down Expand Up @@ -87,6 +88,23 @@ class BodyDef {
/// Does this body start out active?
bool active;

/// Experimental: scales the inertia tensor.
double gravityScale;
/// {@template dynamics.body_def.gravity_override}
/// Changes how the [World] treats the gravity for this body.
///
/// Specifying a [gravityOverride] overrides the world's gravity. For example,
/// if [World.gravity] is (0, -10), and a body has a [gravityOverride] of
/// (0, 0) the body will behave as if the world does not have a gravity.
///
/// If you wish to modify the gravity relative to the world, use
/// [World.gravity] as part of the calculation. However, if you only wish to
/// scale it, use [gravityScale] instead.
/// {@endtemplate}
Vector2? gravityOverride;

/// {@template dynamics.body_def.gravity_scale}
/// Multiplier for the body's gravity.
///
/// If [gravityOverride] is specified, this value also affects it.\
/// {@endtemplate}
Vector2? gravityScale;
}
9 changes: 7 additions & 2 deletions packages/forge2d/lib/src/dynamics/island.dart
Expand Up @@ -184,8 +184,13 @@ class Island {

if (b.bodyType == BodyType.dynamic) {
// Integrate velocities.
v.x += dt * (b.gravityScale * gravity.x + b.inverseMass * b.force.x);
v.y += dt * (b.gravityScale * gravity.y + b.inverseMass * b.force.y);
final bodyGravity = b.gravityOverride ?? gravity;
v.x += dt *
((b.gravityScale?.x ?? 1) * bodyGravity.x +
b.inverseMass * b.force.x);
v.y += dt *
((b.gravityScale?.y ?? 1) * bodyGravity.y +
b.inverseMass * b.force.y);
w += dt * b.inverseInertia * b.torque;

// Apply damping.
Expand Down
79 changes: 79 additions & 0 deletions packages/forge2d/test/dynamics/body_test.dart
@@ -0,0 +1,79 @@
import 'package:forge2d/forge2d.dart';
import 'package:test/expect.dart';
import 'package:test/scaffolding.dart';

void main() {
group('Body', () {
group('gravityOverride', () {
test("body doesn't move when is zero", () {
final gravity = Vector2(10, 10);
final world = World(gravity);

final body = world.createBody(
BodyDef()
..type = BodyType.dynamic
..gravityOverride = Vector2.zero(),
);

final bodyInitialPosition = body.position.clone();

world.stepDt(1);

expect(bodyInitialPosition.x, equals(body.position.x));
expect(bodyInitialPosition.y, equals(body.position.y));
});

test(
"body moves with world's gravity "
'when gravityOverride is not specfied', () {
final gravity = Vector2(10, 10);
final world = World(gravity);

final body = world.createBody(BodyDef()..type = BodyType.dynamic);

final bodyInitialPosition = body.position.clone();

world.stepDt(1);

expect(bodyInitialPosition.x, isNot(equals(body.position.x)));
expect(bodyInitialPosition.y, isNot(equals(body.position.y)));
});
});

group('gravityScale', () {
test("body doesn't move when is zero", () {
final gravity = Vector2(10, 10);
final world = World(gravity);

final body = world.createBody(
BodyDef()
..type = BodyType.dynamic
..gravityScale = Vector2.zero(),
);

final bodyInitialPosition = body.position.clone();

world.stepDt(1);

expect(bodyInitialPosition.x, equals(body.position.x));
expect(bodyInitialPosition.y, equals(body.position.y));
});

test(
"body moves with world's gravity "
'when gravityScale is not specfied', () {
final gravity = Vector2(10, 10);
final world = World(gravity);

final body = world.createBody(BodyDef()..type = BodyType.dynamic);

final bodyInitialPosition = body.position.clone();

world.stepDt(1);

expect(bodyInitialPosition.x, isNot(equals(body.position.x)));
expect(bodyInitialPosition.y, isNot(equals(body.position.y)));
});
});
});
}

0 comments on commit c14b424

Please sign in to comment.