Add named Marks and cross-room NPC pathfinding
- Mark: a debug non-collidable named destination (pixel-art target icon), editor tool + name modal, globally-unique names, programmatic Room:addMark - NPCs walk to Marks: each RGB copy is a per-room resident (like the player), running its own A* on its own colour layer, transferring rooms as it crosses seams; rendered and collided by the room it currently stands in - Player copies are obstacles in NPC pathfinding - A* is footprint-aware for multi-cell NPCs - Editor: click an NPC to open a filterable destination picker - Ink: Dialogue.open binds walk_to; Jorge can be sent to "end"/"begin" - Fix: a blocked NPC now replans each tick and resumes instead of freezing - [npc] move diagnostics under DEBUG (start/goal/route or block reason) - Docs (adding-npcs) + CLAUDE.md LÖVE 11.x/float-colour corrections - Fix test harness loadSprite stub; movement tests green (28) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ad405ed590
commit
c348b81a93
17 changed files with 2755 additions and 43 deletions
|
|
@ -38,11 +38,14 @@ In `main.lua`, next to `startSignBook`:
|
|||
|
||||
## 4. Make the entity
|
||||
|
||||
In `npc.lua`, copy `Sign` — pick your art and name your book:
|
||||
In `npc.lua`, copy `Sign` — pick your art and name your book. Include `Walker`
|
||||
too (it's what lets the NPC path to a Mark; see "Making an NPC walk" below), and
|
||||
call `self:initWalker()` after `Entity.initialize`:
|
||||
|
||||
```lua
|
||||
Oracle = class("Oracle", Entity)
|
||||
Oracle:include(Dialogable)
|
||||
Oracle:include(Walker)
|
||||
|
||||
function Oracle:initialize(x, y)
|
||||
self.book = oracleBook -- from step 3
|
||||
|
|
@ -55,6 +58,7 @@ function Oracle:initialize(x, y)
|
|||
blue = loadSprite("art/npc/oracle_b.png"),
|
||||
},
|
||||
})
|
||||
self:initWalker()
|
||||
end
|
||||
```
|
||||
|
||||
|
|
@ -82,3 +86,44 @@ Then add it to a room's `rooms/<room>.sav` `objects` list:
|
|||
That's it — walk into it and it talks. NPCs are stamped into every colour's
|
||||
collision matrix, so they block movement and obey the world's colour rules (a
|
||||
red-only player reads them in red).
|
||||
|
||||
# Marks — named destinations
|
||||
|
||||
A **Mark** is a debug non-collidable: an editor-only annotation the game reads
|
||||
back. It carries a globally-unique name, and it's the only thing an NPC can be
|
||||
sent to. It is *not* a Note — it just shares the debug overlay toggle. In the
|
||||
editor, click the **target** tool at the bottom of the panel, then click a cell
|
||||
to drop one and type its name (colliding names auto-suffix `_2`, `_3`, …).
|
||||
Left-click an existing mark to rename it; right-click to delete. Marks show only
|
||||
under `DEBUG` while the overlay is on (`Tab`).
|
||||
|
||||
You can also create marks from code so they exist without living in a `.sav`:
|
||||
|
||||
```lua
|
||||
room:addMark("gate", 5, 9) -- registers + renders in debug; skipped by serialize
|
||||
```
|
||||
|
||||
# Making an NPC walk
|
||||
|
||||
Any NPC that includes `Walker` (see step 4) can be sent to a Mark. From Ink, call
|
||||
the bound external function — e.g. to leave once the conversation ends:
|
||||
|
||||
```ink
|
||||
Oracle: The way is open now. Go.
|
||||
~ walk_to("gate")
|
||||
-> END
|
||||
```
|
||||
|
||||
`walk_to(name)` is wired for every Dialogable (`dialogable.lua`); it resolves the
|
||||
Mark by name and calls `npc:sendTo`. Under the hood the NPC becomes the player's
|
||||
RGB model — up to three colour copies, each running its **own** A* on its own
|
||||
collision layer (`pathfinding.lua`), stepping in real time and pathing across
|
||||
room seams over the world grid. Copies split apart and additively re-merge to
|
||||
white on arrival. Pathfinding is footprint-aware, so a 2×2 NPC routes its whole
|
||||
body around obstacles rather than threading a 1-wide gap.
|
||||
|
||||
## Testing without a story
|
||||
|
||||
You don't need an Ink book to try it: in the editor (`DEBUG`), **left-click an
|
||||
NPC** to open the destination picker — a filterable list of every Mark. Type to
|
||||
filter, click a row (or Enter for the top match) to send it; Esc cancels.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue