// depth.test.js — 透视缩放 + zIndex 纵深 + 遮挡判定(render-pixi §8 验收 7)。 // // 对照原型 pixi-stage.js / character-actor.js: // - setActorWorldPos 后角色按 worldY 做透视缩放(近大远小)+ zIndex=round(worldY)。 // - 遮挡片 zIndex=baseY;人物 worldY < baseY 被遮、> baseY 盖住。 import { describe, it, expect } from 'vitest' import { perspectiveScale, depthZIndex } from '../src/geom.js' import { isOccluded } from '../src/occluder.js' import { createPixiRenderer } from '../src/index.js' import { makeStubPixi, StubApplication } from './stub-pixi.js' const depth = { nearY: 1000, farY: 200, nearScale: 1.5, farScale: 0.5 } describe('geom 纵深纯函数', () => { it('perspectiveScale:近(下/大)→nearScale、远(上/小)→farScale、区间外夹紧', () => { expect(perspectiveScale(1000, depth)).toBeCloseTo(1.5) expect(perspectiveScale(200, depth)).toBeCloseTo(0.5) expect(perspectiveScale(600, depth)).toBeCloseTo(1.0) // 中点 expect(perspectiveScale(2000, depth)).toBeCloseTo(1.5) // 夹紧 near expect(perspectiveScale(-100, depth)).toBeCloseTo(0.5) // 夹紧 far }) it('perspectiveScale 单调:worldY 越大缩放越大(近大远小)', () => { expect(perspectiveScale(400, depth)).toBeLessThan(perspectiveScale(800, depth)) }) it('depthZIndex = round(worldY)', () => { expect(depthZIndex(456.4)).toBe(456) expect(depthZIndex(456.6)).toBe(457) }) }) describe('遮挡判定', () => { it('人物脚下 worldY < baseY → 被遮;> baseY → 盖住;== 不被遮', () => { expect(isOccluded(300, 500)).toBe(true) expect(isOccluded(700, 500)).toBe(false) expect(isOccluded(500, 500)).toBe(false) }) }) const rig = { id: 'humanoid_v1', canvas: { width: 1080, height: 1080 }, bones: [{ name: 'root', parent: null, pos: { x: 0, y: 0 }, rotation: 0 }], slots: [{ name: 'torso', bone: 'root', zOrder: 10 }], } describe('setActorWorldPos 集成', () => { function setup() { const PIXI = makeStubPixi() const r = createPixiRenderer(new StubApplication(), { PIXI, rig }) return { r, PIXI } } it('setActorWorldPos 写根容器位置 + zIndex=round(worldY)', () => { const { r } = setup() r.addActor('a', { rigId: 'humanoid_v1', parts: { torso: { url: 't.png' } } }, { x: 0, y: 0, facing: 'left', scale: 1 }) r.setActorWorldPos('a', 250, 740.3) const actor = r._actors.get('a') expect(actor.root.position.x).toBe(250) expect(actor.root.position.y).toBe(740.3) expect(actor.root.zIndex).toBe(740) }) it('loadScene 设 depth 后,角色按 worldY 透视缩放(baseScale=1)', async () => { const { r } = setup() r.addActor('a', { rigId: 'humanoid_v1', parts: { torso: { url: 't.png' } } }, { x: 0, y: 0, facing: 'left', scale: 1 }) await r.loadScene({ world: { w: 2000, h: 1200 }, depth }) r.setActorWorldPos('a', 0, 1000) // 近 const near = Math.abs(r._actors.get('a').root.scale.x) r.setActorWorldPos('a', 0, 200) // 远 const far = Math.abs(r._actors.get('a').root.scale.x) expect(near).toBeCloseTo(1.5) expect(far).toBeCloseTo(0.5) expect(near).toBeGreaterThan(far) }) })