match-three/lib/game/components/gem_component.dart

142 lines
3.5 KiB
Dart

import 'package:flame/components.dart';
import 'package:flame/effects.dart';
import 'package:flame/events.dart';
import 'package:flutter/material.dart';
import '../models/gem.dart';
import '../systems/physics_system.dart';
import 'grid_component.dart';
import 'particle_system.dart';
import '../../utils/constants.dart';
class GemComponent extends RectangleComponent with TapCallbacks {
final Gem gem;
final GridComponent gridComponent;
bool isSelected = false;
static const List<Color> gemColors = [
Colors.red,
Colors.blue,
Colors.green,
Colors.yellow,
Colors.purple,
Colors.orange,
];
GemComponent({required this.gem, required this.gridComponent})
: super(
size: Vector2.all(GameConstants.gemSize - 4),
paint: Paint()..color = gemColors[gem.type % gemColors.length],
);
@override
bool onTapDown(TapDownEvent event) {
if (!gridComponent.canInterract) return false;
gridComponent.onGemTapped(gem);
_animateSelection();
PhysicsSystem.animatePop(this);
return true;
}
void _animateSelection() {
isSelected = !isSelected;
final scaleEffect = ScaleEffect.to(
Vector2.all(isSelected ? 1.1 : 1.0),
EffectController(duration: 0.2),
);
add(scaleEffect);
}
animateMatch() async {
// Add particle explosion
final explosion = ParticleSystem.createMatchExplosion(
position + size / 2,
gemColors[gem.type % gemColors.length],
);
parent?.add(explosion);
// Animate gem destruction
PhysicsSystem.animateMatch(this);
// Remove after animation
await Future.delayed(
Duration(milliseconds: (GameConstants.matchDuration * 1000).round()),
() {
removeFromParent();
});
}
animateFall(Vector2 targetPosition) async {
await PhysicsSystem.animateFall(this, targetPosition);
}
animateCombo() {
final comboEffect = ParticleSystem.createComboEffect(position + size / 2);
parent?.add(comboEffect);
}
@override
void render(Canvas canvas) {
super.render(canvas);
// Add gradient effect
final gradient = RadialGradient(
colors: [
gemColors[gem.type % gemColors.length].withOpacity(0.9),
gemColors[gem.type % gemColors.length],
],
);
final gradientPaint = Paint()
..shader = gradient.createShader(size.toRect());
canvas.drawRRect(
RRect.fromRectAndRadius(
size.toRect(),
const Radius.circular(8),
),
gradientPaint,
);
// Add border and glow effect
final borderColor = isSelected ? Colors.white : Colors.black26;
final borderWidth = isSelected ? 3.0 : 1.0;
canvas.drawRRect(
RRect.fromRectAndRadius(
size.toRect(),
const Radius.circular(8),
),
Paint()
..color = borderColor
..style = PaintingStyle.stroke
..strokeWidth = borderWidth,
);
if (isSelected) {
canvas.drawRRect(
RRect.fromRectAndRadius(
size.toRect().inflate(2),
const Radius.circular(10),
),
Paint()
..color = Colors.white.withOpacity(0.3)
..style = PaintingStyle.stroke
..strokeWidth = 2,
);
}
// Add shine effect
final shinePaint = Paint()
..color = Colors.white.withOpacity(0.3)
..style = PaintingStyle.fill;
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromLTWH(size.x * 0.2, size.y * 0.1, size.x * 0.3, size.y * 0.2),
const Radius.circular(4),
),
shinePaint,
);
}
}