mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-01 10:38:17 +08:00
@ -27,7 +27,7 @@ Currently, Forge2D supports the following joints:
|
|||||||
- [`PulleyJoint`](#pulleyjoint)
|
- [`PulleyJoint`](#pulleyjoint)
|
||||||
- [`RevoluteJoint`](#revolutejoint)
|
- [`RevoluteJoint`](#revolutejoint)
|
||||||
- [`RopeJoint`](#ropejoint)
|
- [`RopeJoint`](#ropejoint)
|
||||||
- WeldJoint
|
- [`WeldJoint`](#weldjoint)
|
||||||
- WheelJoint
|
- WheelJoint
|
||||||
|
|
||||||
|
|
||||||
@ -599,3 +599,38 @@ will have no effect.
|
|||||||
The joint assumes that the maximum length doesn't change during simulation.
|
The joint assumes that the maximum length doesn't change during simulation.
|
||||||
See `DistanceJoint` if you want to dynamically control length.
|
See `DistanceJoint` if you want to dynamically control length.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### `WeldJoint`
|
||||||
|
|
||||||
|
A `WeldJoint` is used to restrict all relative motion between two bodies, effectively joining them
|
||||||
|
together.
|
||||||
|
|
||||||
|
`WeldJointDef` requires two bodies that will be connected, and a world anchor:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
final weldJointDef = WeldJointDef()
|
||||||
|
..initialize(bodyA, bodyB, anchor);
|
||||||
|
|
||||||
|
world.createJoint(WeldJoint(weldJointDef));
|
||||||
|
```
|
||||||
|
|
||||||
|
```{flutter-app}
|
||||||
|
:sources: ../../examples
|
||||||
|
:page: weld_joint
|
||||||
|
:subfolder: stories/bridge_libraries/forge2d/joints
|
||||||
|
:show: code popup
|
||||||
|
```
|
||||||
|
|
||||||
|
- `bodyA`, `bodyB`: Two bodies that will be connected
|
||||||
|
|
||||||
|
- `anchor`: Anchor point in world coordinates, at which two bodies will be welded together
|
||||||
|
to 0, the higher the value, the less springy the joint becomes.
|
||||||
|
|
||||||
|
|
||||||
|
#### Breakable Bodies and WeldJoint
|
||||||
|
|
||||||
|
Since the Forge2D constraint solver is iterative, joints are somewhat flexible. This means that the
|
||||||
|
bodies connected by a WeldJoint may bend slightly. If you want to simulate a breakable body, it's
|
||||||
|
better to create a single body with multiple fixtures. When the body breaks, you can destroy a
|
||||||
|
fixture and recreate it on a new body instead of relying on a `WeldJoint`.
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import 'package:examples/stories/bridge_libraries/forge2d/joints/prismatic_joint
|
|||||||
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/joints/rope_joint.dart';
|
import 'package:examples/stories/bridge_libraries/forge2d/joints/rope_joint.dart';
|
||||||
|
import 'package:examples/stories/bridge_libraries/forge2d/joints/weld_joint.dart';
|
||||||
import 'package:examples/stories/camera_and_viewport/camera_and_viewport.dart';
|
import 'package:examples/stories/camera_and_viewport/camera_and_viewport.dart';
|
||||||
import 'package:examples/stories/collision_detection/collision_detection.dart';
|
import 'package:examples/stories/collision_detection/collision_detection.dart';
|
||||||
import 'package:examples/stories/components/components.dart';
|
import 'package:examples/stories/components/components.dart';
|
||||||
@ -50,6 +51,7 @@ void main() {
|
|||||||
'prismatic_joint': PrismaticJointExample.new,
|
'prismatic_joint': PrismaticJointExample.new,
|
||||||
'revolute_joint': RevoluteJointExample.new,
|
'revolute_joint': RevoluteJointExample.new,
|
||||||
'rope_joint': RopeJointExample.new,
|
'rope_joint': RopeJointExample.new,
|
||||||
|
'weld_joint': WeldJointExample.new,
|
||||||
};
|
};
|
||||||
final game = routes[page]?.call();
|
final game = routes[page]?.call();
|
||||||
if (game != null) {
|
if (game != null) {
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import 'package:examples/stories/bridge_libraries/forge2d/joints/prismatic_joint
|
|||||||
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/joints/rope_joint.dart';
|
import 'package:examples/stories/bridge_libraries/forge2d/joints/rope_joint.dart';
|
||||||
|
import 'package:examples/stories/bridge_libraries/forge2d/joints/weld_joint.dart';
|
||||||
import 'package:examples/stories/bridge_libraries/forge2d/raycast_example.dart';
|
import 'package:examples/stories/bridge_libraries/forge2d/raycast_example.dart';
|
||||||
import 'package:examples/stories/bridge_libraries/forge2d/revolute_joint_with_motor_example.dart';
|
import 'package:examples/stories/bridge_libraries/forge2d/revolute_joint_with_motor_example.dart';
|
||||||
import 'package:examples/stories/bridge_libraries/forge2d/sprite_body_example.dart';
|
import 'package:examples/stories/bridge_libraries/forge2d/sprite_body_example.dart';
|
||||||
@ -166,5 +167,11 @@ void addJointsStories(Dashbook dashbook) {
|
|||||||
(DashbookContext ctx) => GameWidget(game: RopeJointExample()),
|
(DashbookContext ctx) => GameWidget(game: RopeJointExample()),
|
||||||
codeLink: link('rope_joint.dart'),
|
codeLink: link('rope_joint.dart'),
|
||||||
info: RopeJointExample.description,
|
info: RopeJointExample.description,
|
||||||
|
)
|
||||||
|
.add(
|
||||||
|
'WeldJoint',
|
||||||
|
(DashbookContext ctx) => GameWidget(game: WeldJointExample()),
|
||||||
|
codeLink: link('weld_joint.dart'),
|
||||||
|
info: WeldJointExample.description,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,75 @@
|
|||||||
|
import 'package:examples/stories/bridge_libraries/forge2d/utils/balls.dart';
|
||||||
|
import 'package:examples/stories/bridge_libraries/forge2d/utils/boxes.dart';
|
||||||
|
import 'package:flame/input.dart';
|
||||||
|
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class WeldJointExample extends Forge2DGame with TapDetector {
|
||||||
|
static const description = '''
|
||||||
|
This example shows how to use a `WeldJoint`. Tap the screen to add a
|
||||||
|
ball to test the bridge built using a `WeldJoint`
|
||||||
|
''';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> onLoad() async {
|
||||||
|
super.onLoad();
|
||||||
|
|
||||||
|
const pillarHeight = 20.0;
|
||||||
|
final leftPillar = Box(
|
||||||
|
startPosition: Vector2(10, size.y - pillarHeight / 2),
|
||||||
|
width: 5,
|
||||||
|
height: pillarHeight,
|
||||||
|
bodyType: BodyType.static,
|
||||||
|
color: Colors.white,
|
||||||
|
);
|
||||||
|
final rightPillar = Box(
|
||||||
|
startPosition: Vector2(size.x - 10, size.y - pillarHeight / 2),
|
||||||
|
width: 5,
|
||||||
|
height: pillarHeight,
|
||||||
|
bodyType: BodyType.static,
|
||||||
|
color: Colors.white,
|
||||||
|
);
|
||||||
|
|
||||||
|
addAll([leftPillar, rightPillar]);
|
||||||
|
|
||||||
|
createBridge(size.y - pillarHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> createBridge(double positionY) async {
|
||||||
|
const sectionsCount = 10;
|
||||||
|
final sectionWidth = (size.x / sectionsCount).ceilToDouble();
|
||||||
|
Body? prevSection;
|
||||||
|
|
||||||
|
for (var i = 0; i < sectionsCount; i++) {
|
||||||
|
final section = Box(
|
||||||
|
startPosition: Vector2(sectionWidth * i, positionY),
|
||||||
|
width: sectionWidth,
|
||||||
|
height: 1,
|
||||||
|
);
|
||||||
|
await add(section);
|
||||||
|
|
||||||
|
if (prevSection != null) {
|
||||||
|
createJoint(
|
||||||
|
prevSection,
|
||||||
|
section.body,
|
||||||
|
Vector2(sectionWidth * i + sectionWidth, positionY),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
prevSection = section.body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void createJoint(Body first, Body second, Vector2 anchor) {
|
||||||
|
final weldJointDef = WeldJointDef()..initialize(first, second, anchor);
|
||||||
|
|
||||||
|
world.createJoint(WeldJoint(weldJointDef));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> onTapDown(TapDownInfo info) async {
|
||||||
|
super.onTapDown(info);
|
||||||
|
final ball = Ball(info.eventPosition.game, radius: 5);
|
||||||
|
add(ball);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,9 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flame/components.dart';
|
import 'package:flame/components.dart';
|
||||||
import 'package:flame/events.dart';
|
import 'package:flame/events.dart';
|
||||||
|
import 'package:flame/extensions.dart';
|
||||||
|
import 'package:flame/palette.dart';
|
||||||
import 'package:flame_forge2d/flame_forge2d.dart';
|
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||||
|
|
||||||
class Box extends BodyComponent {
|
class Box extends BodyComponent {
|
||||||
@ -13,7 +17,16 @@ class Box extends BodyComponent {
|
|||||||
required this.width,
|
required this.width,
|
||||||
required this.height,
|
required this.height,
|
||||||
this.bodyType = BodyType.dynamic,
|
this.bodyType = BodyType.dynamic,
|
||||||
});
|
Color? color,
|
||||||
|
}) {
|
||||||
|
if (color != null) {
|
||||||
|
paint = PaletteEntry(color).paint();
|
||||||
|
} else {
|
||||||
|
paint = randomPaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Paint randomPaint() => PaintExtension.random(withAlpha: 0.9, base: 100);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Body createBody() {
|
Body createBody() {
|
||||||
|
|||||||
Reference in New Issue
Block a user