fix: 优化跳一跳运行态与地块资源
This commit is contained in:
@@ -6,28 +6,28 @@ import type {
|
||||
} from '../../../packages/shared/src/contracts/jumpHop';
|
||||
import {
|
||||
buildJumpHopVisiblePlatforms,
|
||||
getJumpHopBackendDragVector,
|
||||
getJumpHopCharacterVisualPosition,
|
||||
getJumpHopJumpFeedbackLabel,
|
||||
getJumpHopLandingAssistVisualPosition,
|
||||
getJumpHopPlatformVisualSize,
|
||||
getJumpHopStatusLabel,
|
||||
isJumpHopLandingInsidePlatformFootprint,
|
||||
resolveJumpHopCharacterCanvasPosition,
|
||||
selectJumpHopTileAsset,
|
||||
} from './jumpHopRuntimeModel';
|
||||
|
||||
test('跳一跳地块池按平台编号从 25 个素材中抽取而不是按类型压扁', () => {
|
||||
const tileAssets = Array.from({ length: 25 }, (_, index) => ({
|
||||
test('跳一跳地块池按平台编号从 18 个素材中抽取而不是按类型压扁', () => {
|
||||
const tileAssets = Array.from({ length: 18 }, (_, index) => ({
|
||||
tileType: 'normal',
|
||||
tileId: `tile-${String(index + 1).padStart(2, '0')}`,
|
||||
imageSrc: `asset-${index + 1}`,
|
||||
imageObjectKey: `key-${index + 1}`,
|
||||
assetObjectId: `object-${index + 1}`,
|
||||
sourceAtlasCell: `row-1-col-${index + 1}`,
|
||||
atlasRow: 1,
|
||||
atlasCol: index + 1,
|
||||
sourceAtlasCell: `row-${Math.floor(index / 3) + 1}-col-${(index % 3) + 1}`,
|
||||
atlasRow: Math.floor(index / 3) + 1,
|
||||
atlasCol: (index % 3) + 1,
|
||||
visualWidth: 256,
|
||||
visualHeight: 192,
|
||||
visualHeight: 256,
|
||||
topSurfaceRadius: 42,
|
||||
landingRadius: 34,
|
||||
})) satisfies JumpHopTileAsset[];
|
||||
@@ -59,15 +59,17 @@ test('跳一跳可见平台窗口固定为 3 个并携带选中的地块素材',
|
||||
platform(0.8, 5.1, 'normal'),
|
||||
],
|
||||
};
|
||||
const tileAssets = Array.from({ length: 25 }, (_, index) => ({
|
||||
const tileAssets = Array.from({ length: 18 }, (_, index) => ({
|
||||
tileType: 'normal',
|
||||
tileId: `tile-${String(index + 1).padStart(2, '0')}`,
|
||||
imageSrc: `asset-${index + 1}`,
|
||||
imageObjectKey: `key-${index + 1}`,
|
||||
assetObjectId: `object-${index + 1}`,
|
||||
sourceAtlasCell: `row-1-col-${index + 1}`,
|
||||
sourceAtlasCell: `row-${Math.floor(index / 3) + 1}-col-${(index % 3) + 1}`,
|
||||
atlasRow: Math.floor(index / 3) + 1,
|
||||
atlasCol: (index % 3) + 1,
|
||||
visualWidth: 256,
|
||||
visualHeight: 192,
|
||||
visualHeight: 256,
|
||||
topSurfaceRadius: 42,
|
||||
landingRadius: 34,
|
||||
})) satisfies JumpHopTileAsset[];
|
||||
@@ -119,12 +121,12 @@ test('跳一跳三块可见地块按下方中部上方展开且角色落在当
|
||||
visible,
|
||||
);
|
||||
|
||||
expect(visible[0]?.screenY).toBeGreaterThanOrEqual(68);
|
||||
expect(visible[0]?.screenY).toBeLessThanOrEqual(80);
|
||||
expect(visible[0]?.screenY).toBeGreaterThanOrEqual(60);
|
||||
expect(visible[0]?.screenY).toBeLessThanOrEqual(66);
|
||||
expect(visible[1]?.screenY).toBeGreaterThanOrEqual(40);
|
||||
expect(visible[1]?.screenY).toBeLessThan(visible[0]?.screenY ?? 0);
|
||||
expect(visible[2]?.screenY).toBeLessThan(visible[1]?.screenY ?? 0);
|
||||
expect(visible[2]?.screenY).toBeLessThanOrEqual(26);
|
||||
expect(visible[2]?.screenY).toBeLessThanOrEqual(32);
|
||||
expect(Math.abs((visible[1]?.screenX ?? 0) - (visible[0]?.screenX ?? 0))).toBeGreaterThan(5);
|
||||
expect(Math.abs((visible[2]?.screenX ?? 0) - (visible[1]?.screenX ?? 0))).toBeGreaterThan(5);
|
||||
expect(character?.screenX).toBeCloseTo(visible[0]?.screenX ?? 0, 1);
|
||||
@@ -216,8 +218,8 @@ test('跳一跳三维角色画布坐标与屏幕坐标同向映射到下方起
|
||||
|
||||
expect(canvasPosition?.x).toBeGreaterThan(140);
|
||||
expect(canvasPosition?.x).toBeLessThan(180);
|
||||
expect(canvasPosition?.y).toBeGreaterThan(380);
|
||||
expect(canvasPosition?.y).toBeLessThan(450);
|
||||
expect(canvasPosition?.y).toBeGreaterThan(330);
|
||||
expect(canvasPosition?.y).toBeLessThan(370);
|
||||
});
|
||||
|
||||
test('跳一跳运行态当前地块视觉尺寸按原调参结果放大一倍', () => {
|
||||
@@ -227,7 +229,7 @@ test('跳一跳运行态当前地块视觉尺寸按原调参结果放大一倍',
|
||||
expect(size.height).toBeCloseTo(103.68, 2);
|
||||
});
|
||||
|
||||
test('跳一跳落点辅助标识按后端落点规则随拖拽方向和距离投影', () => {
|
||||
test('跳一跳落点预测按蓄力值沿下一地块中心方向投影', () => {
|
||||
const path: JumpHopPath = {
|
||||
seed: 'forest-tea',
|
||||
difficulty: 'standard',
|
||||
@@ -265,22 +267,12 @@ test('跳一跳落点辅助标识按后端落点规则随拖拽方向和距离
|
||||
const current = visible[0]!;
|
||||
const target = visible[1]!;
|
||||
const stageSize = { width: 320, height: 568 };
|
||||
const currentCanvasPosition = {
|
||||
x: (current.screenX / 100) * stageSize.width,
|
||||
y: (current.screenY / 100) * stageSize.height,
|
||||
};
|
||||
const targetCanvasPosition = {
|
||||
x: (target.screenX / 100) * stageSize.width,
|
||||
y: (target.screenY / 100) * stageSize.height,
|
||||
};
|
||||
const targetWorldDistance = Math.hypot(
|
||||
target.platform.x - current.platform.x,
|
||||
target.platform.y - current.platform.y,
|
||||
);
|
||||
const fullDragDistance =
|
||||
targetWorldDistance / path.scoring.chargeToDistanceRatio;
|
||||
const dragVectorX = -(targetCanvasPosition.x - currentCanvasPosition.x);
|
||||
const dragVectorY = -(targetCanvasPosition.y - currentCanvasPosition.y);
|
||||
|
||||
const fullAssist = getJumpHopLandingAssistVisualPosition(
|
||||
run,
|
||||
@@ -288,8 +280,6 @@ test('跳一跳落点辅助标识按后端落点规则随拖拽方向和距离
|
||||
character,
|
||||
stageSize,
|
||||
fullDragDistance,
|
||||
dragVectorX,
|
||||
dragVectorY,
|
||||
);
|
||||
const halfAssist = getJumpHopLandingAssistVisualPosition(
|
||||
run,
|
||||
@@ -297,23 +287,21 @@ test('跳一跳落点辅助标识按后端落点规则随拖拽方向和距离
|
||||
character,
|
||||
stageSize,
|
||||
fullDragDistance / 2,
|
||||
dragVectorX,
|
||||
dragVectorY,
|
||||
);
|
||||
|
||||
expect(fullAssist?.screenX).toBeCloseTo(target.screenX, 1);
|
||||
expect(fullAssist?.screenY).toBeCloseTo(target.screenY, 1);
|
||||
expect(fullAssist?.screenY).toBeCloseTo(target.screenY - 3, 1);
|
||||
expect(halfAssist?.screenX).toBeCloseTo(
|
||||
current.screenX + (target.screenX - current.screenX) / 2,
|
||||
1,
|
||||
);
|
||||
expect(halfAssist?.screenY).toBeCloseTo(
|
||||
current.screenY + (target.screenY - current.screenY) / 2,
|
||||
current.screenY + (target.screenY - current.screenY) / 2 - 3,
|
||||
1,
|
||||
);
|
||||
});
|
||||
|
||||
test('跳一跳落点辅助标识使用屏幕坐标向后拖拽并投向上方目标地块', () => {
|
||||
test('跳一跳落点预测忽略旧客户端拖拽方向', () => {
|
||||
const path: JumpHopPath = {
|
||||
seed: 'forest-tea',
|
||||
difficulty: 'standard',
|
||||
@@ -351,16 +339,6 @@ test('跳一跳落点辅助标识使用屏幕坐标向后拖拽并投向上方
|
||||
const current = visible[0]!;
|
||||
const target = visible[1]!;
|
||||
const stageSize = { width: 320, height: 568 };
|
||||
const currentCanvasPosition = {
|
||||
x: (current.screenX / 100) * stageSize.width,
|
||||
y: (current.screenY / 100) * stageSize.height,
|
||||
};
|
||||
const targetCanvasPosition = {
|
||||
x: (target.screenX / 100) * stageSize.width,
|
||||
y: (target.screenY / 100) * stageSize.height,
|
||||
};
|
||||
const dragVectorX = -(targetCanvasPosition.x - currentCanvasPosition.x);
|
||||
const dragVectorY = currentCanvasPosition.y - targetCanvasPosition.y;
|
||||
const targetWorldDistance = Math.hypot(
|
||||
target.platform.x - current.platform.x,
|
||||
target.platform.y - current.platform.y,
|
||||
@@ -374,16 +352,29 @@ test('跳一跳落点辅助标识使用屏幕坐标向后拖拽并投向上方
|
||||
character,
|
||||
stageSize,
|
||||
fullDragDistance,
|
||||
dragVectorX,
|
||||
dragVectorY,
|
||||
-999,
|
||||
-999,
|
||||
);
|
||||
|
||||
expect(dragVectorY).toBeGreaterThan(0);
|
||||
expect(assist?.screenX).toBeCloseTo(target.screenX, 1);
|
||||
expect(assist?.screenY).toBeCloseTo(target.screenY, 1);
|
||||
expect(assist?.screenY).toBeCloseTo(target.screenY - 3, 1);
|
||||
expect(assist?.isOnTargetPlatform).toBe(true);
|
||||
});
|
||||
|
||||
test('跳一跳后端落点向量会把屏幕拖拽换算为世界尺度一致的反向弹射', () => {
|
||||
test('跳一跳落点预测用收缩后的视觉顶面 footprint 判断命中', () => {
|
||||
const target = {
|
||||
...platform(1, 0, 'normal'),
|
||||
width: 2,
|
||||
height: 0.6,
|
||||
landingRadius: 0.2,
|
||||
};
|
||||
|
||||
expect(isJumpHopLandingInsidePlatformFootprint(target, 1.6, 0)).toBe(true);
|
||||
expect(isJumpHopLandingInsidePlatformFootprint(target, 1.8, 0)).toBe(false);
|
||||
expect(isJumpHopLandingInsidePlatformFootprint(target, 1, 0.18)).toBe(false);
|
||||
});
|
||||
|
||||
test('跳一跳成功落地后保留真实落点偏移而不是吸附到地块中心', () => {
|
||||
const path: JumpHopPath = {
|
||||
seed: 'forest-tea',
|
||||
difficulty: 'standard',
|
||||
@@ -406,41 +397,34 @@ test('跳一跳后端落点向量会把屏幕拖拽换算为世界尺度一致
|
||||
profileId: 'profile-1',
|
||||
ownerUserId: 'user-1',
|
||||
status: 'playing',
|
||||
currentPlatformIndex: 0,
|
||||
successfulJumpCount: 0,
|
||||
currentPlatformIndex: 1,
|
||||
successfulJumpCount: 1,
|
||||
durationMs: 0,
|
||||
score: 0,
|
||||
score: 1,
|
||||
combo: 0,
|
||||
path,
|
||||
lastJump: null,
|
||||
lastJump: {
|
||||
chargeMs: 300,
|
||||
jumpDistance: 1.0,
|
||||
targetPlatformIndex: 1,
|
||||
landedX: 0.52,
|
||||
landedY: 0.78,
|
||||
result: 'hit',
|
||||
},
|
||||
startedAtMs: 1000,
|
||||
finishedAtMs: null,
|
||||
} as const;
|
||||
const visible = buildJumpHopVisiblePlatforms(path, 0, []);
|
||||
const current = visible[0]!;
|
||||
const target = visible[1]!;
|
||||
const stageSize = { width: 320, height: 568 };
|
||||
const currentCanvasPosition = {
|
||||
x: (current.screenX / 100) * stageSize.width,
|
||||
y: (current.screenY / 100) * stageSize.height,
|
||||
};
|
||||
const targetCanvasPosition = {
|
||||
x: (target.screenX / 100) * stageSize.width,
|
||||
y: (target.screenY / 100) * stageSize.height,
|
||||
};
|
||||
const dragVectorX = -(targetCanvasPosition.x - currentCanvasPosition.x);
|
||||
const dragVectorY = currentCanvasPosition.y - targetCanvasPosition.y;
|
||||
const backendVector = getJumpHopBackendDragVector(
|
||||
run,
|
||||
visible,
|
||||
stageSize,
|
||||
dragVectorX,
|
||||
dragVectorY,
|
||||
);
|
||||
const visible = buildJumpHopVisiblePlatforms(path, 1, []);
|
||||
const character = getJumpHopCharacterVisualPosition(run, visible, {
|
||||
width: 320,
|
||||
height: 568,
|
||||
});
|
||||
const currentCenter = visible[0]!;
|
||||
|
||||
expect(backendVector.dragVectorX).toBeLessThan(0);
|
||||
expect(backendVector.dragVectorY).toBeGreaterThan(0);
|
||||
expect(Math.abs(backendVector.dragVectorY)).toBeLessThan(Math.abs(dragVectorY));
|
||||
expect(character?.screenX).not.toBeCloseTo(currentCenter.screenX, 1);
|
||||
expect(character?.screenY).not.toBeCloseTo(currentCenter.screenY - 3, 1);
|
||||
expect(character?.screenX).toBeLessThan(currentCenter.screenX);
|
||||
expect(character?.screenY).toBeGreaterThan(currentCenter.screenY - 3);
|
||||
});
|
||||
|
||||
test('跳一跳运行态公开反馈不再展示旧 perfect 和通关语义', () => {
|
||||
|
||||
Reference in New Issue
Block a user