Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Added a page for Joints documentation + ConstantVolumeJoint doc and example #2362

Merged
merged 13 commits into from
Feb 26, 2023
1 change: 1 addition & 0 deletions doc/bridge_packages/flame_forge2d/flame_forge2d.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
:hidden:

Overview <forge2d.md>
Joints <joints.md>
```
67 changes: 67 additions & 0 deletions doc/bridge_packages/flame_forge2d/joints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Joints

Joints are used to connect two different bodies together in various ways.
They help to simulate interactions between objects to create hinges, wheels, ropes, chains etc.

One `Body` may be `BodyType.static`.
eukleshnin marked this conversation as resolved.
Show resolved Hide resolved
Joint between `BodyType.static` and/or `BodyType.kinematic` are allowed,
eukleshnin marked this conversation as resolved.
Show resolved Hide resolved
but have no effect and use some processing time.

To construct a `Joint`, you need to create a corresponding subclass of `JointDef` and init it with parameters.
eukleshnin marked this conversation as resolved.
Show resolved Hide resolved

To register a `Joint` use `world.createJoint` and to remove `world.destroyJoint`.
eukleshnin marked this conversation as resolved.
Show resolved Hide resolved


## Built-in joints

Currently, Forge2D supports following joints:
eukleshnin marked this conversation as resolved.
Show resolved Hide resolved

- [`ConstantVolumeJoint`](#constantvolumejoint)
- DistanceJoint
- FrictionJoint
- GearJoint
- MotorJoint
- MouseJoint
- PrismaticJoint
- PulleyJoint
- RevoluteJoint
- RopeJoint
- WeldJoint
- WheelJoint


### `ConstantVolumeJoint`

This type of joint connects a group of bodies together and maintains a constant volume within them.
Essentially, it is a set of `DistantJoint`, that connects all bodies one after another.
eukleshnin marked this conversation as resolved.
Show resolved Hide resolved

It might be useful for "soft-bodies" simulation.
eukleshnin marked this conversation as resolved.
Show resolved Hide resolved

```{flutter-app}
:sources: ../../../packages/flame_forge2d/example
:page: constant_volume_joint
:show: widget code infobox
:width: 200
:height: 200
```

```dart
final constantVolumeJoint = ConstantVolumeJointDef()
..frequencyHz = 10
..dampingRatio = 0.8;

bodies.forEach((body) {
constantVolumeJoint.addBody(body);
});

world.createJoint(ConstantVolumeJoint(world, constantVolumeJoint));
```

`ConstantVolumeJointDef` requires at least 3 bodies to be added using `addBody` method.
eukleshnin marked this conversation as resolved.
Show resolved Hide resolved

Optional param `frequencyHz` defines the frequency of oscillation of the joint.
If it's not 0, the higher the value is, the less springy each of the compound `DistantJoint` is.
eukleshnin marked this conversation as resolved.
Show resolved Hide resolved

Another optional param `dampingRatio` defines how fast the oscillation comes to rest.
eukleshnin marked this conversation as resolved.
Show resolved Hide resolved
It takes values from 0 to 1, where 0 = no damping, 1 = critical damping.

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import 'dart:math';

import 'package:flame/input.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flame_forge2d_example/utils/ball.dart';
import 'package:flame_forge2d_example/utils/walls.dart';

class ConstantVolumeJointExample extends Forge2DGame with TapDetector {
@override
Future<void> onLoad() async {
super.onLoad();
addAll(createBoundaries(this));
}

@override
Future<void> onTapDown(TapDownInfo details) async {
super.onTapDown(details);
final tap = details.eventPosition.game;
eukleshnin marked this conversation as resolved.
Show resolved Hide resolved

const numPieces = 20;
const radius = 5.0;
final center = tap;
final balls = <Ball>[];

for (var i = 0; i < numPieces; i++) {
final xPos = radius * cos(2 * pi * (i / numPieces));
eukleshnin marked this conversation as resolved.
Show resolved Hide resolved
final yPos = radius * sin(2 * pi * (i / numPieces));

final ball = Ball(Vector2(xPos + center.x, yPos + center.y), radius: 0.5);

add(ball);
balls.add(ball);
}

await Future.wait(balls.map((e) => e.loaded));

createJoint(balls);
}

void createJoint(List<Ball> balls) {
final constantVolumeJoint = ConstantVolumeJointDef()
..frequencyHz = 10
..dampingRatio = 0.8;

balls.forEach((ball) {
constantVolumeJoint.addBody(ball.body);
});

world.createJoint(ConstantVolumeJoint(world, constantVolumeJoint));
}
}
29 changes: 24 additions & 5 deletions packages/flame_forge2d/example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
import 'dart:html';

import 'package:flame/game.dart';
import 'package:flame_forge2d_example/joints/constant_volume_joint.dart';
import 'package:flutter/widgets.dart';

void main() {
// There will be a new example in here after Google I/O, stay tuned!
// If you want to see the previous examples, go to the flame_forge2d section
// of https://examples.flame-engine.org
// The source code lives here:
// https://github.com/flame-engine/flame/tree/main/examples/lib/stories/bridge_libraries/forge2d
var page = window.location.search ?? '';
if (page.startsWith('?')) {
page = page.substring(1);
eukleshnin marked this conversation as resolved.
Show resolved Hide resolved
}
final routes = <String, Game Function()>{
'constant_volume_joint': ConstantVolumeJointExample.new,
};
final game = routes[page]?.call();
if (game != null) {
runApp(GameWidget(game: game));
} else {
runApp(
Directionality(
textDirection: TextDirection.ltr,
child: Text('Error: unknown page name "$page"'),
),
);
}
}
43 changes: 43 additions & 0 deletions packages/flame_forge2d/example/lib/utils/ball.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import 'package:flame/palette.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
import 'package:flutter/material.dart';

class Ball extends BodyComponent {
final double radius;
final Vector2 _position;

final _linePaint = BasicPalette.red.paint();

Ball(this._position, {this.radius = 2}) {
paint = BasicPalette.white.paint();
}

@override
Body createBody() {
final shape = CircleShape();
shape.radius = radius;

final fixtureDef = FixtureDef(
shape,
restitution: 0.8,
density: 1.0,
friction: 0.4,
);

final bodyDef = BodyDef(
userData: this,
angularDamping: 0.8,
position: _position,
type: BodyType.dynamic,
);

return world.createBody(bodyDef)..createFixture(fixtureDef);
}

@override
void renderCircle(Canvas c, Offset center, double radius) {
super.renderCircle(c, center, radius);
final lineRotation = Offset(0, radius);
c.drawLine(center, center + lineRotation, _linePaint);
}
}
33 changes: 33 additions & 0 deletions packages/flame_forge2d/example/lib/utils/walls.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'package:flame_forge2d/flame_forge2d.dart';

List<Wall> createBoundaries(Forge2DGame game) {
final topLeft = Vector2.zero();
final bottomRight = game.screenToWorld(game.camera.viewport.effectiveSize);
final topRight = Vector2(bottomRight.x, topLeft.y);
final bottomLeft = Vector2(topLeft.x, bottomRight.y);

return [
Wall(topRight, bottomRight),
Wall(bottomRight, bottomLeft),
Wall(bottomLeft, topLeft),
];
}

class Wall extends BodyComponent {
final Vector2 start;
final Vector2 end;

Wall(this.start, this.end);

@override
Body createBody() {
final shape = EdgeShape()..set(start, end);
final fixtureDef = FixtureDef(shape, friction: 0.3);
final bodyDef = BodyDef(
userData: this, // To be able to determine object in collision
position: Vector2.zero(),
);

return world.createBody(bodyDef)..createFixture(fixtureDef);
}
}
1 change: 1 addition & 0 deletions packages/flame_forge2d/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ environment:

dependencies:
dashbook: ^0.1.6
flame: ^1.6.0
flame_forge2d: ^0.11.0
flutter:
sdk: flutter
Expand Down