feat: wire bark battle platform loop
Some checks failed
CI / verify (pull_request) Has been cancelled
Some checks failed
CI / verify (pull_request) Has been cancelled
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import type { BarkBattlePublishedConfig } from '../../../../packages/shared/src/contracts/barkBattle';
|
||||
import {
|
||||
type BarkBattleConfig,
|
||||
DEFAULT_BARK_BATTLE_CONFIG,
|
||||
@@ -15,6 +16,9 @@ import { BarkBattleResultPanel } from './BarkBattleResultPanel';
|
||||
|
||||
type BarkBattleRuntimeShellProps = {
|
||||
title?: string;
|
||||
workId?: string;
|
||||
publishedConfig?: BarkBattlePublishedConfig | null;
|
||||
onExit?: () => void;
|
||||
};
|
||||
|
||||
type DebugEvent = {
|
||||
@@ -63,8 +67,39 @@ function isMicrophoneFailureReason(reason: unknown): reason is MicrophoneFailure
|
||||
return typeof reason === 'string' && MICROPHONE_FAILURE_REASONS.has(reason as MicrophoneFailureReason);
|
||||
}
|
||||
|
||||
export function BarkBattleRuntimeShell({ title = '汪汪声浪大作战' }: BarkBattleRuntimeShellProps) {
|
||||
const [config, setConfig] = useState(DEFAULT_BARK_BATTLE_CONFIG);
|
||||
function buildRuntimeConfigFromPublishedConfig(
|
||||
publishedConfig?: BarkBattlePublishedConfig | null,
|
||||
): BarkBattleConfig {
|
||||
if (!publishedConfig) {
|
||||
return DEFAULT_BARK_BATTLE_CONFIG;
|
||||
}
|
||||
|
||||
const difficultyOverrides: Record<
|
||||
BarkBattlePublishedConfig['difficultyPreset'],
|
||||
Partial<BarkBattleConfig>
|
||||
> = {
|
||||
easy: { barkThreshold: 0.42, opponentBasePower: 0.16, drawThreshold: 10 },
|
||||
normal: { barkThreshold: 0.5, opponentBasePower: 0.22, drawThreshold: 12 },
|
||||
hard: { barkThreshold: 0.58, opponentBasePower: 0.3, drawThreshold: 14 },
|
||||
};
|
||||
|
||||
return {
|
||||
...DEFAULT_BARK_BATTLE_CONFIG,
|
||||
...difficultyOverrides[publishedConfig.difficultyPreset],
|
||||
};
|
||||
}
|
||||
|
||||
export function BarkBattleRuntimeShell({
|
||||
title = '汪汪声浪大作战',
|
||||
workId,
|
||||
publishedConfig,
|
||||
onExit,
|
||||
}: BarkBattleRuntimeShellProps) {
|
||||
const initialConfig = useMemo(
|
||||
() => buildRuntimeConfigFromPublishedConfig(publishedConfig),
|
||||
[publishedConfig],
|
||||
);
|
||||
const [config, setConfig] = useState(initialConfig);
|
||||
const controllerRef = useRef<BarkBattleController | null>(null);
|
||||
if (!controllerRef.current) {
|
||||
controllerRef.current = new BarkBattleController(config);
|
||||
@@ -110,6 +145,12 @@ export function BarkBattleRuntimeShell({ title = '汪汪声浪大作战' }: Bark
|
||||
microphoneSamplerRef.current = null;
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setConfig(initialConfig);
|
||||
controller.updateConfig(initialConfig);
|
||||
syncSnapshot();
|
||||
}, [controller, initialConfig, syncSnapshot]);
|
||||
|
||||
const startMicrophone = useCallback(async () => {
|
||||
stopMicrophone();
|
||||
try {
|
||||
@@ -225,7 +266,11 @@ export function BarkBattleRuntimeShell({ title = '汪汪声浪大作战' }: Bark
|
||||
<button type="button" onClick={startMock}>开始</button>
|
||||
<button type="button" onClick={finishNow}>结束</button>
|
||||
<button type="button" onClick={restart}>重置</button>
|
||||
{onExit ? <button type="button" onClick={onExit}>返回配置</button> : null}
|
||||
</div>
|
||||
{workId ? (
|
||||
<p className="bark-battle-debug-panel__work-id">作品:{workId}</p>
|
||||
) : null}
|
||||
<div className="bark-battle-debug-metrics" aria-label="触发反馈">
|
||||
<span className="bark-battle-debug-metrics__wide">输入模式:{inputMode === 'microphone' ? '真实麦克风' : 'Mock 输入'}</span>
|
||||
<span>实时音量:{(liveInputVolume * 100).toFixed(0)}%</span>
|
||||
|
||||
Reference in New Issue
Block a user