fix: delay after fire
This commit is contained in:
@@ -50,6 +50,14 @@ class HokmGame extends FlameGame {
|
||||
List<String> _prevTrick = const [];
|
||||
bool _highlightedTrick = false; // آیا کارتِ برندهی دستِ کامل هایلایت شده (یکبار)
|
||||
int _bestTrumpRank = 0; // بالاترین رتبهی حکمِ بازیشده در دستِ جاری (برای افکتِ بریدن)
|
||||
int _cutCombo = 0; // شمارِ بریدنِ پیاپیِ سریع (روبُریدنها) برای افکتِ آتش
|
||||
double _lastCutAt = -999; // زمانِ آخرین بریدن (برای پنجرهی کمبو)
|
||||
// «مکثِ آتش»: پس از افکتِ آتشِ کمبو، صحنه کوتاه فریز میشود تا لحظه دیده شود؛
|
||||
// وضعیتهای ورودی بافر میشوند و پس از مکث اعمال میگردند (کاربر و بات فرقی ندارند).
|
||||
bool _cutHold = false;
|
||||
double _cutHoldUntil = 0;
|
||||
GameState? _pendingState;
|
||||
static const double _cutHoldSec = 1.0;
|
||||
int _prevHandSize = 0; // برای تشخیصِ پخشِ کارت (دستِ جدید) جهت صدای بُر زدن
|
||||
String _prevHandSig = ''; // امضای دست؛ برای تشخیصِ بُرِ مجدد (تغییرِ ۵ کارت در فازِ حکم)
|
||||
bool _silent = false; // هنگام خروج از میز، دیگر صدایی پخش نشود
|
||||
@@ -91,39 +99,12 @@ class HokmGame extends FlameGame {
|
||||
_sub = cubit.stream.listen((ui) {
|
||||
if (ui.state == null) return;
|
||||
final s = ui.state!;
|
||||
_checkTrickSounds(s);
|
||||
// شروعِ دستِ جدید (پخشِ کارت): انیمیشن و صدای بُر زدن.
|
||||
// دستِ اول تا پایانِ نمایشِ «جستجوی حریف» به تعویق میافتد تا انیمیشن
|
||||
// زیرِ اوورلی پنهان نشود و صدا با تصویر هماهنگ باشد.
|
||||
if (_prevHandSize == 0 && s.yourHand.isNotEmpty && !_silent) {
|
||||
if (_introActive) {
|
||||
_pendingShuffle = true;
|
||||
} else {
|
||||
_shuffleNow();
|
||||
}
|
||||
// در حینِ «مکثِ آتش»، آخرین وضعیت را بافر کن و بعد از مکث اعمالش کن.
|
||||
if (_cutHold) {
|
||||
_pendingState = s;
|
||||
return;
|
||||
}
|
||||
// بُرِ مجدد: هنوز در فازِ حکم هستیم اما ۵ کارتِ حاکم عوض شده ⇒ انیمیشنِ بُر دوباره.
|
||||
final sig = (s.yourHand.toList()..sort()).join(',');
|
||||
if (!_silent &&
|
||||
!_introActive &&
|
||||
s.phase == 'choose_trump' &&
|
||||
s.trump == null &&
|
||||
_prevHandSize > 0 &&
|
||||
_prevHandSig.isNotEmpty &&
|
||||
sig != _prevHandSig) {
|
||||
_shuffleNow();
|
||||
}
|
||||
_prevHandSig = sig;
|
||||
// لحظهی انتخابِ حکم: صدا + نمایشِ بزرگِ حکم در مرکز.
|
||||
if (_prevTrump == null && s.trump != null && !_silent) {
|
||||
AppSounds.selectHokm();
|
||||
_spawnTrumpReveal(s.trump!);
|
||||
_dealAllNow(); // پخشِ بقیهی کارتها (بازی تا پایانِ آن قفل است)
|
||||
}
|
||||
_prevTrump = s.trump;
|
||||
_prevHandSize = s.yourHand.length;
|
||||
_s = s;
|
||||
_relayout();
|
||||
_applyState(s);
|
||||
});
|
||||
if (cubit.state.state != null) {
|
||||
_prevTrick = cubit.state.state!.trick.map((t) => t.card).toList();
|
||||
@@ -135,6 +116,44 @@ class HokmGame extends FlameGame {
|
||||
}
|
||||
}
|
||||
|
||||
/// اعمالِ یک وضعیتِ بازی روی صحنه (صداها/انیمیشنها + چیدمانِ دوباره). در حالتِ
|
||||
/// عادی مستقیم از استریم صدا زده میشود؛ در «مکثِ آتش» پس از پایانِ مکث.
|
||||
void _applyState(GameState s) {
|
||||
_checkTrickSounds(s);
|
||||
// شروعِ دستِ جدید (پخشِ کارت): انیمیشن و صدای بُر زدن.
|
||||
// دستِ اول تا پایانِ نمایشِ «جستجوی حریف» به تعویق میافتد تا انیمیشن
|
||||
// زیرِ اوورلی پنهان نشود و صدا با تصویر هماهنگ باشد.
|
||||
if (_prevHandSize == 0 && s.yourHand.isNotEmpty && !_silent) {
|
||||
if (_introActive) {
|
||||
_pendingShuffle = true;
|
||||
} else {
|
||||
_shuffleNow();
|
||||
}
|
||||
}
|
||||
// بُرِ مجدد: هنوز در فازِ حکم هستیم اما ۵ کارتِ حاکم عوض شده ⇒ انیمیشنِ بُر دوباره.
|
||||
final sig = (s.yourHand.toList()..sort()).join(',');
|
||||
if (!_silent &&
|
||||
!_introActive &&
|
||||
s.phase == 'choose_trump' &&
|
||||
s.trump == null &&
|
||||
_prevHandSize > 0 &&
|
||||
_prevHandSig.isNotEmpty &&
|
||||
sig != _prevHandSig) {
|
||||
_shuffleNow();
|
||||
}
|
||||
_prevHandSig = sig;
|
||||
// لحظهی انتخابِ حکم: صدا + نمایشِ بزرگِ حکم در مرکز.
|
||||
if (_prevTrump == null && s.trump != null && !_silent) {
|
||||
AppSounds.selectHokm();
|
||||
_spawnTrumpReveal(s.trump!);
|
||||
_dealAllNow(); // پخشِ بقیهی کارتها (بازی تا پایانِ آن قفل است)
|
||||
}
|
||||
_prevTrump = s.trump;
|
||||
_prevHandSize = s.yourHand.length;
|
||||
_s = s;
|
||||
_relayout();
|
||||
}
|
||||
|
||||
@override
|
||||
void onGameResize(Vector2 size) {
|
||||
super.onGameResize(size);
|
||||
@@ -176,8 +195,20 @@ class HokmGame extends FlameGame {
|
||||
_bestTrumpRank = rank;
|
||||
_shake = 1.0;
|
||||
add(Lightning());
|
||||
// کمبوِ بریدن: روبُریدنهای سریعِ پیاپی (پنجرهی ~۶ ثانیه) را میشمارد.
|
||||
_cutCombo = (_t - _lastCutAt < 6.0) ? _cutCombo + 1 : 1;
|
||||
_lastCutAt = _t;
|
||||
if (!AppSettings.I.lowGraphics.value) {
|
||||
add(CutBurst()); // فلاش + شوکویو + جرقه (کممصرف: خاموش)
|
||||
// سه بریدنِ پیاپی یا بیشتر ⇒ افکتِ آتش (هرچه کمبو بیشتر، شعله بلندتر).
|
||||
if (_cutCombo >= 3) {
|
||||
_shake = 1.4; // تکانِ قویتر برای اوجِ کمبو
|
||||
add(FireBurst(intensity: _cutCombo));
|
||||
// مکثِ کوتاه پس از آتش تا لحظه دیده شود؛ کارتِ بعدی (کاربر یا بات)
|
||||
// تا پایانِ مکث اعمال نمیشود.
|
||||
_cutHold = true;
|
||||
_cutHoldUntil = _t + _cutHoldSec;
|
||||
}
|
||||
}
|
||||
AppSounds.cut(); // بریدن با حکم (شمشیر)
|
||||
HapticFeedback.heavyImpact(); // ضربهی لمسیِ بُرِش با حکم
|
||||
@@ -193,6 +224,8 @@ class HokmGame extends FlameGame {
|
||||
/// قطعِ صداهای بازی هنگام خروج از میز (جلوگیری از پخشِ صدای کارت پس از ترک).
|
||||
void silence() {
|
||||
_silent = true;
|
||||
_cutHold = false; // مکثِ آتش را لغو کن تا وضعیتِ بافرشده اعمال/رها نشود
|
||||
_pendingState = null;
|
||||
AppSounds.stopHeartBeat();
|
||||
}
|
||||
|
||||
@@ -276,6 +309,19 @@ class HokmGame extends FlameGame {
|
||||
void update(double dt) {
|
||||
super.update(dt);
|
||||
_t += dt;
|
||||
// پایانِ «مکثِ آتش»: آخرین وضعیتِ بافرشده را اعمال کن (یا صحنه را تازه کن).
|
||||
if (_cutHold && _t >= _cutHoldUntil) {
|
||||
_cutHold = false;
|
||||
final p = _pendingState;
|
||||
_pendingState = null;
|
||||
if (!_silent) {
|
||||
if (p != null) {
|
||||
_applyState(p);
|
||||
} else if (_s != null) {
|
||||
_relayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_shake > 0) _shake = math.max(0, _shake - dt * 2.2);
|
||||
_updateHeartBeat(dt);
|
||||
}
|
||||
@@ -376,8 +422,8 @@ class HokmGame extends FlameGame {
|
||||
// آیا این کارت در نوبتِ فعلی قابل بازی است (با رعایت follow-suit)؟
|
||||
bool _legal(String code) {
|
||||
final s = _s!;
|
||||
// هنگامِ اینترو/بُر زدن/پخشِ کارتها، بازیِ کارت مجاز نیست.
|
||||
if (_introActive || _shuffling || _dealing) return false;
|
||||
// هنگامِ اینترو/بُر زدن/پخشِ کارتها یا مکثِ آتش، بازیِ کارت مجاز نیست.
|
||||
if (_introActive || _shuffling || _dealing || _cutHold) return false;
|
||||
if (s.phase != 'playing' || s.trickDone || !s.isMyTurn) return false;
|
||||
final lead = s.leadSuit;
|
||||
if (lead == null || lead.isEmpty) return true;
|
||||
@@ -471,6 +517,7 @@ class HokmGame extends FlameGame {
|
||||
c.size = Vector2(hw, hh);
|
||||
}
|
||||
c.angle = a; // چرخشِ کارت همراستا با شعاعِ قوس
|
||||
c.homeAngle = a; // زاویهی مرجع برای بازگشت پس از کشیدنِ ناقص
|
||||
c.onPlay = legal ? () => cubit.playCard(code) : null;
|
||||
c.dimmed = s.phase == 'playing' && s.isMyTurn && !legal;
|
||||
c.home = target;
|
||||
|
||||
Reference in New Issue
Block a user