feedback6 R21F: an enemy flyer hovers FLY_HOVER above the road whatever tile it crosses (GitHub #277: one high-ground / forbidden block on its way lifted it 0.42 / 0.3 tiles and dropped it again like a step) — UnitView.sync keeps every enemy at z 0, operators and summons keep their tile top, the flyer's shadow lies on the tile under it (shadowZ) on the 2D and the 3D board; golden: unchanged
This commit is contained in:
1 parent
783bd30afd
commit
14df10a5a3
5 files changed
+81
-11
No files matched your search
@@ -345,3 +345,49 @@ describe('flying units hover FLY_HOVER above the ground, whatever their model',
|
||||
assert.ok(Math.abs(fly.shadow.position.y - ground.shadow.position.y) < 1e-9, 'the shadow stays on the ground');
|
||||
});
|
||||
});
|
||||
|
||||
// GitHub #277 (@FrogThai): 飞机经过一格方块时会跟走楼梯一样,有高低差 — a flyer crossing one raised tile (high ground,
|
||||
// a forbidden block) rose onto the block and dropped back like a step, because the view added the tile's height under
|
||||
// it before its FLY_HOVER. The official lift is one constant over the route (docs/research/12: Vector3(0, 0.35, 0) added
|
||||
// while flying), so an enemy flyer hovers from the road (z 0) whatever tile it crosses; its shadow lies on the tile top
|
||||
// under it. Ground enemies keep to the road as before, and an operator on high ground keeps standing on the block.
|
||||
describe('an enemy flyer crossing a raised tile keeps its height (GitHub #277)', () => {
|
||||
const RAISED = { row: 12, col: 6, h: 0.42 }; // one high-ground block ('h', TILE_H.wall) on the flyer's row
|
||||
const heightAt = (r, c) => (r === RAISED.row && c === RAISED.col ? RAISED.h : 0);
|
||||
const sample = (x, flags) => ({ x, y: 12, hp: 100, maxHp: 100, sp: 0, spMax: 0, flags, anim: 1, vx: 0.5 });
|
||||
|
||||
test('the body stays FLY_HOVER above the road over the block; the shadow lies on the block top', async () => {
|
||||
const { FLY_HOVER } = await import('../../public/js/render/units.js');
|
||||
const ctx = fakeViewCtx(fake.P, { assets: store(), cam, heightAt });
|
||||
const fly = new UnitView(ctx, { id: 1, side: 'enemy', kind: 'enemy', defId: 'enemy_1005_yokai', x: 4, y: 12, maxHp: 100, motion: 'FLY' }, {});
|
||||
await tick(); await tick();
|
||||
let t = 0;
|
||||
const step = (x) => { fly.sync(sample(x, 512), t); fly.update(1 / 60, cam(), t); t += 1 / 60; };
|
||||
for (let i = 0; i < 180; i++) step(4); // settle the lift on the road
|
||||
const heights = [];
|
||||
for (let i = 0; i <= 80; i++) { step(4 + i * 0.05); heights.push(fly.z + fly.hover); } // x 4 → 8 across col 6
|
||||
const rise = Math.max(...heights) - Math.min(...heights);
|
||||
assert.ok(rise < 1e-6, `the body height never changes over the block (rose ${rise.toFixed(3)} tiles; before: +${RAISED.h})`);
|
||||
assert.ok(Math.abs(heights[0] - FLY_HOVER) < 1e-3, `FLY_HOVER above the road (${heights[0].toFixed(3)})`);
|
||||
for (let i = 0; i < 60; i++) step(6); // hold over the block
|
||||
assert.equal(fly.z, 0, 'the flyer hovers from the road plane');
|
||||
const c = cam();
|
||||
assert.ok(Math.abs(fly.screen.y - c.project(6, 12, FLY_HOVER).y) < 1e-6, 'drawn FLY_HOVER above the road, not above the block');
|
||||
assert.ok(Math.abs(fly.shadow.position.y - c.project(6, 12, RAISED.h).y) < 0.05, 'its shadow lies on the block top under it');
|
||||
for (let i = 0; i < 60; i++) step(8); // back over the road
|
||||
assert.ok(Math.abs(fly.shadow.position.y - c.project(8, 12, 0).y) < 0.05, 'and on the road again past it');
|
||||
});
|
||||
|
||||
test('ground enemies stay on the road and an operator on the block stands on its top', async () => {
|
||||
const ctx = fakeViewCtx(fake.P, { assets: store(), cam, heightAt });
|
||||
const walker = new UnitView(ctx, { id: 2, side: 'enemy', kind: 'enemy', defId: 'enemy_1007_slime', x: 6, y: 12, maxHp: 100 }, {});
|
||||
const op = new UnitView(ctx, { id: 3, side: 'ally', kind: 'chess', defId: 'char_x', tier: 1, x: 6, y: 12, maxHp: 100 }, {});
|
||||
await tick(); await tick();
|
||||
for (let i = 0; i < 60; i++) {
|
||||
walker.sync(sample(6, 0), i / 60); walker.update(1 / 60, cam(), i / 60);
|
||||
op.sync({ ...sample(6, 0), anim: 0, vx: 0 }, i / 60); op.update(1 / 60, cam(), i / 60);
|
||||
}
|
||||
assert.equal(walker.z, 0, 'a ground enemy is never popped onto a block');
|
||||
assert.ok(Math.abs(op.z - RAISED.h) < 1e-6, `the operator stands on the high ground (${op.z})`);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user