Skip to content

Commit

Permalink
Leer nodos de archivos con varios objetos
Browse files Browse the repository at this point in the history
- Modificado baseScene y bedroomMorningDay1 para leer correctamente nodos de archivos con varios nodos root
- Modificado dialogManager para que no se pueda interactuar con nada del fondo mientras hay diálogos activos y se pueda pasar de diálogo haciendo click en cualquier sitio
  • Loading branch information
MattCastUCM committed Jul 20, 2024
1 parent 7bcae7f commit 5157831
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 74 deletions.
62 changes: 38 additions & 24 deletions src/managers/dialogManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ export default class DialogManager {
this.dispatcher = this.gameManager.dispatcher;

this.textbox = new TextBox(scene, this);
this.textbox.activate(false);
this.activateOptions(false);

// Mascara para los retratos de los personajes (para que no se pinten fuera de la caja de texto)
let mask = scene.add.image(this.textbox.getTransform().x, this.textbox.getTransform().y, 'textboxMask');
Expand All @@ -33,6 +31,17 @@ export default class DialogManager {
this.portraitMask = mask.createBitmapMask();

this.talking = false;

// Anade un rectangulo para bloquear la interaccion con los elementos del fondo
this.bgBlock = scene.add.rectangle(0, 0, this.scene.CANVAS_WIDTH, this.scene.CANVAS_HEIGHT, 0xfff, 0).setOrigin(0, 0);
this.bgBlock.setDepth(this.textbox.box.depth - 1);
this.bgBlock.on('pointerdown', () => {
this.nextDialog();
});

this.textbox.activate(false);
this.activateOptions(false);
this.bgBlock.disableInteractive();
}

// IMPORTANTE: SE TIENE QUE LLAMAR ANTES DE CAMBIAR LA ESCENA
Expand Down Expand Up @@ -118,6 +127,7 @@ export default class DialogManager {
processNode() {
// Si el nodo actual es valido
if (this.currNode) {
this.bgBlock.setInteractive();
// Si el nodo es un nodo condicional
if (this.currNode.type === "condition") {
let conditionMet = false;
Expand Down Expand Up @@ -223,38 +233,42 @@ export default class DialogManager {
}
else {
this.talking = false;
this.bgBlock.disableInteractive();
}
}

// Pasa al siguiente dialogo
// (llamado al hacer click en la caja de texto)
nextDialog() {
// Si aun no ha acabado de mostrarse todo el texto, lo muestra de golpe
if (!this.textbox.finished) {
this.textbox.forceFinish();
}
// Si ha acabado de mostrarse todo el dialogo
else {
// Actualiza el dialogo que se esta mostrando del nodo actual
this.currNode.currDialog++;

// Si aun no se han mostrado todos los dialogos del nodo, muestra el siguiente dialogo
if (this.currNode.currDialog < this.currNode.dialogs.length) {
this.setText(this.currNode.dialogs[this.currNode.currDialog], true);
if (this.currNode.type === "text") {
// Si aun no ha acabado de mostrarse todo el texto, lo muestra de golpe
if (!this.textbox.finished) {
this.textbox.forceFinish();
}
// Si ya se han mostrado todos los dialogos
// Si ha acabado de mostrarse todo el dialogo
else {
// Se oculta la caja de texto y una vez terminada la animacion,
// reinicia el dialogo del nodo actual y actualiza el nodo al siguiente
this.textbox.activate(false, () => {
this.currNode.currDialog = 0;
// Actualiza el dialogo que se esta mostrando del nodo actual
this.currNode.currDialog++;

// IMPORTANTE: DESPUES DE UN NODO DE DIALOGO SOLO HAY UN NODO, POR LO QUE
// EL SIGUIENTE NODO SERA EL PRIMER NODO DEL ARRAY DE NODOS SIGUIENTES
this.currNode = this.currNode.next[0];
this.processNode();
}, 0);
// Si aun no se han mostrado todos los dialogos del nodo, muestra el siguiente dialogo
if (this.currNode.currDialog < this.currNode.dialogs.length) {
this.setText(this.currNode.dialogs[this.currNode.currDialog], true);
}
// Si ya se han mostrado todos los dialogos
else {
// Se oculta la caja de texto y una vez terminada la animacion,
// reinicia el dialogo del nodo actual y actualiza el nodo al siguiente
this.textbox.activate(false, () => {
this.currNode.currDialog = 0;

// IMPORTANTE: DESPUES DE UN NODO DE DIALOGO SOLO HAY UN NODO, POR LO QUE
// EL SIGUIENTE NODO SERA EL PRIMER NODO DEL ARRAY DE NODOS SIGUIENTES
this.currNode = this.currNode.next[0];
this.processNode();
}, 0);
}
}

}
}

Expand Down
6 changes: 3 additions & 3 deletions src/scenes/bootScene.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@ export default class BootScene extends Phaser.Scene {
// en cualquier idioma (aunque o existiese)
supportedLngs: ['en', 'es'],
// namespaces que se cargan para cada uno de los idiomas
ns: ['titleMenu', 'userInfoMenu', 'names', 'phoneInfo',
'transitionScenes', 'day1/bedroomMorningDay1',
'momDialog', 'dadDialog', 'chat1', 'computer'], // TEST
ns: ['titleMenu', 'userInfoMenu', 'names', 'phoneInfo', 'computer',
'transitionScenes', 'day1\\bedroomMorningDay1',
'momDialog', 'dadDialog', 'chat1', ], // TEST
preload: ['en', 'es'],
// mostrar informacion de ayuda por consola
debug: true,
Expand Down
91 changes: 53 additions & 38 deletions src/scenes/gameLoop/baseScene.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,7 @@ export default class BaseScene extends Phaser.Scene {
* @param {String} id - id del nodo que se lee. El nodo inicial es root
* @param {Object} file - objeto obtenido como resultado de leer el json
* @param {String} namespace - nombre del archivo de localizacion del que se va a leer
* @param {String} playerName - nombre del jugador
* @param {String} context - contexto en el que se va a referir al personaje (male / female)
* @param {String} objectName - nombre del objeto en el que esta el dialogo, si es que el json contiene varios dialogos de distintos objetos
* @param {Boolean} getObjs - si se quiere devolver el nodo leido como un objeto
*
*
Expand All @@ -105,24 +104,40 @@ export default class BaseScene extends Phaser.Scene {
* traducciones es el que se pasa en el parametro namespace, y tiene que pasarse un string con el nombre del
* archivo sin la extension .json
*/
readNodes(id, file, namespace, getObjs) {
readNodes(id, file, namespace, objectName, getObjs) {
let playerName = this.gameManager.getUserInfo().name;
let context = this.gameManager.getUserInfo().gender;

let fileObj = file;
let translationId = id;

// Si el dialogo esta dentro de algun objeto, se ajusta tanto el objeto
// del json en el que buscar los nodos, como la id que utilizar para encontrar
// la traduccion del nodo. Esto es porque la id del nodo debe coincidir tanto
// en el json como en el archivo de traducciones, pero al estar dentro de un objeto
// con (por ejemplo) nombre object, un nodo con la id name deberia buscarse en el
// archivo de traducciones como object.name, pero la id de nodo seguiria siendo name
if (objectName !== "") {
fileObj = file[objectName];
translationId = objectName + "." + id;
}
// console.log(fileObj);
// console.log(this.i18next.t(translationId, { ns: namespace, name: playerName, context: context, returnObjects: getObjs }));

// Crea el nodo y guarda sus atributos (se estableceran en el nodo al final)
let node = null;
let nodeId = id;
let type = file[id].type;
let type = fileObj[id].type;

// Si el nodo es de tipo condicion
if (type === "condition") {
node = new ConditionNode();

// Se leen todas las condiciones. Cada condicion lleva a un nodo distinto y
// en una condicion se pueden comprobar multiples variables
for (let i = 0; i < file[id].conditions.length; i++) {
for (let i = 0; i < fileObj[id].conditions.length; i++) {
// Obtiene el nombre de las variables a comprobar (suprimiendo la propiedad next)
let obj = Object.keys(file[id].conditions[i]);
let obj = Object.keys(fileObj[id].conditions[i]);
let vars = obj.filter(key => key !== "next");

let nodeConditions = [];
Expand All @@ -133,7 +148,7 @@ export default class BaseScene extends Phaser.Scene {
let varName = vars[j];

// Obtiene el objeto que guarda las propiedades que tiene que cumplir la variable
let obj = file[id].conditions[i][varName];
let obj = fileObj[id].conditions[i][varName];

// Crea un objeto igual que obj, pero que tambien guarda su nombre
let condition = obj;
Expand All @@ -152,8 +167,8 @@ export default class BaseScene extends Phaser.Scene {
node.conditions.push(nodeConditions);

// Si hay un nodo despues de este, se crea de manera recursiva el nodo siguiente que corresponde a cumplir dichas condiciones
if (file[id].conditions[i].next) {
node.next.push(this.readNodes(file[id].conditions[i].next, file, namespace, playerName, context, getObjs));
if (fileObj[id].conditions[i].next) {
node.next.push(this.readNodes(fileObj[id].conditions[i].next, file, namespace, objectName, getObjs));
}
}
}
Expand All @@ -163,19 +178,19 @@ export default class BaseScene extends Phaser.Scene {

// Obtiene el nombre del personaje del archivo de nombres localizados
// En el caso de que se trate del jugador, obtiene su nombre
let character = file[id].character;
let character = fileObj[id].character;
if (character === "player") {
node.name = this.gameManager.getUserInfo().name;
}
else {
node.name = this.i18next.t(file[id].character, { ns: "names", returnObjects: getObjs });
node.name = this.i18next.t(fileObj[id].character, { ns: "names", returnObjects: getObjs });
}
node.character = character;

// Se crea un dialogo con todo el texto a mostrar
let split = {
// Obtiene el texto del archivo de textos traducidos
text: this.i18next.t(id + ".text", { ns: namespace, name: playerName, context: context, returnObjects: getObjs }),
text: this.i18next.t(translationId + ".text", { ns: namespace, name: playerName, context: context, returnObjects: getObjs }),
//character: character,
name: node.name
}
Expand All @@ -184,25 +199,25 @@ export default class BaseScene extends Phaser.Scene {
node.currDialog = 0;

// Si hay un nodo despues de este, se crea de manera recursiva
if (file[id].next) {
node.next.push(this.readNodes(file[id].next, file, namespace, playerName, context, getObjs));
if (fileObj[id].next) {
node.next.push(this.readNodes(fileObj[id].next, file, namespace, objectName, getObjs));
}
}
// Si el nodo es de tipo opcion multiple
else if (type === "choice") {
node = new ChoiceNode();

// Se obtienen los textos de las opciones del archivo de textos traducidos
let texts = this.i18next.t(id, { ns: namespace, name: playerName, context: context, returnObjects: getObjs })
let texts = this.i18next.t(translationId, { ns: namespace, name: playerName, context: context, returnObjects: getObjs })

for (let i = 0; i < file[id].choices.length; i++) {
for (let i = 0; i < fileObj[id].choices.length; i++) {
// Se guarda el texto de la eleccion y se crea de manera recursiva
// el nodo siguiente que corresponde a elegir dicha opcion
node.choices.push(texts[i].text);

// Si hay un nodo despues de este, se crea de manera recursiva
if (file[id].choices[i].next) {
node.next.push(this.readNodes(file[id].choices[i].next, file, namespace, playerName, context, getObjs));
if (fileObj[id].choices[i].next) {
node.next.push(this.readNodes(fileObj[id].choices[i].next, file, namespace, objectName, getObjs));
}
}
}
Expand All @@ -211,12 +226,12 @@ export default class BaseScene extends Phaser.Scene {
node = new EventNode();

// Recorre todas las variables obtenidas
for (let i = 0; i < file[id].events.length; i++) {
for (let i = 0; i < fileObj[id].events.length; i++) {
// Lee el nombre del evento
let evtName = Object.keys(file[id].events[i]);
let evtName = Object.keys(fileObj[id].events[i]);

// Obtiene el objeto que guarda los parametros del evento
let obj = file[id].events[i][evtName];
let obj = fileObj[id].events[i][evtName];

// Crea un objeto igual que obj, pero que tambien guarda su nombre
let evt = { ...obj };
Expand All @@ -227,64 +242,64 @@ export default class BaseScene extends Phaser.Scene {
}

// Si hay un nodo despues de este, se crea de manera recursiva
if (file[id].next) {
node.next.push(this.readNodes(file[id].next, file, namespace, playerName, context, getObjs));
if (fileObj[id].next) {
node.next.push(this.readNodes(fileObj[id].next, file, namespace, objectName, getObjs));
}
}
// Si el nodo es de tipo mensaje de texto
else if (type === "chatMessage") {
node = new ChatNode();

// Obtiene el texto del archivo de textos traducidos y lo guarda
let text = this.i18next.t(id + ".text", { ns: namespace, name: playerName, context: context, returnObjects: getObjs });
let text = this.i18next.t(translationId + ".text", { ns: namespace, name: playerName, context: context, returnObjects: getObjs });
node.text = text;

// Obtiene el nombre del personaje del archivo de nombres localizados
// En el caso de que se trate del jugador, obtiene su nombre
let character = file[id].character;
let character = fileObj[id].character;
if (character === "player") {
node.name = this.gameManager.getUserInfo().name;
}
else {
node.name = this.i18next.t(file[id].character, { ns: "names" });
node.name = this.i18next.t(fileObj[id].character, { ns: "names" });
}
node.character = character;

// Guarda el chat en el que tiene que ir la respuesta y el retardo con el que se envia
node.chat = this.i18next.t("textMessages" + "." + file[id].chat, { ns: "phoneInfo" });
node.chat = this.i18next.t("textMessages" + "." + fileObj[id].chat, { ns: "phoneInfo" });

if (file[id].replyDelay) {
node.replyDelay = file[id].replyDelay;
if (fileObj[id].replyDelay) {
node.replyDelay = fileObj[id].replyDelay;
}

// Si hay un nodo despues de este, se crea de manera recursiva
if (file[id].next) {
node.next.push(this.readNodes(file[id].next, file, namespace, playerName, context, getObjs));
if (fileObj[id].next) {
node.next.push(this.readNodes(fileObj[id].next, file, namespace, objectName, getObjs));
}
}
// Si el nodo es de tipo mensaje de texto
// Si el nodo es de tipo comentario de la red social
else if (type === "socialNetMessage") {
node = new SocialNetNode();

// Obtiene el texto del archivo de textos traducidos y lo guarda
let text = this.i18next.t(id + ".text", { ns: namespace, name: playerName, context: context, returnObjects: getObjs });
let text = this.i18next.t(translationId + ".text", { ns: namespace, name: playerName, context: context, returnObjects: getObjs });
node.text = text;

node.character = file[id].character;
node.character = fileObj[id].character;
// Obtiene el nombre del jugador del archivo de nombres localizados
// En el caso de se trate del propio del jugador, obtiene el pronombre personal Tu
// traducido en el idioma correspondiente
node.name = this.i18next.t(file[id].character, { ns: "names" });
node.name = this.i18next.t(fileObj[id].character, { ns: "names" });

// Guarda el usuario que ha subido el post
node.user = file[id].user;
node.user = fileObj[id].user;

// Guarda el numero del post del usuario
node.post = filed[id].post;

// Si hay un nodo despues de este, se crea de manera recursiva
if (file[id].next) {
node.next.push(this.readNodes(file[id].next, file, namespace, playerName, context, getObjs));
if (fileObj[id].next) {
node.next.push(this.readNodes(fileObj[id].next, file, namespace, objectName, getObjs));
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/scenes/gameLoop/day1/bedroomMorningDay1.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ export default class BedroomMorningDay1 extends BedroomBase {

let nodes = this.cache.json.get('bedroomMorningDay1');

this.wardrobe1Node = super.readNodes("root", nodes.wardrobe1, "day1/bedroomMorningDay1", true);
this.wardrobe2Node = super.readNodes("root", nodes.wardrobe2, "day1/bedroomMorningDay1", true);
this.pcNode = super.readNodes("root", nodes.pc, "day1/bedroomMorningDay1", true);
this.bedNode = super.readNodes("root", nodes.bed, "day1/bedroomMorningDay1", true);
this.wardrobe1Node = super.readNodes("root", nodes, "day1\\bedroomMorningDay1", "wardrobe1", true);
this.wardrobe2Node = super.readNodes("root", nodes, "day1\\bedroomMorningDay1", "wardrobe2", true);
this.pcNode = super.readNodes("root", nodes, "day1\\bedroomMorningDay1", "pc", true);
this.bedNode = super.readNodes("root", nodes, "day1\\bedroomMorningDay1", "bed", true);

// Mochila
let bagNode = super.readNodes("root", nodes.bag, "day1/bedroomMorningDay1", true);
let bagNode = super.readNodes("root", nodes, "day1\\bedroomMorningDay1", "bag", true);
let bag = this.add.image(170, this.CANVAS_HEIGHT - 170, 'bag').setOrigin(0, 0).setScale(this.scale);
bag.setInteractive();
bag.on('pointerdown', () => {
Expand Down
8 changes: 4 additions & 4 deletions src/scenes/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ export default class Test extends BaseScene {
let test3 = this.cache.json.get('chat1');
let computerTest = this.cache.json.get('computer');

let momNode = super.readNodes("root", test1, "momDialog", true);
let dadNode = super.readNodes("root", test2, "dadDialog", true);
let choices = super.readNodes("root", test3, "chat1", true);
let computerNode = super.readNodes("root1", computerTest, "computer", true);
let momNode = super.readNodes("root", test1, "momDialog", "",true);
let dadNode = super.readNodes("root", test2, "dadDialog", "", true);
let choices = super.readNodes("root", test3, "chat1", "", true);
let computerNode = super.readNodes("root1", computerTest, "computer", "", true);

// Telefono
let chatName = this.i18next.t("textMessages.chat1", { ns: "phoneInfo", returnObjects: true });
Expand Down

0 comments on commit 5157831

Please sign in to comment.