0.2.6: the device slabs stay drawn on an official scene (GitHub #569) — 射击台, 特制水上平台 and 封印的地面 lived only in the procedural board's bucket that a scene replaces, so 战场#03's raised tiles by the blue gate were flat and 战场#05(上半)'s water platforms read as open water; buildBoard repeats them into buckets.raised / raisedDecal with sides reaching under the scene's ground and setStage draws just those on a scene (the 'h' high ground is the scenes' own and is not repeated); DESIGN §31.11, client §15; golden: unchanged
This commit is contained in:
1 parent
d8aab0a2db
commit
205f3bb7f7
7 files changed
+99
-8
No files matched your search
@@ -385,6 +385,23 @@ describe('BoardScene with an official scene (stub renderer)', () => {
|
||||
assert.equal(board.sceneRes.size, 0, 'scene resources disposed');
|
||||
});
|
||||
|
||||
test('#569: the device slabs stay drawn on an official scene (the procedural board is gone); a stage without slabs adds nothing', () => {
|
||||
const board = new BoardScene(THREE, fakePack(), { renderer: stubRenderer() });
|
||||
const m03 = stages.act1autochess_m03;
|
||||
board.setScenePack(m03.id, fakeScenePack());
|
||||
board.setStage(m03);
|
||||
assert.ok(board.official && !board.meshes.board, 'the scene replaces the board');
|
||||
assert.ok(board.meshes.raised, 'the 射击台 slabs beside the blue gate stay');
|
||||
assert.equal(board.meshes.raised.geometry.getAttribute('position').count, board.board.buckets.raised.vertexCount);
|
||||
assert.equal(board.meshes.raised.material, board.mat.board, 'drawn like the procedural board');
|
||||
assert.equal(board.setScenePack(m03.id, null), true);
|
||||
assert.ok(board.meshes.board && !board.meshes.raised, 'without the scene the board draws them itself');
|
||||
board.setScenePack(stage.id, fakeScenePack());
|
||||
board.setStage(stage);
|
||||
assert.ok(board.official && !board.meshes.raised && !board.meshes.raisedDecal, `${stage.id}: no slab devices`);
|
||||
board.destroy();
|
||||
});
|
||||
|
||||
test('another stage, or dropping the scene, shows the procedural board again', () => {
|
||||
const board = new BoardScene(THREE, fakePack(), { renderer: stubRenderer() });
|
||||
board.setScenePack(stage.id, fakeScenePack());
|
||||
|
||||
@@ -13,6 +13,7 @@ import { SURFACES, SOURCES, surfaceUV, resolveUvTable, cleanSurface, sideRect, t
|
||||
import { parseObj, mapMesh } from '../../public/js/render/board3d/obj.js';
|
||||
import {
|
||||
buildBoard, classifyStage, heightOf, AREAS, areaFor, unionAreas, objToBoard, boxProjectUV, tube, Geom, uvAt, ROWS, COLS,
|
||||
DEVICE_H, RAISED_FOOT,
|
||||
} from '../../public/js/render/board3d/layout.js';
|
||||
import { BoardScene, gatePulse, DIR_TURNS, boxData, LIGHTING } from '../../public/js/render/board3d/scene.js';
|
||||
import { loadBoardPack, loadThree, resetBoardPack, PACK_IMAGES } from '../../public/js/render/board3d/load.js';
|
||||
@@ -173,6 +174,33 @@ describe('board geometry (layout.js)', () => {
|
||||
assert.ok(!buildBoard(stages.act1autochess_m02).devices.some((d) => d.kind === 'crate'));
|
||||
});
|
||||
|
||||
test('#569: the device slabs (射击台 / 特制水上平台 / 封印的地面) are repeated for an official scene, their sides reaching under its ground; nothing else is', () => {
|
||||
const SLAB = new Set(['platform', 'waterPlatform', 'sealedFloor']);
|
||||
for (const [id, st] of Object.entries(stages)) {
|
||||
if (!Array.isArray(st?.rows)) continue;
|
||||
for (const area of [AREAS.normal, AREAS.boss]) {
|
||||
const b = buildBoard(st, { area });
|
||||
const slabs = b.devices.filter((d) => SLAB.has(d.kind));
|
||||
const decals = slabs.filter((d) => d.kind === 'sealedFloor').length;
|
||||
// per slab four sides, plus its top: a plate (raised) or the hazard decal of a sealed floor (raisedDecal)
|
||||
assert.equal(b.buckets.raised.vertexCount, (slabs.length * 5 - decals) * 4, `${id}: raised quads`);
|
||||
assert.equal(b.buckets.raisedDecal.vertexCount, decals * 4, `${id}: raised decal quads`);
|
||||
const P = b.buckets.raised.position;
|
||||
for (let i = 0; i < P.length; i += 3) {
|
||||
const d = slabs.find((x) => Math.abs(P[i] - x.c) <= 0.5 && Math.abs(P[i + 1] - x.r) <= 0.5);
|
||||
assert.ok(d, `${id}: every raised vertex is on a slab tile`);
|
||||
const h = b.grid[d.r][d.c].h;
|
||||
assert.ok(near(P[i + 2], h + DEVICE_H[d.kind]) || near(P[i + 2], h - RAISED_FOOT), `${id}: a slab top or its foot, z ${P[i + 2]}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
// the report's 射击台 beside the blue gate (战场#03) and the water platforms (战场#05 上半) are there; the 'h' high
|
||||
// ground of act2 m01 / m02 is the scenes' own geometry and is not repeated
|
||||
assert.ok(buildBoard(stages.act1autochess_m03, { area: AREAS.normal }).buckets.raised.vertexCount > 0);
|
||||
assert.equal(buildBoard(stages.act1autochess_m05, { area: AREAS.normal }).devices.filter((d) => d.kind === 'waterPlatform').length, 16);
|
||||
for (const id of ['act2autochess_m01', 'act2autochess_m02']) assert.equal(buildBoard(stages[id], { area: AREAS.normal }).buckets.raised.vertexCount, 0, id);
|
||||
});
|
||||
|
||||
test('malformed stages never throw and still build an island', () => {
|
||||
for (const st of [null, {}, { rows: ['xyz'] }, { rows: Array(19).fill('r'.repeat(21)), devices: [{ role: 'crate', pos: [3, 3] }, { role: 'crate', pos: 'x' }] }]) {
|
||||
const b = buildBoard(st, { area: AREAS.all });
|
||||
|
||||
Reference in new issue
Block a user