mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-03 12:28:03 +08:00
docs: PrismaticJoint docs and example (#2470)
PrismaticJoint example and documentation
This commit is contained in:
@ -23,7 +23,7 @@ Currently, Forge2D supports the following joints:
|
|||||||
- GearJoint
|
- GearJoint
|
||||||
- [`MotorJoint`](#motorjoint)
|
- [`MotorJoint`](#motorjoint)
|
||||||
- [`MouseJoint`](#mousejoint)
|
- [`MouseJoint`](#mousejoint)
|
||||||
- PrismaticJoint
|
- [`PrismaticJoint`] (#prismaticjoint)
|
||||||
- [`PulleyJoint`](#pulleyjoint)
|
- [`PulleyJoint`](#pulleyjoint)
|
||||||
- [`RevoluteJoint`](#revolutejoint)
|
- [`RevoluteJoint`](#revolutejoint)
|
||||||
- RopeJoint
|
- RopeJoint
|
||||||
@ -274,6 +274,103 @@ final mouseJointDef = MouseJointDef()
|
|||||||
initially.
|
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`
|
### `PulleyJoint`
|
||||||
|
|
||||||
A `PulleyJoint` is used to create an idealized pulley. The pulley connects two bodies to the ground
|
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.
|
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.
|
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
|
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.
|
provided so that infinite forces are not generated.
|
||||||
|
|||||||
@ -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/friction_joint.dart';
|
||||||
import 'package:examples/stories/bridge_libraries/forge2d/joints/motor_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/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/pulley_joint.dart';
|
||||||
import 'package:examples/stories/bridge_libraries/forge2d/joints/revolute_joint.dart';
|
import 'package:examples/stories/bridge_libraries/forge2d/joints/revolute_joint.dart';
|
||||||
import 'package:examples/stories/camera_and_viewport/camera_and_viewport.dart';
|
import 'package:examples/stories/camera_and_viewport/camera_and_viewport.dart';
|
||||||
@ -43,6 +44,7 @@ void main() {
|
|||||||
'motor_joint': MotorJointExample.new,
|
'motor_joint': MotorJointExample.new,
|
||||||
'mouse_joint': MouseJointExample.new,
|
'mouse_joint': MouseJointExample.new,
|
||||||
'pulley_joint': PulleyJointExample.new,
|
'pulley_joint': PulleyJointExample.new,
|
||||||
|
'prismatic_joint': PrismaticJointExample.new,
|
||||||
'revolute_joint': RevoluteJointExample.new,
|
'revolute_joint': RevoluteJointExample.new,
|
||||||
};
|
};
|
||||||
final game = routes[page]?.call();
|
final game = routes[page]?.call();
|
||||||
|
|||||||
@ -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/friction_joint.dart';
|
||||||
import 'package:examples/stories/bridge_libraries/forge2d/joints/motor_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/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/pulley_joint.dart';
|
||||||
import 'package:examples/stories/bridge_libraries/forge2d/joints/revolute_joint.dart';
|
import 'package:examples/stories/bridge_libraries/forge2d/joints/revolute_joint.dart';
|
||||||
import 'package:examples/stories/bridge_libraries/forge2d/raycast_example.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'),
|
codeLink: link('joints/mouse_joint.dart'),
|
||||||
info: MouseJointExample.description,
|
info: MouseJointExample.description,
|
||||||
)
|
)
|
||||||
|
.add(
|
||||||
|
'PrismaticJoint',
|
||||||
|
(DashbookContext ctx) => GameWidget(game: PrismaticJointExample()),
|
||||||
|
codeLink: link('joints/prismatic_joint.dart'),
|
||||||
|
info: PrismaticJointExample.description,
|
||||||
|
)
|
||||||
.add(
|
.add(
|
||||||
'PulleyJoint',
|
'PulleyJoint',
|
||||||
(DashbookContext ctx) => GameWidget(game: PulleyJointExample()),
|
(DashbookContext ctx) => GameWidget(game: PulleyJointExample()),
|
||||||
|
|||||||
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user