docs: PrismaticJoint docs and example (#2470)

PrismaticJoint example and documentation
This commit is contained in:
Eugene Kleshnin
2023-04-07 13:17:05 +01:00
committed by GitHub
parent de630a1c3a
commit e4f741ef23
4 changed files with 172 additions and 3 deletions

View File

@ -23,7 +23,7 @@ Currently, Forge2D supports the following joints:
- GearJoint
- [`MotorJoint`](#motorjoint)
- [`MouseJoint`](#mousejoint)
- PrismaticJoint
- [`PrismaticJoint`] (#prismaticjoint)
- [`PulleyJoint`](#pulleyjoint)
- [`RevoluteJoint`](#revolutejoint)
- RopeJoint
@ -274,6 +274,103 @@ final mouseJointDef = MouseJointDef()
initially.
### `PrismaticJoint`
The `PrismaticJoint` provides a single degree of freedom, allowing for a relative translation of two
bodies along an axis fixed in bodyA. Relative rotation is prevented.
`PrismaticJointDef` requires defining a line of motion using an axis and an anchor point.
The definition uses local anchor points and a local axis so that the initial configuration
can violate the constraint slightly.
The joint translation is zero when the local anchor points coincide in world space.
Using local anchors and a local axis helps when saving and loading a game.
```{warning}
At least one body should by dynamic with a non-fixed rotation.
```
The `PrismaticJoint` definition is similar to the [`RevoluteJoint`](#revolutejoint) definition, but
instead of rotation, it uses translation.
```{dart}
final prismaticJointDef = PrismaticJointDef()
..initialize(
dynamicBody,
groundBody,
dynamicBody.worldCenter,
Vector2(1, 0),
)
```
```{flutter-app}
:sources: ../../examples
:page: prismatic_joint
:subfolder: stories/bridge_libraries/forge2d/joints
:show: code popup
```
- `b1`, `b2`: Bodies connected by the joint.
- `anchor`: World anchor point, to put the axis through. Usually the center of the first body.
- `axis`: World translation axis, along which the translation will be fixed.
In some cases you might wish to control the range of motion. For this, the `PrismaticJointDef` has
optional parameters that allow you to simulate a joint limit and/or a motor.
#### Prismatic Joint Limit
You can limit the relative rotation with a joint limit that specifies a lower and upper translation.
```dart
jointDef
..enableLimit = true
..lowerTranslation = -20
..upperTranslation = 20;
```
- `enableLimit`: Set to true to enable translation limits
- `lowerTranslation`: The lower translation limit in meters
- `upperTranslation`: The upper translation limit in meters
You change the limits after the joint was created with this method:
```dart
prismaticJoint.setLimits(-10, 10);
```
#### Prismatic Joint Motor
You can use a motor to drive the motion or to model joint friction. A maximum motor force is
provided so that infinite forces are not generated.
```dart
jointDef
..enableMotor = true
..motorSpeed = 1
..maxMotorForce = 100;
```
- `enableMotor`: Set to true to enable the motor
- `motorSpeed`: The desired motor speed in radians per second
- `maxMotorForce`: The maximum motor torque used to achieve the desired motor speed in N-m.
You change the motor's speed and force after the joint was created using these methods:
```dart
prismaticJoint.setMotorSpeed(2);
prismaticJoint.setMaxMotorForce(200);
```
Also, you can get the joint angle and speed using the following methods:
```dart
prismaticJoint.getJointTranslation();
prismaticJoint.getJointSpeed();
```
### `PulleyJoint`
A `PulleyJoint` is used to create an idealized pulley. The pulley connects two bodies to the ground
@ -366,7 +463,7 @@ In some cases you might wish to control the joint angle. For this, the `Revolute
optional parameters that allow you to simulate a joint limit and/or a motor.
#### Joint Limit
#### Revolute Joint Limit
You can limit the relative rotation with a joint limit that specifies a lower and upper angle.
@ -388,7 +485,7 @@ revoluteJoint.setLimits(0, pi);
```
#### Joint Motor
#### Revolute Joint Motor
You can use a motor to drive the relative rotation about the shared point. A maximum motor torque is
provided so that infinite forces are not generated.

View File

@ -11,6 +11,7 @@ import 'package:examples/stories/bridge_libraries/forge2d/joints/distance_joint.
import 'package:examples/stories/bridge_libraries/forge2d/joints/friction_joint.dart';
import 'package:examples/stories/bridge_libraries/forge2d/joints/motor_joint.dart';
import 'package:examples/stories/bridge_libraries/forge2d/joints/mouse_joint.dart';
import 'package:examples/stories/bridge_libraries/forge2d/joints/prismatic_joint.dart';
import 'package:examples/stories/bridge_libraries/forge2d/joints/pulley_joint.dart';
import 'package:examples/stories/bridge_libraries/forge2d/joints/revolute_joint.dart';
import 'package:examples/stories/camera_and_viewport/camera_and_viewport.dart';
@ -43,6 +44,7 @@ void main() {
'motor_joint': MotorJointExample.new,
'mouse_joint': MouseJointExample.new,
'pulley_joint': PulleyJointExample.new,
'prismatic_joint': PrismaticJointExample.new,
'revolute_joint': RevoluteJointExample.new,
};
final game = routes[page]?.call();

View File

@ -12,6 +12,7 @@ import 'package:examples/stories/bridge_libraries/forge2d/joints/distance_joint.
import 'package:examples/stories/bridge_libraries/forge2d/joints/friction_joint.dart';
import 'package:examples/stories/bridge_libraries/forge2d/joints/motor_joint.dart';
import 'package:examples/stories/bridge_libraries/forge2d/joints/mouse_joint.dart';
import 'package:examples/stories/bridge_libraries/forge2d/joints/prismatic_joint.dart';
import 'package:examples/stories/bridge_libraries/forge2d/joints/pulley_joint.dart';
import 'package:examples/stories/bridge_libraries/forge2d/joints/revolute_joint.dart';
import 'package:examples/stories/bridge_libraries/forge2d/raycast_example.dart';
@ -134,6 +135,12 @@ void addJointsStories(Dashbook dashbook) {
codeLink: link('joints/mouse_joint.dart'),
info: MouseJointExample.description,
)
.add(
'PrismaticJoint',
(DashbookContext ctx) => GameWidget(game: PrismaticJointExample()),
codeLink: link('joints/prismatic_joint.dart'),
info: PrismaticJointExample.description,
)
.add(
'PulleyJoint',
(DashbookContext ctx) => GameWidget(game: PulleyJointExample()),

View File

@ -0,0 +1,63 @@
import 'dart:ui';
import 'package:examples/stories/bridge_libraries/forge2d/utils/boxes.dart';
import 'package:flame/events.dart';
import 'package:flame/input.dart';
import 'package:flame_forge2d/flame_forge2d.dart';
class PrismaticJointExample extends Forge2DGame
with TapDetector, HasDraggables {
static const description = '''
This example shows how to use a `PrismaticJoint`.
Drag the box along the specified axis, bound between lower and upper limits.
Also, there's a motor enabled that's pulling the box to the lower limit.
''';
late PrismaticJoint joint;
late Vector2 anchor = size / 2;
@override
Future<void> onLoad() async {
super.onLoad();
final box = DraggableBox(startPosition: anchor, width: 3, height: 3);
add(box);
await Future.wait([box.loaded]);
createJoint(box.body, anchor);
}
void createJoint(Body box, Vector2 anchor) {
final groundBody = world.createBody(BodyDef());
final prismaticJointDef = PrismaticJointDef()
..initialize(
box,
groundBody,
anchor,
Vector2(1, 0),
)
..enableLimit = true
..lowerTranslation = -20
..upperTranslation = 20
..enableMotor = true
..motorSpeed = 1
..maxMotorForce = 100;
joint = PrismaticJoint(prismaticJointDef);
world.createJoint(joint);
}
@override
void render(Canvas canvas) {
super.render(canvas);
final p1 =
worldToScreen(anchor + joint.getLocalAxisA() * joint.getLowerLimit());
final p2 =
worldToScreen(anchor + joint.getLocalAxisA() * joint.getUpperLimit());
canvas.drawLine(p1.toOffset(), p2.toOffset(), debugPaint);
}
}