统一跳一跳三维地块与落点判定
修正跳一跳长按起跳预测为真实脚点指向下一块顶面中心 统一前端指示器飞行动画与后端顶面 footprint 判定 调整 Three.js 方块贴图与角色顶面投影表现 补充跳一跳 UV 图集切片与运行态规则文档
This commit is contained in:
@@ -11,9 +11,22 @@ import { useResolvedAssetReadUrl } from '../../hooks/useResolvedAssetReadUrl';
|
||||
import { useJumpHopLeaderboard } from '../../services/jump-hop/useJumpHopLeaderboard';
|
||||
import {
|
||||
JUMP_HOP_THREE_CAMERA_UP_Y,
|
||||
JUMP_HOP_THREE_CHARACTER_RENDER_ORDER,
|
||||
JUMP_HOP_THREE_PLATFORM_MATERIAL_TRANSPARENT,
|
||||
JUMP_HOP_THREE_PLATFORM_MESH_RENDER_ORDER_BASE,
|
||||
JUMP_HOP_THREE_PLATFORM_YAW_RAD,
|
||||
JUMP_HOP_THREE_MATERIAL_FACE_ORDER,
|
||||
JUMP_HOP_THREE_CHARACTER_TOP_FACE_Z_OFFSET,
|
||||
JUMP_HOP_THREE_PLATFORM_CUBE_SIZE_MULTIPLIER,
|
||||
JUMP_HOP_THREE_TEXTURE_TRANSFORMS,
|
||||
JumpHopRuntimeShell,
|
||||
getJumpHopThreeCharacterFootZ,
|
||||
getJumpHopThreeCubeSide,
|
||||
getJumpHopThreeProjectedY,
|
||||
getJumpHopThreeWorldYForScreenY,
|
||||
getJumpHopTileTextureSignature,
|
||||
hasCompleteJumpHopTileFaceAssets,
|
||||
resolveJumpHopThreeCharacterFrame,
|
||||
} from './JumpHopRuntimeShell';
|
||||
|
||||
vi.mock('../../hooks/useResolvedAssetReadUrl', () => ({
|
||||
@@ -91,16 +104,14 @@ test('跳一跳运行态松手时提交长按蓄力值和后端方向向量', as
|
||||
|
||||
expect(onJump).toHaveBeenCalledTimes(1);
|
||||
const jumpPayload = onJump.mock.calls[0]?.[0];
|
||||
expect(typeof jumpPayload?.dragVectorX).toBe('number');
|
||||
expect(typeof jumpPayload?.dragVectorY).toBe('number');
|
||||
expect(Number.isFinite(jumpPayload?.dragVectorX)).toBe(true);
|
||||
expect(Number.isFinite(jumpPayload?.dragVectorY)).toBe(true);
|
||||
expect(jumpPayload).not.toHaveProperty('dragVectorX');
|
||||
expect(jumpPayload).not.toHaveProperty('dragVectorY');
|
||||
expect(jumpPayload?.dragDistance).toBeGreaterThanOrEqual(360);
|
||||
expect(jumpPayload?.dragDistance).toBeLessThanOrEqual(380);
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
test('跳一跳运行态手指移动不改变蓄力时长但仍提交方向向量', async () => {
|
||||
test('跳一跳运行态手指移动不改变蓄力时长且不提交方向向量', async () => {
|
||||
vi.useFakeTimers();
|
||||
const onJump = vi.fn().mockResolvedValue(undefined);
|
||||
const run = buildRun();
|
||||
@@ -141,10 +152,8 @@ test('跳一跳运行态手指移动不改变蓄力时长但仍提交方向向
|
||||
});
|
||||
|
||||
const jumpPayload = onJump.mock.calls[0]?.[0];
|
||||
expect(typeof jumpPayload?.dragVectorX).toBe('number');
|
||||
expect(typeof jumpPayload?.dragVectorY).toBe('number');
|
||||
expect(Number.isFinite(jumpPayload?.dragVectorX)).toBe(true);
|
||||
expect(Number.isFinite(jumpPayload?.dragVectorY)).toBe(true);
|
||||
expect(jumpPayload).not.toHaveProperty('dragVectorX');
|
||||
expect(jumpPayload).not.toHaveProperty('dragVectorY');
|
||||
expect(jumpPayload?.dragDistance).toBeGreaterThanOrEqual(240);
|
||||
expect(jumpPayload?.dragDistance).toBeLessThanOrEqual(260);
|
||||
vi.useRealTimers();
|
||||
@@ -448,49 +457,133 @@ test('跳一跳 Three.js 平台层和 DOM 角色层保持同向屏幕坐标', ()
|
||||
expect(getJumpHopThreeProjectedY(200, 568)).toBeGreaterThan(284);
|
||||
});
|
||||
|
||||
test('跳一跳蓄力时隐藏落点辅助标识但保留蓄力引导', async () => {
|
||||
const onJump = vi.fn().mockResolvedValue(undefined);
|
||||
test('跳一跳 Three.js 顶面脚点投影会扣除立方体高度偏移', () => {
|
||||
const projectedTopY = getJumpHopThreeProjectedY(360, 568);
|
||||
const cubeTopWorldY = getJumpHopThreeWorldYForScreenY(360, 568, 48);
|
||||
|
||||
render(
|
||||
<JumpHopRuntimeShell
|
||||
profile={buildProfile({ tileAssets: buildTileAssets() })}
|
||||
run={buildRun()}
|
||||
onJump={onJump}
|
||||
onRestart={() => {}}
|
||||
/>,
|
||||
expect(cubeTopWorldY).toBeLessThan(projectedTopY);
|
||||
expect(getJumpHopThreeWorldYForScreenY(360, 568, 0)).toBe(projectedTopY);
|
||||
});
|
||||
|
||||
test('跳一跳 Three.js 方块只放大模型尺寸不改变屏幕间距规则', () => {
|
||||
const run = buildRun();
|
||||
const platform = run.path.platforms[0]!;
|
||||
|
||||
expect(JUMP_HOP_THREE_PLATFORM_CUBE_SIZE_MULTIPLIER).toBe(2);
|
||||
expect(getJumpHopThreeCubeSide(platform, 1)).toBeCloseTo(165.12, 2);
|
||||
expect(run.path.platforms[1]!.x - run.path.platforms[0]!.x).toBeCloseTo(
|
||||
1.78,
|
||||
);
|
||||
expect(run.path.platforms[1]!.y - run.path.platforms[0]!.y).toBeCloseTo(
|
||||
1.78,
|
||||
);
|
||||
});
|
||||
|
||||
const stage = screen.getByTestId('jump-hop-stage');
|
||||
await act(async () => {
|
||||
dispatchPointerEvent(stage, 'pointerdown', {
|
||||
pointerId: 1,
|
||||
clientX: 180,
|
||||
clientY: 420,
|
||||
});
|
||||
test('跳一跳 Three.js 角色帧沿真实预测落点插值并保留飞行弧线', () => {
|
||||
const from = {
|
||||
screenX: 50,
|
||||
screenY: 64,
|
||||
sceneX: 0,
|
||||
sceneY: 0.84,
|
||||
sceneZ: 0,
|
||||
isMiss: false,
|
||||
};
|
||||
const to = {
|
||||
screenX: 64,
|
||||
screenY: 47,
|
||||
sceneX: 1.1,
|
||||
sceneY: 0.84,
|
||||
sceneZ: 3.4,
|
||||
isMiss: true,
|
||||
};
|
||||
|
||||
const midFrame = resolveJumpHopThreeCharacterFrame({
|
||||
characterPosition: null,
|
||||
visualJump: { from, to },
|
||||
jumpAnimationProgress: 0.5,
|
||||
isJumpAnimating: true,
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
dispatchPointerEvent(stage, 'pointermove', {
|
||||
pointerId: 1,
|
||||
clientX: 148,
|
||||
clientY: 454,
|
||||
});
|
||||
expect(midFrame?.progress).toBe(0.5);
|
||||
expect(midFrame?.position.screenX).toBeGreaterThan(from.screenX);
|
||||
expect(midFrame?.position.screenX).toBeLessThan(to.screenX);
|
||||
expect(midFrame?.position.screenY).toBeLessThan(to.screenY);
|
||||
expect(midFrame?.position.sceneZ).toBeGreaterThan(from.sceneZ);
|
||||
expect(midFrame?.position.sceneZ).toBeLessThan(to.sceneZ);
|
||||
expect(midFrame?.position.isMiss).toBe(true);
|
||||
|
||||
const landedFrame = resolveJumpHopThreeCharacterFrame({
|
||||
characterPosition: from,
|
||||
visualJump: { from, to },
|
||||
jumpAnimationProgress: 2,
|
||||
isJumpAnimating: true,
|
||||
});
|
||||
expect(landedFrame?.progress).toBe(1);
|
||||
expect(landedFrame?.position).toMatchObject(to);
|
||||
|
||||
expect(screen.queryByTestId('jump-hop-landing-assist')).toBeNull();
|
||||
expect(stage.querySelector('.jump-hop-runtime__charge-guide')).toBeTruthy();
|
||||
|
||||
await act(async () => {
|
||||
dispatchPointerEvent(stage, 'pointermove', {
|
||||
pointerId: 1,
|
||||
clientX: 112,
|
||||
clientY: 492,
|
||||
});
|
||||
expect(
|
||||
resolveJumpHopThreeCharacterFrame({
|
||||
characterPosition: from,
|
||||
visualJump: { from, to },
|
||||
jumpAnimationProgress: 0.5,
|
||||
isJumpAnimating: false,
|
||||
}),
|
||||
).toEqual({
|
||||
position: from,
|
||||
progress: 1,
|
||||
});
|
||||
});
|
||||
|
||||
expect(screen.queryByTestId('jump-hop-landing-assist')).toBeNull();
|
||||
expect(stage.querySelector('.jump-hop-runtime__charge-guide')).toBeTruthy();
|
||||
expect(stage.querySelector('.jump-hop-runtime__slingshot-guide')).toBeNull();
|
||||
test('跳一跳蓄力时实时显示松手后的预测落点', async () => {
|
||||
vi.useFakeTimers();
|
||||
try {
|
||||
const onJump = vi.fn().mockResolvedValue(undefined);
|
||||
|
||||
render(
|
||||
<JumpHopRuntimeShell
|
||||
profile={buildProfile({ tileAssets: buildTileAssets() })}
|
||||
run={buildRun()}
|
||||
onJump={onJump}
|
||||
onRestart={() => {}}
|
||||
/>,
|
||||
);
|
||||
|
||||
const stage = screen.getByTestId('jump-hop-stage');
|
||||
await act(async () => {
|
||||
dispatchPointerEvent(stage, 'pointerdown', {
|
||||
pointerId: 1,
|
||||
clientX: 180,
|
||||
clientY: 420,
|
||||
});
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
vi.advanceTimersByTime(240);
|
||||
});
|
||||
|
||||
const firstAssist = screen.getByTestId('jump-hop-landing-assist');
|
||||
expect(firstAssist).toBeTruthy();
|
||||
expect(firstAssist.getAttribute('data-on-target')).toMatch(/^(true|false)$/);
|
||||
expect(stage.querySelector('.jump-hop-runtime__charge-guide')).toBeTruthy();
|
||||
const firstLeft = firstAssist.style.getPropertyValue('--jump-hop-landing-x');
|
||||
const firstTop = firstAssist.style.getPropertyValue('--jump-hop-landing-y');
|
||||
|
||||
await act(async () => {
|
||||
vi.advanceTimersByTime(260);
|
||||
});
|
||||
|
||||
const secondAssist = screen.getByTestId('jump-hop-landing-assist');
|
||||
expect(secondAssist.style.getPropertyValue('--jump-hop-landing-x')).not.toBe(
|
||||
firstLeft,
|
||||
);
|
||||
expect(secondAssist.style.getPropertyValue('--jump-hop-landing-y')).not.toBe(
|
||||
firstTop,
|
||||
);
|
||||
expect(stage.querySelector('.jump-hop-runtime__charge-guide')).toBeTruthy();
|
||||
expect(stage.querySelector('.jump-hop-runtime__slingshot-guide')).toBeNull();
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
});
|
||||
|
||||
test('跳一跳运行态直接渲染生成的地板贴图切片图片', () => {
|
||||
@@ -504,14 +597,14 @@ test('跳一跳运行态直接渲染生成的地板贴图切片图片', () => {
|
||||
);
|
||||
|
||||
const tileImages = screen.getAllByTestId('jump-hop-tile-image');
|
||||
expect(tileImages).toHaveLength(3);
|
||||
expect(tileImages).toHaveLength(2);
|
||||
expect(document.querySelector('.jump-hop-runtime__fallback-tile')).toBeNull();
|
||||
const generatedReadUrlCalls = vi
|
||||
.mocked(useResolvedAssetReadUrl)
|
||||
.mock.calls.filter(([source]) =>
|
||||
source?.includes('/generated-jump-hop-assets/'),
|
||||
);
|
||||
expect(generatedReadUrlCalls.length).toBeGreaterThanOrEqual(3);
|
||||
expect(generatedReadUrlCalls.length).toBeGreaterThanOrEqual(2);
|
||||
for (const [, options] of generatedReadUrlCalls) {
|
||||
expect(options).toEqual(
|
||||
expect.objectContaining({
|
||||
@@ -539,7 +632,7 @@ test('跳一跳运行态提前预加载下一屏地块且不在真实图片加
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getAllByTestId('jump-hop-tile-image')).toHaveLength(3);
|
||||
expect(screen.getAllByTestId('jump-hop-tile-image')).toHaveLength(2);
|
||||
expect(document.querySelector('.jump-hop-runtime__fallback-tile')).toBeNull();
|
||||
const preloadImages = screen.getAllByTestId('jump-hop-tile-preload-image');
|
||||
expect(preloadImages.length).toBeGreaterThan(0);
|
||||
@@ -613,7 +706,63 @@ test('跳一跳 Three.js 地板贴图签名包含六面贴图 URL', () => {
|
||||
expect(signature).toContain('bottom-url');
|
||||
});
|
||||
|
||||
test('跳一跳运行态首块地块落在中下方并且后续两块向中央和上方展开', () => {
|
||||
test('跳一跳 Three 立方体按玩法 Z 轴顶面映射 UV 六面贴图', () => {
|
||||
expect(JUMP_HOP_THREE_PLATFORM_YAW_RAD).toBeCloseTo(Math.PI / 4);
|
||||
expect(JUMP_HOP_THREE_MATERIAL_FACE_ORDER).toEqual([
|
||||
'right',
|
||||
'left',
|
||||
'back',
|
||||
'front',
|
||||
'top',
|
||||
'bottom',
|
||||
]);
|
||||
expect(JUMP_HOP_THREE_TEXTURE_TRANSFORMS).toMatchObject({
|
||||
top: { flipX: true, flipY: false },
|
||||
front: { flipX: true, flipY: true },
|
||||
right: { flipX: false, flipY: true },
|
||||
back: { flipX: false, flipY: true },
|
||||
left: { flipX: true, flipY: true },
|
||||
bottom: { flipX: true, flipY: true },
|
||||
});
|
||||
});
|
||||
|
||||
test('跳一跳 Three 角色绘制层级高于地块并且脚点落在顶面中心高度', () => {
|
||||
expect(JUMP_HOP_THREE_PLATFORM_MATERIAL_TRANSPARENT).toBe(false);
|
||||
expect(JUMP_HOP_THREE_CHARACTER_RENDER_ORDER).toBeGreaterThan(
|
||||
JUMP_HOP_THREE_PLATFORM_MESH_RENDER_ORDER_BASE + 18,
|
||||
);
|
||||
expect(JUMP_HOP_THREE_CHARACTER_TOP_FACE_Z_OFFSET).toBe(0);
|
||||
expect(getJumpHopThreeCharacterFootZ(96, false)).toBe(48);
|
||||
expect(getJumpHopThreeCharacterFootZ(96, true)).toBeLessThan(
|
||||
getJumpHopThreeCharacterFootZ(96, false),
|
||||
);
|
||||
expect(getJumpHopThreeCharacterFootZ(40, false)).toBe(20);
|
||||
});
|
||||
|
||||
test('跳一跳旧单图地块资源不启用 Three UV 贴面层', () => {
|
||||
const oldAssets = buildTileAssets();
|
||||
const uvAssets = buildTileAssets({ withFaceAssets: true });
|
||||
expect(hasCompleteJumpHopTileFaceAssets(oldAssets[0])).toBe(false);
|
||||
expect(hasCompleteJumpHopTileFaceAssets(uvAssets[0])).toBe(true);
|
||||
|
||||
render(
|
||||
<JumpHopRuntimeShell
|
||||
profile={buildProfile({ tileAssets: oldAssets })}
|
||||
run={buildRun()}
|
||||
onJump={vi.fn().mockResolvedValue(undefined)}
|
||||
onRestart={() => {}}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(
|
||||
screen
|
||||
.getByTestId('jump-hop-camera-layer')
|
||||
.getAttribute('data-three-platform-ready'),
|
||||
).toBe('false');
|
||||
expect(screen.getAllByTestId('jump-hop-tile-image')).toHaveLength(2);
|
||||
});
|
||||
|
||||
test('跳一跳运行态只展示当前块和下一块并给下一块留出视野空间', () => {
|
||||
render(
|
||||
<JumpHopRuntimeShell
|
||||
profile={buildProfile({ tileAssets: buildTileAssets() })}
|
||||
@@ -624,16 +773,16 @@ test('跳一跳运行态首块地块落在中下方并且后续两块向中央
|
||||
);
|
||||
|
||||
const tileImages = screen.getAllByTestId('jump-hop-tile-image');
|
||||
expect(tileImages).toHaveLength(3);
|
||||
expect(tileImages).toHaveLength(2);
|
||||
const first = tileImages[0]?.parentElement?.parentElement as HTMLElement | undefined;
|
||||
const second = tileImages[1]?.parentElement?.parentElement as HTMLElement | undefined;
|
||||
const third = tileImages[2]?.parentElement?.parentElement as HTMLElement | undefined;
|
||||
expect(first?.style.top).toBe('64%');
|
||||
expect(second?.style.top).toBe('47%');
|
||||
expect(third?.style.top).toBe('30%');
|
||||
expect(Number.parseFloat(first?.style.left ?? '0')).toBeLessThan(50);
|
||||
expect(Number.parseFloat(second?.style.left ?? '0')).toBeGreaterThan(50);
|
||||
});
|
||||
|
||||
test('跳一跳运行态用固定基准宽高和深度 scale 表达地块尺寸', () => {
|
||||
test('跳一跳运行态地块从出现开始保持真实尺寸', () => {
|
||||
render(
|
||||
<JumpHopRuntimeShell
|
||||
profile={buildProfile({ tileAssets: buildTileAssets() })}
|
||||
@@ -649,7 +798,7 @@ test('跳一跳运行态用固定基准宽高和深度 scale 表达地块尺寸'
|
||||
expect(firstTile?.style.width).toBe('116px');
|
||||
expect(firstTile?.style.height).toBe('96px');
|
||||
expect(firstTile?.style.getPropertyValue('--jump-hop-platform-scale')).toBe(
|
||||
'1.08',
|
||||
'',
|
||||
);
|
||||
});
|
||||
|
||||
@@ -722,8 +871,8 @@ test('跳一跳后端回包较慢时角色停在目标点等待推进', async ()
|
||||
chargeMs: 420,
|
||||
jumpDistance: 1.68,
|
||||
targetPlatformIndex: 1,
|
||||
landedX: 0.93,
|
||||
landedY: 1.4,
|
||||
landedX: 1.7,
|
||||
landedY: 1.74,
|
||||
result: 'hit',
|
||||
},
|
||||
};
|
||||
@@ -787,6 +936,17 @@ test('跳一跳后端回包较慢时角色停在目标点等待推进', async ()
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByTestId('jump-hop-stage').getAttribute('data-jump-animating')).toBe(
|
||||
'true',
|
||||
);
|
||||
expect(screen.getByTestId('jump-hop-stage').getAttribute('data-platform-advancing')).toBe(
|
||||
'false',
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
await vi.advanceTimersByTimeAsync(300);
|
||||
});
|
||||
|
||||
expect(screen.getByTestId('jump-hop-stage').getAttribute('data-jump-animating')).toBe(
|
||||
'false',
|
||||
);
|
||||
@@ -808,8 +968,8 @@ test('跳一跳成功落点偏移后下一跳视觉仍朝下一块地块方向',
|
||||
chargeMs: 300,
|
||||
jumpDistance: 1.0,
|
||||
targetPlatformIndex: 1,
|
||||
landedX: 0,
|
||||
landedY: 1.2,
|
||||
landedX: 1.7,
|
||||
landedY: 1.74,
|
||||
result: 'hit',
|
||||
},
|
||||
};
|
||||
@@ -866,8 +1026,8 @@ test('跳一跳松手后先播放飞行动画再切换到下一块地块', async
|
||||
chargeMs: 420,
|
||||
jumpDistance: 1.68,
|
||||
targetPlatformIndex: 1,
|
||||
landedX: 0.93,
|
||||
landedY: 1.4,
|
||||
landedX: 1.7,
|
||||
landedY: 1.74,
|
||||
result: 'hit',
|
||||
},
|
||||
};
|
||||
@@ -880,8 +1040,8 @@ test('跳一跳松手后先播放飞行动画再切换到下一块地块', async
|
||||
chargeMs: 360,
|
||||
jumpDistance: 1.44,
|
||||
targetPlatformIndex: 2,
|
||||
landedX: -0.2,
|
||||
landedY: 2.4,
|
||||
landedX: 0,
|
||||
landedY: 3.56,
|
||||
result: 'hit',
|
||||
},
|
||||
};
|
||||
@@ -958,6 +1118,17 @@ test('跳一跳松手后先播放飞行动画再切换到下一块地块', async
|
||||
await vi.advanceTimersByTimeAsync(580);
|
||||
});
|
||||
|
||||
expect(screen.getByTestId('jump-hop-stage').getAttribute('data-jump-animating')).toBe(
|
||||
'true',
|
||||
);
|
||||
expect(screen.getByTestId('jump-hop-stage').getAttribute('data-platform-advancing')).toBe(
|
||||
'false',
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
await vi.advanceTimersByTimeAsync(300);
|
||||
});
|
||||
|
||||
expect(screen.getByTestId('jump-hop-stage').getAttribute('data-jump-animating')).toBe(
|
||||
'false',
|
||||
);
|
||||
@@ -978,16 +1149,19 @@ test('跳一跳松手后先播放飞行动画再切换到下一块地块', async
|
||||
const cameraLayer = screen.getByTestId('jump-hop-camera-layer');
|
||||
expect(cameraLayer.getAttribute('data-platform-advancing')).toBe('true');
|
||||
expect(cameraLayer.style.getPropertyValue('--jump-hop-camera-zoom')).toBe(
|
||||
'1.3',
|
||||
'1.69',
|
||||
);
|
||||
expect(cameraLayer.style.getPropertyValue('--jump-hop-camera-shift-y')).toBe(
|
||||
'-17%',
|
||||
);
|
||||
// 下一块在反向时,当前块会切换到场地反侧锚点,横向镜头推进应被侧边视野校正抵消。
|
||||
expect(
|
||||
Number.parseFloat(
|
||||
cameraLayer.style.getPropertyValue('--jump-hop-camera-shift-x'),
|
||||
Math.abs(
|
||||
Number.parseFloat(
|
||||
cameraLayer.style.getPropertyValue('--jump-hop-camera-shift-x'),
|
||||
),
|
||||
),
|
||||
).toBeCloseTo(8.96, 2);
|
||||
).toBeLessThan(1);
|
||||
const styleText = Array.from(document.querySelectorAll('style'))
|
||||
.map((style) => style.textContent ?? '')
|
||||
.join('\n');
|
||||
@@ -1028,7 +1202,7 @@ test('跳一跳松手后先播放飞行动画再切换到下一块地块', async
|
||||
'64%',
|
||||
);
|
||||
expect(screen.getAllByTestId('jump-hop-tile-image')[1]?.parentElement?.parentElement?.style.getPropertyValue('--jump-hop-platform-scale')).toBe(
|
||||
'1.08',
|
||||
'',
|
||||
);
|
||||
expect(screen.getAllByTestId('jump-hop-tile-image')[2]?.parentElement?.parentElement?.getAttribute('data-platform-id')).toBe(
|
||||
'p2',
|
||||
@@ -1127,6 +1301,14 @@ test('跳一跳松手后先播放飞行动画再切换到下一块地块', async
|
||||
await vi.advanceTimersByTimeAsync(580);
|
||||
});
|
||||
|
||||
expect(screen.getByTestId('jump-hop-stage').getAttribute('data-platform-advancing')).toBe(
|
||||
'false',
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
await vi.advanceTimersByTimeAsync(300);
|
||||
});
|
||||
|
||||
const movedOldPlatform = screen
|
||||
.getByTestId('jump-hop-stage')
|
||||
.querySelector("[data-platform-id='p0']") as HTMLElement | null;
|
||||
@@ -1181,8 +1363,8 @@ function buildRun(): JumpHopRuntimeRunSnapshotResponse {
|
||||
{
|
||||
platformId: 'p1',
|
||||
tileType: 'normal',
|
||||
x: 0.8,
|
||||
y: 1.2,
|
||||
x: 1.78,
|
||||
y: 1.78,
|
||||
width: 1,
|
||||
height: 1,
|
||||
landingRadius: 0.5,
|
||||
@@ -1192,8 +1374,8 @@ function buildRun(): JumpHopRuntimeRunSnapshotResponse {
|
||||
{
|
||||
platformId: 'p2',
|
||||
tileType: 'target',
|
||||
x: -0.2,
|
||||
y: 2.4,
|
||||
x: 0,
|
||||
y: 3.56,
|
||||
width: 1,
|
||||
height: 1,
|
||||
landingRadius: 0.5,
|
||||
@@ -1239,8 +1421,8 @@ function buildRunWithExtraPreviewPlatform(): JumpHopRuntimeRunSnapshotResponse {
|
||||
{
|
||||
platformId: 'p3',
|
||||
tileType: 'normal',
|
||||
x: 0.5,
|
||||
y: 3.6,
|
||||
x: 1.78,
|
||||
y: 5.34,
|
||||
width: 1,
|
||||
height: 1,
|
||||
landingRadius: 0.5,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user