match-three/lib/game/match_three_game.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

87 lines
2.2 KiB
Dart

import 'dart:ui';
import 'package:flame/game.dart';
import 'package:match_three/game/components/gem_component.dart';
import 'package:match_three/game/systems/match_detector.dart';
import 'components/grid_component.dart';
import 'components/background_component.dart';
import 'models/gem.dart';
import '../bloc/game_bloc.dart';
const gridSize = 8 * 64.0 + 32.0; // 8 gems * 64px + padding
class MatchThreeGame extends FlameGame {
late BackgroundComponent backgroundComponent;
late GameBloc gameBloc;
final int levelId;
final int gridHeight;
final int gridWidth;
GridComponent? gridComponent;
Gem? selectedGem;
MatchThreeGame(
{required this.levelId,
required this.gridHeight,
required this.gridWidth})
: super();
@override
Future<void> onLoad() async {
backgroundComponent = BackgroundComponent();
add(backgroundComponent);
gridComponent = GridComponent(this, levelId, gridHeight, gridWidth);
add(gridComponent!);
}
@override
void onGameResize(Vector2 size) {
super.onGameResize(size);
// Center the grid on screen
if (gridComponent != null && hasLayout) {
gridComponent!.position = Vector2(
(size.x - gridSize) / 2,
(size.y - gridSize) / 2,
);
}
}
void selectGem(Gem gem) {
print(">>> Selecting gem ${gem.name}(${gem.type}) ${gem.row}, ${gem.col}");
if (selectedGem == null) {
selectedGem = gem;
return;
}
var theGem = selectedGem;
selectedGem = null;
if (MatchDetector.isValidSwap(
gridComponent!.gameGrid, theGem!.row, theGem.col, gem.row, gem.col)) {
// Attempt swap
print(
")) Valid swapping ${theGem.row}, ${theGem.col} with ${gem.row}, ${gem.col}");
gameBloc.add(SwapGems(
theGem.row,
theGem.col,
gem.row,
gem.col,
));
} else {
print(
"(( Invalid swapping ${theGem.row}, ${theGem.col} with ${gem.row}, ${gem.col}");
}
if (gridComponent == null) {
return;
}
for (var comp in gridComponent!.children) {
if (comp is GemComponent && comp.gem != gem) {
comp.isSelected = false;
}
}
}
void setGameBloc(GameBloc bloc) {
gameBloc = bloc;
}
}