Milestone two: the pane becomes the wand hand
Clicks in the first-person view now act. The renderer keeps what the last frame knew — per-column depth, warp bends, every wall hit's edge, every sprite's screen rect with its identity — and hitTest inverts the projection: the nearest visible sprite answers as its wizard or creature, a struck wall or door answers as its edge, and the ground answers as the square under the pixel, warp-bent columns mapping their virtual floor back to real cells through the warp's own rigid motion. The pane hands each target to the very functions the top-down board's clicks use, so pane and map can never disagree: click the floor ahead and you walk there; click a door with a key selected and the lock turns; click a wizard with an attack and the spell flies. The keymap token now wears a golden wedge showing the camera's compass quadrant — the cockpit and the chart always agree on which way you face. Verified live: a floor click became a real move command in the room ledger, edge clicks resolve and defer correctly, and the wedge tracks quarter-turns. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015RCWSTnb1KYTPyL4GmhGnF
This commit is contained in:
co-authored by
Claude Fable 5
parent
aac06dd2b5
commit
42d872df6d
@@ -23,6 +23,7 @@
|
||||
onCellClick,
|
||||
onEdgeClick,
|
||||
onPlayerClick,
|
||||
povFacing = null,
|
||||
onCreatureClick,
|
||||
onWarpClick,
|
||||
onCellPeek,
|
||||
@@ -43,6 +44,9 @@
|
||||
onCellClick?: (cell: { x: number; y: number }) => void;
|
||||
onEdgeClick?: (cell: { x: number; y: number }, side: Side) => void;
|
||||
onPlayerClick?: (playerId: string) => void;
|
||||
/** Which way YOUR first-person camera faces: a wedge on your token
|
||||
* keeps the keymap and the pane pointing the same way. */
|
||||
povFacing?: "N" | "E" | "S" | "W" | null;
|
||||
onCreatureClick?: (creatureId: string) => void;
|
||||
onWarpClick?: (cell: { x: number; y: number }, side: Side) => void;
|
||||
/** Long-press on a square: read the card behind whatever occupies it. */
|
||||
@@ -539,6 +543,14 @@
|
||||
{@const cx = p.position.x * CELL + CELL / 2 + (group.length > 1 ? (gi - (group.length - 1) / 2) * 14 : 0)}
|
||||
{@const cy = p.position.y * CELL + CELL * 0.36}
|
||||
<g class="mover" class:snap={snapsTo(`w:${p.id}`, cx, cy)} style={`transform: translate(${cx}px, ${cy}px)`}>
|
||||
{#if povFacing && p.id === view.you}
|
||||
{@const fr = CELL * 0.34}
|
||||
{@const fa = povFacing === "E" ? 0 : povFacing === "S" ? Math.PI / 2 : povFacing === "W" ? Math.PI : -Math.PI / 2}
|
||||
<polygon
|
||||
points={`${Math.cos(fa) * fr},${Math.sin(fa) * fr} ${Math.cos(fa + 2.6) * fr * 0.55},${Math.sin(fa + 2.6) * fr * 0.55} ${Math.cos(fa - 2.6) * fr * 0.55},${Math.sin(fa - 2.6) * fr * 0.55}`}
|
||||
class="pov-wedge"
|
||||
/>
|
||||
{/if}
|
||||
<g
|
||||
role="button" tabindex="-1"
|
||||
onclick={(ev) => { ev.stopPropagation(); if (peekFired) { peekFired = false; return; } onPlayerClick?.(p.id); }}
|
||||
@@ -765,6 +777,11 @@
|
||||
fill: #6a5c44;
|
||||
pointer-events: none;
|
||||
}
|
||||
.pov-wedge {
|
||||
fill: #c9a72a;
|
||||
opacity: 0.85;
|
||||
pointer-events: none;
|
||||
}
|
||||
.peekable { cursor: pointer; pointer-events: all; }
|
||||
.sight-corner {
|
||||
fill: none;
|
||||
|
||||
Reference in New Issue
Block a user