Files
front-hokm/lib/features/game/flame/table_pieces.dart
T
2026-06-15 18:57:00 +03:30

125 lines
3.8 KiB
Dart

import 'dart:math' as math;
import 'package:flame/components.dart';
import 'package:flutter/material.dart';
// رنگ‌های مشترکِ میز.
const _gold = Color(0xFFE9B949);
const _goldDark = Color(0xFFB8860B);
/// نمدِ سبزِ بیضی‌شکلِ میز با حاشیه‌ی طلایی.
class Felt extends PositionComponent with HasGameReference {
@override
void render(Canvas canvas) {
final w = game.size.x, h = game.size.y;
final rect = Rect.fromCenter(
center: Offset(w / 2, h / 2),
width: w * 0.86,
height: h * 0.62,
);
final rrect = RRect.fromRectAndRadius(rect, Radius.circular(h * 0.3));
canvas.drawRRect(rrect, Paint()..color = const Color(0xFF1B5E20));
canvas.drawRRect(
rrect,
Paint()
..style = PaintingStyle.stroke
..strokeWidth = 6
..color = _goldDark,
);
}
}
/// دیسکِ فلزیِ شمارش (امتیاز تیم) با عددِ وسط؛ از ۰ تا ۷.
class ScorePuck extends PositionComponent {
final int count;
ScorePuck(this.count, {required double radius, super.position})
: super(size: Vector2.all(radius * 2), anchor: Anchor.center);
@override
void render(Canvas canvas) {
final r = size.x / 2;
final c = Offset(r, r);
canvas.drawCircle(c, r, Paint()..color = const Color(0xFF14110F));
canvas.drawCircle(
c,
r * 0.92,
Paint()
..style = PaintingStyle.stroke
..strokeWidth = r * 0.22
..color = _goldDark,
);
final tp = TextPainter(
text: TextSpan(
text: '$count',
style: TextStyle(
fontFamily: 'Dana',
color: _gold,
fontSize: r * 1.05,
fontWeight: FontWeight.bold,
),
),
textDirection: TextDirection.ltr,
)..layout();
tp.paint(canvas, c - Offset(tp.width / 2, tp.height / 2));
}
}
/// افکت رعد روی زمین هنگام «بریدن با حکم»؛ پس از مدت کوتاهی خودش حذف می‌شود.
class Lightning extends PositionComponent with HasGameReference {
static const _max = 0.55;
double _life = _max;
final _rng = math.Random();
final List<List<Offset>> _bolts = [];
@override
Future<void> onLoad() async {
size = game.size;
final center = Offset(size.x / 2, size.y / 2);
for (var i = 0; i < 3; i++) {
// هر رعد یک خط شکسته از یک نقطه‌ی تصادفیِ بالا به سمت مرکز.
final start =
Offset(_rng.nextDouble() * size.x, _rng.nextDouble() * size.y * 0.4);
final pts = <Offset>[start];
const segs = 6;
for (var s = 1; s <= segs; s++) {
final t = s / segs;
final base = Offset.lerp(start, center, t)!;
final jitter = (1 - t) * size.x * 0.06;
pts.add(base +
Offset((_rng.nextDouble() - 0.5) * jitter,
(_rng.nextDouble() - 0.5) * jitter));
}
_bolts.add(pts);
}
}
@override
void update(double dt) {
_life -= dt;
if (_life <= 0) removeFromParent();
}
@override
void render(Canvas canvas) {
final op = (_life / _max).clamp(0.0, 1.0);
final glow = Paint()
..color = const Color(0xFFFFE082).withValues(alpha: op * 0.5)
..style = PaintingStyle.stroke
..strokeWidth = size.x * 0.02
..maskFilter = const MaskFilter.blur(BlurStyle.normal, 6);
final core = Paint()
..color = const Color(0xFFFFFDE7).withValues(alpha: op)
..style = PaintingStyle.stroke
..strokeWidth = size.x * 0.006
..strokeCap = StrokeCap.round;
for (final bolt in _bolts) {
final path = Path()..moveTo(bolt.first.dx, bolt.first.dy);
for (final p in bolt.skip(1)) {
path.lineTo(p.dx, p.dy);
}
canvas.drawPath(path, glow);
canvas.drawPath(path, core);
}
}
}