diff --git a/lib/feature/game/presentation/bloc/game_bloc.dart b/lib/feature/game/presentation/bloc/game_bloc.dart index 6375573..2d5f0b6 100644 --- a/lib/feature/game/presentation/bloc/game_bloc.dart +++ b/lib/feature/game/presentation/bloc/game_bloc.dart @@ -44,6 +44,7 @@ class GameBloc extends Bloc { (event, emit) => repository.send({'type': 'choose_trump', 'suit': event.suit})); on( (event, emit) => repository.send({'type': 'play_card', 'card': event.card})); + on((event, emit) => repository.send({'type': 'reshuffle'})); on((event, emit) => repository.send({'type': 'leave'})); on((event, emit) => repository.send({'type': 'start_table', 'hands': event.hands})); @@ -83,6 +84,7 @@ class GameBloc extends Bloc { // --- متدهای کمکی برای موتور Flame و صفحه‌ها --- void chooseTrump(String suit) => add(ChooseTrumpEvent(suit)); + void reshuffle() => add(ReshuffleEvent()); void playCard(String card) => add(PlayCardEvent(card)); void leave() => add(LeaveGameEvent()); void startTable(int hands) => add(StartTableEvent(hands)); diff --git a/lib/feature/game/presentation/bloc/game_event.dart b/lib/feature/game/presentation/bloc/game_event.dart index e9f6588..4787c1d 100644 --- a/lib/feature/game/presentation/bloc/game_event.dart +++ b/lib/feature/game/presentation/bloc/game_event.dart @@ -30,6 +30,8 @@ class PlayCardEvent extends GameEvent { PlayCardEvent(this.card); } +class ReshuffleEvent extends GameEvent {} // بُرِ مجدد با مصرفِ یک بلیت + class LeaveGameEvent extends GameEvent {} class StartTableEvent extends GameEvent { diff --git a/lib/feature/game/presentation/screen/game_screen.dart b/lib/feature/game/presentation/screen/game_screen.dart index 9c1e8d0..3b05ce1 100644 --- a/lib/feature/game/presentation/screen/game_screen.dart +++ b/lib/feature/game/presentation/screen/game_screen.dart @@ -11,6 +11,7 @@ import '../../../../core/service/app_sounds.dart'; import '../../../../core/theme/app_theme.dart'; import '../../../wallet/presentation/bloc/wallet_bloc.dart'; import '../../../wallet/presentation/bloc/wallet_event.dart'; +import '../../../wallet/presentation/bloc/wallet_state.dart'; import '../../../wallet/presentation/bloc/wallet_status.dart'; import '../../domain/entities/game_entities.dart'; import '../bloc/game_bloc.dart'; @@ -446,6 +447,53 @@ class _GameScreenState extends State { ), ], ), + const SizedBox(height: 16), + const Divider(color: Color(0x33E9B949), height: 1), + const SizedBox(height: 12), + // بُرِ مجدد با مصرفِ یک بلیت (۵ کارتِ تازه، سپس باز هم انتخابِ حکم). + BlocBuilder( + builder: (context, ws) { + final tickets = ws.walletStatus is WalletLoaded + ? (ws.walletStatus as WalletLoaded).wallet.tickets + : 0; + final canReshuffle = tickets > 0; + return Column( + children: [ + ElevatedButton.icon( + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF8E1B7A), + disabledBackgroundColor: const Color(0xFF3A2233), + minimumSize: const Size(220, 48), + ), + onPressed: canReshuffle + ? () { + AppSounds.button(); + context.read().reshuffle(); + // پس از مصرفِ بلیت، موجودی را تازه کن (بدون نگه‌داشتنِ context). + final wallet = context.read(); + Future.delayed(const Duration(milliseconds: 500), + () => wallet.add(LoadWalletEvent())); + } + : null, + icon: const Icon(Icons.casino, color: Colors.white), + label: const Text( + 'بُر مجدد (۱ بلیت)', + style: TextStyle( + color: Colors.white, fontWeight: FontWeight.bold), + ), + ), + const SizedBox(height: 4), + Text( + canReshuffle + ? 'بلیت‌های شما: $tickets' + : 'بلیت کافی ندارید', + style: const TextStyle( + color: Colors.white60, fontSize: 12), + ), + ], + ); + }, + ), ], ), ), diff --git a/lib/feature/game/presentation/widgets/flame/hokm_game.dart b/lib/feature/game/presentation/widgets/flame/hokm_game.dart index ed56786..81db71a 100644 --- a/lib/feature/game/presentation/widgets/flame/hokm_game.dart +++ b/lib/feature/game/presentation/widgets/flame/hokm_game.dart @@ -47,6 +47,7 @@ class HokmGame extends FlameGame { List _prevTrick = const []; int _bestTrumpRank = 0; // بالاترین رتبه‌ی حکمِ بازی‌شده در دستِ جاری (برای افکتِ بریدن) int _prevHandSize = 0; // برای تشخیصِ پخشِ کارت (دستِ جدید) جهت صدای بُر زدن + String _prevHandSig = ''; // امضای دست؛ برای تشخیصِ بُرِ مجدد (تغییرِ ۵ کارت در فازِ حکم) bool _silent = false; // هنگام خروج از میز، دیگر صدایی پخش نشود bool _introActive = true; // تا پایانِ نمایشِ «جستجوی حریف» bool _pendingShuffle = @@ -89,6 +90,18 @@ class HokmGame extends FlameGame { _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(); @@ -103,6 +116,7 @@ class HokmGame extends FlameGame { if (cubit.state.state != null) { _prevTrick = cubit.state.state!.trick.map((t) => t.card).toList(); _prevHandSize = cubit.state.state!.yourHand.length; + _prevHandSig = (cubit.state.state!.yourHand.toList()..sort()).join(','); _prevTrump = cubit.state.state!.trump; _s = cubit.state.state; _relayout();