-
-
Notifications
You must be signed in to change notification settings - Fork 899
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: Added a page for Joints documentation + ConstantVolumeJoint doc…
… and example (#2362) Added a page for Forge2D joints documentation. Added a `ConstantVolumeJoint` documentation and example. Will add other joint types in the next PRs.
- Loading branch information
1 parent
a681c70
commit 957ad24
Showing
6 changed files
with
215 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,5 @@ | |
:hidden: | ||
Overview <forge2d.md> | ||
Joints <joints.md> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
# 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` in a joint may be of type `BodyType.static`. | ||
Joints between `BodyType.static` and/or `BodyType.kinematic` are allowed, | ||
but have no effect and use some processing time. | ||
|
||
To construct a `Joint`, you need to create a corresponding subclass of `JointDef` | ||
and initialize it with its parameters. | ||
|
||
To register a `Joint` use `world.createJoint` | ||
and later use `world.destroyJoint` when you want to remove it. | ||
|
||
|
||
## Built-in joints | ||
|
||
Currently, Forge2D supports the following joints: | ||
|
||
- [`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 `DistanceJoint`s, that connects all bodies one after another. | ||
|
||
It can for example be useful when simulating "soft-bodies". | ||
|
||
```{flutter-app} | ||
:sources: ../../../examples/stories/bridge_libraries/forge2d/joints/ | ||
: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 the `addBody` method. | ||
|
||
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`s are. | ||
|
||
Another optional parameter is `dampingRatio`, it defines how fast the oscillation comes to rest. | ||
It takes values from 0 to 1, where 0 = no damping, 1 = critical damping. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50 changes: 50 additions & 0 deletions
50
examples/lib/stories/bridge_libraries/forge2d/joints/constant_volume_joint.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import 'dart:math'; | ||
|
||
import 'package:examples/stories/bridge_libraries/forge2d/utils/balls.dart'; | ||
import 'package:examples/stories/bridge_libraries/forge2d/utils/boundaries.dart'; | ||
import 'package:flame/input.dart'; | ||
import 'package:flame_forge2d/flame_forge2d.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 center = details.eventPosition.game; | ||
|
||
const numPieces = 20; | ||
const radius = 5.0; | ||
final balls = <Ball>[]; | ||
|
||
for (var i = 0; i < numPieces; i++) { | ||
final x = radius * cos(2 * pi * (i / numPieces)); | ||
final y = radius * sin(2 * pi * (i / numPieces)); | ||
|
||
final ball = Ball(Vector2(x + center.x, y + 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)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,85 @@ | ||
import 'package:flame/components.dart'; | ||
import 'package:flame/game.dart'; | ||
import 'package:flame_forge2d/flame_forge2d.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 | ||
runApp(GameWidget(game: Forge2DExample())); | ||
} | ||
|
||
class Forge2DExample extends Forge2DGame with HasTappables { | ||
@override | ||
Future<void> onLoad() async { | ||
add(Ball(size / 2)); | ||
addAll(createBoundaries()); | ||
|
||
return super.onLoad(); | ||
} | ||
|
||
List<Component> createBoundaries() { | ||
final topLeft = Vector2.zero(); | ||
final bottomRight = screenToWorld(camera.viewport.effectiveSize); | ||
final topRight = Vector2(bottomRight.x, topLeft.y); | ||
final bottomLeft = Vector2(topLeft.x, bottomRight.y); | ||
|
||
return [ | ||
Wall(topLeft, topRight), | ||
Wall(topRight, bottomRight), | ||
Wall(bottomLeft, bottomRight), | ||
Wall(topLeft, bottomLeft) | ||
]; | ||
} | ||
} | ||
|
||
class Ball extends BodyComponent with Tappable { | ||
final Vector2 _position; | ||
|
||
Ball(this._position); | ||
|
||
@override | ||
Body createBody() { | ||
final shape = CircleShape(); | ||
shape.radius = 5; | ||
|
||
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 | ||
bool onTapDown(_) { | ||
body.applyLinearImpulse(Vector2.random() * 5000); | ||
return false; | ||
} | ||
} | ||
|
||
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, | ||
position: Vector2.zero(), | ||
); | ||
|
||
return world.createBody(bodyDef)..createFixture(fixtureDef); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters