Migration guide
pixi-vn
Migration from v1.4.x to v1.5.0
In this update, the pixi.js dependency has been marked as external for non-CDN builds (for example, when using Vite.js or the official templates).
When using a CDN, the version of pixi.js bundled with the library will continue to be used. This ensures compatibility, prevents known issues, and preserves the overall integrity of the library.
Why is pixi.js now external? pixi.js does not support multiple instances. Making it external allows developers to safely integrate third-party libraries that are designed to work with pixi.js, without running into instance conflicts.
In v1.5.4, the canvas resizing logic has also been changed. If you used an official template, it's recommended to modify the CSS as follows:
@import "tailwindcss";
@plugin "@tailwindcss/typography";
@plugin "tailwindcss-motion";
:root {
background-color: #242424;
}
html,
body {
height: 100%;
}
body {
margin: 0;
min-height: 100vh;
display: flex;
overflow: hidden;
}Migration from v1.3.x to v1.4.0
This document describes the changes that need to be made to your code to migrate from v1.3.x to v1.4.0.
In this release, some functions for managing "navigation of the narrative" have been modified to allow for the easy implementation of rollback and rollforward. Specifically, it is now possible to execute multiple back and continue requests synchronously, and the system will internally queue them and calculate the delta to execute only the necessary processes. You can read more about this in the Rollback and Rollforward section.
For this reason it was necessary to modify the stepHistory.back() function and the Game.init() function. stepHistory.back() now requires a path navigation function rather than a StepLabelProps function. You can now define the path navigation function in Game.init().
stepHistory.back((_path) => {
// TODO: navigate in the url path
// READ THIS: https://pixi-vn.web.app/start/interface.html#navigate-switch-between-ui-screens
})
const gameProps = {};
stepHistory.back(gameProps); Game.init(body, {
height: 1080,
width: 1920,
backgroundColor: "#303030",
navigate: (_path) => {
// TODO: navigate in the url path
},
}).then(() => {
// ...
});Some long-deprecated features have been removed in this release, including: stepHistory.goBack, narration.goNext, PIXI, canvas.canvasWidth, canvas.canvasHeight, canvas.onEndOfTicker, FadeAlphaTicker, MoveTicker, RotateTicker, ZoomTicker, narration.canContinue, narration.callLabel, narration.jumpLabel, narration.choiceMenuOptions, storage.startingStorage, storage.setVariable, storage.getVariable and storage.removeVariable.
Migration from v1.2.x to v1.3.0
This document describes the changes that need to be made to your code to migrate from v1.2.x to v1.3.0.
In this release, the canvas component animations have been revolutionized. The core animation function is now canvas.animate, a function that combines PixiJS tickers and motion. So the provided tickers preset (FadeAlphaTicker, MoveTicker, RotateTicker, ZoomTicker) has been deprecated.
Migration from v0.10.x to v1.0
This document describes the changes that need to be made to your code to migrate from v0.10.x to v1.0.
Being version 1.0.0 it is the first complete release of the library. It is a breaking change and the API has changed significantly. The fundamental change of this release was to split the entire engine into independent modules. This allows for a more modular and flexible design, making it easier to use the engine in different contexts. The size of packages has been reduced significantly (150 MB to 50 MB) and the engine is now more efficient and faster.
The Game namespace object has been introduced for the which contains all the functionality that exploits multiple modules. This is the main entry point for the engine and is used to access all the functions of the engine.
The stepHistory module has been introduced to manage the history of the game. Previously the entire management of the game's history was handled by narration.
clearAllGameDatas();
Game.clear(); canvas
.initialize(body, {
height: 1080,
width: 1920,
backgroundColor: "#303030",
})
.then(() => {
// Pixi.JS UI Layer
canvas.addLayer(CANVAS_UI_LAYER_NAME, new Container());
Game.init(body, {
height: 1080,
width: 1920,
backgroundColor: "#303030",
}).then(() => {
// Pixi.JS UI Layer
canvas.addLayer(CANVAS_UI_LAYER_NAME, new Container()); getSaveData();
Game.exportGameState(); getSaveJson();
JSON.stringify(Game.exportGameState()); loadSaveData(data, navigate);
Game.restoreGameState(data, navigate); loadSaveJson(data, navigate);
Game.restoreGameState(JSON.parse(dataString) as GameState, navigate); loadSaveJson(data, navigate);
Game.restoreGameState(JSON.parse(dataString) as GameState, navigate); jsonToSaveData(json);
JSON.parse(json); narration.canGoBack;
stepHistory.canGoBack; narration.back();
stepHistory.back(); narration.narrativeHistory;
stepHistory.narrativeHistory; nqtr
Migration from v0.7.x to v0.8.0 (nqtr)
ink
This version does not support save files created with previous versions if temporary commitment were used (i.e., if they were added using routine.add).
To make the saves compatible, you need to modify the save file (remember that it is a JSON) by changing the ___nqtr-temporary_commitment___ variable from an array of strings (a list of commitment IDs) to an object with keys corresponding to the commitment IDs and values corresponding to an object containing id and roomId (the latter is required to identify the link between the commitment and the room).
{
// ...
"___nqtr-temporary_commitment___": [
"alice_sleep",
"alice_eat",
],
"___nqtr-temporary_commitment___": {
"alice_sleep": {
"id": "alice_sleep",
"roomId": "alice_room"
},
"alice_eat": {
"id": "alice_eat",
"roomId": "alice_room"
},
},
// ...
}This document describes the changes that need to be made to your code to migrate from v0.7.x to v0.8.0.
In this release, the way to link a commitment to a room has been changed. You can now define its routine directly inside the room. Therefore, instead of passing the room in the commitment constructor, you can define the routine directly in the room constructor.
This change was made to simplify the management of routines and to make the relationship between commitment and room clearer.
export default class Commitment extends CommitmentStoredClass implements CommitmentInterface {
constructor(
id: string,
characters: CharacterInterface | CharacterInterface[],
room: RoomInterface,
props: {
name?: string;
image?: PixiUIParam<Commitment>;
background?: PixiUIParam<Commitment>;
icon?: ReactUIParam<Commitment>;
onRun?: OnRunEvent<CommitmentInterface>;
disabled?: boolean | (() => boolean);
hidden?: boolean | (() => boolean);
} & CommitmentStoredClassProps,
) {
characters = Array.isArray(characters) ? characters : [characters];
super(id, characters, room, props.onRun, props);
super(id, characters, props.onRun, props);
this.name = props.name || "";
this._image = props.image;
this._background = props.background;
this._icon = props.icon;
this._defaultDisabled = props.disabled || false;
this._defaultHidden = props.hidden || false;
}
// ...
override get isActive(): boolean {
override isActive(options?: ActiveScheduling): boolean {
if (this.hidden) {
return false;
}
return super.isActive;
return super.isActive(options);
}
}export default class Room extends RoomStoredClass implements RoomInterface {
constructor(
id: string,
location: LocationInterface,
props: {
name: string;
disabled?: boolean | (() => boolean);
hidden?: boolean | (() => boolean);
background: PixiUIParam<Room>;
activities?: ActivityInterface[];
routine?: CommitmentInterface[];
isEntrance?: boolean;
},
) {
super(id, location, props.activities);
super(id, location, {
activities: props.activities || [],
routine: props.routine || [],
});
this.name = props.name;
this._defaultDisabled = props.disabled || false;
this._defaultHidden = props.hidden || false;
this._background = props.background;
this.isEntrance = props.isEntrance || false;
}
// ...
}export default class Activity extends ActivityStoredClass implements ActivityInterface {
// ...
override get isActive(): boolean {
override isActive(options?: ActiveScheduling): boolean {
if (this.hidden) {
return false;
}
return super.isActive;
return super.isActive(options);
}
}const aliceSleep = new Commitment("alice_sleep", alice, aliceRoom, {
const aliceSleep = new Commitment("alice_sleep", alice, {
priority: 1,
timeSlot: {
from: 20,
to: 10,
},
// ...
});
// ...
export const fixedRoutine = [aliceSleep, ...];
RegisteredCommitments.add(fixedRoutine);
RegisteredCommitments.add([aliceSleep, ...]); export function initializeNQTR() {
// ...
routine.fixedRoutine = fixedRoutine;
}export const aliceRoom = new Room("alice_room", mcHome, {
name: "Alice room",
background: new TimeSlotsImage({
morning: "location_aliceroom-0",
afternoon: "location_aliceroom-1",
evening: "location_aliceroom-2",
night: "location_aliceroom-3",
}),
routine: [aliceSleep],
});routine.add(aliceSleep);
aliceRoom.addCommitment(aliceSleep);