refactor: more regicide stuff
This commit is contained in:
@@ -1,9 +1,53 @@
|
||||
import { useComputed } from '@preact/signals';
|
||||
import { useComputed, signal } from '@preact/signals';
|
||||
import { createGameHost, type GameModule } from 'boardgame-core';
|
||||
import Phaser from 'phaser';
|
||||
import { h } from 'preact';
|
||||
import { PhaserGame, PhaserScene } from 'boardgame-phaser';
|
||||
|
||||
// 全局信号:从 GameScene 传递反击阶段的状态到 UI
|
||||
export const counterattackInfo = signal<{
|
||||
phase: string;
|
||||
selectedCards: string[];
|
||||
totalValue: number;
|
||||
maxHandValue: number; // 手牌最大可提供的点数
|
||||
requiredValue: number;
|
||||
canSubmit: boolean;
|
||||
canWin: boolean; // 手牌是否足以获胜
|
||||
error: string | null;
|
||||
}>({
|
||||
phase: '',
|
||||
selectedCards: [],
|
||||
totalValue: 0,
|
||||
maxHandValue: 0,
|
||||
requiredValue: 0,
|
||||
canSubmit: false,
|
||||
canWin: false,
|
||||
error: null,
|
||||
});
|
||||
|
||||
// 全局信号:牌堆信息
|
||||
export const deckInfo = signal<{
|
||||
castleDeck: number; // 敌人牌堆剩余
|
||||
tavernDeck: number; // 酒馆牌堆剩余
|
||||
discardPile: number; // 弃牌堆数量
|
||||
hand: number; // 手牌数
|
||||
defeatedEnemies: number; // 已击败敌人数
|
||||
jestersUsed: number; // 已用小丑牌数
|
||||
}>({
|
||||
castleDeck: 0,
|
||||
tavernDeck: 0,
|
||||
discardPile: 0,
|
||||
hand: 0,
|
||||
defeatedEnemies: 0,
|
||||
jestersUsed: 0,
|
||||
});
|
||||
|
||||
// 存储当前场景引用(由 GameScene 在 create 时设置)
|
||||
let currentGameScene: any = null;
|
||||
export function setGameSceneRef(scene: any) {
|
||||
currentGameScene = scene;
|
||||
}
|
||||
|
||||
export default function App<TState extends Record<string, unknown>>(props: { gameModule: GameModule<TState>, gameScene: { new(): Phaser.Scene } }) {
|
||||
|
||||
const gameHost = useComputed(() => {
|
||||
@@ -18,10 +62,24 @@ export default function App<TState extends Record<string, unknown>>(props: { gam
|
||||
console.log('Game finished!', result);
|
||||
};
|
||||
|
||||
const label = useComputed(() =>
|
||||
const label = useComputed(() =>
|
||||
gameHost.value.gameHost.status.value === 'running' ? '重新开始' : '开始游戏'
|
||||
);
|
||||
|
||||
// 反击阶段提交
|
||||
const handleSubmitCounterattack = () => {
|
||||
if (currentGameScene && typeof currentGameScene.submitCounterattack === 'function') {
|
||||
currentGameScene.submitCounterattack();
|
||||
}
|
||||
};
|
||||
|
||||
// 反击阶段认输
|
||||
const handleSurrender = () => {
|
||||
if (currentGameScene && typeof currentGameScene.surrenderCounterattack === 'function') {
|
||||
currentGameScene.surrenderCounterattack();
|
||||
}
|
||||
};
|
||||
|
||||
// Phaser 画布配置
|
||||
const phaserConfig = {
|
||||
type: Phaser.AUTO,
|
||||
@@ -40,16 +98,111 @@ export default function App<TState extends Record<string, unknown>>(props: { gam
|
||||
</div>
|
||||
|
||||
{/* 底部控制栏 */}
|
||||
<div class="p-4 bg-gray-900 border-t border-gray-700 flex justify-between items-center">
|
||||
<div class="text-sm text-gray-400">
|
||||
⚔️ Regicide - 击败所有12个敌人
|
||||
<div class="p-4 bg-gray-900 border-t border-gray-700 flex flex-col gap-3">
|
||||
{/* 牌堆信息 */}
|
||||
<div class="flex items-center justify-center gap-6 text-sm">
|
||||
<div class="flex items-center gap-1.5">
|
||||
<span class="text-lg">🏰</span>
|
||||
<span class="text-gray-400">城堡牌堆:</span>
|
||||
<span class="text-purple-400 font-bold">{deckInfo.value.castleDeck}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<span class="text-lg">🍺</span>
|
||||
<span class="text-gray-400">酒馆牌堆:</span>
|
||||
<span class="text-amber-400 font-bold">{deckInfo.value.tavernDeck}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<span class="text-lg">🗑️</span>
|
||||
<span class="text-gray-400">弃牌堆:</span>
|
||||
<span class="text-gray-300 font-bold">{deckInfo.value.discardPile}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<span class="text-lg">🃏</span>
|
||||
<span class="text-gray-400">手牌:</span>
|
||||
<span class="text-blue-400 font-bold">{deckInfo.value.hand}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<span class="text-lg">💀</span>
|
||||
<span class="text-gray-400">已击败:</span>
|
||||
<span class="text-red-400 font-bold">{deckInfo.value.defeatedEnemies}/12</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<span class="text-lg">🃏</span>
|
||||
<span class="text-gray-400">小丑牌:</span>
|
||||
<span class="text-green-400 font-bold">{2 - deckInfo.value.jestersUsed}/2</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 反击阶段信息 + 按钮 */}
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="text-sm text-gray-400">
|
||||
⚔️ Regicide - 击败所有12个敌人
|
||||
</div>
|
||||
|
||||
{/* 反击阶段信息面板 */}
|
||||
{counterattackInfo.value.phase === 'enemyCounterattack' && (
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="text-sm text-gray-300">
|
||||
<span class="text-yellow-400 font-bold">💥 反击阶段</span>
|
||||
<span class="ml-2">需要: </span>
|
||||
<span class="text-red-400 font-bold">{counterattackInfo.value.requiredValue}</span>
|
||||
<span class="ml-2">| 手牌最多: </span>
|
||||
<span class={counterattackInfo.value.canWin ? 'text-green-400 font-bold' : 'text-red-400 font-bold'}>
|
||||
{counterattackInfo.value.maxHandValue}
|
||||
</span>
|
||||
</div>
|
||||
{counterattackInfo.value.selectedCards.length > 0 && (
|
||||
<div class="text-sm text-gray-300">
|
||||
<span>已选: </span>
|
||||
<span class="text-blue-400 font-bold">{counterattackInfo.value.selectedCards.length}张</span>
|
||||
<span class="ml-2">点数: </span>
|
||||
<span class={counterattackInfo.value.canSubmit ? 'text-green-400 font-bold' : 'text-orange-400 font-bold'}>
|
||||
{counterattackInfo.value.totalValue}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{counterattackInfo.value.error && (
|
||||
<div class="text-sm text-red-400">
|
||||
❌ {counterattackInfo.value.error}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div class="flex gap-2">
|
||||
{/* 反击确认按钮 */}
|
||||
{counterattackInfo.value.phase === 'enemyCounterattack' && counterattackInfo.value.selectedCards.length > 0 && (
|
||||
<button
|
||||
onClick={handleSubmitCounterattack}
|
||||
disabled={!counterattackInfo.value.canSubmit}
|
||||
class={`px-4 py-2 rounded font-medium transition-colors ${
|
||||
counterattackInfo.value.canSubmit
|
||||
? 'bg-green-600 text-white hover:bg-green-700'
|
||||
: 'bg-gray-600 text-gray-400 cursor-not-allowed'
|
||||
}`}
|
||||
>
|
||||
✓ 确认出牌
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* 认输按钮 */}
|
||||
{counterattackInfo.value.phase === 'enemyCounterattack' && !counterattackInfo.value.canWin && (
|
||||
<button
|
||||
onClick={handleSurrender}
|
||||
class="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700 transition-colors font-medium"
|
||||
>
|
||||
🏳️ 认输
|
||||
</button>
|
||||
)}
|
||||
|
||||
<button
|
||||
onClick={handleReset}
|
||||
class="px-6 py-2 bg-yellow-600 text-white rounded hover:bg-yellow-700 disabled:bg-gray-600 disabled:cursor-not-allowed transition-colors font-medium"
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={handleReset}
|
||||
class="px-6 py-2 bg-yellow-600 text-white rounded hover:bg-yellow-700 disabled:bg-gray-600 disabled:cursor-not-allowed transition-colors font-medium"
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user