feat: add child motion entry and fix auth env
Some checks failed
CI / verify (push) Has been cancelled
Some checks failed
CI / verify (push) Has been cancelled
This commit is contained in:
274
src/components/child-motion-demo/childMotionWarmupModel.ts
Normal file
274
src/components/child-motion-demo/childMotionWarmupModel.ts
Normal file
@@ -0,0 +1,274 @@
|
||||
export type ChildMotionWarmupStepId =
|
||||
| 'center_arrive'
|
||||
| 'wave_greeting'
|
||||
| 'warmup_intro'
|
||||
| 'move_left'
|
||||
| 'return_center_1'
|
||||
| 'move_right'
|
||||
| 'return_center_2'
|
||||
| 'wave_left_hand'
|
||||
| 'wave_right_hand'
|
||||
| 'jump_once'
|
||||
| 'warmup_finish'
|
||||
| 'level_select'
|
||||
| 'play_placeholder';
|
||||
|
||||
export type ChildMotionWarmupTarget = 'center' | 'left' | 'right';
|
||||
|
||||
export type ChildMotionWarmupStepKind =
|
||||
| 'position'
|
||||
| 'gesture'
|
||||
| 'narration'
|
||||
| 'finish'
|
||||
| 'levelSelect'
|
||||
| 'placeholder';
|
||||
|
||||
export type ChildMotionWarmupStep = {
|
||||
id: ChildMotionWarmupStepId;
|
||||
kind: ChildMotionWarmupStepKind;
|
||||
title: string;
|
||||
spokenLines: string[];
|
||||
target?: ChildMotionWarmupTarget;
|
||||
};
|
||||
|
||||
export type ChildMotionPoint = {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
|
||||
export type ChildMotionWarmupCalibration = {
|
||||
leftBoundary: number | null;
|
||||
rightBoundary: number | null;
|
||||
leftHandPath: ChildMotionPoint[];
|
||||
rightHandPath: ChildMotionPoint[];
|
||||
jumpSpace: number | null;
|
||||
};
|
||||
|
||||
export type ChildMotionWarmupCompletion =
|
||||
| {
|
||||
type: 'position';
|
||||
avatarX: number;
|
||||
}
|
||||
| {
|
||||
type: 'left-hand';
|
||||
path: ChildMotionPoint[];
|
||||
}
|
||||
| {
|
||||
type: 'right-hand';
|
||||
path: ChildMotionPoint[];
|
||||
}
|
||||
| {
|
||||
type: 'jump';
|
||||
jumpSpace: number;
|
||||
}
|
||||
| {
|
||||
type: 'narration';
|
||||
};
|
||||
|
||||
export const CHILD_MOTION_CENTER_X = 0.5;
|
||||
export const CHILD_MOTION_LEFT_X = 0.34;
|
||||
export const CHILD_MOTION_RIGHT_X = 0.66;
|
||||
export const CHILD_MOTION_POSITION_EPSILON = 0.045;
|
||||
export const CHILD_MOTION_HOLD_DURATION_MS = 2000;
|
||||
export const CHILD_MOTION_NARRATION_DURATION_MS = 900;
|
||||
export const CHILD_MOTION_FINISH_DURATION_MS = 1200;
|
||||
|
||||
export const CHILD_MOTION_WARMUP_STEPS: ChildMotionWarmupStep[] = [
|
||||
{
|
||||
id: 'center_arrive',
|
||||
kind: 'position',
|
||||
title: '来到圆圈这里',
|
||||
spokenLines: ['欢迎你,小朋友,见到你真开心', '请你来到圆圈这里和我打个招呼吧'],
|
||||
target: 'center',
|
||||
},
|
||||
{
|
||||
id: 'wave_greeting',
|
||||
kind: 'gesture',
|
||||
title: '打个招呼',
|
||||
spokenLines: ['请你来到圆圈这里和我打个招呼吧'],
|
||||
},
|
||||
{
|
||||
id: 'warmup_intro',
|
||||
kind: 'narration',
|
||||
title: '准备热身',
|
||||
spokenLines: ['你好呀小朋友,为了你玩的安全和开心,先来和我一起热个身吧'],
|
||||
},
|
||||
{
|
||||
id: 'move_left',
|
||||
kind: 'position',
|
||||
title: '向左一步',
|
||||
spokenLines: ['向左一步'],
|
||||
target: 'left',
|
||||
},
|
||||
{
|
||||
id: 'return_center_1',
|
||||
kind: 'position',
|
||||
title: '回到中间来',
|
||||
spokenLines: ['回到中间来'],
|
||||
target: 'center',
|
||||
},
|
||||
{
|
||||
id: 'move_right',
|
||||
kind: 'position',
|
||||
title: '向右一步',
|
||||
spokenLines: ['向右一步'],
|
||||
target: 'right',
|
||||
},
|
||||
{
|
||||
id: 'return_center_2',
|
||||
kind: 'position',
|
||||
title: '回到中间来',
|
||||
spokenLines: ['回到中间来'],
|
||||
target: 'center',
|
||||
},
|
||||
{
|
||||
id: 'wave_left_hand',
|
||||
kind: 'gesture',
|
||||
title: '挥动左手',
|
||||
spokenLines: ['挥动左手'],
|
||||
},
|
||||
{
|
||||
id: 'wave_right_hand',
|
||||
kind: 'gesture',
|
||||
title: '挥动右手',
|
||||
spokenLines: ['挥动右手'],
|
||||
},
|
||||
{
|
||||
id: 'jump_once',
|
||||
kind: 'gesture',
|
||||
title: '原地跳一下',
|
||||
spokenLines: ['原地跳一下'],
|
||||
},
|
||||
{
|
||||
id: 'warmup_finish',
|
||||
kind: 'finish',
|
||||
title: '热身完成',
|
||||
spokenLines: ['真厉害,你是我见过最聪明的小朋友', '别走开,现在开始我们的游戏吧'],
|
||||
},
|
||||
{
|
||||
id: 'level_select',
|
||||
kind: 'levelSelect',
|
||||
title: '准备开始',
|
||||
spokenLines: ['现在开始我们的游戏吧'],
|
||||
},
|
||||
{
|
||||
id: 'play_placeholder',
|
||||
kind: 'placeholder',
|
||||
title: '下一关',
|
||||
spokenLines: ['游戏关卡正在准备中'],
|
||||
},
|
||||
];
|
||||
|
||||
const STEP_BY_ID = new Map(
|
||||
CHILD_MOTION_WARMUP_STEPS.map((step) => [step.id, step]),
|
||||
);
|
||||
|
||||
const NEXT_STEP_BY_ID = new Map<ChildMotionWarmupStepId, ChildMotionWarmupStepId>(
|
||||
CHILD_MOTION_WARMUP_STEPS.slice(0, -1).map((step, index) => [
|
||||
step.id,
|
||||
CHILD_MOTION_WARMUP_STEPS[index + 1]!.id,
|
||||
]),
|
||||
);
|
||||
|
||||
let childMotionWarmupCompletedInRuntime = false;
|
||||
|
||||
export function getChildMotionWarmupStep(id: ChildMotionWarmupStepId) {
|
||||
return STEP_BY_ID.get(id) ?? CHILD_MOTION_WARMUP_STEPS[0]!;
|
||||
}
|
||||
|
||||
export function getChildMotionTargetX(target: ChildMotionWarmupTarget) {
|
||||
if (target === 'left') {
|
||||
return CHILD_MOTION_LEFT_X;
|
||||
}
|
||||
|
||||
if (target === 'right') {
|
||||
return CHILD_MOTION_RIGHT_X;
|
||||
}
|
||||
|
||||
return CHILD_MOTION_CENTER_X;
|
||||
}
|
||||
|
||||
export function isAvatarOnWarmupTarget(
|
||||
step: ChildMotionWarmupStep,
|
||||
avatarX: number,
|
||||
) {
|
||||
if (step.kind !== 'position' || !step.target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
Math.abs(avatarX - getChildMotionTargetX(step.target)) <=
|
||||
CHILD_MOTION_POSITION_EPSILON
|
||||
);
|
||||
}
|
||||
|
||||
export function resolveNextChildMotionWarmupStep(
|
||||
stepId: ChildMotionWarmupStepId,
|
||||
) {
|
||||
return NEXT_STEP_BY_ID.get(stepId) ?? stepId;
|
||||
}
|
||||
|
||||
export function createEmptyChildMotionCalibration(): ChildMotionWarmupCalibration {
|
||||
return {
|
||||
leftBoundary: null,
|
||||
rightBoundary: null,
|
||||
leftHandPath: [],
|
||||
rightHandPath: [],
|
||||
jumpSpace: null,
|
||||
};
|
||||
}
|
||||
|
||||
export function applyChildMotionWarmupCompletion(
|
||||
stepId: ChildMotionWarmupStepId,
|
||||
calibration: ChildMotionWarmupCalibration,
|
||||
completion: ChildMotionWarmupCompletion,
|
||||
): ChildMotionWarmupCalibration {
|
||||
if (stepId === 'move_left' && completion.type === 'position') {
|
||||
return {
|
||||
...calibration,
|
||||
leftBoundary: Math.max(0, CHILD_MOTION_CENTER_X - completion.avatarX),
|
||||
};
|
||||
}
|
||||
|
||||
if (stepId === 'move_right' && completion.type === 'position') {
|
||||
return {
|
||||
...calibration,
|
||||
rightBoundary: Math.max(0, completion.avatarX - CHILD_MOTION_CENTER_X),
|
||||
};
|
||||
}
|
||||
|
||||
if (stepId === 'wave_left_hand' && completion.type === 'left-hand') {
|
||||
return {
|
||||
...calibration,
|
||||
leftHandPath: completion.path,
|
||||
};
|
||||
}
|
||||
|
||||
if (stepId === 'wave_right_hand' && completion.type === 'right-hand') {
|
||||
return {
|
||||
...calibration,
|
||||
rightHandPath: completion.path,
|
||||
};
|
||||
}
|
||||
|
||||
if (stepId === 'jump_once' && completion.type === 'jump') {
|
||||
return {
|
||||
...calibration,
|
||||
jumpSpace: completion.jumpSpace,
|
||||
};
|
||||
}
|
||||
|
||||
return calibration;
|
||||
}
|
||||
|
||||
export function hasCompletedChildMotionWarmupInRuntime() {
|
||||
return childMotionWarmupCompletedInRuntime;
|
||||
}
|
||||
|
||||
export function markChildMotionWarmupCompletedInRuntime() {
|
||||
childMotionWarmupCompletedInRuntime = true;
|
||||
}
|
||||
|
||||
export function resetChildMotionWarmupRuntimeSession() {
|
||||
childMotionWarmupCompletedInRuntime = false;
|
||||
}
|
||||
Reference in New Issue
Block a user