fix skill
This commit is contained in:
31
src/App.jsx
31
src/App.jsx
@@ -20,6 +20,10 @@ export default function App() {
|
||||
const [timeScale, setTimeScale] = useState(100);
|
||||
const [camSpeed, setCamSpeed] = useState(0.05);
|
||||
const [vrmModel, setVrmModel] = useState('ai.vrm');
|
||||
const [lang, setLang] = useState('ja');
|
||||
const langRef = useRef('ja');
|
||||
const voiceIndexRef = useRef(0);
|
||||
const voicePattern = ['normal','normal','normal','normal','normal','normal','normal','normal','skill','skill'];
|
||||
const actionIndexRef = useRef(0);
|
||||
const teleportIndexRef = useRef(0);
|
||||
const countRef = useRef(0);
|
||||
@@ -28,11 +32,25 @@ export default function App() {
|
||||
return onAdminChange((v) => setIsAdmin(v));
|
||||
}, []);
|
||||
|
||||
const handleLangChange = useCallback((v) => { setLang(v); langRef.current = v; }, []);
|
||||
|
||||
const playSkillVoice = useCallback(() => {
|
||||
const type = voicePattern[voiceIndexRef.current % voicePattern.length];
|
||||
voiceIndexRef.current += 1;
|
||||
const suffix = langRef.current === 'en' ? '_en' : '';
|
||||
const file = `${import.meta.env.BASE_URL}voice/ai/${type}_1${suffix}.mp3`;
|
||||
const audio = new Audio(file);
|
||||
audio.volume = 0.7;
|
||||
audio.play().catch(() => {});
|
||||
}, []);
|
||||
|
||||
const playAnim = useCallback((name) => {
|
||||
countRef.current += 1;
|
||||
setAnimState({ name, count: countRef.current });
|
||||
}, []);
|
||||
|
||||
const doSkillRef = useRef(null);
|
||||
|
||||
const handleKey = useCallback((e) => {
|
||||
if (e.code === 'Escape') {
|
||||
setView(view === 'nasa' ? 'avatar' : 'nasa');
|
||||
@@ -53,8 +71,7 @@ export default function App() {
|
||||
teleportIndexRef.current = idx + 1;
|
||||
} else if (e.code === 'KeyS') {
|
||||
e.preventDefault();
|
||||
playAnim('skill');
|
||||
setVrmModel(prev => prev === 'ai.vrm' ? 'ai_mode.vrm' : 'ai.vrm');
|
||||
doSkillRef.current?.();
|
||||
}
|
||||
}, [playAnim, view]);
|
||||
|
||||
@@ -93,10 +110,16 @@ export default function App() {
|
||||
teleportIndexRef.current = idx + 1;
|
||||
}, [playAnim]);
|
||||
|
||||
const skillCoolRef = useRef(0);
|
||||
const doSkill = useCallback(() => {
|
||||
const now = Date.now();
|
||||
if (now - skillCoolRef.current < 3000) return;
|
||||
skillCoolRef.current = now;
|
||||
playAnim('skill');
|
||||
playSkillVoice();
|
||||
setVrmModel(prev => prev === 'ai.vrm' ? 'ai_mode.vrm' : 'ai.vrm');
|
||||
}, [playAnim]);
|
||||
}, [playAnim, playSkillVoice]);
|
||||
doSkillRef.current = doSkill;
|
||||
|
||||
const appStartRef = useRef(Date.now());
|
||||
const lastSwitchRef = useRef(0);
|
||||
@@ -179,6 +202,8 @@ export default function App() {
|
||||
camSpeed={camSpeed}
|
||||
onCamSpeedChange={setCamSpeed}
|
||||
onSkill={doSkill}
|
||||
lang={lang}
|
||||
onLangChange={handleLangChange}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
@@ -73,6 +73,14 @@ export default function VrmCharacter({ selectedAnimation: animState, vrmModel =
|
||||
const vrm = gltf.userData.vrm;
|
||||
vrmRef.current = vrm;
|
||||
VRMUtils.removeUnnecessaryJoints(vrm.scene);
|
||||
// SpringBone: centerをRotatingStage(親group)に設定し、回転に追従させる
|
||||
const sbm = vrm.springBoneManager;
|
||||
if (sbm) {
|
||||
const stageGroup = vrm.scene.parent;
|
||||
sbm.joints?.forEach(joint => {
|
||||
if (stageGroup) joint.center = stageGroup;
|
||||
});
|
||||
}
|
||||
vrm.humanoid.resetPose();
|
||||
vrm.scene.rotation.y = Math.PI;
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ const btnStyle = {
|
||||
width: '100%',
|
||||
};
|
||||
|
||||
export default function ControlPanel({ timeScale, onTimeScaleChange, camSpeed, onCamSpeedChange, onSkill }) {
|
||||
export default function ControlPanel({ timeScale, onTimeScaleChange, camSpeed, onCamSpeedChange, onSkill, lang, onLangChange }) {
|
||||
return (
|
||||
<div style={containerStyle}>
|
||||
<div>
|
||||
@@ -77,8 +77,19 @@ export default function ControlPanel({ timeScale, onTimeScaleChange, camSpeed, o
|
||||
style={sliderStyle}
|
||||
/>
|
||||
</div>
|
||||
<button style={btnStyle} onClick={() => onSkill?.()}>
|
||||
Skill
|
||||
<button
|
||||
style={{ ...btnStyle, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6 }}
|
||||
onClick={() => onSkill?.()}
|
||||
>
|
||||
<img src={`${import.meta.env.BASE_URL}icon/dot.svg`} alt="" style={{ width: 14, height: 14, filter: 'brightness(0) invert(1)', opacity: 0.7 }} />
|
||||
<span>Skill</span>
|
||||
</button>
|
||||
<button
|
||||
style={{ ...btnStyle, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6 }}
|
||||
onClick={() => onLangChange?.(lang === 'ja' ? 'en' : 'ja')}
|
||||
>
|
||||
<img src={`${import.meta.env.BASE_URL}icon/language.svg`} alt="" style={{ width: 14, height: 14, filter: 'brightness(0) invert(1)', opacity: 0.7 }} />
|
||||
<span>{lang?.toUpperCase()}</span>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user