The glass board's marks are drawn over the glass and the figures: a dot on an empty square a piece may go to, a ring around a figure it may take or that is chosen, a halo for the last move, each on a dark rim so it reads on the pale air as well as the underworld
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CCLa2PaEeCj8njQZSWGqHx
This commit is contained in:
1 parent
ff69d53e8c
commit
cf92c9bd27
1 file changed
+25
-13
@@ -121,15 +121,27 @@
|
||||
}
|
||||
|
||||
// Marks on squares: what is selected, where it may go, the last move, a King in check.
|
||||
// They are drawn over everything, so that neither the glass above nor a figure on the
|
||||
// square can hide them, and each sits on a dark rim so it reads on the pale air as well as
|
||||
// the underworld. A dot is an empty square a piece may go to; a ring hugs a figure's base.
|
||||
const marks = new THREE.Group();
|
||||
scene.add(marks);
|
||||
const markGeometry = new THREE.PlaneGeometry(CELL * 0.92, CELL * 0.92);
|
||||
function mark(i: number, colour: string, opacity: number) {
|
||||
const m = new THREE.Mesh(markGeometry, new THREE.MeshBasicMaterial({ color: colour, transparent: true, opacity, depthWrite: false }));
|
||||
m.userData.square = i;
|
||||
m.rotation.x = -Math.PI / 2;
|
||||
m.position.copy(at(i)).add(new THREE.Vector3(0, 0.015, 0));
|
||||
marks.add(m);
|
||||
const SHAPE = {
|
||||
dot: [new THREE.CircleGeometry(CELL * 0.18, 24), new THREE.CircleGeometry(CELL * 0.23, 24)],
|
||||
ring: [new THREE.RingGeometry(CELL * 0.5, CELL * 0.6, 48), new THREE.RingGeometry(CELL * 0.46, CELL * 0.64, 48)],
|
||||
halo: [new THREE.RingGeometry(CELL * 0.66, CELL * 0.74, 48), new THREE.RingGeometry(CELL * 0.63, CELL * 0.77, 48)]
|
||||
};
|
||||
function mark(i: number, shape: keyof typeof SHAPE, colour: string, opacity = 1) {
|
||||
const [face, rim] = SHAPE[shape];
|
||||
const layers: [THREE.BufferGeometry, string, number][] = [[rim, '#1b1410', opacity * 0.75], [face, colour, opacity]];
|
||||
for (const [geometry, color, alpha] of layers) {
|
||||
const m = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ color, transparent: true, opacity: alpha, depthWrite: false, depthTest: false, toneMapped: false }));
|
||||
m.userData.square = i;
|
||||
m.renderOrder = 10 + marks.children.length;
|
||||
m.rotation.x = -Math.PI / 2;
|
||||
m.position.copy(at(i)).add(new THREE.Vector3(0, 0.015, 0));
|
||||
marks.add(m);
|
||||
}
|
||||
}
|
||||
|
||||
// Figures: one scene per kind, shared geometry, a livery per side and a dimmed one for a piece held by a Basilisk.
|
||||
@@ -356,12 +368,12 @@
|
||||
});
|
||||
$effect(() => {
|
||||
marks.clear();
|
||||
for (const i of reach) mark(i, MARK.reach, 0.22);
|
||||
for (const i of shownSquares) mark(i, MARK.last, 0.4);
|
||||
for (const i of shownCaptured) mark(i, MARK.fallen, 0.45);
|
||||
for (const i of targets) mark(i, MARK.target, 0.5);
|
||||
if (selected !== null) mark(selected, MARK.selected, 0.6);
|
||||
if (checkSquare >= 0) mark(checkSquare, MARK.check, 0.6);
|
||||
for (const i of reach) mark(i, g.cells[i] === '' ? 'dot' : 'ring', MARK.reach, 0.85);
|
||||
for (const i of shownSquares) mark(i, 'halo', MARK.last);
|
||||
for (const i of shownCaptured) mark(i, 'halo', MARK.fallen);
|
||||
for (const i of targets) mark(i, g.cells[i] === '' ? 'dot' : 'ring', MARK.target);
|
||||
if (selected !== null) mark(selected, 'ring', MARK.selected);
|
||||
if (checkSquare >= 0 && checkSquare !== selected) mark(checkSquare, 'ring', MARK.check);
|
||||
wake();
|
||||
});
|
||||
$effect(() => look(view));
|
||||
|
||||
Reference in new issue
Block a user