added behaviors and cutscene logic like here: https://www.youtube.com/watch?v=e144CXGy2mc&list=PLcjhmZ8oLT0r9dSiIK6RB_PuBWlG1KSq_&index=9
This commit is contained in:
		
							parent
							
								
									6361a6c539
								
							
						
					
					
						commit
						d4a7de346d
					
				| @ -1,5 +1,6 @@ | |||||||
| class GameObject { | class GameObject { | ||||||
| 	constructor(config) { | 	constructor(config) { | ||||||
|  | 		this.id = null; | ||||||
| 		this.isMounted = false; | 		this.isMounted = false; | ||||||
| 		this.x = config.x || 0; | 		this.x = config.x || 0; | ||||||
| 		this.y = config.y || 0; | 		this.y = config.y || 0; | ||||||
| @ -9,14 +10,42 @@ class GameObject { | |||||||
| 			src: config.src || "/images/characters/people/hero.png", | 			src: config.src || "/images/characters/people/hero.png", | ||||||
| 
 | 
 | ||||||
| 		}); | 		}); | ||||||
|  | 
 | ||||||
|  | 		this.behaviorLoop = config.behaviorLoop || []; | ||||||
|  | 		this.behaviorLoopIndex = 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	mount(map) { | 	mount(map) { | ||||||
| 		this.isMounted = true; | 		this.isMounted = true; | ||||||
| 		map.addWall(this.x, this.y); | 		map.addWall(this.x, this.y); | ||||||
|  | 
 | ||||||
|  | 		// when behavior kick off after delay
 | ||||||
|  | 		setTimeout(() => { | ||||||
|  | 			this.doBehaviorEvent(map); | ||||||
|  | 		}, 10); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	update() { | 	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); | ||||||
|  | 	} | ||||||
| } | } | ||||||
							
								
								
									
										11
									
								
								Overworld.js
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								Overworld.js
									
									
									
									
									
								
							| @ -22,7 +22,9 @@ class Overworld { | |||||||
| 
 | 
 | ||||||
| 			this.map.drawLowerImage(this.ctx, cameraPerson); | 			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); | 				object.sprite.draw(this.ctx, cameraPerson); | ||||||
| 			}) | 			}) | ||||||
| 
 | 
 | ||||||
| @ -43,5 +45,12 @@ class Overworld { | |||||||
| 		this.directionInput.init(); | 		this.directionInput.init(); | ||||||
| 
 | 
 | ||||||
| 		this.startGameLoop(); | 		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" }, | ||||||
|  | 		]) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
							
								
								
									
										54
									
								
								OverworldEvent.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								OverworldEvent.js
									
									
									
									
									
										Normal file
									
								
							| @ -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) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -8,6 +8,8 @@ class OverworldMap { | |||||||
| 
 | 
 | ||||||
| 		this.upperImage = new Image(); | 		this.upperImage = new Image(); | ||||||
| 		this.upperImage.src = config.upperSrc; | 		this.upperImage.src = config.upperSrc; | ||||||
|  | 
 | ||||||
|  | 		this.isCutscenePlaying = false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	drawLowerImage(ctx, cameraPerson) { | 	drawLowerImage(ctx, cameraPerson) { | ||||||
| @ -24,13 +26,29 @@ class OverworldMap { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	mountObjects() { | 	mountObjects() { | ||||||
| 		Object.values(this.gameObjects).forEach(o => { | 		Object.keys(this.gameObjects).forEach(key => { | ||||||
| 			// todoL determine if this object should actually mount
 | 			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) { | 	addWall(x, y) { | ||||||
| 		this.walls[`${x},${y}`] = true; | 		this.walls[`${x},${y}`] = true; | ||||||
| 	} | 	} | ||||||
| @ -56,10 +74,27 @@ window.OverworldMaps = { | |||||||
| 				x: utils.withGrid(8), | 				x: utils.withGrid(8), | ||||||
| 				y: utils.withGrid(2), | 				y: utils.withGrid(2), | ||||||
| 			}), | 			}), | ||||||
| 			// npc1: new Person({
 | 			npc1: new Person({ | ||||||
| 			// 	x: utils.withGrid(6),
 | 				x: utils.withGrid(6), | ||||||
| 			// 	y: utils.withGrid(7),
 | 				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: { | 		walls: { | ||||||
| 			// "16,16": true
 | 			// "16,16": true
 | ||||||
|  | |||||||
							
								
								
									
										20
									
								
								Person.js
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								Person.js
									
									
									
									
									
								
							| @ -21,7 +21,7 @@ class Person extends GameObject { | |||||||
| 			// more cases for starting to walk come here
 | 			// more cases for starting to walk come here
 | ||||||
| 
 | 
 | ||||||
| 			// case: keyboard ready and arrow pressed
 | 			// case: keyboard ready and arrow pressed
 | ||||||
| 			if (this.isPlayerControlled && state.arrow) { | 			if (state.map.isCutscenePlaying == false && this.isPlayerControlled && state.arrow) { | ||||||
| 				this.startBehavior(state, { | 				this.startBehavior(state, { | ||||||
| 					type: "walk", | 					type: "walk", | ||||||
| 					direction: state.arrow | 					direction: state.arrow | ||||||
| @ -37,12 +37,24 @@ class Person extends GameObject { | |||||||
| 		if (behavior.type === "walk") { | 		if (behavior.type === "walk") { | ||||||
| 			// stop if space is not free
 | 			// stop if space is not free
 | ||||||
| 			if (state.map.isSpaceTaken(this.x, this.y, this.direction)) { | 			if (state.map.isSpaceTaken(this.x, this.y, this.direction)) { | ||||||
|  | 				behavior.retry && setTimeout(() => { | ||||||
|  | 					this.startBehavior(state, behavior); | ||||||
|  | 				}, 10); | ||||||
| 				return; | 				return; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			// ready to walk
 | 			// ready to walk
 | ||||||
| 			state.map.moveWall(this.x, this.y, this.direction); | 			state.map.moveWall(this.x, this.y, this.direction); | ||||||
| 			this.movementProgressRemaining = 16; | 			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]; | 		const [property, change] = this.directionUpdate[this.direction]; | ||||||
| 		this[property] += change; | 		this[property] += change; | ||||||
| 		this.movementProgressRemaining -= 1; | 		this.movementProgressRemaining -= 1; | ||||||
|  | 
 | ||||||
|  | 		if (this.movementProgressRemaining === 0) { | ||||||
|  | 			utils.emitEvent("PersonWalkingComplete", { | ||||||
|  | 				whoId: this.id | ||||||
|  | 			}) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	updateSprite() { | 	updateSprite() { | ||||||
|  | |||||||
| @ -18,6 +18,7 @@ | |||||||
| 	<script src="/Person.js"></script> | 	<script src="/Person.js"></script> | ||||||
| 	<script src="/Sprite.js"></script> | 	<script src="/Sprite.js"></script> | ||||||
| 	<script src="/OverworldMap.js"></script> | 	<script src="/OverworldMap.js"></script> | ||||||
|  | 	<script src="/OverworldEvent.js"></script> | ||||||
| 	<script src="/init.js"></script> | 	<script src="/init.js"></script> | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user