priority of cards fixed

This commit is contained in:
2026-06-19 21:35:23 +03:30
parent c4c1453f7e
commit 04b97ca163
3 changed files with 106 additions and 29 deletions
@@ -49,9 +49,16 @@ class HokmGame extends FlameGame {
bool _introActive = true; // تا پایانِ نمایشِ «جستجوی حریف»
bool _pendingShuffle =
false; // بُرِ دستِ اول که تا پایانِ اینترو به تعویق افتاده
bool _shuffling = false; // در حالِ پخشِ انیمیشنِ بُر زدن (بازیِ کارت ممنوع)
bool _shuffling = false; // در حالِ بُر زدن/پخشِ ۵ کارت (بازیِ کارت ممنوع)
bool _dealing = false; // در حالِ پخشِ بقیه‌ی کارت‌ها پس از حکم (بازی ممنوع)
String? _prevTrump; // برای تشخیصِ لحظه‌ی انتخابِ حکم
/// آیا انیمیشنی در حال اجراست (اینترو/بُر زدن/پخشِ کارت). صفحه از این برای
/// پنهان‌کردنِ دیالوگِ انتخابِ حکم تا پایانِ پخشِ کارت‌ها استفاده می‌کند.
final ValueNotifier<bool> animating = ValueNotifier(true);
void _refreshAnimating() =>
animating.value = _introActive || _shuffling || _dealing;
// مدیریتِ ضربانِ قلب (فقط نوبتِ خودِ کاربر؛ مستقل از بازساختِ صحنه).
double _turnElapsed = 0;
bool _beatPlayed = false; // یک‌بار در هر نوبت، هنگام رسیدن به آستانه
@@ -83,6 +90,7 @@ class HokmGame extends FlameGame {
if (_prevTrump == null && s.trump != null && !_silent) {
AppSounds.selectHokm();
_spawnTrumpReveal(s.trump!);
_dealAllNow(); // پخشِ بقیه‌ی کارت‌ها (بازی تا پایانِ آن قفل است)
}
_prevTrump = s.trump;
_prevHandSize = s.yourHand.length;
@@ -117,7 +125,8 @@ class HokmGame extends FlameGame {
// شمشیر + تکان + رعد)؛ خالی‌شدنِ زمین ⇒ صدای جمع‌شدنِ دست.
void _checkTrickSounds(GameState s) {
final now = s.trick.map((t) => t.card).toList();
if (_silent) {
// در زمانِ اینترو/بُر زدن/پخش، کارتی روی میز نشان داده نمی‌شود ⇒ صدا هم نه.
if (_silent || _introActive || _shuffling || _dealing) {
_prevTrick = now;
return;
}
@@ -157,6 +166,7 @@ class HokmGame extends FlameGame {
_pendingShuffle = false;
_shuffleNow();
}
_refreshAnimating();
}
/// اجرای هم‌زمانِ انیمیشن و صدای بُر زدن (صدا با پایانِ انیمیشن قطع می‌شود).
@@ -166,12 +176,28 @@ class HokmGame extends FlameGame {
AppSounds.shuffle(cutoffMs: ShuffleAnimation.totalMs);
add(ShuffleAnimation(size));
_shuffling = true;
_refreshAnimating();
Future.delayed(const Duration(milliseconds: ShuffleAnimation.totalMs), () {
_shuffling = false;
_refreshAnimating();
if (_s != null && !_silent) _relayout(); // فعال‌سازیِ دوباره‌ی کارت‌ها
});
}
/// پخشِ بقیه‌ی کارت‌ها پس از انتخابِ حکم؛ تا پایانِ انیمیشن بازیِ کارت قفل است.
void _dealAllNow() {
if (_silent) return;
AppSounds.shuffle(cutoffMs: ShuffleAnimation.dealMs);
add(ShuffleAnimation(size, dealOnly: true));
_dealing = true;
_refreshAnimating();
Future.delayed(const Duration(milliseconds: ShuffleAnimation.dealMs), () {
_dealing = false;
_refreshAnimating();
if (_s != null && !_silent) _relayout();
});
}
/// نمایشِ بزرگ و گذرای حکمِ انتخاب‌شده در مرکزِ میز (با پاپ).
void _spawnTrumpReveal(String trump) {
final (sym, col) = _trumpGlyph(trump);
@@ -286,8 +312,8 @@ class HokmGame extends FlameGame {
// آیا این کارت در نوبتِ فعلی قابل بازی است (با رعایت follow-suit)؟
bool _legal(String code) {
final s = _s!;
// هنگامِ نمایشِ اینترو یا انیمیشنِ بُر زدن، بازیِ کارت مجاز نیست.
if (_introActive || _shuffling) return false;
// هنگامِ اینترو/بُر زدن/پخشِ کارت‌ها، بازیِ کارت مجاز نیست.
if (_introActive || _shuffling || _dealing) return false;
if (s.phase != 'playing' || s.trickDone || !s.isMyTurn) return false;
final lead = s.leadSuit;
if (lead == null || lead.isEmpty) return true;
@@ -317,6 +343,15 @@ class HokmGame extends FlameGame {
Rect.fromLTRB(size.x * 0.15, size.y * 0.22, size.x * 0.85, size.y * 0.66);
void _layoutHand(GameState s) {
// در زمانِ اینترو/بُر زدنِ ابتدای هَند، کارت‌های دست پنهان‌اند و پس از پایانِ
// بُر زدن «پخش» می‌شوند (می‌آیند). در زمانِ پخشِ بقیه‌ی کارت‌ها مخفی نمی‌شوند.
if (_introActive || _shuffling) {
for (final c in _hand.values.toList()) {
c.removeFromParent();
}
_hand.clear();
return;
}
// مرتب‌سازی بر اساس خال و رتبه تا انتخاب برای بازیکن راحت‌تر باشد.
final codes = List<String>.from(s.yourHand)..sort(compareCards);
final n = codes.length;
@@ -372,6 +407,15 @@ class HokmGame extends FlameGame {
}
void _layoutTrick(GameState s) {
// در زمانِ اینترو/بُر زدن/پخش، کارت‌های روی میز پنهان می‌مانند تا با انیمیشن
// تداخل نکنند (پس از پایانِ انیمیشن دوباره چیده می‌شوند).
if (_introActive || _shuffling || _dealing) {
for (final c in _trick.values.toList()) {
c.removeFromParent();
}
_trick.clear();
return;
}
final present = s.trick.map((t) => t.card).toSet();
// کارت‌های trick که دیگر نیستند (دست جمع شد) ⇒ به سمت برنده برو و حذف شو.
@@ -463,7 +507,10 @@ class HokmGame extends FlameGame {
_backs.clear();
_info.clear();
for (var seat = 0; seat < 4; seat++) {
// پشتِ کارتِ حریفان در زمانِ بُر زدنِ ابتدای هَند پنهان است (انیمیشنِ بُر
// خودش کارت‌ها را پخش می‌کند)؛ پس از آن نمایش داده می‌شود.
final hideBacks = _introActive || _shuffling;
for (var seat = 0; seat < 4 && !hideBacks; seat++) {
if (seat == s.yourSeat) continue;
final count = seat < s.handCounts.length ? s.handCounts[seat] : 0;
_addBacks(_rel(seat), count);