fix: delay after fire

This commit is contained in:
2026-07-08 19:20:30 +03:30
parent 6b9b9a0f3a
commit 2496580e86
3 changed files with 217 additions and 35 deletions
@@ -1,4 +1,5 @@
import 'dart:math' as math;
import 'dart:ui' as ui;
import 'package:flame/components.dart';
import 'package:flutter/material.dart';
@@ -327,6 +328,128 @@ class _Spark {
_Spark(this.ang, this.speed, this.r);
}
/// افکتِ آتش برای «بریدنِ پیاپیِ حکم» (کمبو: چند روبُریدنِ سریع در یک دست).
/// شعله‌هایی که از مرکزِ میز بالا می‌آیند + ذراتِ اخگرِ صعودی. هر چه شدتِ کمبو
/// بیشتر (تعدادِ بریدن) شعله بلندتر و پرحجم‌تر است.
class FireBurst extends PositionComponent with HasGameReference {
/// شدت (۱..۳+): تعدادِ بریدنِ پیاپی؛ ارتفاع/حجمِ شعله را تعیین می‌کند.
final int intensity;
FireBurst({this.intensity = 3});
static const _max = 1.15;
double _life = _max;
double _t = 0;
final _rng = math.Random();
late final List<_Ember> _embers;
late final List<_Flame> _flames;
double get _scale => (intensity.clamp(3, 6)) / 3.0; // ۱.۰ در ۳ بریدن، بیشتر با کمبو
@override
Future<void> onLoad() async {
size = game.size;
final n = (18 * _scale).round();
_embers = List.generate(n, (_) {
final spread = (_rng.nextDouble() - 0.5) * size.x * 0.34;
final rise = 0.30 + _rng.nextDouble() * 0.55; // کسری از ارتفاعِ صعود
final delay = _rng.nextDouble() * 0.35;
return _Ember(spread, rise, delay, 1.5 + _rng.nextDouble() * 2.8);
});
final f = (5 * _scale).round();
_flames = List.generate(f, (i) {
final off = (_rng.nextDouble() - 0.5) * size.x * 0.22;
final w = size.x * (0.07 + _rng.nextDouble() * 0.06);
final h = size.x * (0.18 + _rng.nextDouble() * 0.12) * _scale;
final ph = _rng.nextDouble() * math.pi * 2;
return _Flame(off, w, h, ph);
});
}
@override
void update(double dt) {
_t += dt;
_life -= dt;
if (_life <= 0) removeFromParent();
}
@override
void render(Canvas canvas) {
final prog = (1 - _life / _max).clamp(0.0, 1.0);
// پاکتِ شدت: سریع بالا می‌آید، آرام محو می‌شود.
final env = prog < 0.2 ? prog / 0.2 : (1 - (prog - 0.2) / 0.8);
final base = Offset(size.x / 2, size.y * 0.56); // کفِ شعله (نزدیکِ مرکزِ میز)
// ۱) هاله‌ی نارنجیِ گرم پشتِ شعله.
canvas.drawCircle(
base,
size.x * 0.28 * env * _scale,
Paint()
..color = const Color(0xFFFF7A18).withValues(alpha: 0.22 * env)
..maskFilter = MaskFilter.blur(BlurStyle.normal, size.x * 0.05),
);
// ۲) زبانه‌های شعله (نارنجی→زرد) با لرزشِ افقی.
for (final fl in _flames) {
final sway = math.sin(_t * 9 + fl.phase) * size.x * 0.02;
final cx = base.dx + fl.off + sway;
final h = fl.h * env;
final tip = Offset(cx + sway * 0.6, base.dy - h);
final path = Path()
..moveTo(cx - fl.w / 2, base.dy)
..quadraticBezierTo(cx - fl.w * 0.5, base.dy - h * 0.5, tip.dx, tip.dy)
..quadraticBezierTo(cx + fl.w * 0.5, base.dy - h * 0.5, cx + fl.w / 2, base.dy)
..close();
canvas.drawPath(
path,
Paint()
..shader = _flameShader(base.dy, base.dy - h, env)
..maskFilter = MaskFilter.blur(BlurStyle.normal, size.x * 0.008),
);
}
// ۳) اخگرهای صعودی.
for (final e in _embers) {
final lt = ((prog - e.delay) / (1 - e.delay)).clamp(0.0, 1.0);
if (lt <= 0) continue;
final y = base.dy - lt * size.y * 0.42 * e.rise * _scale;
final x = base.dx + e.spread * lt + math.sin(lt * 8 + e.spread) * 3;
final a = (1 - lt) * env;
canvas.drawCircle(
Offset(x, y),
e.r * (1 - lt * 0.5),
Paint()
..color = Color.lerp(
const Color(0xFFFFE082),
const Color(0xFFFF5722),
lt,
)!.withValues(alpha: a),
);
}
}
// گرادیانِ عمودیِ شعله: کفِ زرد/سفید (y0) → نوکِ نارنجیِ کم‌رنگ (y1).
Shader _flameShader(double y0, double y1, double env) => ui.Gradient.linear(
Offset(0, y0),
Offset(0, y1),
[
const Color(0xFFFFF3C4).withValues(alpha: 0.95 * env),
const Color(0xFFFFB300).withValues(alpha: 0.85 * env),
const Color(0xFFFF5722).withValues(alpha: 0.15 * env),
],
const [0.0, 0.45, 1.0],
);
}
class _Ember {
final double spread, rise, delay, r;
_Ember(this.spread, this.rise, this.delay, this.r);
}
class _Flame {
final double off, w, h, phase;
_Flame(this.off, this.w, this.h, this.phase);
}
class Lightning extends PositionComponent with HasGameReference {
static const _max = 0.55;
double _life = _max;