mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-22 08:15:53 +00:00
- BuddyPanel 新增 Battle tab,BattleFlow 加 isActive 控制 - BattleFlow configSelect 阶段支持 ↑↓ 选择物种 - packages/pokemon/src/data/ → dex/,解决根 .gitignore 匹配问题 - 全量 Tab→2空格 缩进转换 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
73 lines
2.0 KiB
TypeScript
73 lines
2.0 KiB
TypeScript
import React, { useEffect, useState } from 'react'
|
|
import { Box, Text, type Color } from '@anthropic/ink'
|
|
import type { AnimMode } from '../types'
|
|
import { renderAnimatedSprite, getIdleAnimMode, getPetOverlay } from '../sprites/renderer'
|
|
|
|
/** Vertical padding — bounce shifts within this space */
|
|
const V_PAD = 4
|
|
|
|
interface SpriteAnimatorProps {
|
|
/** Base sprite lines (ANSI is preserved) */
|
|
lines: string[]
|
|
/** Text color for the sprite */
|
|
color?: Color
|
|
/** Tick interval in ms (default 250) */
|
|
tickMs?: number
|
|
/** Single mode; omit for idle auto-play */
|
|
mode?: AnimMode
|
|
/** Center horizontally (default true) */
|
|
centered?: boolean
|
|
/** Show pet hearts overlay */
|
|
petting?: boolean
|
|
}
|
|
|
|
/**
|
|
* Animated sprite renderer with built-in tick loop.
|
|
*
|
|
* - Keeps ANSI intact (parse → pixel grid → transform → render)
|
|
* - Pads vertically so bounce never shifts layout
|
|
* - Grid transforms guarantee fixed output height
|
|
*/
|
|
export function SpriteAnimator({
|
|
lines,
|
|
color,
|
|
tickMs = 100,
|
|
mode,
|
|
centered = true,
|
|
petting,
|
|
}: SpriteAnimatorProps) {
|
|
const [tick, setTick] = useState(0)
|
|
|
|
useEffect(() => {
|
|
const timer = setInterval(() => setTick(t => t + 1), tickMs)
|
|
return () => clearInterval(timer)
|
|
}, [tickMs])
|
|
|
|
// Add vertical padding — bounce shifts within this space
|
|
const padded = [...Array(V_PAD).fill(''), ...lines, ...Array(V_PAD).fill('')]
|
|
|
|
// Apply animation (renderer parses to pixels, transforms, renders back)
|
|
const currentMode = mode ?? getIdleAnimMode(tick)
|
|
const animated = renderAnimatedSprite(padded, tick, currentMode)
|
|
|
|
// Pet hearts overlay
|
|
const overlay = petting ? getPetOverlay(tick) : null
|
|
const displayLines = overlay ? [...overlay, ...animated] : animated
|
|
|
|
const spriteBlock = (
|
|
<Box flexDirection="column">
|
|
{displayLines.map((line, i) => (
|
|
<Text key={i} color={color}>{line || ' '}</Text>
|
|
))}
|
|
</Box>
|
|
)
|
|
|
|
if (!centered) return spriteBlock
|
|
|
|
return (
|
|
<Box flexDirection="row" justifyContent="center" width="100%">
|
|
{spriteBlock}
|
|
</Box>
|
|
)
|
|
}
|