diff --git a/GameObject.js b/GameObject.js
index 16cc04e..e3d7d87 100644
--- a/GameObject.js
+++ b/GameObject.js
@@ -1,5 +1,6 @@
class GameObject {
constructor(config) {
+ this.id = null;
this.isMounted = false;
this.x = config.x || 0;
this.y = config.y || 0;
@@ -9,14 +10,42 @@ class GameObject {
src: config.src || "/images/characters/people/hero.png",
});
+
+ this.behaviorLoop = config.behaviorLoop || [];
+ this.behaviorLoopIndex = 0;
}
mount(map) {
this.isMounted = true;
map.addWall(this.x, this.y);
+
+ // when behavior kick off after delay
+ setTimeout(() => {
+ this.doBehaviorEvent(map);
+ }, 10);
}
update() {
}
+
+ async doBehaviorEvent(map) {
+ // stop if cutscene is playing
+ if (map.isCutscenePlaying || this.behaviorLoop.length === 0) {
+ return;
+ }
+
+ let eventConfig = this.behaviorLoop[this.behaviorLoopIndex];
+ eventConfig.who = this.id;
+
+ const eventHandler = new OverworldEvent({ map, event: eventConfig });
+ await eventHandler.init();
+
+ this.behaviorLoopIndex += 1;
+ if (this.behaviorLoopIndex === this.behaviorLoop.length) {
+ this.behaviorLoopIndex = 0;
+ }
+
+ this.doBehaviorEvent(map);
+ }
}
\ No newline at end of file
diff --git a/Overworld.js b/Overworld.js
index 2a253d9..489d21a 100644
--- a/Overworld.js
+++ b/Overworld.js
@@ -22,7 +22,9 @@ class Overworld {
this.map.drawLowerImage(this.ctx, cameraPerson);
- Object.values(this.map.gameObjects).forEach(object => {
+ Object.values(this.map.gameObjects).sort((a,b) => {
+ return a.y - b.y;
+ }).forEach(object => {
object.sprite.draw(this.ctx, cameraPerson);
})
@@ -43,5 +45,12 @@ class Overworld {
this.directionInput.init();
this.startGameLoop();
+
+ this.map.startCutscene([
+ { who: "hero", type: "walk", direction: "down" },
+ { who: "hero", type: "walk", direction: "down" },
+ { who: "hero", type: "walk", direction: "down" },
+ { who: "npc1", type: "walk", direction: "right" },
+ ])
}
}
\ No newline at end of file
diff --git a/OverworldEvent.js b/OverworldEvent.js
new file mode 100644
index 0000000..7e98057
--- /dev/null
+++ b/OverworldEvent.js
@@ -0,0 +1,54 @@
+class OverworldEvent {
+ constructor({map, event}) {
+ this.map = map;
+ this.event = event;
+ }
+
+ stand(resolve) {
+ const who = this.map.gameObjects[ this.event.who ];
+ who.startBehavior({
+ map: this.map
+ }, {
+ type: "stand",
+ direction: this.event.direction,
+ time: this.event.time
+ })
+
+ // handler to complete when correct person is done walking
+ const completeHandler = e => {
+ if (e.detail.whoId === this.event.who) {
+ document.removeEventListener("PersonStandComplete", completeHandler);
+ resolve();
+ }
+ }
+
+ document.addEventListener("PersonStandComplete", completeHandler)
+ }
+
+ walk(resolve) {
+ const who = this.map.gameObjects[ this.event.who ];
+ who.startBehavior({
+ map: this.map
+ }, {
+ type: "walk",
+ direction: this.event.direction,
+ retry: true
+ })
+
+ // handler to complete when correct person is done walking
+ const completeHandler = e => {
+ if (e.detail.whoId === this.event.who) {
+ document.removeEventListener("PersonWalkingComplete", completeHandler);
+ resolve();
+ }
+ }
+
+ document.addEventListener("PersonWalkingComplete", completeHandler)
+ }
+
+ init() {
+ return new Promise(resolve => {
+ this[this.event.type](resolve)
+ })
+ }
+}
\ No newline at end of file
diff --git a/OverworldMap.js b/OverworldMap.js
index 7c1ccb3..21a873b 100644
--- a/OverworldMap.js
+++ b/OverworldMap.js
@@ -8,6 +8,8 @@ class OverworldMap {
this.upperImage = new Image();
this.upperImage.src = config.upperSrc;
+
+ this.isCutscenePlaying = false;
}
drawLowerImage(ctx, cameraPerson) {
@@ -24,13 +26,29 @@ class OverworldMap {
}
mountObjects() {
- Object.values(this.gameObjects).forEach(o => {
- // todoL determine if this object should actually mount
+ Object.keys(this.gameObjects).forEach(key => {
+ let object = this.gameObjects[key];
+ object.id = key;
- o.mount(this);
+
+ object.mount(this);
})
}
+ async startCutscene(events) {
+ this.isCutscenePlaying = true;
+
+ for (let i = 0; i < events.length; i++) {
+ const eventHandler = new OverworldEvent({
+ event: events[i],
+ map: this,
+ })
+ await eventHandler.init();
+ }
+
+ this.isCutscenePlaying = false;
+ }
+
addWall(x, y) {
this.walls[`${x},${y}`] = true;
}
@@ -56,10 +74,27 @@ window.OverworldMaps = {
x: utils.withGrid(8),
y: utils.withGrid(2),
}),
- // npc1: new Person({
- // x: utils.withGrid(6),
- // y: utils.withGrid(7),
- // })
+ npc1: new Person({
+ x: utils.withGrid(6),
+ y: utils.withGrid(5),
+ behaviorLoop: [
+ { type: "stand", direction: "down", time: 800 },
+ { type: "stand", direction: "right", time: 300 },
+ { type: "stand", direction: "down", time: 400 },
+ { type: "stand", direction: "up", time: 700 },
+ ]
+ }),
+ npc2: new Person({
+ x: utils.withGrid(8),
+ y: utils.withGrid(9),
+ behaviorLoop: [
+ { type: "walk", direction: "left" },
+ { type: "stand", direction: "up", time: 800 },
+ { type: "walk", direction: "up" },
+ { type: "walk", direction: "right" },
+ { type: "walk", direction: "down" },
+ ]
+ })
},
walls: {
// "16,16": true
diff --git a/Person.js b/Person.js
index b1b55a5..de86efd 100644
--- a/Person.js
+++ b/Person.js
@@ -21,7 +21,7 @@ class Person extends GameObject {
// more cases for starting to walk come here
// case: keyboard ready and arrow pressed
- if (this.isPlayerControlled && state.arrow) {
+ if (state.map.isCutscenePlaying == false && this.isPlayerControlled && state.arrow) {
this.startBehavior(state, {
type: "walk",
direction: state.arrow
@@ -37,12 +37,24 @@ class Person extends GameObject {
if (behavior.type === "walk") {
// stop if space is not free
if (state.map.isSpaceTaken(this.x, this.y, this.direction)) {
+ behavior.retry && setTimeout(() => {
+ this.startBehavior(state, behavior);
+ }, 10);
return;
}
// ready to walk
state.map.moveWall(this.x, this.y, this.direction);
this.movementProgressRemaining = 16;
+ this.updateSprite(state);
+ }
+
+ if (behavior.type = "stand") {
+ setTimeout(() => {
+ utils.emitEvent("PersonStandComplete", {
+ whoId: this.id
+ })
+ }, behavior.time);
}
}
@@ -50,6 +62,12 @@ class Person extends GameObject {
const [property, change] = this.directionUpdate[this.direction];
this[property] += change;
this.movementProgressRemaining -= 1;
+
+ if (this.movementProgressRemaining === 0) {
+ utils.emitEvent("PersonWalkingComplete", {
+ whoId: this.id
+ })
+ }
}
updateSprite() {
diff --git a/index.html b/index.html
index e629de6..313bb4b 100644
--- a/index.html
+++ b/index.html
@@ -18,6 +18,7 @@
+