chore: Update min Dart constraint to 3.8 (#3676)

Update min Dart constraint to 3.8, which will enable us to use the
fancier collection literals.

This requires bumping the min Flutter version as well:

<img width="1892" height="1122" alt="image"
src="https://github.com/user-attachments/assets/7c7b07fc-4d96-4987-824d-9a7133ecfb85"
/>
This commit is contained in:
Luan Nico
2025-08-10 12:42:31 -04:00
committed by GitHub
parent cc58aef5b5
commit b79fee0ae2
604 changed files with 6458 additions and 5590 deletions

View File

@ -9,7 +9,7 @@ on:
env: env:
FLUTTER_MIN_VERSION: '3.27.1' FLUTTER_MIN_VERSION: '3.32.0'
jobs: jobs:
# BEGIN LINTING STAGE # BEGIN LINTING STAGE

View File

@ -36,11 +36,11 @@ class RectangleCollidable extends PositionComponent with CollisionCallbacks {
late ShapeHitbox hitbox; late ShapeHitbox hitbox;
RectangleCollidable(Vector2 position) RectangleCollidable(Vector2 position)
: super( : super(
position: position, position: position,
size: Vector2.all(50), size: Vector2.all(50),
anchor: Anchor.center, anchor: Anchor.center,
); );
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {

View File

@ -101,11 +101,15 @@ class DragTarget extends PositionComponent with DragCallbacks {
class Trail extends Component { class Trail extends Component {
Trail(Vector2 origin) Trail(Vector2 origin)
: _paths = [Path()..moveTo(origin.x, origin.y)], : _paths = [Path()..moveTo(origin.x, origin.y)],
_opacities = [1], _opacities = [1],
_lastPoint = origin.clone(), _lastPoint = origin.clone(),
_color = _color = HSLColor.fromAHSL(
HSLColor.fromAHSL(1, random.nextDouble() * 360, 1, 0.8).toColor(); 1,
random.nextDouble() * 360,
1,
0.8,
).toColor();
final List<Path> _paths; final List<Path> _paths;
final List<double> _opacities; final List<double> _opacities;

View File

@ -8,8 +8,8 @@ class EmberPlayer extends SpriteAnimationComponent with TapCallbacks {
required super.size, required super.size,
super.position, super.position,
void Function(EmberPlayer player)? onTap, void Function(EmberPlayer player)? onTap,
}) : _onTap = onTap, }) : _onTap = onTap,
super(); super();
Vector2 velocity = Vector2(0, 0); Vector2 velocity = Vector2(0, 0);
final void Function(EmberPlayer player)? _onTap; final void Function(EmberPlayer player)? _onTap;

View File

@ -14,8 +14,8 @@ class Flower extends PositionComponent
void Function(Flower)? onTap, void Function(Flower)? onTap,
Decorator? decorator, Decorator? decorator,
super.position, super.position,
}) : _onTap = onTap, }) : _onTap = onTap,
super(size: Vector2.all(size), anchor: Anchor.center) { super(size: Vector2.all(size), anchor: Anchor.center) {
this.decorator.addLast(decorator); this.decorator.addLast(decorator);
final radius = size * 0.38; final radius = size * 0.38;
_paths.add(_makePath(radius * 1.4, 6, -0.05, 0.8)); _paths.add(_makePath(radius * 1.4, 6, -0.05, 0.8));

View File

@ -16,14 +16,14 @@ class GlowEffectExample extends FlameGame {
anchor: Anchor.center, anchor: Anchor.center,
paint: paint, paint: paint,
)..add( )..add(
GlowEffect( GlowEffect(
10.0, 10.0,
EffectController( EffectController(
duration: 2, duration: 2,
infinite: true, infinite: true,
),
), ),
), ),
),
); );
} }
} }

View File

@ -23,16 +23,19 @@ class HoverTarget extends PositionComponent with HoverCallbacks {
static final Random _random = Random(); static final Random _random = Random();
HoverTarget(Vector2 position) HoverTarget(Vector2 position)
: super( : super(
position: position, position: position,
size: Vector2.all(50), size: Vector2.all(50),
anchor: Anchor.center, anchor: Anchor.center,
); );
final _paint = Paint() final _paint = Paint()
..color = HSLColor.fromAHSL(1, _random.nextDouble() * 360, 1, 0.8) ..color = HSLColor.fromAHSL(
.toColor() 1,
.withValues(alpha: 0.5); _random.nextDouble() * 360,
1,
0.8,
).toColor().withValues(alpha: 0.5);
@override @override
void render(Canvas canvas) { void render(Canvas canvas) {

View File

@ -33,8 +33,8 @@ class RemoveEffectGame extends FlameGame with TapDetector {
@override @override
void update(double dt) { void update(double dt) {
textComponent.text = textComponent.text = (effect.controller.progress * delayTime)
(effect.controller.progress * delayTime).toStringAsFixed(2); .toStringAsFixed(2);
super.update(dt); super.update(dt);
} }
} }

View File

@ -9,8 +9,9 @@ class RiveExampleGame extends FlameGame with TapDetector {
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {
final skillsArtboard = final skillsArtboard = await loadArtboard(
await loadArtboard(RiveFile.asset('assets/skills.riv')); RiveFile.asset('assets/skills.riv'),
);
final controller = StateMachineController.fromArtboard( final controller = StateMachineController.fromArtboard(
skillsArtboard, skillsArtboard,

View File

@ -86,12 +86,12 @@ class RoundedButton extends PositionComponent with TapCallbacks {
super.position, super.position,
super.anchor = Anchor.center, super.anchor = Anchor.center,
}) : _textDrawable = TextPaint( }) : _textDrawable = TextPaint(
style: const TextStyle( style: const TextStyle(
fontSize: 20, fontSize: 20,
color: Color(0xFF000000), color: Color(0xFF000000),
fontWeight: FontWeight.w800, fontWeight: FontWeight.w800,
), ),
).toTextPainter(text) { ).toTextPainter(text) {
size = Vector2(150, 40); size = Vector2(150, 40);
_textOffset = Offset( _textOffset = Offset(
(size.x - _textDrawable.width) / 2, (size.x - _textDrawable.width) / 2,
@ -179,15 +179,15 @@ abstract class SimpleButton extends PositionComponent with TapCallbacks {
class BackButton extends SimpleButton with HasGameReference<RouterGame> { class BackButton extends SimpleButton with HasGameReference<RouterGame> {
BackButton() BackButton()
: super( : super(
Path() Path()
..moveTo(22, 8) ..moveTo(22, 8)
..lineTo(10, 20) ..lineTo(10, 20)
..lineTo(22, 32) ..lineTo(22, 32)
..moveTo(12, 20) ..moveTo(12, 20)
..lineTo(34, 20), ..lineTo(34, 20),
position: Vector2.all(10), position: Vector2.all(10),
); );
@override @override
void action() => game.router.pop(); void action() => game.router.pop();
@ -195,14 +195,14 @@ class BackButton extends SimpleButton with HasGameReference<RouterGame> {
class PauseButton extends SimpleButton with HasGameReference<RouterGame> { class PauseButton extends SimpleButton with HasGameReference<RouterGame> {
PauseButton() PauseButton()
: super( : super(
Path() Path()
..moveTo(14, 10) ..moveTo(14, 10)
..lineTo(14, 30) ..lineTo(14, 30)
..moveTo(26, 10) ..moveTo(26, 10)
..lineTo(26, 30), ..lineTo(26, 30),
position: Vector2(60, 10), position: Vector2(60, 10),
); );
bool isPaused = false; bool isPaused = false;
@ -345,10 +345,10 @@ class Orbit extends PositionComponent {
required this.planet, required this.planet,
required this.revolutionPeriod, required this.revolutionPeriod,
double initialAngle = 0, double initialAngle = 0,
}) : _paint = Paint() }) : _paint = Paint()
..style = PaintingStyle.stroke ..style = PaintingStyle.stroke
..color = const Color(0x888888aa), ..color = const Color(0x888888aa),
_angle = initialAngle { _angle = initialAngle {
add(planet); add(planet);
} }

View File

@ -63,8 +63,12 @@ class TapTarget extends PositionComponent with TapCallbacks {
class ExpandingCircle extends Component { class ExpandingCircle extends Component {
ExpandingCircle(this._center) ExpandingCircle(this._center)
: _baseColor = : _baseColor = HSLColor.fromAHSL(
HSLColor.fromAHSL(1, random.nextDouble() * 360, 1, 0.8).toColor(); 1,
random.nextDouble() * 360,
1,
0.8,
).toColor();
final Color _baseColor; final Color _baseColor;
final Vector2 _center; final Vector2 _center;

View File

@ -83,15 +83,15 @@ class RateRoute extends ValueRoute<int>
class DialogBackground extends RectangleComponent with TapCallbacks { class DialogBackground extends RectangleComponent with TapCallbacks {
DialogBackground({super.position, super.size, super.children}) DialogBackground({super.position, super.size, super.children})
: super( : super(
anchor: Anchor.center, anchor: Anchor.center,
paint: Paint()..color = const Color(0xee858585), paint: Paint()..color = const Color(0xee858585),
); );
} }
class Star extends PositionComponent with TapCallbacks { class Star extends PositionComponent with TapCallbacks {
Star({required this.value, required this.radius, super.position}) Star({required this.value, required this.radius, super.position})
: super(size: Vector2.all(2 * radius), anchor: Anchor.center); : super(size: Vector2.all(2 * radius), anchor: Anchor.center);
final int value; final int value;
final double radius; final double radius;

View File

@ -5,7 +5,7 @@ version: 1.0.0
publish_to: none publish_to: none
environment: environment:
sdk: ">=3.6.0 <4.0.0" sdk: ">=3.8.0 <4.0.0"
flutter: ">=3.27.1" flutter: ">=3.27.1"
dependencies: dependencies:

View File

@ -17,10 +17,10 @@ void main() {
'step4' => step4.main(), 'step4' => step4.main(),
'step5' => step5.main(), 'step5' => step5.main(),
_ => runApp( _ => runApp(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Text('Error=> unknown page name "$page"'), child: Text('Error=> unknown page name "$page"'),
),
), ),
),
}; };
} }

View File

@ -28,8 +28,10 @@ class KlondikeGame extends FlameGame {
4, 4,
(i) => Foundation() (i) => Foundation()
..size = cardSize ..size = cardSize
..position = ..position = Vector2(
Vector2((i + 3) * (cardWidth + cardGap) + cardGap, cardGap), (i + 3) * (cardWidth + cardGap) + cardGap,
cardGap,
),
); );
final piles = List.generate( final piles = List.generate(
7, 7,
@ -46,8 +48,10 @@ class KlondikeGame extends FlameGame {
world.addAll(foundations); world.addAll(foundations);
world.addAll(piles); world.addAll(piles);
camera.viewfinder.visibleGameSize = camera.viewfinder.visibleGameSize = Vector2(
Vector2(cardWidth * 7 + cardGap * 8, 4 * cardHeight + 3 * cardGap); cardWidth * 7 + cardGap * 8,
4 * cardHeight + 3 * cardGap,
);
camera.viewfinder.position = Vector2(cardWidth * 3.5 + cardGap * 4, 0); camera.viewfinder.position = Vector2(cardWidth * 3.5 + cardGap * 4, 0);
camera.viewfinder.anchor = Anchor.topCenter; camera.viewfinder.anchor = Anchor.topCenter;
} }

View File

@ -8,10 +8,10 @@ import '../suit.dart';
class Card extends PositionComponent { class Card extends PositionComponent {
Card(int intRank, int intSuit) Card(int intRank, int intSuit)
: rank = Rank.fromInt(intRank), : rank = Rank.fromInt(intRank),
suit = Suit.fromInt(intSuit), suit = Suit.fromInt(intSuit),
_faceUp = false, _faceUp = false,
super(size: KlondikeGame.cardSize); super(size: KlondikeGame.cardSize);
final Rank rank; final Rank rank;
final Suit suit; final Suit suit;

View File

@ -31,8 +31,10 @@ class KlondikeGame extends FlameGame {
4, 4,
(i) => Foundation() (i) => Foundation()
..size = cardSize ..size = cardSize
..position = ..position = Vector2(
Vector2((i + 3) * (cardWidth + cardGap) + cardGap, cardGap), (i + 3) * (cardWidth + cardGap) + cardGap,
cardGap,
),
); );
final piles = List.generate( final piles = List.generate(
7, 7,
@ -49,8 +51,10 @@ class KlondikeGame extends FlameGame {
world.addAll(foundations); world.addAll(foundations);
world.addAll(piles); world.addAll(piles);
camera.viewfinder.visibleGameSize = camera.viewfinder.visibleGameSize = Vector2(
Vector2(cardWidth * 7 + cardGap * 8, 4 * cardHeight + 3 * cardGap); cardWidth * 7 + cardGap * 8,
4 * cardHeight + 3 * cardGap,
);
camera.viewfinder.position = Vector2(cardWidth * 3.5 + cardGap * 4, 0); camera.viewfinder.position = Vector2(cardWidth * 3.5 + cardGap * 4, 0);
camera.viewfinder.anchor = Anchor.topCenter; camera.viewfinder.anchor = Anchor.topCenter;

View File

@ -21,8 +21,8 @@ class Rank {
double y2, double y2,
double w, double w,
double h, double h,
) : redSprite = klondikeSprite(x1, y1, w, h), ) : redSprite = klondikeSprite(x1, y1, w, h),
blackSprite = klondikeSprite(x2, y2, w, h); blackSprite = klondikeSprite(x2, y2, w, h);
final int value; final int value;
final String label; final String label;

View File

@ -13,7 +13,7 @@ class Suit {
} }
Suit._(this.value, this.label, double x, double y, double w, double h) Suit._(this.value, this.label, double x, double y, double w, double h)
: sprite = klondikeSprite(x, y, w, h); : sprite = klondikeSprite(x, y, w, h);
final int value; final int value;
final String label; final String label;

View File

@ -11,9 +11,9 @@ import 'tableau_pile.dart';
class Card extends PositionComponent with DragCallbacks { class Card extends PositionComponent with DragCallbacks {
Card(int intRank, int intSuit) Card(int intRank, int intSuit)
: rank = Rank.fromInt(intRank), : rank = Rank.fromInt(intRank),
suit = Suit.fromInt(intSuit), suit = Suit.fromInt(intSuit),
super(size: KlondikeGame.cardSize); super(size: KlondikeGame.cardSize);
final Rank rank; final Rank rank;
final Suit suit; final Suit suit;

View File

@ -9,8 +9,8 @@ import 'card.dart';
class FoundationPile extends PositionComponent implements Pile { class FoundationPile extends PositionComponent implements Pile {
FoundationPile(int intSuit, {super.position}) FoundationPile(int intSuit, {super.position})
: suit = Suit.fromInt(intSuit), : suit = Suit.fromInt(intSuit),
super(size: KlondikeGame.cardSize); super(size: KlondikeGame.cardSize);
final Suit suit; final Suit suit;
final List<Card> _cards = []; final List<Card> _cards = [];

View File

@ -26,8 +26,9 @@ class KlondikeGame extends FlameGame {
await Flame.images.load('klondike-sprites.png'); await Flame.images.load('klondike-sprites.png');
final stock = StockPile(position: Vector2(cardGap, cardGap)); final stock = StockPile(position: Vector2(cardGap, cardGap));
final waste = final waste = WastePile(
WastePile(position: Vector2(cardWidth + 2 * cardGap, cardGap)); position: Vector2(cardWidth + 2 * cardGap, cardGap),
);
final foundations = List.generate( final foundations = List.generate(
4, 4,
(i) => FoundationPile( (i) => FoundationPile(
@ -50,8 +51,10 @@ class KlondikeGame extends FlameGame {
world.addAll(foundations); world.addAll(foundations);
world.addAll(piles); world.addAll(piles);
camera.viewfinder.visibleGameSize = camera.viewfinder.visibleGameSize = Vector2(
Vector2(cardWidth * 7 + cardGap * 8, 4 * cardHeight + 3 * cardGap); cardWidth * 7 + cardGap * 8,
4 * cardHeight + 3 * cardGap,
);
camera.viewfinder.position = Vector2(cardWidth * 3.5 + cardGap * 4, 0); camera.viewfinder.position = Vector2(cardWidth * 3.5 + cardGap * 4, 0);
camera.viewfinder.anchor = Anchor.topCenter; camera.viewfinder.anchor = Anchor.topCenter;

View File

@ -21,8 +21,8 @@ class Rank {
double y2, double y2,
double w, double w,
double h, double h,
) : redSprite = klondikeSprite(x1, y1, w, h), ) : redSprite = klondikeSprite(x1, y1, w, h),
blackSprite = klondikeSprite(x2, y2, w, h); blackSprite = klondikeSprite(x2, y2, w, h);
final int value; final int value;
final String label; final String label;

View File

@ -13,7 +13,7 @@ class Suit {
} }
Suit._(this.value, this.label, double x, double y, double w, double h) Suit._(this.value, this.label, double x, double y, double w, double h)
: sprite = klondikeSprite(x, y, w, h); : sprite = klondikeSprite(x, y, w, h);
final int value; final int value;
final String label; final String label;

View File

@ -18,11 +18,11 @@ import 'tableau_pile.dart';
class Card extends PositionComponent class Card extends PositionComponent
with DragCallbacks, TapCallbacks, HasWorldReference<KlondikeWorld> { with DragCallbacks, TapCallbacks, HasWorldReference<KlondikeWorld> {
Card(int intRank, int intSuit, {this.isBaseCard = false}) Card(int intRank, int intSuit, {this.isBaseCard = false})
: rank = Rank.fromInt(intRank), : rank = Rank.fromInt(intRank),
suit = Suit.fromInt(intSuit), suit = Suit.fromInt(intSuit),
super( super(
size: KlondikeGame.cardSize, size: KlondikeGame.cardSize,
); );
final Rank rank; final Rank rank;
final Suit suit; final Suit suit;

View File

@ -10,24 +10,24 @@ class FlatButton extends ButtonComponent {
super.onReleased, super.onReleased,
super.position, super.position,
}) : super( }) : super(
button: ButtonBackground(const Color(0xffece8a3)), button: ButtonBackground(const Color(0xffece8a3)),
buttonDown: ButtonBackground(Colors.red), buttonDown: ButtonBackground(Colors.red),
children: [ children: [
TextComponent( TextComponent(
text: text, text: text,
textRenderer: TextPaint( textRenderer: TextPaint(
style: TextStyle( style: TextStyle(
fontSize: 0.5 * size!.y, fontSize: 0.5 * size!.y,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: const Color(0xffdbaf58), color: const Color(0xffdbaf58),
), ),
), ),
position: size / 2.0, position: size / 2.0,
anchor: Anchor.center, anchor: Anchor.center,
), ),
], ],
anchor: Anchor.center, anchor: Anchor.center,
); );
} }
class ButtonBackground extends PositionComponent with HasAncestor<FlatButton> { class ButtonBackground extends PositionComponent with HasAncestor<FlatButton> {

View File

@ -9,8 +9,8 @@ import 'card.dart';
class FoundationPile extends PositionComponent implements Pile { class FoundationPile extends PositionComponent implements Pile {
FoundationPile(int intSuit, this.checkWin, {super.position}) FoundationPile(int intSuit, this.checkWin, {super.position})
: suit = Suit.fromInt(intSuit), : suit = Suit.fromInt(intSuit),
super(size: KlondikeGame.cardSize); super(size: KlondikeGame.cardSize);
final VoidCallback checkWin; final VoidCallback checkWin;

View File

@ -111,7 +111,8 @@ class TableauPile extends PositionComponent implements Pile {
} }
void calculateHitArea() { void calculateHitArea() {
height = KlondikeGame.cardHeight * 1.5 + height =
KlondikeGame.cardHeight * 1.5 +
(_cards.length < 2 ? 0.0 : _cards.last.y - _cards.first.y); (_cards.length < 2 ? 0.0 : _cards.last.y - _cards.first.y);
} }

View File

@ -74,8 +74,10 @@ class KlondikeWorld extends World with HasGameReference<KlondikeGame> {
addAll(cards); addAll(cards);
add(baseCard); add(baseCard);
playAreaSize = playAreaSize = Vector2(
Vector2(7 * cardSpaceWidth + cardGap, 4 * cardSpaceHeight + topGap); 7 * cardSpaceWidth + cardGap,
4 * cardSpaceHeight + topGap,
);
final gameMidX = playAreaSize.x / 2; final gameMidX = playAreaSize.x / 2;
addButton('New deal', gameMidX, Action.newDeal); addButton('New deal', gameMidX, Action.newDeal);

View File

@ -21,8 +21,8 @@ class Rank {
double y2, double y2,
double w, double w,
double h, double h,
) : redSprite = klondikeSprite(x1, y1, w, h), ) : redSprite = klondikeSprite(x1, y1, w, h),
blackSprite = klondikeSprite(x2, y2, w, h); blackSprite = klondikeSprite(x2, y2, w, h);
final int value; final int value;
final String label; final String label;

View File

@ -13,7 +13,7 @@ class Suit {
} }
Suit._(this.value, this.label, double x, double y, double w, double h) Suit._(this.value, this.label, double x, double y, double w, double h)
: sprite = klondikeSprite(x, y, w, h); : sprite = klondikeSprite(x, y, w, h);
final int value; final int value;
final String label; final String label;

View File

@ -5,7 +5,7 @@ version: 1.0.0
publish_to: none publish_to: none
environment: environment:
sdk: ">=3.6.0 <4.0.0" sdk: ">=3.8.0 <4.0.0"
dependencies: dependencies:
flame: ^1.30.1 flame: ^1.30.1

View File

@ -46,11 +46,13 @@ class EmberPlayer extends SpriteAnimationComponent
@override @override
bool onKeyEvent(KeyEvent event, Set<LogicalKeyboardKey> keysPressed) { bool onKeyEvent(KeyEvent event, Set<LogicalKeyboardKey> keysPressed) {
horizontalDirection = 0; horizontalDirection = 0;
horizontalDirection += (keysPressed.contains(LogicalKeyboardKey.keyA) || horizontalDirection +=
(keysPressed.contains(LogicalKeyboardKey.keyA) ||
keysPressed.contains(LogicalKeyboardKey.arrowLeft)) keysPressed.contains(LogicalKeyboardKey.arrowLeft))
? -1 ? -1
: 0; : 0;
horizontalDirection += (keysPressed.contains(LogicalKeyboardKey.keyD) || horizontalDirection +=
(keysPressed.contains(LogicalKeyboardKey.keyD) ||
keysPressed.contains(LogicalKeyboardKey.arrowRight)) keysPressed.contains(LogicalKeyboardKey.arrowRight))
? 1 ? 1
: 0; : 0;
@ -114,7 +116,8 @@ class EmberPlayer extends SpriteAnimationComponent
if (other is GroundBlock || other is PlatformBlock) { if (other is GroundBlock || other is PlatformBlock) {
if (intersectionPoints.length == 2) { if (intersectionPoints.length == 2) {
// Calculate the collision normal and separation distance. // Calculate the collision normal and separation distance.
final mid = (intersectionPoints.elementAt(0) + final mid =
(intersectionPoints.elementAt(0) +
intersectionPoints.elementAt(1)) / intersectionPoints.elementAt(1)) /
2; 2;
@ -154,12 +157,13 @@ class EmberPlayer extends SpriteAnimationComponent
} }
add( add(
OpacityEffect.fadeOut( OpacityEffect.fadeOut(
EffectController( EffectController(
alternate: true, alternate: true,
duration: 0.1, duration: 0.1,
repeatCount: 5, repeatCount: 5,
), ),
)..onComplete = () { )
..onComplete = () {
hitByEnemy = false; hitByEnemy = false;
}, },
); );

View File

@ -58,21 +58,21 @@ class EmberQuestGame extends FlameGame
for (final block in segments[segmentIndex]) { for (final block in segments[segmentIndex]) {
final component = switch (block.blockType) { final component = switch (block.blockType) {
const (GroundBlock) => GroundBlock( const (GroundBlock) => GroundBlock(
gridPosition: block.gridPosition, gridPosition: block.gridPosition,
xOffset: xPositionOffset, xOffset: xPositionOffset,
), ),
const (PlatformBlock) => PlatformBlock( const (PlatformBlock) => PlatformBlock(
gridPosition: block.gridPosition, gridPosition: block.gridPosition,
xOffset: xPositionOffset, xOffset: xPositionOffset,
), ),
const (Star) => Star( const (Star) => Star(
gridPosition: block.gridPosition, gridPosition: block.gridPosition,
xOffset: xPositionOffset, xOffset: xPositionOffset,
), ),
const (WaterEnemy) => WaterEnemy( const (WaterEnemy) => WaterEnemy(
gridPosition: block.gridPosition, gridPosition: block.gridPosition,
xOffset: xPositionOffset, xOffset: xPositionOffset,
), ),
_ => throw UnimplementedError(), _ => throw UnimplementedError(),
}; };
world.add(component); world.add(component);

View File

@ -5,7 +5,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1 version: 1.0.0+1
environment: environment:
sdk: ">=3.6.0 <4.0.0" sdk: ">=3.8.0 <4.0.0"
flutter: ">=3.27.1" flutter: ">=3.27.1"
dependencies: dependencies:

View File

@ -21,11 +21,11 @@ void main() {
'step5' => step5.main(), 'step5' => step5.main(),
'step6' => step6.main(), 'step6' => step6.main(),
_ => runApp( _ => runApp(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Text('''Error: unknown page. Pass "step{1,6}" as a GET param; child: Text('''Error: unknown page. Pass "step{1,6}" as a GET param;
e.g: ${web.window.location}?step1'''), e.g: ${web.window.location}?step1'''),
),
), ),
),
}; };
} }

View File

@ -25,10 +25,10 @@ class SpaceShooterGame extends FlameGame with PanDetector {
class Player extends SpriteComponent with HasGameReference<SpaceShooterGame> { class Player extends SpriteComponent with HasGameReference<SpaceShooterGame> {
Player() Player()
: super( : super(
size: Vector2(100, 150), size: Vector2(100, 150),
anchor: Anchor.center, anchor: Anchor.center,
); );
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {

View File

@ -39,10 +39,10 @@ class SpaceShooterGame extends FlameGame with PanDetector {
class Player extends SpriteAnimationComponent class Player extends SpriteAnimationComponent
with HasGameReference<SpaceShooterGame> { with HasGameReference<SpaceShooterGame> {
Player() Player()
: super( : super(
size: Vector2(100, 150), size: Vector2(100, 150),
anchor: Anchor.center, anchor: Anchor.center,
); );
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {

View File

@ -49,10 +49,10 @@ class SpaceShooterGame extends FlameGame with PanDetector {
class Player extends SpriteAnimationComponent class Player extends SpriteAnimationComponent
with HasGameReference<SpaceShooterGame> { with HasGameReference<SpaceShooterGame> {
Player() Player()
: super( : super(
size: Vector2(100, 150), size: Vector2(100, 150),
anchor: Anchor.center, anchor: Anchor.center,
); );
late final SpawnComponent _bulletSpawner; late final SpawnComponent _bulletSpawner;
@ -76,7 +76,8 @@ class Player extends SpriteAnimationComponent
selfPositioning: true, selfPositioning: true,
factory: (index) { factory: (index) {
return Bullet( return Bullet(
position: position + position:
position +
Vector2( Vector2(
0, 0,
-height / 2, -height / 2,
@ -107,9 +108,9 @@ class Bullet extends SpriteAnimationComponent
Bullet({ Bullet({
super.position, super.position,
}) : super( }) : super(
size: Vector2(25, 50), size: Vector2(25, 50),
anchor: Anchor.center, anchor: Anchor.center,
); );
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {

View File

@ -60,10 +60,10 @@ class SpaceShooterGame extends FlameGame with PanDetector {
class Player extends SpriteAnimationComponent class Player extends SpriteAnimationComponent
with HasGameReference<SpaceShooterGame> { with HasGameReference<SpaceShooterGame> {
Player() Player()
: super( : super(
size: Vector2(100, 150), size: Vector2(100, 150),
anchor: Anchor.center, anchor: Anchor.center,
); );
late final SpawnComponent _bulletSpawner; late final SpawnComponent _bulletSpawner;
@ -87,7 +87,8 @@ class Player extends SpriteAnimationComponent
selfPositioning: true, selfPositioning: true,
factory: (index) { factory: (index) {
return Bullet( return Bullet(
position: position + position:
position +
Vector2( Vector2(
0, 0,
-height / 2, -height / 2,
@ -118,9 +119,9 @@ class Bullet extends SpriteAnimationComponent
Bullet({ Bullet({
super.position, super.position,
}) : super( }) : super(
size: Vector2(25, 50), size: Vector2(25, 50),
anchor: Anchor.center, anchor: Anchor.center,
); );
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {
@ -153,9 +154,9 @@ class Enemy extends SpriteAnimationComponent
Enemy({ Enemy({
super.position, super.position,
}) : super( }) : super(
size: Vector2.all(enemySize), size: Vector2.all(enemySize),
anchor: Anchor.center, anchor: Anchor.center,
); );
static const enemySize = 50.0; static const enemySize = 50.0;

View File

@ -62,10 +62,10 @@ class SpaceShooterGame extends FlameGame
class Player extends SpriteAnimationComponent class Player extends SpriteAnimationComponent
with HasGameReference<SpaceShooterGame> { with HasGameReference<SpaceShooterGame> {
Player() Player()
: super( : super(
size: Vector2(100, 150), size: Vector2(100, 150),
anchor: Anchor.center, anchor: Anchor.center,
); );
late final SpawnComponent _bulletSpawner; late final SpawnComponent _bulletSpawner;
@ -89,7 +89,8 @@ class Player extends SpriteAnimationComponent
selfPositioning: true, selfPositioning: true,
factory: (index) { factory: (index) {
return Bullet( return Bullet(
position: position + position:
position +
Vector2( Vector2(
0, 0,
-height / 2, -height / 2,
@ -120,9 +121,9 @@ class Bullet extends SpriteAnimationComponent
Bullet({ Bullet({
super.position, super.position,
}) : super( }) : super(
size: Vector2(25, 50), size: Vector2(25, 50),
anchor: Anchor.center, anchor: Anchor.center,
); );
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {
@ -161,9 +162,9 @@ class Enemy extends SpriteAnimationComponent
Enemy({ Enemy({
super.position, super.position,
}) : super( }) : super(
size: Vector2.all(enemySize), size: Vector2.all(enemySize),
anchor: Anchor.center, anchor: Anchor.center,
); );
static const enemySize = 50.0; static const enemySize = 50.0;
@ -214,10 +215,10 @@ class Explosion extends SpriteAnimationComponent
Explosion({ Explosion({
super.position, super.position,
}) : super( }) : super(
size: Vector2.all(150), size: Vector2.all(150),
anchor: Anchor.center, anchor: Anchor.center,
removeOnFinish: true, removeOnFinish: true,
); );
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {

View File

@ -7,7 +7,7 @@ publish_to: 'none'
version: 1.0.0+1 version: 1.0.0+1
environment: environment:
sdk: ">=3.6.0 <4.0.0" sdk: ">=3.8.0 <4.0.0"
dependencies: dependencies:
flame: ^1.30.1 flame: ^1.30.1

View File

@ -21,17 +21,18 @@ and the glowing effect of the crystal ball.
class _CrystalBallWidgetState extends State<CrystalBallWidget> { class _CrystalBallWidgetState extends State<CrystalBallWidget> {
// PreloadedPrograms is a simple data class that holds the preloaded // PreloadedPrograms is a simple data class that holds the preloaded
late final Future<PreloadedPrograms> preloadedPrograms = Future.wait([ late final Future<PreloadedPrograms> preloadedPrograms =
FragmentProgram.fromAsset('packages/crystal_ball/shaders/ground.frag'), Future.wait([
FragmentProgram.fromAsset('packages/crystal_ball/shaders/fog.frag'), FragmentProgram.fromAsset('packages/crystal_ball/shaders/ground.frag'),
FragmentProgram.fromAsset('packages/crystal_ball/shaders/firefly.frag'), FragmentProgram.fromAsset('packages/crystal_ball/shaders/fog.frag'),
]).then( FragmentProgram.fromAsset('packages/crystal_ball/shaders/firefly.frag'),
(l) => ( ]).then(
waterFragmentProgram: l[0], (l) => (
fogFragmentProgram: l[1], waterFragmentProgram: l[0],
fireflyFragmentProgram: l[2], fogFragmentProgram: l[1],
), fireflyFragmentProgram: l[2],
); ),
);
CrystalBallGame? game; CrystalBallGame? game;

View File

@ -7,10 +7,10 @@ import 'package:flutter/services.dart';
class InputHandler extends PositionComponent class InputHandler extends PositionComponent
with TapCallbacks, HasGameReference<CrystalBallGame> { with TapCallbacks, HasGameReference<CrystalBallGame> {
InputHandler() InputHandler()
: super( : super(
anchor: Anchor.center, anchor: Anchor.center,
size: kCameraSize, size: kCameraSize,
); );
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {

View File

@ -17,37 +17,37 @@ class Rectangle extends PositionComponent
ParentIsA<Ground>, ParentIsA<Ground>,
HasGameReference<CrystalBallGame> { HasGameReference<CrystalBallGame> {
Rectangle(double y) Rectangle(double y)
: super( : super(
anchor: Anchor.topCenter, anchor: Anchor.topCenter,
position: Vector2(0, y), position: Vector2(0, y),
size: Vector2( size: Vector2(
kCameraSize.x, kCameraSize.x,
kCameraSize.y / 2, kCameraSize.y / 2,
),
children: [
RectangleHitbox(
size: Vector2(
kCameraSize.x,
kCameraSize.y / 2,
),
), ),
children: [ RectangleHitbox(
position: Vector2(0, kPlayerRadius),
size: Vector2(
kCameraSize.x,
kCameraSize.y / 2,
),
),
for (var i = 2; i < 30; i++)
RectangleHitbox( RectangleHitbox(
position: Vector2(0, kPlayerRadius * i),
size: Vector2( size: Vector2(
kCameraSize.x, kCameraSize.x,
kCameraSize.y / 2, kCameraSize.y / 2,
), ),
), ),
RectangleHitbox( ],
position: Vector2(0, kPlayerRadius), );
size: Vector2(
kCameraSize.x,
kCameraSize.y / 2,
),
),
for (var i = 2; i < 30; i++)
RectangleHitbox(
position: Vector2(0, kPlayerRadius * i),
size: Vector2(
kCameraSize.x,
kCameraSize.y / 2,
),
),
],
);
double get topEdge => absolutePositionOfAnchor(Anchor.topCenter).y; double get topEdge => absolutePositionOfAnchor(Anchor.topCenter).y;
} }

View File

@ -16,15 +16,15 @@ class TheBall extends PositionComponent
TheBall({ TheBall({
required Vector2 super.position, required Vector2 super.position,
}) : super( }) : super(
anchor: Anchor.center, anchor: Anchor.center,
priority: 100000, priority: 100000,
children: [ children: [
CircleHitbox( CircleHitbox(
radius: kPlayerRadius, radius: kPlayerRadius,
anchor: Anchor.center, anchor: Anchor.center,
), ),
], ],
); );
final Vector2 velocity = Vector2.zero(); final Vector2 velocity = Vector2.zero();

View File

@ -20,12 +20,12 @@ class CrystalBallGame extends FlameGame<CrystalBallGameWorld>
CrystalBallGame({ CrystalBallGame({
required this.preloadedPrograms, required this.preloadedPrograms,
}) : super( }) : super(
camera: CameraComponent.withFixedResolution( camera: CameraComponent.withFixedResolution(
width: kCameraSize.x, width: kCameraSize.x,
height: kCameraSize.y, height: kCameraSize.y,
), ),
world: CrystalBallGameWorld(), world: CrystalBallGameWorld(),
) { ) {
camera.postProcess = PostProcessGroup( camera.postProcess = PostProcessGroup(
postProcesses: [ postProcesses: [
PostProcessSequentialGroup( PostProcessSequentialGroup(

View File

@ -60,8 +60,12 @@ class BallGlowPostProcess extends PostProcess {
Vector2 size, Vector2 size,
Canvas canvas, Canvas canvas,
) { ) {
final origin = final origin = world
world.findGame()!.camera.visibleWorldRect.topLeft.toVector2(); .findGame()!
.camera
.visibleWorldRect
.topLeft
.toVector2();
final theBall = world.theBall; final theBall = world.theBall;
final ballPosition = theBall.absolutePosition; final ballPosition = theBall.absolutePosition;
final uvBall = (ballPosition - origin)..divide(kCameraSize); final uvBall = (ballPosition - origin)..divide(kCameraSize);

View File

@ -33,8 +33,9 @@ class FireflyPostProcess extends PostProcess {
final groundPosition = final groundPosition =
world.ground.rectangle.absolutePosition + Vector2(0, 1800); world.ground.rectangle.absolutePosition + Vector2(0, 1800);
final globalGroundPosition = final globalGroundPosition = camera.viewfinder.localToGlobal(
camera.viewfinder.localToGlobal(groundPosition); groundPosition,
);
final uvGround = globalGroundPosition.y / size.y; final uvGround = globalGroundPosition.y / size.y;
final cameraVerticalPos = world.cameraTarget.position.clone() final cameraVerticalPos = world.cameraTarget.position.clone()

View File

@ -27,8 +27,8 @@ class ForegroundFogPostProcess extends PostProcess {
@override @override
void postProcess(Vector2 size, Canvas canvas) { void postProcess(Vector2 size, Canvas canvas) {
final origin = final origin = CameraComponent.currentCamera!.visibleWorldRect.topLeft
CameraComponent.currentCamera!.visibleWorldRect.topLeft.toVector2(); .toVector2();
shader.setFloatUniforms((value) { shader.setFloatUniforms((value) {
value.setVector(size); value.setVector(size);

View File

@ -27,8 +27,9 @@ class WaterPostProcess extends PostProcess {
void postProcess(Vector2 size, Canvas canvas) { void postProcess(Vector2 size, Canvas canvas) {
final groundPosition = world.ground.rectangle.position; final groundPosition = world.ground.rectangle.position;
final camera = CameraComponent.currentCamera!; final camera = CameraComponent.currentCamera!;
final globalGroundPosition = final globalGroundPosition = camera.viewfinder.localToGlobal(
camera.viewfinder.localToGlobal(groundPosition); groundPosition,
);
final uvGround = globalGroundPosition.y / size.y; final uvGround = globalGroundPosition.y / size.y;
final preRenderedSubtree = rasterizeSubtree(); final preRenderedSubtree = rasterizeSubtree();

View File

@ -5,7 +5,7 @@ publish_to: 'none'
version: "0.1.0" version: "0.1.0"
environment: environment:
sdk: ">=3.6.0 <4.0.0" sdk: ">=3.8.0 <4.0.0"
flutter: ">=3.27.1" flutter: ">=3.27.1"
dependencies: dependencies:

View File

@ -88,10 +88,11 @@ List<Ball> createBalls(Vector2 trackSize, List<Wall> walls, Ball bigBall) {
); );
final touchesBall = final touchesBall =
ball.initialPosition.distanceTo(bigBall.initialPosition) < ball.initialPosition.distanceTo(bigBall.initialPosition) <
ball.radius + bigBall.radius; ball.radius + bigBall.radius;
if (!touchesBall) { if (!touchesBall) {
final touchesWall = final touchesWall = walls.any(
walls.any((wall) => wall.asRect.overlaps(ball.asRect)); (wall) => wall.asRect.overlaps(ball.asRect),
);
if (!touchesWall) { if (!touchesWall) {
balls.add(ball); balls.add(ball);
} }

View File

@ -11,10 +11,10 @@ import 'package:padracing/tire.dart';
class Car extends BodyComponent<PadRacingGame> { class Car extends BodyComponent<PadRacingGame> {
Car({required this.playerNumber, required this.cameraComponent}) Car({required this.playerNumber, required this.cameraComponent})
: super( : super(
priority: 3, priority: 3,
paint: Paint()..color = colors[playerNumber], paint: Paint()..color = colors[playerNumber],
); );
static final colors = [ static final colors = [
GameColors.green.color, GameColors.green.color,

View File

@ -11,7 +11,7 @@ import 'package:padracing/game_colors.dart';
class LapLine extends BodyComponent with ContactCallbacks { class LapLine extends BodyComponent with ContactCallbacks {
LapLine(this.id, this.initialPosition, this.size, {required this.isFinish}) LapLine(this.id, this.initialPosition, this.size, {required this.isFinish})
: super(priority: 1); : super(priority: 1);
final int id; final int id;
final bool isFinish; final bool isFinish;
@ -94,8 +94,9 @@ class LapLine extends BodyComponent with ContactCallbacks {
other.lapNotifier.value++; other.lapNotifier.value++;
other.passedStartControl.clear(); other.passedStartControl.clear();
} else if (!isFinish) { } else if (!isFinish) {
other.passedStartControl other.passedStartControl.removeWhere(
.removeWhere((passedControl) => passedControl.id > id); (passedControl) => passedControl.id > id,
);
other.passedStartControl.add(this); other.passedStartControl.add(this);
} }
} }

View File

@ -8,7 +8,7 @@ import 'package:padracing/padracing_game.dart';
class LapText extends PositionComponent with HasGameReference<PadRacingGame> { class LapText extends PositionComponent with HasGameReference<PadRacingGame> {
LapText({required this.car, required Vector2 position}) LapText({required this.car, required Vector2 position})
: super(position: position); : super(position: position);
final Car car; final Car car;
late final ValueNotifier<int> lapNotifier = car.lapNotifier; late final ValueNotifier<int> lapNotifier = car.lapNotifier;

View File

@ -133,14 +133,14 @@ class PadRacingGame extends Forge2DGame with KeyboardEvents {
..paint.style = PaintingStyle.stroke; ..paint.style = PaintingStyle.stroke;
final cameras = List.generate(numberOfPlayers, (i) { final cameras = List.generate(numberOfPlayers, (i) {
return CameraComponent( return CameraComponent(
world: world, world: world,
viewport: FixedSizeViewport(viewportSize.x, viewportSize.y) viewport: FixedSizeViewport(viewportSize.x, viewportSize.y)
..position = alignedVector( ..position = alignedVector(
longMultiplier: i == 0 ? 0.0 : 1 / (i + 1), longMultiplier: i == 0 ? 0.0 : 1 / (i + 1),
shortMultiplier: 0.0, shortMultiplier: 0.0,
) )
..add(viewportRimGenerator()), ..add(viewportRimGenerator()),
) )
..viewfinder.anchor = Anchor.center ..viewfinder.anchor = Anchor.center
..viewfinder.zoom = playZoom; ..viewfinder.zoom = playZoom;
}); });
@ -149,13 +149,13 @@ class PadRacingGame extends Forge2DGame with KeyboardEvents {
const mapCameraZoom = 0.5; const mapCameraZoom = 0.5;
final mapCameras = List.generate(numberOfPlayers, (i) { final mapCameras = List.generate(numberOfPlayers, (i) {
return CameraComponent( return CameraComponent(
world: world, world: world,
viewport: FixedSizeViewport(mapCameraSize.x, mapCameraSize.y) viewport: FixedSizeViewport(mapCameraSize.x, mapCameraSize.y)
..position = Vector2( ..position = Vector2(
viewportSize.x - mapCameraSize.x * mapCameraZoom - 50, viewportSize.x - mapCameraSize.x * mapCameraZoom - 50,
50, 50,
), ),
) )
..viewfinder.anchor = Anchor.topLeft ..viewfinder.anchor = Anchor.topLeft
..viewfinder.zoom = mapCameraZoom; ..viewfinder.zoom = mapCameraZoom;
}); });

View File

@ -15,12 +15,12 @@ class Tire extends BodyComponent<PadRacingGame> {
required this.jointDef, required this.jointDef,
this.isTurnableTire = false, this.isTurnableTire = false,
}) : super( }) : super(
paint: Paint() paint: Paint()
..color = car.paint.color ..color = car.paint.color
..strokeWidth = 0.2 ..strokeWidth = 0.2
..style = PaintingStyle.stroke, ..style = PaintingStyle.stroke,
priority: 2, priority: 2,
); );
static const double _backTireMaxDriveForce = 300.0; static const double _backTireMaxDriveForce = 300.0;
static const double _frontTireMaxDriveForce = 600.0; static const double _frontTireMaxDriveForce = 600.0;
@ -39,10 +39,12 @@ class Tire extends BodyComponent<PadRacingGame> {
final Set<LogicalKeyboardKey> pressedKeys; final Set<LogicalKeyboardKey> pressedKeys;
late final double _maxDriveForce = late final double _maxDriveForce = isFrontTire
isFrontTire ? _frontTireMaxDriveForce : _backTireMaxDriveForce; ? _frontTireMaxDriveForce
late final double _maxLateralImpulse = : _backTireMaxDriveForce;
isFrontTire ? _frontTireMaxLateralImpulse : _backTireMaxLateralImpulse; late final double _maxLateralImpulse = isFrontTire
? _frontTireMaxLateralImpulse
: _backTireMaxLateralImpulse;
// Make mutable if ice or something should be implemented // Make mutable if ice or something should be implemented
final double _currentTraction = 1.0; final double _currentTraction = 1.0;
@ -165,8 +167,10 @@ class Tire extends BodyComponent<PadRacingGame> {
if (isTurnableTire && isTurning) { if (isTurnableTire && isTurning) {
final turnPerTimeStep = _turnSpeedPerSecond * dt; final turnPerTimeStep = _turnSpeedPerSecond * dt;
final angleNow = joint.jointAngle(); final angleNow = joint.jointAngle();
final angleToTurn = final angleToTurn = (desiredAngle - angleNow).clamp(
(desiredAngle - angleNow).clamp(-turnPerTimeStep, turnPerTimeStep); -turnPerTimeStep,
turnPerTimeStep,
);
final angle = angleNow + angleToTurn; final angle = angleNow + angleToTurn;
joint.setLimits(angle, angle); joint.setLimits(angle, angle);
} else { } else {

View File

@ -5,7 +5,7 @@ publish_to: 'none'
version: 1.0.0+1 version: 1.0.0+1
environment: environment:
sdk: ">=3.6.0 <4.0.0" sdk: ">=3.8.0 <4.0.0"
dependencies: dependencies:
collection: ^1.17.1 collection: ^1.17.1

View File

@ -9,7 +9,7 @@ class BulletComponent extends SpriteAnimationComponent
final Vector2 deltaPosition = Vector2.zero(); final Vector2 deltaPosition = Vector2.zero();
BulletComponent({required super.position, super.angle}) BulletComponent({required super.position, super.angle})
: super(size: Vector2(10, 20), anchor: Anchor.center); : super(size: Vector2(10, 20), anchor: Anchor.center);
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {

View File

@ -9,7 +9,7 @@ class EnemyComponent extends SpriteAnimationComponent
static final Vector2 initialSize = Vector2.all(25); static final Vector2 initialSize = Vector2.all(25);
EnemyComponent({required super.position}) EnemyComponent({required super.position})
: super(size: initialSize, anchor: Anchor.center); : super(size: initialSize, anchor: Anchor.center);
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {

View File

@ -3,11 +3,11 @@ import 'package:flame/components.dart';
class ExplosionComponent extends SpriteAnimationComponent class ExplosionComponent extends SpriteAnimationComponent
with HasGameReference { with HasGameReference {
ExplosionComponent({super.position}) ExplosionComponent({super.position})
: super( : super(
size: Vector2.all(50), size: Vector2.all(50),
anchor: Anchor.center, anchor: Anchor.center,
removeOnFinish: true, removeOnFinish: true,
); );
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {

View File

@ -4,7 +4,7 @@ class StarComponent extends SpriteAnimationComponent with HasGameReference {
static const speed = 10; static const speed = 10;
StarComponent({super.animation, super.position}) StarComponent({super.animation, super.position})
: super(size: Vector2.all(20)); : super(size: Vector2.all(20));
@override @override
void update(double dt) { void update(double dt) {

View File

@ -7,7 +7,7 @@ publish_to: 'none'
version: 0.1.0 version: 0.1.0
environment: environment:
sdk: ">=3.6.0 <4.0.0" sdk: ">=3.8.0 <4.0.0"
flutter: ">=3.27.1" flutter: ">=3.27.1"
dependencies: dependencies:

View File

@ -6,10 +6,10 @@ import 'package:trex_game/trex_game.dart';
class Cloud extends SpriteComponent class Cloud extends SpriteComponent
with ParentIsA<CloudManager>, HasGameReference<TRexGame> { with ParentIsA<CloudManager>, HasGameReference<TRexGame> {
Cloud({required Vector2 position}) Cloud({required Vector2 position})
: super( : super(
position: position, position: position,
size: initialSize, size: initialSize,
); );
static final Vector2 initialSize = Vector2(92.0, 28.0); static final Vector2 initialSize = Vector2(92.0, 28.0);
@ -53,7 +53,8 @@ class Cloud extends SpriteComponent
@override @override
void onGameResize(Vector2 size) { void onGameResize(Vector2 size) {
super.onGameResize(size); super.onGameResize(size);
y = ((absolutePosition.y / 2 - (maxSkyLevel - minSkyLevel)) + y =
((absolutePosition.y / 2 - (maxSkyLevel - minSkyLevel)) +
game.random.nextDoubleBetween(minSkyLevel, maxSkyLevel)) - game.random.nextDoubleBetween(minSkyLevel, maxSkyLevel)) -
absolutePositionOf(absoluteTopLeftPosition).y; absolutePositionOf(absoluteTopLeftPosition).y;
} }

View File

@ -66,7 +66,8 @@ class Horizon extends PositionComponent with HasGameReference<TRexGame> {
List<SpriteComponent> _generateLines() { List<SpriteComponent> _generateLines() {
final number = 1 + (game.size.x / lineSize.x).ceil() - groundLayers.length; final number = 1 + (game.size.x / lineSize.x).ceil() - groundLayers.length;
final lastX = (groundLayers.lastOrNull?.x ?? 0) + final lastX =
(groundLayers.lastOrNull?.x ?? 0) +
(groundLayers.lastOrNull?.width ?? 0); (groundLayers.lastOrNull?.width ?? 0);
return List.generate( return List.generate(
max(number, 0), max(number, 0),

View File

@ -29,8 +29,8 @@ class Obstacle extends SpriteComponent with HasGameReference<TRexGame> {
} }
double computeGap(double gapCoefficient, double speed) { double computeGap(double gapCoefficient, double speed) {
final minGap = final minGap = (width * speed * settings.minGap * gapCoefficient)
(width * speed * settings.minGap * gapCoefficient).roundToDouble(); .roundToDouble();
final maxGap = (minGap * _maxGapCoefficient).roundToDouble(); final maxGap = (minGap * _maxGapCoefficient).roundToDouble();
return game.random.nextDoubleBetween(minGap, maxGap); return game.random.nextDoubleBetween(minGap, maxGap);
} }

View File

@ -91,15 +91,15 @@ class ObstacleTypeSettings {
Sprite sprite(Image spriteImage) { Sprite sprite(Image spriteImage) {
return switch (type) { return switch (type) {
ObstacleType.cactusSmall => Sprite( ObstacleType.cactusSmall => Sprite(
spriteImage, spriteImage,
srcPosition: Vector2(446.0, 2.0), srcPosition: Vector2(446.0, 2.0),
srcSize: size, srcSize: size,
), ),
ObstacleType.cactusLarge => Sprite( ObstacleType.cactusLarge => Sprite(
spriteImage, spriteImage,
srcPosition: Vector2(652.0, 2.0), srcPosition: Vector2(652.0, 2.0),
srcSize: size, srcSize: size,
), ),
}; };
} }
} }

View File

@ -7,7 +7,7 @@ publish_to: 'none'
version: 0.1.0 version: 0.1.0
environment: environment:
sdk: ">=3.6.0 <4.0.0" sdk: ">=3.8.0 <4.0.0"
flutter: ">=3.27.1" flutter: ">=3.27.1"
dependencies: dependencies:

View File

@ -5,10 +5,10 @@ import 'package:meta/meta.dart';
class Ember<T extends FlameGame> extends SpriteAnimationComponent class Ember<T extends FlameGame> extends SpriteAnimationComponent
with HasGameReference<T> { with HasGameReference<T> {
Ember({super.position, Vector2? size, super.priority, super.key}) Ember({super.position, Vector2? size, super.priority, super.key})
: super( : super(
size: size ?? Vector2.all(50), size: size ?? Vector2.all(50),
anchor: Anchor.center, anchor: Anchor.center,
); );
@mustCallSuper @mustCallSuper
@override @override

View File

@ -4,7 +4,9 @@ import 'package:examples/stories/bridge_libraries/audio/basic_audio_example.dart
import 'package:flame/game.dart'; import 'package:flame/game.dart';
void addAudioStories(Dashbook dashbook) { void addAudioStories(Dashbook dashbook) {
dashbook.storiesOf('Audio').add( dashbook
.storiesOf('Audio')
.add(
'Basic Audio', 'Basic Audio',
(_) => GameWidget(game: BasicAudioExample()), (_) => GameWidget(game: BasicAudioExample()),
codeLink: baseLink('bridge_libraries/audio/basic_audio_example.dart'), codeLink: baseLink('bridge_libraries/audio/basic_audio_example.dart'),

View File

@ -15,10 +15,10 @@ class AnimatedBodyExample extends Forge2DGame {
'''; ''';
AnimatedBodyExample() AnimatedBodyExample()
: super( : super(
gravity: Vector2.zero(), gravity: Vector2.zero(),
world: AnimatedBodyWorld(), world: AnimatedBodyWorld(),
); );
} }
class AnimatedBodyWorld extends Forge2DWorld class AnimatedBodyWorld extends Forge2DWorld

View File

@ -28,12 +28,12 @@ class CompositionExample extends Forge2DGame {
class TappableText extends TextComponent with TapCallbacks { class TappableText extends TextComponent with TapCallbacks {
TappableText(Vector2 position) TappableText(Vector2 position)
: super( : super(
text: 'A normal tappable Flame component', text: 'A normal tappable Flame component',
textRenderer: TextPaint(style: _textStyle), textRenderer: TextPaint(style: _textStyle),
position: position, position: position,
anchor: Anchor.center, anchor: Anchor.center,
); );
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {

View File

@ -15,7 +15,7 @@ class ContactCallbacksExample extends Forge2DGame {
'''; ''';
ContactCallbacksExample() ContactCallbacksExample()
: super(gravity: Vector2(0, 10.0), world: ContactCallbackWorld()); : super(gravity: Vector2(0, 10.0), world: ContactCallbackWorld());
} }
class ContactCallbackWorld extends Forge2DWorld class ContactCallbackWorld extends Forge2DWorld

View File

@ -14,7 +14,7 @@ class DominoExample extends Forge2DGame {
'''; ''';
DominoExample() DominoExample()
: super(gravity: Vector2(0, 10.0), world: DominoExampleWorld()); : super(gravity: Vector2(0, 10.0), world: DominoExampleWorld());
} }
class DominoExampleWorld extends Forge2DWorld class DominoExampleWorld extends Forge2DWorld

View File

@ -11,7 +11,7 @@ class FrictionJointExample extends Forge2DGame {
'''; ''';
FrictionJointExample() FrictionJointExample()
: super(gravity: Vector2.all(0), world: FrictionJointWorld()); : super(gravity: Vector2.all(0), world: FrictionJointWorld());
} }
class FrictionJointWorld extends Forge2DWorld class FrictionJointWorld extends Forge2DWorld

View File

@ -28,8 +28,11 @@ class GearJointWorld extends Forge2DWorld with HasGameReference<Forge2DGame> {
Future<void> onLoad() async { Future<void> onLoad() async {
super.onLoad(); super.onLoad();
final box = final box = DraggableBox(
DraggableBox(startPosition: boxAnchor, width: boxWidth, height: 20); startPosition: boxAnchor,
width: boxWidth,
height: 20,
);
add(box); add(box);
final ball1Anchor = boxAnchor - Vector2(boxWidth / 2 + ball1Radius, 0); final ball1Anchor = boxAnchor - Vector2(boxWidth / 2 + ball1Radius, 0);

View File

@ -13,7 +13,7 @@ class MotorJointExample extends Forge2DGame {
'''; ''';
MotorJointExample() MotorJointExample()
: super(gravity: Vector2.zero(), world: MotorJointWorld()); : super(gravity: Vector2.zero(), world: MotorJointWorld());
} }
class MotorJointWorld extends Forge2DWorld with TapCallbacks { class MotorJointWorld extends Forge2DWorld with TapCallbacks {

View File

@ -12,7 +12,7 @@ class MouseJointExample extends Forge2DGame {
'''; ''';
MouseJointExample() MouseJointExample()
: super(gravity: Vector2(0, 10.0), world: MouseJointWorld()); : super(gravity: Vector2(0, 10.0), world: MouseJointWorld());
} }
class MouseJointWorld extends Forge2DWorld class MouseJointWorld extends Forge2DWorld

View File

@ -15,7 +15,7 @@ class RevoluteJointExample extends Forge2DGame {
'''; ''';
RevoluteJointExample() RevoluteJointExample()
: super(gravity: Vector2(0, 10.0), world: RevoluteJointWorld()); : super(gravity: Vector2(0, 10.0), world: RevoluteJointWorld());
} }
class RevoluteJointWorld extends Forge2DWorld class RevoluteJointWorld extends Forge2DWorld

View File

@ -54,11 +54,12 @@ class WeldJointWorld extends Forge2DWorld
// screen space then gives us the coordinates of the upper left corner in // screen space then gives us the coordinates of the upper left corner in
// world space. // world space.
final halfSize = game.screenToWorld(Vector2.zero())..absolute(); final halfSize = game.screenToWorld(Vector2.zero())..absolute();
final sectionWidth = ((leftPillar.center.x.abs() + final sectionWidth =
rightPillar.center.x.abs() + ((leftPillar.center.x.abs() +
pillarWidth) / rightPillar.center.x.abs() +
sectionsCount) pillarWidth) /
.ceilToDouble(); sectionsCount)
.ceilToDouble();
Body? prevSection; Body? prevSection;
for (var i = 0; i < sectionsCount; i++) { for (var i = 0; i < sectionsCount; i++) {

View File

@ -12,10 +12,10 @@ class SpriteBodyExample extends Forge2DGame {
'''; ''';
SpriteBodyExample() SpriteBodyExample()
: super( : super(
gravity: Vector2(0, 10.0), gravity: Vector2(0, 10.0),
world: SpriteBodyWorld(), world: SpriteBodyWorld(),
); );
} }
class SpriteBodyWorld extends Forge2DWorld class SpriteBodyWorld extends Forge2DWorld

View File

@ -22,7 +22,7 @@ class Wall extends BodyComponent {
final double strokeWidth; final double strokeWidth;
Wall(this.start, this.end, {double? strokeWidth}) Wall(this.start, this.end, {double? strokeWidth})
: strokeWidth = strokeWidth ?? 1; : strokeWidth = strokeWidth ?? 1;
@override @override
Body createBody() { Body createBody() {

View File

@ -4,7 +4,9 @@ import 'package:examples/stories/bridge_libraries/flame_isolate/simple_isolate_e
import 'package:flame/game.dart'; import 'package:flame/game.dart';
void addFlameIsolateExample(Dashbook dashbook) { void addFlameIsolateExample(Dashbook dashbook) {
dashbook.storiesOf('FlameIsolate').add( dashbook
.storiesOf('FlameIsolate')
.add(
'Simple isolate example', 'Simple isolate example',
(_) => GameWidget( (_) => GameWidget(
game: SimpleIsolateExample(), game: SimpleIsolateExample(),

View File

@ -10,7 +10,7 @@ class CommandLifecycleDialogueController extends DialogueControllerComponent {
}); });
final FutureOr<void> Function(UserDefinedCommand command) onCommandOverride; final FutureOr<void> Function(UserDefinedCommand command) onCommandOverride;
final FutureOr<void> Function(UserDefinedCommand command) final FutureOr<void> Function(UserDefinedCommand command)
onCommandFinishOverride; onCommandFinishOverride;
@override @override
FutureOr<void> onCommand(UserDefinedCommand command) async { FutureOr<void> onCommand(UserDefinedCommand command) async {

View File

@ -4,14 +4,14 @@ import 'package:flutter/material.dart';
class DialogueTextBox extends TextBoxComponent { class DialogueTextBox extends TextBoxComponent {
DialogueTextBox({required super.text}) DialogueTextBox({required super.text})
: super( : super(
position: Vector2(16, 16), position: Vector2(16, 16),
size: Vector2(704, 96), size: Vector2(704, 96),
textRenderer: TextPaint( textRenderer: TextPaint(
style: const TextStyle( style: const TextStyle(
fontSize: fontSize, fontSize: fontSize,
color: Colors.black, color: Colors.black,
),
), ),
); ),
);
} }

View File

@ -25,13 +25,15 @@ commands work.
final yarnProject = YarnProject(); final yarnProject = YarnProject();
final dialogueControllerComponent = CommandLifecycleDialogueController( final dialogueControllerComponent = CommandLifecycleDialogueController(
onCommandOverride: (command) async { onCommandOverride: (command) async {
final exampleVariable = final exampleVariable = yarnProject.variables.getVariable(
yarnProject.variables.getVariable(r'$exampleVariable'); r'$exampleVariable',
);
onCommandLabel.text = 'onCommand: $exampleVariable'; onCommandLabel.text = 'onCommand: $exampleVariable';
}, },
onCommandFinishOverride: (command) async { onCommandFinishOverride: (command) async {
final exampleVariable = final exampleVariable = yarnProject.variables.getVariable(
yarnProject.variables.getVariable(r'$exampleVariable'); r'$exampleVariable',
);
onCommandFinishLabel.text = 'onCommandFinish: $exampleVariable'; onCommandFinishLabel.text = 'onCommandFinish: $exampleVariable';
}, },
); );

View File

@ -4,7 +4,9 @@ import 'package:examples/stories/bridge_libraries/flame_lottie/lottie_animation_
import 'package:flame/game.dart'; import 'package:flame/game.dart';
void addFlameLottieExample(Dashbook dashbook) { void addFlameLottieExample(Dashbook dashbook) {
dashbook.storiesOf('FlameLottie').add( dashbook
.storiesOf('FlameLottie')
.add(
'Lottie Animation example', 'Lottie Animation example',
(_) => GameWidget( (_) => GameWidget(
game: LottieAnimationExample(), game: LottieAnimationExample(),

View File

@ -11,8 +11,9 @@ void addFlameSpineExamples(Dashbook dashbook) {
(_) => GameWidget( (_) => GameWidget(
game: FlameSpineExample(), game: FlameSpineExample(),
), ),
codeLink: codeLink: baseLink(
baseLink('bridge_libraries/flame_spine/basic_spine_example.dart'), 'bridge_libraries/flame_spine/basic_spine_example.dart',
),
info: FlameSpineExample.description, info: FlameSpineExample.description,
) )
..add( ..add(

View File

@ -85,8 +85,9 @@ void addCameraAndViewportStories(Dashbook dashbook) {
..add( ..add(
'Follow and World bounds', 'Follow and World bounds',
(_) => GameWidget(game: CameraFollowAndWorldBoundsExample()), (_) => GameWidget(game: CameraFollowAndWorldBoundsExample()),
codeLink: codeLink: baseLink(
baseLink('camera_and_viewport/camera_follow_and_world_bounds.dart'), 'camera_and_viewport/camera_follow_and_world_bounds.dart',
),
info: CameraFollowAndWorldBoundsExample.description, info: CameraFollowAndWorldBoundsExample.description,
); );
} }

View File

@ -36,8 +36,10 @@ class CameraComponentExample extends FlameGame<AntWorld> with PanDetector {
camera.viewfinder.position = Vector2(center.x, center.y); camera.viewfinder.position = Vector2(center.x, center.y);
}); });
magnifyingGlass = magnifyingGlass = CameraComponent(
CameraComponent(world: world, viewport: CircularViewport(radius)); world: world,
viewport: CircularViewport(radius),
);
magnifyingGlass.viewport.add(Bezel(radius)); magnifyingGlass.viewport.add(Bezel(radius));
magnifyingGlass.viewfinder.zoom = zoom; magnifyingGlass.viewfinder.zoom = zoom;
} }
@ -77,10 +79,10 @@ class CameraComponentExample extends FlameGame<AntWorld> with PanDetector {
class Bezel extends PositionComponent { class Bezel extends PositionComponent {
Bezel(this.radius) Bezel(this.radius)
: super( : super(
size: Vector2.all(2 * radius), size: Vector2.all(2 * radius),
position: Vector2.all(radius), position: Vector2.all(radius),
); );
final double radius; final double radius;
late final Path rim; late final Path rim;
@ -106,23 +108,27 @@ class Bezel extends PositionComponent {
rimBorder = Path() rimBorder = Path()
..addOval(Rect.fromLTRB(-outer, -outer, outer, outer)) ..addOval(Rect.fromLTRB(-outer, -outer, outer, outer))
..addOval(Rect.fromLTRB(-inner, -inner, inner, inner)); ..addOval(Rect.fromLTRB(-inner, -inner, inner, inner));
handle = (Path() handle =
..addRRect( (Path()..addRRect(
RRect.fromLTRBR( RRect.fromLTRBR(
radius, radius,
-handleWidth / 2, -handleWidth / 2,
handleLength + radius, handleLength + radius,
handleWidth / 2, handleWidth / 2,
const Radius.circular(5.0), const Radius.circular(5.0),
), ),
)) ))
.transform32((Matrix4.identity()..rotateZ(pi / 4)).storage); .transform32((Matrix4.identity()..rotateZ(pi / 4)).storage);
connector = (Path() connector =
..addArc(Rect.fromLTRB(-outer, -outer, outer, outer), -0.22, 0.44)) (Path()..addArc(
.transform32((Matrix4.identity()..rotateZ(pi / 4)).storage); Rect.fromLTRB(-outer, -outer, outer, outer),
specularHighlight = (Path() -0.22,
..addOval(Rect.fromLTWH(-radius * 0.8, -8, 16, radius * 0.3))) 0.44,
.transform32((Matrix4.identity()..rotateZ(pi / 4)).storage); ))
.transform32((Matrix4.identity()..rotateZ(pi / 4)).storage);
specularHighlight =
(Path()..addOval(Rect.fromLTWH(-radius * 0.8, -8, 16, radius * 0.3)))
.transform32((Matrix4.identity()..rotateZ(pi / 4)).storage);
glassPaint = Paint()..color = const Color(0x1400ffae); glassPaint = Paint()..color = const Color(0x1400ffae);
rimBorderPaint = Paint() rimBorderPaint = Paint()
@ -428,8 +434,9 @@ class Ant extends PositionComponent {
'nextIndex is outside of the bounds of travelPath', 'nextIndex is outside of the bounds of travelPath',
); );
final nextPosition = travelPath[nextIndex]; final nextPosition = travelPath[nextIndex];
var nextAngle = var nextAngle = angle = -(nextPosition - position).angleToSigned(
angle = -(nextPosition - position).angleToSigned(Vector2(0, -1)); Vector2(0, -1),
);
if (nextAngle - angle > tau / 2) { if (nextAngle - angle > tau / 2) {
nextAngle -= tau; nextAngle -= tau;
} }
@ -481,9 +488,9 @@ class InsectLeg {
this.l2, this.l2,
this.l3, { this.l3, {
required bool mirrorBendDirection, required bool mirrorBendDirection,
}) : dir = mirrorBendDirection ? -1 : 1, }) : dir = mirrorBendDirection ? -1 : 1,
path = Path(), path = Path(),
foot = Vector2.zero() { foot = Vector2.zero() {
final ok = placeFoot(Vector2(x1, y1)); final ok = placeFoot(Vector2(x1, y1));
assert(ok, 'The foot was not properly placed'); assert(ok, 'The foot was not properly placed');
} }

View File

@ -22,13 +22,14 @@ class CameraComponentPropertiesExample extends FlameGame {
'''; ''';
CameraComponentPropertiesExample() CameraComponentPropertiesExample()
: super( : super(
camera: CameraComponent( camera:
viewport: FixedSizeViewport(200, 200)..add(ViewportFrame()), CameraComponent(
) viewport: FixedSizeViewport(200, 200)..add(ViewportFrame()),
..viewfinder.zoom = 5 )
..viewfinder.anchor = const Anchor(0.25, 0.75), ..viewfinder.zoom = 5
); ..viewfinder.anchor = const Anchor(0.25, 0.75),
);
late RectangleComponent _cullRect; late RectangleComponent _cullRect;
@ -128,15 +129,15 @@ class Background extends Component with TapCallbacks {
class ExpandingCircle extends CircleComponent { class ExpandingCircle extends CircleComponent {
ExpandingCircle(Offset center) ExpandingCircle(Offset center)
: super( : super(
position: Vector2(center.dx, center.dy), position: Vector2(center.dx, center.dy),
anchor: Anchor.center, anchor: Anchor.center,
radius: 0, radius: 0,
paint: Paint() paint: Paint()
..color = const Color(0xffffffff) ..color = const Color(0xffffffff)
..style = PaintingStyle.stroke ..style = PaintingStyle.stroke
..strokeWidth = 1, ..strokeWidth = 1,
); );
static const maxRadius = 50; static const maxRadius = 50;

View File

@ -31,9 +31,7 @@ class CameraFollowAndWorldBoundsExample extends FlameGame
} }
class Ground extends PositionComponent { class Ground extends PositionComponent {
Ground() Ground() : pebbles = [], super(size: Vector2(1000, 30)) {
: pebbles = [],
super(size: Vector2(1000, 30)) {
final random = Random(); final random = Random();
for (var i = 0; i < 25; i++) { for (var i = 0; i < 25; i++) {
pebbles.add( pebbles.add(
@ -67,19 +65,19 @@ class Ground extends PositionComponent {
class Player extends PositionComponent with KeyboardHandler { class Player extends PositionComponent with KeyboardHandler {
Player() Player()
: body = Path() : body = Path()
..moveTo(10, 0) ..moveTo(10, 0)
..cubicTo(17, 0, 28, 20, 10, 20) ..cubicTo(17, 0, 28, 20, 10, 20)
..cubicTo(-8, 20, 3, 0, 10, 0) ..cubicTo(-8, 20, 3, 0, 10, 0)
..close(), ..close(),
eyes = Path() eyes = Path()
..addOval(const Rect.fromLTWH(12.5, 9, 4, 6)) ..addOval(const Rect.fromLTWH(12.5, 9, 4, 6))
..addOval(const Rect.fromLTWH(6.5, 9, 4, 6)), ..addOval(const Rect.fromLTWH(6.5, 9, 4, 6)),
pupils = Path() pupils = Path()
..addOval(const Rect.fromLTWH(14, 11, 2, 2)) ..addOval(const Rect.fromLTWH(14, 11, 2, 2))
..addOval(const Rect.fromLTWH(8, 11, 2, 2)), ..addOval(const Rect.fromLTWH(8, 11, 2, 2)),
velocity = Vector2.zero(), velocity = Vector2.zero(),
super(size: Vector2(20, 20), anchor: Anchor.bottomCenter); super(size: Vector2(20, 20), anchor: Anchor.bottomCenter);
final Path body; final Path body;
final Path eyes; final Path eyes;
@ -144,11 +142,14 @@ class Player extends PositionComponent with KeyboardHandler {
@override @override
bool onKeyEvent(KeyEvent event, Set<LogicalKeyboardKey> keysPressed) { bool onKeyEvent(KeyEvent event, Set<LogicalKeyboardKey> keysPressed) {
final isKeyDown = event is KeyDownEvent; final isKeyDown = event is KeyDownEvent;
final keyLeft = (event.logicalKey == LogicalKeyboardKey.arrowLeft) || final keyLeft =
(event.logicalKey == LogicalKeyboardKey.arrowLeft) ||
(event.logicalKey == LogicalKeyboardKey.keyA); (event.logicalKey == LogicalKeyboardKey.keyA);
final keyRight = (event.logicalKey == LogicalKeyboardKey.arrowRight) || final keyRight =
(event.logicalKey == LogicalKeyboardKey.arrowRight) ||
(event.logicalKey == LogicalKeyboardKey.keyD); (event.logicalKey == LogicalKeyboardKey.keyD);
final keyUp = (event.logicalKey == LogicalKeyboardKey.arrowUp) || final keyUp =
(event.logicalKey == LogicalKeyboardKey.arrowUp) ||
(event.logicalKey == LogicalKeyboardKey.keyW); (event.logicalKey == LogicalKeyboardKey.keyW);
if (isKeyDown) { if (isKeyDown) {
@ -161,9 +162,11 @@ class Player extends PositionComponent with KeyboardHandler {
nJumpsLeft -= 1; nJumpsLeft -= 1;
} }
} else { } else {
final hasLeft = keysPressed.contains(LogicalKeyboardKey.arrowLeft) || final hasLeft =
keysPressed.contains(LogicalKeyboardKey.arrowLeft) ||
keysPressed.contains(LogicalKeyboardKey.keyA); keysPressed.contains(LogicalKeyboardKey.keyA);
final hasRight = keysPressed.contains(LogicalKeyboardKey.arrowRight) || final hasRight =
keysPressed.contains(LogicalKeyboardKey.arrowRight) ||
keysPressed.contains(LogicalKeyboardKey.keyD); keysPressed.contains(LogicalKeyboardKey.keyD);
if (hasLeft && hasRight) { if (hasLeft && hasRight) {
// Leave the current speed unchanged // Leave the current speed unchanged

View File

@ -19,10 +19,10 @@ class FixedResolutionExample extends FlameGame
'''; ''';
FixedResolutionExample() FixedResolutionExample()
: super( : super(
camera: CameraComponent.withFixedResolution(width: 600, height: 1024), camera: CameraComponent.withFixedResolution(width: 600, height: 1024),
world: FixedResolutionWorld(), world: FixedResolutionWorld(),
); );
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {
@ -118,25 +118,25 @@ class TextButton extends ButtonComponent {
super.anchor, super.anchor,
TextRenderer? textRenderer, TextRenderer? textRenderer,
}) : super( }) : super(
button: RectangleComponent( button: RectangleComponent(
size: Vector2(200, 100), size: Vector2(200, 100),
paint: Paint() paint: Paint()
..color = Colors.orange ..color = Colors.orange
..strokeWidth = 2 ..strokeWidth = 2
..style = PaintingStyle.stroke, ..style = PaintingStyle.stroke,
), ),
buttonDown: RectangleComponent( buttonDown: RectangleComponent(
size: Vector2(200, 100), size: Vector2(200, 100),
paint: Paint() paint: Paint()
..color = BasicPalette.orange.color.withValues(alpha: 0.5), ..color = BasicPalette.orange.color.withValues(alpha: 0.5),
), ),
children: [ children: [
TextComponent( TextComponent(
text: text, text: text,
textRenderer: textRenderer, textRenderer: textRenderer,
position: Vector2(100, 50), position: Vector2(100, 50),
anchor: Anchor.center, anchor: Anchor.center,
), ),
], ],
); );
} }

View File

@ -24,12 +24,12 @@ class FollowComponentExample extends FlameGame
'''; ''';
FollowComponentExample({required this.viewportResolution}) FollowComponentExample({required this.viewportResolution})
: super( : super(
camera: CameraComponent.withFixedResolution( camera: CameraComponent.withFixedResolution(
width: viewportResolution.x, width: viewportResolution.x,
height: viewportResolution.y, height: viewportResolution.y,
), ),
); );
late MovableEmber ember; late MovableEmber ember;
final Vector2 viewportResolution; final Vector2 viewportResolution;
@ -182,12 +182,12 @@ class Map extends Component {
class Rock extends SpriteComponent with HasGameReference, TapCallbacks { class Rock extends SpriteComponent with HasGameReference, TapCallbacks {
Rock(Vector2 position) Rock(Vector2 position)
: super( : super(
position: position, position: position,
size: Vector2.all(50), size: Vector2.all(50),
priority: 1, priority: 1,
anchor: Anchor.center, anchor: Anchor.center,
); );
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {

View File

@ -22,12 +22,12 @@ class StaticComponentsExample extends FlameGame
StaticComponentsExample({ StaticComponentsExample({
required Vector2 viewportResolution, required Vector2 viewportResolution,
}) : super( }) : super(
camera: CameraComponent.withFixedResolution( camera: CameraComponent.withFixedResolution(
width: viewportResolution.x, width: viewportResolution.x,
height: viewportResolution.y, height: viewportResolution.y,
), ),
world: _StaticComponentWorld(), world: _StaticComponentWorld(),
); );
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {

View File

@ -12,10 +12,10 @@ class CirclesExample extends FlameGame {
'''; ''';
CirclesExample() CirclesExample()
: super( : super(
camera: CameraComponent.withFixedResolution(width: 600, height: 400), camera: CameraComponent.withFixedResolution(width: 600, height: 400),
world: MyWorld(), world: MyWorld(),
); );
} }
class MyWorld extends World with TapCallbacks, HasCollisionDetection { class MyWorld extends World with TapCallbacks, HasCollisionDetection {
@ -30,7 +30,7 @@ class MyWorld extends World with TapCallbacks, HasCollisionDetection {
class MyCollidable extends PositionComponent class MyCollidable extends PositionComponent
with HasGameReference<CirclesExample>, CollisionCallbacks { with HasGameReference<CirclesExample>, CollisionCallbacks {
MyCollidable({super.position}) MyCollidable({super.position})
: super(size: Vector2.all(30), anchor: Anchor.center); : super(size: Vector2.all(30), anchor: Anchor.center);
late Vector2 velocity; late Vector2 velocity;
final _collisionColor = Colors.amber; final _collisionColor = Colors.amber;

View File

@ -62,11 +62,11 @@ class AnimatedComponent extends SpriteAnimationComponent
Vector2 size, { Vector2 size, {
double angle = -pi / 4, double angle = -pi / 4,
}) : super( }) : super(
position: position, position: position,
size: size, size: size,
angle: angle, angle: angle,
anchor: Anchor.center, anchor: Anchor.center,
); );
@override @override
Future<void> onLoad() async { Future<void> onLoad() async {
@ -82,15 +82,15 @@ class AnimatedComponent extends SpriteAnimationComponent
..style = PaintingStyle.stroke; ..style = PaintingStyle.stroke;
add( add(
PolygonHitbox.relative( PolygonHitbox.relative(
[ [
Vector2(0.0, -1.0), Vector2(0.0, -1.0),
Vector2(-1.0, -0.1), Vector2(-1.0, -0.1),
Vector2(-0.2, 0.4), Vector2(-0.2, 0.4),
Vector2(0.2, 0.4), Vector2(0.2, 0.4),
Vector2(1.0, -0.1), Vector2(1.0, -0.1),
], ],
parentSize: size, parentSize: size,
) )
..paint = hitboxPaint ..paint = hitboxPaint
..renderShape = true, ..renderShape = true,
); );

View File

@ -19,8 +19,9 @@ void addCollisionDetectionStories(Dashbook dashbook) {
..add( ..add(
'Collidable AnimationComponent', 'Collidable AnimationComponent',
(_) => GameWidget(game: CollidableAnimationExample()), (_) => GameWidget(game: CollidableAnimationExample()),
codeLink: codeLink: baseLink(
baseLink('collision_detection/collidable_animation_example.dart'), 'collision_detection/collidable_animation_example.dart',
),
info: CollidableAnimationExample.description, info: CollidableAnimationExample.description,
) )
..add( ..add(
@ -74,8 +75,9 @@ void addCollisionDetectionStories(Dashbook dashbook) {
..add( ..add(
'Raycasting Max Distance', 'Raycasting Max Distance',
(_) => GameWidget(game: RaycastMaxDistanceExample()), (_) => GameWidget(game: RaycastMaxDistanceExample()),
codeLink: codeLink: baseLink(
baseLink('collision_detection/raycast_max_distance_example.dart'), 'collision_detection/raycast_max_distance_example.dart',
),
info: RaycastMaxDistanceExample.description, info: RaycastMaxDistanceExample.description,
) )
..add( ..add(

View File

@ -25,10 +25,10 @@ class MultipleShapesExample extends FlameGame with HasCollisionDetection {
'''; ''';
MultipleShapesExample() MultipleShapesExample()
: super( : super(
world: MultiShapesWorld(), world: MultiShapesWorld(),
camera: CameraComponent()..viewfinder.anchor = Anchor.topLeft, camera: CameraComponent()..viewfinder.anchor = Anchor.topLeft,
); );
} }
class MultiShapesWorld extends World with HasGameReference { class MultiShapesWorld extends World with HasGameReference {
@ -67,7 +67,8 @@ class MultiShapesWorld extends World with HasGameReference {
ScreenHitbox screenHitbox, ScreenHitbox screenHitbox,
) { ) {
final collidableSize = Vector2.all(50) + Vector2.random(_rng) * 100; final collidableSize = Vector2.all(50) + Vector2.random(_rng) * 100;
final isXOverflow = lastCollidable.position.x + final isXOverflow =
lastCollidable.position.x +
lastCollidable.size.x / 2 + lastCollidable.size.x / 2 +
_distance.x + _distance.x +
collidableSize.x > collidableSize.x >
@ -223,7 +224,7 @@ class SnowmanPart extends CircleHitbox {
final Color hitColor; final Color hitColor;
SnowmanPart(double radius, Vector2 position, this.hitColor) SnowmanPart(double radius, Vector2 position, this.hitColor)
: super(radius: radius, position: position, anchor: Anchor.center) { : super(radius: radius, position: position, anchor: Anchor.center) {
paint.color = startColor; paint.color = startColor;
} }
@ -288,12 +289,23 @@ MyCollidable randomCollidable(
final rotationSpeed = 0.5 - rng.nextDouble(); final rotationSpeed = 0.5 - rng.nextDouble();
final shapeType = Shapes.values[rng.nextInt(Shapes.values.length)]; final shapeType = Shapes.values[rng.nextInt(Shapes.values.length)];
return switch (shapeType) { return switch (shapeType) {
Shapes.circle => CollidableCircle(position, size, velocity, screenHitbox) Shapes.circle => CollidableCircle(
..rotationSpeed = rotationSpeed, position,
Shapes.rectangle => size,
CollidableRectangle(position, size, velocity, screenHitbox) velocity,
..rotationSpeed = rotationSpeed, screenHitbox,
Shapes.polygon => CollidablePolygon(position, size, velocity, screenHitbox) )..rotationSpeed = rotationSpeed,
..rotationSpeed = rotationSpeed, Shapes.rectangle => CollidableRectangle(
position,
size,
velocity,
screenHitbox,
)..rotationSpeed = rotationSpeed,
Shapes.polygon => CollidablePolygon(
position,
size,
velocity,
screenHitbox,
)..rotationSpeed = rotationSpeed,
}; };
} }

Some files were not shown because too many files have changed in this diff Show More