fix: delay after fire
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user