class OverworldMap { constructor(config) { this.overworld = null; this.gameObjects = config.gameObjects; this.cutsceneSpaces = config.cutsceneSpaces || {}; this.walls = config.walls || {}; this.lowerImage = new Image(); this.lowerImage.src = config.lowerSrc; this.upperImage = new Image(); this.upperImage.src = config.upperSrc; this.isCutscenePlaying = false; } drawLowerImage(ctx, cameraPerson) { ctx.drawImage(this.lowerImage, utils.withGrid(10.5) - cameraPerson.x, utils.withGrid(6) - cameraPerson.y); } drawUpperImage(ctx, cameraPerson) { ctx.drawImage(this.upperImage, utils.withGrid(10.5) - cameraPerson.x, utils.withGrid(6) - cameraPerson.y); } isSpaceTaken(currentX, currentY, direction) { const {x, y} = utils.nextPosition(currentX, currentY, direction); return this.walls[`${x},${y}`] || false; } mountObjects() { Object.keys(this.gameObjects).forEach(key => { let object = this.gameObjects[key]; object.id = key; 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; // reset npcs Object.values(this.gameObjects).forEach(object => object.doBehaviorEvent(this)) } checkForActionCutscene() { const hero = this.gameObjects["hero"]; const nextCoords = utils.nextPosition(hero.x, hero.y, hero.direction); const match = Object.values(this.gameObjects).find(object => { return `${object.x},${object.y}` === `${nextCoords.x},${nextCoords.y}` }); if (!this.isCutscenePlaying && match && match.talking.length) { this.startCutscene(match.talking[0].events); } } checkForFootstepCutscene() { const hero = this.gameObjects["hero"]; const match = this.cutsceneSpaces[ `${hero.x},${hero.y}`]; if (!this.isCutscenePlaying && match) { this.startCutscene(match[0].events); } } addWall(x, y) { this.walls[`${x},${y}`] = true; } removeWall(x, y) { delete this.walls[`${x},${y}`]; } moveWall(wasX, wasY, direction) { this.removeWall(wasX, wasY); const {x, y} = utils.nextPosition(wasX, wasY, direction); this.addWall(x, y); } } window.OverworldMaps = { DemoRoom: { lowerSrc: "/images/maps/map-room-entrance.png", upperSrc: "", gameObjects: { hero: new Person({ isPlayerControlled: true, x: utils.withGrid(8), y: utils.withGrid(2), }), 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 }, ], talking: [ { events: [ { type: "textMessage", text: "Schau dich ruhig um.", faceHero: "npc1" }, { type: "textMessage", text: "Vielleicht findest du etwas interessantes ..." }, ] } ] }), npc2: new Person({ x: utils.withGrid(2), y: utils.withGrid(5), behaviorLoop: [ { type: "stand", direction: "right", time: 300 }, // { type: "stand", direction: "down", time: 300 }, ], talking: [ { events: [ { type: "textMessage", text: "Dieser Raum darf nicht betreten werden.", faceHero: "npc2" }, { type: "textMessage", text: "Geh weg!" }, { who: "hero", type: "walk", direction: "right" }, ] } ] }), npc3: new Person({ x: utils.withGrid(9), y: utils.withGrid(3), src: "/images/characters/people/hero-test.png", behaviorLoop: [ { type: "stand", direction: "down", time: 2000 }, { type: "stand", direction: "right", time: 2000 }, { type: "stand", direction: "up", time: 2000 }, { type: "stand", direction: "left", time: 2000 }, ], }) }, walls: { // "16,16": true [utils.asGridCoord(5,2)] : true, [utils.asGridCoord(5,3)] : true, [utils.asGridCoord(5,4)] : true, [utils.asGridCoord(4,4)] : true, [utils.asGridCoord(3,4)] : true, [utils.asGridCoord(2,4)] : true, [utils.asGridCoord(1,5)] : true, [utils.asGridCoord(0,6)] : true, [utils.asGridCoord(1,7)] : true, [utils.asGridCoord(2,8)] : true, [utils.asGridCoord(3,8)] : true, [utils.asGridCoord(4,8)] : true, [utils.asGridCoord(5,8)] : true, [utils.asGridCoord(5,9)] : true, [utils.asGridCoord(5,10)] : true, [utils.asGridCoord(4,11)] : true, [utils.asGridCoord(5,12)] : true, [utils.asGridCoord(6,12)] : true, [utils.asGridCoord(7,12)] : true, [utils.asGridCoord(7,13)] : true, [utils.asGridCoord(8,14)] : true, [utils.asGridCoord(9,13)] : true, [utils.asGridCoord(9,12)] : true, [utils.asGridCoord(10,12)] : true, [utils.asGridCoord(11,12)] : true, [utils.asGridCoord(12,11)] : true, [utils.asGridCoord(11,10)] : true, [utils.asGridCoord(11,9)] : true, [utils.asGridCoord(11,8)] : true, [utils.asGridCoord(11,7)] : true, [utils.asGridCoord(11,6)] : true, [utils.asGridCoord(12,5)] : true, [utils.asGridCoord(11,4)] : true, [utils.asGridCoord(11,3)] : true, [utils.asGridCoord(11,2)] : true, [utils.asGridCoord(10,1)] : true, [utils.asGridCoord(9,1)] : true, [utils.asGridCoord(8,1)] : true, [utils.asGridCoord(7,1)] : true, [utils.asGridCoord(6,1)] : true, }, cutsceneSpaces: { [utils.asGridCoord(1,6)]: [ { events: [ { who: "npc2", type: "walk", direction: "down" }, { who: "npc2", type: "stand", direction: "left" }, { who: "hero", type: "stand", direction: "right", time: 300 }, { type: "textMessage", text: "Du kannst hier nicht rein!" }, { who: "npc2", type: "walk", direction: "up" }, { who: "npc2", type: "stand", direction: "right" }, { who: "hero", type: "walk", direction: "right" }, { who: "hero", type: "walk", direction: "right" }, ] } ], [utils.asGridCoord(11,5)]: [ { events: [ { type: "changeMap", map: "Kitchen" } ] } ], [utils.asGridCoord(11,11)]: [ { events: [ { type: "changeMap", map: "Bedroom" } ] } ], [utils.asGridCoord(8,13)]: [ { events: [ { type: "changeMap", map: "Bathroom" } ] } ], [utils.asGridCoord(5,11)]: [ { events: [ { type: "changeMap", map: "Livingroom" } ] } ], [utils.asGridCoord(1,6)]: [ { events: [ { type: "changeMap", map: "Office" } ] } ], } }, Kitchen: { lowerSrc: "/images/maps/map-room-kitchen.png", // upperSrc: "/images/maps/room-builder.png", upperSrc: "", gameObjects: { hero: new Person({ isPlayerControlled: true, x: utils.withGrid(1), y: utils.withGrid(4), }), npc1: new Person({ x: utils.withGrid(3), y: utils.withGrid(6), // src: "/images/characters/people/hero-run.png", talking: [ { events: [ { type: "textMessage", text: "You made it!", faceHero: "npc1" }, ] } ] }) }, walls: { // "16,16": true [utils.asGridCoord(1,1)] : true, [utils.asGridCoord(1,2)] : true, [utils.asGridCoord(1,3)] : true, [utils.asGridCoord(0,4)] : true, [utils.asGridCoord(1,5)] : true, [utils.asGridCoord(1,6)] : true, [utils.asGridCoord(2,7)] : true, [utils.asGridCoord(3,7)] : true, [utils.asGridCoord(4,7)] : true, [utils.asGridCoord(5,7)] : true, [utils.asGridCoord(6,7)] : true, [utils.asGridCoord(7,7)] : true, [utils.asGridCoord(8,6)] : true, [utils.asGridCoord(8,5)] : true, [utils.asGridCoord(8,4)] : true, [utils.asGridCoord(8,3)] : true, [utils.asGridCoord(8,2)] : true, [utils.asGridCoord(7,1)] : true, [utils.asGridCoord(6,1)] : true, [utils.asGridCoord(5,1)] : true, [utils.asGridCoord(4,1)] : true, [utils.asGridCoord(3,1)] : true, [utils.asGridCoord(2,1)] : true, }, cutsceneSpaces: { [utils.asGridCoord(1,4)]: [ { events: [ { type: "changeMap", map: "DemoRoom" } ] } ], } }, Bedroom: { lowerSrc: "/images/maps/map-room-bedroom.png", // upperSrc: "/images/maps/room-builder.png", upperSrc: "", gameObjects: { hero: new Person({ isPlayerControlled: true, x: utils.withGrid(1), y: utils.withGrid(4), }), }, walls: { // "16,16": true [utils.asGridCoord(1,2)] : true, [utils.asGridCoord(1,3)] : true, [utils.asGridCoord(0,4)] : true, [utils.asGridCoord(1,5)] : true, [utils.asGridCoord(1,6)] : true, [utils.asGridCoord(1,7)] : true, [utils.asGridCoord(1,8)] : true, [utils.asGridCoord(2,9)] : true, [utils.asGridCoord(3,9)] : true, [utils.asGridCoord(4,9)] : true, [utils.asGridCoord(5,9)] : true, [utils.asGridCoord(6,9)] : true, [utils.asGridCoord(7,9)] : true, [utils.asGridCoord(8,8)] : true, [utils.asGridCoord(8,7)] : true, [utils.asGridCoord(8,6)] : true, [utils.asGridCoord(8,5)] : true, [utils.asGridCoord(8,4)] : true, [utils.asGridCoord(8,3)] : true, [utils.asGridCoord(8,2)] : true, [utils.asGridCoord(7,1)] : true, [utils.asGridCoord(6,1)] : true, [utils.asGridCoord(5,1)] : true, [utils.asGridCoord(4,1)] : true, [utils.asGridCoord(3,1)] : true, [utils.asGridCoord(2,1)] : true, }, cutsceneSpaces: { [utils.asGridCoord(1,4)]: [ { events: [ { type: "changeMap", map: "DemoRoom" } ] } ], } }, Bathroom: { lowerSrc: "/images/maps/map-room-bathroom.png", // upperSrc: "/images/maps/room-builder.png", upperSrc: "", gameObjects: { hero: new Person({ isPlayerControlled: true, x: utils.withGrid(3), y: utils.withGrid(1), }), }, walls: { // "16,16": true [utils.asGridCoord(0,2)] : true, [utils.asGridCoord(0,3)] : true, [utils.asGridCoord(0,4)] : true, [utils.asGridCoord(0,5)] : true, [utils.asGridCoord(0,6)] : true, [utils.asGridCoord(1,7)] : true, [utils.asGridCoord(2,7)] : true, [utils.asGridCoord(3,7)] : true, [utils.asGridCoord(4,7)] : true, [utils.asGridCoord(5,6)] : true, [utils.asGridCoord(5,5)] : true, [utils.asGridCoord(5,4)] : true, [utils.asGridCoord(5,3)] : true, [utils.asGridCoord(5,2)] : true, [utils.asGridCoord(4,1)] : true, [utils.asGridCoord(3,0)] : true, [utils.asGridCoord(2,1)] : true, [utils.asGridCoord(1,1)] : true, }, cutsceneSpaces: { [utils.asGridCoord(3,1)]: [ { events: [ { type: "changeMap", map: "DemoRoom" } ] } ], } }, Livingroom: { lowerSrc: "/images/maps/map-room-livingroom.png", // upperSrc: "/images/maps/room-builder.png", upperSrc: "", gameObjects: { hero: new Person({ isPlayerControlled: true, x: utils.withGrid(11), y: utils.withGrid(4), }), }, walls: { // "16,16": true [utils.asGridCoord(0,2)] : true, [utils.asGridCoord(0,3)] : true, [utils.asGridCoord(0,4)] : true, [utils.asGridCoord(0,5)] : true, [utils.asGridCoord(0,6)] : true, [utils.asGridCoord(0,7)] : true, [utils.asGridCoord(1,8)] : true, [utils.asGridCoord(2,8)] : true, [utils.asGridCoord(3,8)] : true, [utils.asGridCoord(4,8)] : true, [utils.asGridCoord(5,8)] : true, [utils.asGridCoord(6,8)] : true, [utils.asGridCoord(7,8)] : true, [utils.asGridCoord(8,8)] : true, [utils.asGridCoord(9,8)] : true, [utils.asGridCoord(10,8)] : true, [utils.asGridCoord(11,7)] : true, [utils.asGridCoord(11,6)] : true, [utils.asGridCoord(11,5)] : true, [utils.asGridCoord(12,4)] : true, [utils.asGridCoord(11,3)] : true, [utils.asGridCoord(11,2)] : true, [utils.asGridCoord(10,1)] : true, [utils.asGridCoord(9,1)] : true, [utils.asGridCoord(8,1)] : true, [utils.asGridCoord(7,1)] : true, [utils.asGridCoord(6,1)] : true, [utils.asGridCoord(5,1)] : true, [utils.asGridCoord(4,1)] : true, [utils.asGridCoord(3,1)] : true, [utils.asGridCoord(2,1)] : true, [utils.asGridCoord(1,1)] : true, }, cutsceneSpaces: { [utils.asGridCoord(11,4)]: [ { events: [ { type: "changeMap", map: "DemoRoom" } ] } ], } }, Office: { lowerSrc: "/images/maps/map-room-office.png", // upperSrc: "/images/maps/room-builder.png", upperSrc: "", gameObjects: { hero: new Person({ isPlayerControlled: true, x: utils.withGrid(8), y: utils.withGrid(4), }), }, walls: { // "16,16": true [utils.asGridCoord(0,2)] : true, [utils.asGridCoord(0,3)] : true, [utils.asGridCoord(0,4)] : true, [utils.asGridCoord(0,5)] : true, [utils.asGridCoord(0,6)] : true, [utils.asGridCoord(1,7)] : true, [utils.asGridCoord(2,7)] : true, [utils.asGridCoord(3,7)] : true, [utils.asGridCoord(4,7)] : true, [utils.asGridCoord(5,7)] : true, [utils.asGridCoord(6,7)] : true, [utils.asGridCoord(7,7)] : true, [utils.asGridCoord(8,6)] : true, [utils.asGridCoord(8,5)] : true, [utils.asGridCoord(9,4)] : true, [utils.asGridCoord(8,3)] : true, [utils.asGridCoord(8,2)] : true, [utils.asGridCoord(7,1)] : true, [utils.asGridCoord(6,1)] : true, [utils.asGridCoord(5,1)] : true, [utils.asGridCoord(4,1)] : true, [utils.asGridCoord(3,1)] : true, [utils.asGridCoord(2,1)] : true, [utils.asGridCoord(1,1)] : true, }, cutsceneSpaces: { [utils.asGridCoord(8,4)]: [ { events: [ { type: "changeMap", map: "DemoRoom" } ] } ], } }, }