match-three/lib/game/systems/physics_system.dart
savinmax eaa6947e93 Refactor gem swap logic to handle invalid moves and animations
- Add proper validation for null gems during swap operations
- Implement swap-back animation for invalid moves (no matches)
- Restructure swap flow to emit animation states before match detection
- Add move limit validation before processing matches
- Improve error handling and logging for edge cases
2025-09-28 13:00:45 +02:00

73 lines
1.9 KiB
Dart

import 'dart:async';
import 'package:flame/components.dart';
import 'package:flame/effects.dart';
import 'package:flutter/material.dart';
import '../components/gem_component.dart';
import '../../utils/constants.dart';
class PhysicsSystem {
static animateSwap(GemComponent gem1, GemComponent gem2) async {
final pos1 = gem1.position.clone();
final pos2 = gem2.position.clone();
gem1.add(MoveEffect.to(
pos2,
EffectController(duration: GameConstants.swapDuration),
));
gem2.add(MoveEffect.to(
pos1,
EffectController(duration: GameConstants.swapDuration),
));
await Future.delayed(
Duration(milliseconds: (GameConstants.swapDuration * 1000).toInt()));
}
static Future<void> animateFall(
GemComponent gem, Vector2 targetPosition) async {
final fallDistance = targetPosition.y - gem.position.y;
final fallTime =
(fallDistance / 400).clamp(0.2, GameConstants.fallDuration);
gem.add(MoveEffect.to(
targetPosition,
EffectController(
duration: fallTime,
curve: Curves.easeIn,
),
));
await Future.delayed(Duration(milliseconds: (fallTime * 1000).toInt()));
}
static Future<void> animateMatch(GemComponent gem) async {
final scaleDone = Completer();
final opacityDone = Completer();
// Scale down and fade out
gem.add(ScaleEffect.to(
Vector2.zero(),
EffectController(duration: GameConstants.matchDuration),
onComplete: () => scaleDone.complete(),
));
gem.add(OpacityEffect.to(
0.0,
EffectController(duration: GameConstants.matchDuration),
onComplete: () => opacityDone.complete(),
));
await Future.wait([scaleDone.future, opacityDone.future]);
}
static void animatePop(GemComponent gem) {
// Quick scale up then down
gem.add(ScaleEffect.by(
Vector2.all(1.3),
EffectController(
duration: 0.1,
reverseDuration: 0.1,
),
));
}
}