Navigation and map
How to define, organize, and navigate rooms, locations, and maps in Pixi’VN, including custom classes and usage examples.
Nomenclature
Usually in video games, navigation elements used to identify the position of characters are called room, location (e.g. restaurant, house, hospital, etc.), and map. For this reason, names that follow this logic are used.
This does not prevent you from using these elements to manage navigation with the same logic but with different terms. For example, in a game set in space where the player moves between planets, rooms can be the planets, locations can be the solar systems, and maps can be the galaxy.
The navigation system is composed of the following elements:
rooms
: The core elements of navigation, from which the position of themc
andnpc
is deduced.locations
: A container ofrooms
.maps
: A container oflocations
.
The player can move between rooms
. The location
and the map
are also determined based on the room
in which the player is located.
Initialize
To initialize a room
/location
/map
, create a new instance of the RoomBaseModel
/ LocationBaseModel
/ MapBaseModel
class (or your custom class) and add it to the game room/location/map dictionary when the game is initialized.
It is recommended to import the instances at project startup, see the src/main.ts
file.
To create a new instance of RoomBaseModel
, you need the following parameters:
id
: A unique identifier (string). Used to reference theroom
in the game (must be unique).location
: Thelocation
where theroom
is.props
: An object with the room's properties:name
(Optional): The room's name.image
(Optional): The room's image URL.activities
(Optional): The activities available in this room.disabled
(Optional): Whether the room is disabled. You can also pass a Pixi’VN flag name.hidden
(Optional): Whether the room is hidden. You can also pass a Pixi’VN flag name.icon
(Optional): The room's icon image URL.
To create a new instance of LocationBaseModel
, you need the following parameters:
id
: A unique identifier (string). Used to reference thelocation
in the game (must be unique).map
: Themap
where thelocation
is.props
: An object with the location's properties:name
(Optional): The location's name.icon
(Optional): The location's icon image URL.activities
(Optional): The activities available in this location.disabled
(Optional): Whether the location is disabled. You can also pass a Pixi’VN flag name.hidden
(Optional): Whether the location is hidden. You can also pass a Pixi’VN flag name.
To create a new instance of MapBaseModel
, you need the following parameters:
id
: A unique identifier (string). Used to reference themap
in the game (must be unique).props
: An object with the map's properties:name
(Optional): The map's name.image
(Optional): The map's image URL.activities
(Optional): The activities available in this map.
import { RegisteredRooms, RoomBaseModel } from "@drincs/nqtr";
import { bed } from "./activity";
import { mcHome } from "./locations";
export const mcRoom = new RoomBaseModel("mc_room", mcHome, {
name: "MC room",
image: "location_myroom",
activities: [bed],
});
export const aliceRoom = new RoomBaseModel("alice_room", mcHome, {
name: "Alice room",
image: "location_aliceroom",
});
export const annRoom = new RoomBaseModel("ann_room", mcHome, {
name: "Ann room",
image: "location_annroom",
});
export const bathroom = new RoomBaseModel("bathroom", mcHome, {
name: "Bathroom",
image: "location_bathroom",
});
export const lounge = new RoomBaseModel("lounge", mcHome, {
name: "Lounge",
image: "location_lounge",
});
export const terrace = new RoomBaseModel("terrace", mcHome, {
name: "Terrace",
image: "location_terrace",
});
RegisteredRooms.add([mcRoom, aliceRoom, annRoom, bathroom, lounge, terrace]);
RegisteredRooms.add
/ RegisteredLocations.add
/ RegisteredMaps.add
is required to save the rooms
/locations
/maps
in the game.
You can also create a function to load rooms
/locations
/maps
. The important thing is that it is called at least once before the rooms
/locations
/maps
are used in the game, otherwise they will not be available.
It is also recommended to set the current room during the start of the game.
import { navigator } from "@drincs/nqtr";
import { newLabel } from "@drincs/pixi-vn";
import { mcRoom } from "../values/rooms";
const startLabel = newLabel("start", [
async () => {
navigator.currentRoom = mcRoom;
// ... other initialization logic
},
]);
export default startLabel;
Get
To get a room
/location
/map
by its id
, use the RegisteredRooms.get
/ RegisteredLocations.get
/ RegisteredMaps.get
function.
import { RegisteredRooms } from "@drincs/nqtr";
const mcRoom = RegisteredRooms.get('mc_room');
Get all
To get all rooms
/locations
/maps
, use the RegisteredRooms.values
/ RegisteredLocations.values
/ RegisteredMaps.values
function.
import { RegisteredRooms } from "@drincs/nqtr";
const rooms = RegisteredRooms.values();
Navigate
As explained above, the player can navigate between rooms
, and the current room
determines the current location
and map
.
To navigate to a room
, set the navigator.currentRoom
property to the desired room instance. This will automatically update the current location
and map
based on the room's location and map.
import { navigator } from "@drincs/nqtr";
import { mcRoom } from "../values/rooms";
navigator.currentRoom = mcRoom;
Custom class
Templates
In all templates, the Room
/ Location
/ Map
class is already defined in the file models/nqtr/Room.ts
/ models/nqtr/Location.ts
/ models/nqtr/Map.ts
. You can use it directly or modify it to suit your needs.
It is recommended to create your own class Room
/ Location
/ Map
that extends RoomStoredClass
/ LocationStoredClass
/ MapStoredClass
and "override" the interface RoomInterface
/ LocationInterface
/ MapInterface
to add, edit, or remove properties or methods.
For example, if you want to create a class Room
/ Location
/ Map
, you must "override" the interface RoomInterface
/ LocationInterface
/ MapInterface
to use your properties or methods. (See the file nqtr.d.ts
)
Now you can create a class Room
/ Location
/ Map
that extends RoomStoredClass
/ LocationStoredClass
/ MapStoredClass
and implements the RoomInterface
/ LocationInterface
/ MapInterface
. (For more information on how to create a class in TypeScript, read the official documentation)
To create a property that stores its value in the game storage, you can create Getters/Setters and use the this.getStorageProperty()
/ this.setStorageProperty()
methods. (See the file Room.ts
/ Location.ts
/ Map.ts
)
import { ActivityInterface, LocationInterface, RoomInterface, RoomStoredClass } from "@drincs/nqtr";
import ImageTimeSlots from "../ImageTimeSlots";
export default class Room extends RoomStoredClass implements RoomInterface {
constructor(
id: string,
location: LocationInterface,
props: {
name: string;
disabled?: boolean | (() => boolean);
hidden?: boolean | (() => boolean);
image: ImageTimeSlots;
activities?: ActivityInterface[];
isEntrance?: boolean;
}
) {
super(id, location, props.activities);
this.name = props.name;
this._defaultdisabled = props.disabled || false;
this._defaulthidden = props.hidden || false;
this.image = props.image;
this.isEntrance = props.isEntrance || false;
}
readonly name: string;
readonly image: ImageTimeSlots;
readonly isEntrance: boolean;
private _defaultdisabled: boolean | (() => boolean) = false;
get disabled(): boolean {
let value = this.getStorageProperty<boolean>("disabled") || this._defaultdisabled;
if (typeof value === "function") {
return value();
}
return value;
}
set disabled(value: boolean) {
this.setStorageProperty("disabled", value);
}
private _defaulthidden: boolean | (() => boolean) = false;
get hidden(): boolean {
let value = this.getStorageProperty<boolean>("hidden") || this._defaulthidden;
if (typeof value === "function") {
return value();
}
return value;
}
set hidden(value: boolean) {
this.setStorageProperty("hidden", value);
}
}