修复跳一跳运行态方向与贴图刷新
恢复跳一跳运行态拖拽方向提交与后端方向落点计算 补齐平台六面贴图刷新签名和对应前端测试 更新跳一跳玩法链路文档与PRD方向契约说明
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
||||
JUMP_HOP_THREE_CAMERA_UP_Y,
|
||||
JumpHopRuntimeShell,
|
||||
getJumpHopThreeProjectedY,
|
||||
getJumpHopTileTextureSignature,
|
||||
} from './JumpHopRuntimeShell';
|
||||
|
||||
vi.mock('../../hooks/useResolvedAssetReadUrl', () => ({
|
||||
@@ -47,7 +48,7 @@ function dispatchPointerEvent(
|
||||
target.dispatchEvent(event);
|
||||
}
|
||||
|
||||
test('跳一跳运行态松手时只提交长按蓄力值', async () => {
|
||||
test('跳一跳运行态松手时提交长按蓄力值和后端方向向量', async () => {
|
||||
vi.useFakeTimers();
|
||||
const onJump = vi.fn().mockResolvedValue(undefined);
|
||||
const run = buildRun();
|
||||
@@ -90,14 +91,16 @@ test('跳一跳运行态松手时只提交长按蓄力值', async () => {
|
||||
|
||||
expect(onJump).toHaveBeenCalledTimes(1);
|
||||
const jumpPayload = onJump.mock.calls[0]?.[0];
|
||||
expect(jumpPayload?.dragVectorX).toBeUndefined();
|
||||
expect(jumpPayload?.dragVectorY).toBeUndefined();
|
||||
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?.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();
|
||||
@@ -138,8 +141,10 @@ test('跳一跳运行态手指移动不改变提交方向', async () => {
|
||||
});
|
||||
|
||||
const jumpPayload = onJump.mock.calls[0]?.[0];
|
||||
expect(jumpPayload?.dragVectorX).toBeUndefined();
|
||||
expect(jumpPayload?.dragVectorY).toBeUndefined();
|
||||
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?.dragDistance).toBeGreaterThanOrEqual(240);
|
||||
expect(jumpPayload?.dragDistance).toBeLessThanOrEqual(260);
|
||||
vi.useRealTimers();
|
||||
@@ -585,6 +590,29 @@ test('跳一跳新 UV 地板资源会解析六张面贴图而不是复用单张
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('跳一跳 Three.js 地板贴图签名包含六面贴图 URL', () => {
|
||||
const asset = buildTileAssets({ withFaceAssets: true })[0];
|
||||
const signature = getJumpHopTileTextureSignature(
|
||||
{
|
||||
'p1::top': 'top-url',
|
||||
'p1::front': 'front-url',
|
||||
'p1::right': 'right-url',
|
||||
'p1::back': 'back-url',
|
||||
'p1::left': 'left-url',
|
||||
'p1::bottom': 'bottom-url',
|
||||
},
|
||||
'p1',
|
||||
asset,
|
||||
);
|
||||
|
||||
expect(signature).toContain('top-url');
|
||||
expect(signature).toContain('front-url');
|
||||
expect(signature).toContain('right-url');
|
||||
expect(signature).toContain('back-url');
|
||||
expect(signature).toContain('left-url');
|
||||
expect(signature).toContain('bottom-url');
|
||||
});
|
||||
|
||||
test('跳一跳运行态首块地块落在中下方并且后续两块向中央和上方展开', () => {
|
||||
render(
|
||||
<JumpHopRuntimeShell
|
||||
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
formatJumpHopDurationLabel,
|
||||
getJumpHopCharacterVisualPosition,
|
||||
getJumpHopJumpFeedbackLabel,
|
||||
getJumpHopBackendDragVector,
|
||||
getJumpHopLandingAssistVisualPosition,
|
||||
getJumpHopPlatformVisualSize,
|
||||
getJumpHopRunDurationMs,
|
||||
@@ -44,8 +45,8 @@ import { RuntimeResourcePendingMarker } from '../common/RuntimeResourcePendingMa
|
||||
|
||||
type JumpHopRuntimeJumpPayload = {
|
||||
dragDistance: number;
|
||||
dragVectorX?: number;
|
||||
dragVectorY?: number;
|
||||
dragVectorX: number;
|
||||
dragVectorY: number;
|
||||
};
|
||||
|
||||
type JumpHopVisualJump = {
|
||||
@@ -289,6 +290,20 @@ function getJumpHopTileTextureUrl(
|
||||
return textureUrls[getJumpHopTileTextureKey(renderKey, face)] ?? textureUrls[renderKey] ?? '';
|
||||
}
|
||||
|
||||
export function getJumpHopTileTextureSignature(
|
||||
textureUrls: Record<string, string>,
|
||||
renderKey: string,
|
||||
asset: JumpHopTileAsset | null | undefined,
|
||||
) {
|
||||
if (!asset?.faceAssets) {
|
||||
return textureUrls[renderKey] ?? '';
|
||||
}
|
||||
|
||||
return JUMP_HOP_TILE_FACE_KEYS.map((face) =>
|
||||
getJumpHopTileTextureUrl(textureUrls, renderKey, face),
|
||||
).join('|');
|
||||
}
|
||||
|
||||
function hasJumpHopTileTexturesReady(
|
||||
textureUrls: Record<string, string>,
|
||||
renderKey: string,
|
||||
@@ -953,7 +968,11 @@ function JumpHopThreeScene({
|
||||
item.screenY.toFixed(3),
|
||||
item.scale.toFixed(3),
|
||||
cubeSide.toFixed(2),
|
||||
textureUrls[item.renderKey] ?? '',
|
||||
getJumpHopTileTextureSignature(
|
||||
textureUrls,
|
||||
item.renderKey,
|
||||
item.asset,
|
||||
),
|
||||
item.advanceState,
|
||||
].join(':');
|
||||
})
|
||||
@@ -2027,8 +2046,17 @@ export function JumpHopRuntimeShell({
|
||||
x: targetDirection ? -targetDirection.unitScreenX : 0,
|
||||
y: targetDirection ? -targetDirection.unitScreenY : 0,
|
||||
});
|
||||
const backendDragVector = getJumpHopBackendDragVector(
|
||||
predictionRun ?? activeRun,
|
||||
visiblePlatforms,
|
||||
landingAssistStageSize,
|
||||
targetDirection ? -targetDirection.unitScreenX : 0,
|
||||
targetDirection ? -targetDirection.unitScreenY : 0,
|
||||
);
|
||||
await onJump({
|
||||
dragDistance: nextDragDistance,
|
||||
dragVectorX: backendDragVector.dragVectorX,
|
||||
dragVectorY: backendDragVector.dragVectorY,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user