feat: v2 — queue matchmaking, procedural audio, sprite archetypes, auth
- Add queue-based matchmaking with Elo-proximity and 10s timeout - Procedural sound engine (SFX, voice announcer, 4-track music) - Sprite system refactored into 6 archetypes (standard, lobster, sheep, cyborg, blob, tank) - 42+ fight choreographies with themed/generic/wild card selection - 4 KO finish styles, super-speed mode, hyperdetail close-ups - Auth routes, JoinBout page, bot profile with stats - 7-tier ranking system (Baby through Legend) - Arena and challenge system expansions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
335c148866
commit
47d20fbe66
@@ -0,0 +1,63 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, watch } from 'vue'
|
||||
import { generateSpriteSheet, getBotColors, FRAME_SIZE, ANIMATIONS } from '../game/sprites'
|
||||
|
||||
const props = defineProps<{
|
||||
seed: string
|
||||
archetype?: string
|
||||
size?: number
|
||||
}>()
|
||||
|
||||
const canvasRef = ref<HTMLCanvasElement>()
|
||||
let img: HTMLImageElement | null = null
|
||||
let frame = 0
|
||||
let animHandle: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
function render() {
|
||||
if (!canvasRef.value || !img?.complete) return
|
||||
const ctx = canvasRef.value.getContext('2d')!
|
||||
const displaySize = props.size || 64
|
||||
canvasRef.value.width = displaySize
|
||||
canvasRef.value.height = displaySize
|
||||
ctx.clearRect(0, 0, displaySize, displaySize)
|
||||
ctx.imageSmoothingEnabled = false
|
||||
|
||||
const idleAnim = ANIMATIONS.idle
|
||||
const f = frame % idleAnim.frames
|
||||
ctx.drawImage(
|
||||
img,
|
||||
f * FRAME_SIZE, idleAnim.row * FRAME_SIZE, FRAME_SIZE, FRAME_SIZE,
|
||||
0, 0, displaySize, displaySize,
|
||||
)
|
||||
|
||||
frame++
|
||||
animHandle = setTimeout(() => render(), 180)
|
||||
}
|
||||
|
||||
function loadSprite() {
|
||||
const colors = getBotColors(props.seed)
|
||||
const dataUrl = generateSpriteSheet(props.seed, 0, colors.primary, colors.secondary, props.archetype)
|
||||
img = new Image()
|
||||
img.onload = () => render()
|
||||
img.src = dataUrl
|
||||
}
|
||||
|
||||
onMounted(() => loadSprite())
|
||||
|
||||
watch(() => [props.seed, props.archetype], () => {
|
||||
if (animHandle) clearTimeout(animHandle)
|
||||
frame = 0
|
||||
loadSprite()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (animHandle) clearTimeout(animHandle)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<canvas
|
||||
ref="canvasRef"
|
||||
:style="{ width: `${size || 64}px`, height: `${size || 64}px`, imageRendering: 'pixelated' }"
|
||||
/>
|
||||
</template>
|
||||
Reference in New Issue
Block a user