Official docs: pixi-vn.com/nqtr/navigation. Index: nqtr. Prefer ink for story-side navigation when the project uses ink: nqtr-ink.
Concepts
| Element | Role |
|---|---|
room |
The core element; the position of the MC and NPCs is deduced from it |
location |
Container of rooms |
map |
Container of locations |
The player moves between rooms; the current location and map are derived from the current room. The terms are conventional (in a space game: planets/solar systems/galaxy).
Initialize
Create map → location → room (each needs its parent) and register them. Registered*.add is required.
import { MapBaseModel, RegisteredMaps } from "@drincs/nqtr";
export const mainMap = new MapBaseModel("main_map", { name: "Main Map", image: "map" });
RegisteredMaps.add(mainMap);
import { LocationBaseModel, RegisteredLocations } from "@drincs/nqtr";
import { mainMap } from "@/content/maps";
export const mcHome = new LocationBaseModel("mc_home", mainMap, { name: "MC Home" });
RegisteredLocations.add(mcHome);
import { RegisteredRooms, RoomBaseModel } from "@drincs/nqtr";
import { mcHome } from "@/content/locations";
export const mcRoom = new RoomBaseModel("mc_room", mcHome, {
name: "MC room",
image: "location_myroom",
activities: ["bed"], // see nqtr-activity
});
export const aliceRoom = new RoomBaseModel("alice_room", mcHome, {
name: "Alice room",
image: "location_aliceroom",
routine: ["alice_sleep"], // see nqtr-routine
});
RegisteredRooms.add(mcRoom, aliceRoom);
Import order: content files that reference each other must not form cycles; the parent (map, then location) is imported by the child.
Get / get all
RegisteredRooms.get(id), RegisteredLocations.get(id), RegisteredMaps.get(id); .values() returns all. navigator.rooms/locations/maps list the registered entities.
Navigate
Set the current room; location and map update automatically. Do it at game start too.
=== start ===
# enter room mc_room
-> DONE
import { navigator } from "@drincs/nqtr";
navigator.currentRoom = mcRoom; // accepts a room or its id
navigator.currentRoomId; navigator.currentLocation; navigator.currentMap;
navigator.clearExpiredActivities() drops activities whose schedule ended.
Custom classes
Extend RoomStoredClass / LocationStoredClass / MapStoredClass, implement the matching interface, and augment it in nqtr.d.ts (name, sprite/background, disabled, hidden, entrance, ...). Constructor shapes: Room(id, location, { activities?, routine? }), Location(id, map, activities?), Map(id, activities?). Store mutable flags with getStorageProperty/setStorageProperty:
export default class Room extends RoomStoredClass implements RoomInterface {
constructor(id: string, location: LocationInterface, props: { name: string; activities?: (ActivityInterface | ActivityIdType)[]; routine?: (CommitmentInterface | CommitmentIdType)[]; isEntrance?: boolean }) {
super(id, location, { activities: props.activities || [], routine: props.routine || [] });
this.name = props.name;
this.isEntrance = props.isEntrance || false;
}
readonly name: string;
readonly isEntrance: boolean;
get hidden(): boolean { return this.getStorageProperty<boolean>("hidden") || false; }
set hidden(value: boolean) { this.setStorageProperty("hidden", value); }
}
Graphical elements (background, sprite, icon)
backgroundaccepts a string (the alias of a linked asset) or aTimeSlotsImage(see time) to change the image by time of day.spriteaccepts either a string (the alias of a linked asset) or a function returning a PixiJS element (e.g. aSpritewitheventMode: "static"and apointerdownhandler) when you need full control.iconis a function returning a UI element (e.g. a React button).
Default ("entrance") room of a location
Add isEntrance to Room (and RoomInterface), and in Location expose get entrance() returning super.rooms.find((r) => r.isEntrance) || super.rooms[0] (or undefined if empty). A map UI then does navigator.currentRoom = location.entrance when the location icon is clicked.
Pitfalls
- Forgetting
Registered*.add: the room cannot be saved or entered from ink. - Overriding
rooms/locationsgetters to filterhiddenis common; remember hidden rooms are then absent fromlocation.rooms.