mirror of
https://github.com/flame-engine/flame.git
synced 2025-10-30 16:36:57 +08:00
114 lines
3.2 KiB
Dart
114 lines
3.2 KiB
Dart
import 'dart:math';
|
|
|
|
import 'package:flame/components.dart';
|
|
import 'package:flame/events.dart';
|
|
import 'package:flame/extensions.dart';
|
|
import 'package:flame/game.dart';
|
|
import 'package:flame/palette.dart';
|
|
import 'package:flame/sprite.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
class LookAtExample extends FlameGame {
|
|
static const description = 'This example demonstrates how a component can be '
|
|
'made to look at a specific target using the lookAt method. Tap anywhere '
|
|
'to change the target point for both the choppers. '
|
|
'It also shows how nativeAngle can be used to make the component '
|
|
'oriented in the desired direction if the image is not facing the '
|
|
'correct direction.';
|
|
|
|
LookAtExample() : super(world: _TapWorld());
|
|
|
|
late SpriteAnimationComponent _chopper1;
|
|
late SpriteAnimationComponent _chopper2;
|
|
|
|
@override
|
|
Color backgroundColor() => const Color.fromARGB(255, 96, 145, 112);
|
|
|
|
@override
|
|
Future<void> onLoad() async {
|
|
final spriteSheet = SpriteSheet(
|
|
image: await images.load('animations/chopper.png'),
|
|
srcSize: Vector2.all(48),
|
|
);
|
|
|
|
_spawnChoppers(spriteSheet);
|
|
_spawnInfoText();
|
|
}
|
|
|
|
void _spawnChoppers(SpriteSheet spriteSheet) {
|
|
// Notice now the nativeAngle is set to pi because the chopper
|
|
// is facing in down/south direction in the original image.
|
|
world.add(
|
|
_chopper1 = SpriteAnimationComponent(
|
|
nativeAngle: pi,
|
|
size: Vector2.all(128),
|
|
anchor: Anchor.center,
|
|
animation: spriteSheet.createAnimation(row: 0, stepTime: 0.05),
|
|
),
|
|
);
|
|
|
|
// This chopper does not use correct nativeAngle, hence using
|
|
// lookAt on it results in the sprite pointing in incorrect
|
|
// direction visually.
|
|
world.add(
|
|
_chopper2 = SpriteAnimationComponent(
|
|
size: Vector2.all(128),
|
|
anchor: Anchor.center,
|
|
animation: spriteSheet.createAnimation(row: 0, stepTime: 0.05),
|
|
position: Vector2(0, 160),
|
|
),
|
|
);
|
|
}
|
|
|
|
// Just displays some information. No functional contribution to the example.
|
|
void _spawnInfoText() {
|
|
final shaded = TextPaint(
|
|
style: TextStyle(
|
|
color: BasicPalette.white.color,
|
|
fontSize: 30.0,
|
|
shadows: const [
|
|
Shadow(offset: Offset(1, 1), blurRadius: 1),
|
|
],
|
|
),
|
|
);
|
|
|
|
world.add(
|
|
TextComponent(
|
|
text: 'nativeAngle = pi',
|
|
textRenderer: shaded,
|
|
anchor: Anchor.center,
|
|
position: _chopper1.absolutePosition + Vector2(0, -70),
|
|
),
|
|
);
|
|
|
|
world.add(
|
|
TextComponent(
|
|
text: 'nativeAngle = 0',
|
|
textRenderer: shaded,
|
|
anchor: Anchor.center,
|
|
position: _chopper2.absolutePosition + Vector2(0, -70),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _TapWorld extends World with TapCallbacks {
|
|
final CircleComponent _targetComponent = CircleComponent(
|
|
radius: 5,
|
|
anchor: Anchor.center,
|
|
paint: BasicPalette.black.paint(),
|
|
);
|
|
|
|
@override
|
|
void onTapDown(TapDownEvent event) {
|
|
if (!_targetComponent.isMounted) {
|
|
add(_targetComponent);
|
|
}
|
|
_targetComponent.position = event.localPosition;
|
|
final choppers = children.query<SpriteAnimationComponent>();
|
|
for (final chopper in choppers) {
|
|
chopper.lookAt(event.localPosition);
|
|
}
|
|
}
|
|
}
|