98 lines
2.8 KiB
Vue
98 lines
2.8 KiB
Vue
<script setup lang="ts">
|
|
import { ref } from 'vue'
|
|
import ArcadeCharacterSelect from '../components/ArcadeCharacterSelect.vue'
|
|
import ArcadeViewer from '../components/ArcadeViewer.vue'
|
|
|
|
type GameState = 'select' | 'fighting' | 'result'
|
|
|
|
const state = ref<GameState>('select')
|
|
const matchWinner = ref<1 | 2 | null>(null)
|
|
|
|
const fightConfig = ref<{
|
|
p1: { seed: string; tier: number; archetype: string; name: string }
|
|
p2: { seed: string; tier: number; archetype: string; name: string }
|
|
arena: string
|
|
rounds: 1 | 3 | 5
|
|
roundTime: 30 | 60 | 99
|
|
cpuBotId?: string
|
|
} | null>(null)
|
|
|
|
function onStart(config: typeof fightConfig.value): void {
|
|
fightConfig.value = config
|
|
state.value = 'fighting'
|
|
matchWinner.value = null
|
|
}
|
|
|
|
function onMatchEnd(winner: 1 | 2): void {
|
|
matchWinner.value = winner
|
|
state.value = 'result'
|
|
}
|
|
|
|
function rematch(): void {
|
|
// Restart with same config
|
|
state.value = 'fighting'
|
|
matchWinner.value = null
|
|
// Force re-mount by toggling through select briefly
|
|
const cfg = fightConfig.value
|
|
fightConfig.value = null
|
|
requestAnimationFrame(() => {
|
|
fightConfig.value = cfg
|
|
})
|
|
}
|
|
|
|
function backToSelect(): void {
|
|
state.value = 'select'
|
|
fightConfig.value = null
|
|
matchWinner.value = null
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="p-4">
|
|
<!-- Character Select -->
|
|
<ArcadeCharacterSelect
|
|
v-if="state === 'select'"
|
|
@start="onStart"
|
|
/>
|
|
|
|
<!-- Fighting -->
|
|
<ArcadeViewer
|
|
v-if="state === 'fighting' && fightConfig"
|
|
:key="fightConfig.p1.seed + fightConfig.p2.seed"
|
|
:config="fightConfig"
|
|
@match-end="onMatchEnd"
|
|
/>
|
|
|
|
<!-- Result -->
|
|
<div v-if="state === 'result' && fightConfig" class="flex flex-col items-center gap-6 pt-8">
|
|
<h2 class="font-display font-black text-3xl tracking-[0.2em]"
|
|
:class="matchWinner === 1 ? 'text-neon-cyan glow-cyan' : 'text-neon-pink glow-pink'">
|
|
{{ matchWinner === 1 ? fightConfig.p1.name.toUpperCase() : fightConfig.p2.name.toUpperCase() }}
|
|
WINS!
|
|
</h2>
|
|
|
|
<div class="flex gap-4">
|
|
<button
|
|
class="px-6 py-2 font-display font-bold text-sm tracking-widest rounded-lg
|
|
border border-neon-cyan text-neon-cyan hover:bg-neon-cyan/10 transition-all"
|
|
@click="rematch"
|
|
>
|
|
REMATCH
|
|
</button>
|
|
<button
|
|
class="px-6 py-2 font-display font-bold text-sm tracking-widest rounded-lg
|
|
border border-border text-text-secondary hover:border-text-muted transition-all"
|
|
@click="backToSelect"
|
|
>
|
|
NEW FIGHTERS
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.glow-cyan { text-shadow: 0 0 10px rgba(0, 240, 255, 0.5), 0 0 20px rgba(0, 240, 255, 0.2); }
|
|
.glow-pink { text-shadow: 0 0 10px rgba(255, 0, 128, 0.5), 0 0 20px rgba(255, 0, 128, 0.2); }
|
|
</style>
|