2023-05-03
物理エンジン Box2D を Dart に移植したforge2dによって物理演算を行うことができます。 Flame 向けにはflame_forge2dが用意されています。
FlameGame
の代わりにForge2dGame
を使うことで forge2d の機能を簡単に使うことができます。
左右と下に壁を作り、タップした場所にボールを生成するサンプルを作ってみます。
まずはflame_forge2d
を導入します。
flame_forge2d: ^0.16.0+4
壁クラスを用意します。BodyComponent
を継承して作ります。
class Wall extends BodyComponent {
Wall({required this.pos, required this.size})
: super(paint: BasicPalette.gray.paint());
final Vector2 pos;
final Vector2 size;
@override
Body createBody() {
final shape = PolygonShape()..setAsBox(size.x, size.y, pos, 0);
final fixtureDef = FixtureDef(shape, friction: 0.3);
final bodyDef = BodyDef(userData: this);
return world.createBody(bodyDef)..createFixture(fixtureDef);
}
}
ボールクラスを用意します。 回転がわかりやすいように線を引いています。
class Ball extends BodyComponent {
Ball({required this.pos});
final Vector2 pos;
@override
Body createBody() {
final shape = CircleShape()..radius = 2;
final fixtureDef = FixtureDef(
shape,
restitution: 0.8,
density: 1.0,
friction: 0.4,
);
final bodyDef = BodyDef(
userData: this,
position: pos,
type: BodyType.dynamic,
);
return world.createBody(bodyDef)..createFixture(fixtureDef);
}
@override
void renderCircle(Canvas canvas, Offset center, double radius) {
super.renderCircle(canvas, center, radius);
canvas.drawLine(
center,
center + Offset(0, radius),
BasicPalette.black.paint(),
);
}
}
Forge2dGame
を継承したゲームクラスで、壁やボールを生成します。
class PhysicsGame extends Forge2DGame with TapCallbacks {
@override
Future<void> onLoad() async {
super.onLoad();
final rect = camera.visibleWorldRect;
await world.add(
Wall(pos: rect.bottomLeft.toVector2(), size: Vector2(rect.width, 1)),
);
await world.add(
Wall(pos: rect.topLeft.toVector2(), size: Vector2(1, rect.height)),
);
await world.add(
Wall(pos: rect.topRight.toVector2(), size: Vector2(1, rect.height)),
);
}
@override
void onTapDown(TapDownEvent event) {
super.onTapDown(event);
world.add(
Ball(pos: screenToWorld(event.localPosition)),
);
}
}
これで物理演算が動くようになりました。
© 2023 tnantoka