Skip to content

Commit

Permalink
Collision detection + npc movement
Browse files Browse the repository at this point in the history
  • Loading branch information
Chasmiccoder committed Feb 2, 2022
1 parent 325b3cd commit 4bfee38
Show file tree
Hide file tree
Showing 22 changed files with 290 additions and 44 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.vs/
.vscode/
3 changes: 0 additions & 3 deletions .vscode/settings.json

This file was deleted.

Binary file added createdTiles/Frame 1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added createdTiles/Frame 10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added createdTiles/Frame 11.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added createdTiles/Frame 2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added createdTiles/Frame 3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added createdTiles/Frame 4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added createdTiles/Frame 5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added createdTiles/Frame 6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added createdTiles/Frame 9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added createdTiles/Frame.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/myTile01.aseprite
Binary file not shown.
Binary file added images/myTileMap01.aseprite
Binary file not shown.
Binary file added images/myTileMap02.aseprite
Binary file not shown.
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<script src="./js/Person.js"></script>
<script src="./js/Sprite.js"></script>
<script src="./js/OverworldMap.js"></script>
<script src="./js/OverworldEvent.js"></script>
<script src="./js/init.js"></script>
</body>
</html>
43 changes: 43 additions & 0 deletions js/GameObject.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,58 @@
class GameObject {
constructor(config) {
this.id = null;
this.isMounted = false;
this.x = config.x || 0;
this.y = config.y || 0;
this.direction = config.direction || "down";
this.sprite = new Sprite({
gameObject: this,
src: config.src || "./images/hero.png",
});

this.behaviorLoop = config.behaviorLoop || [];
this.behaviorLoopIndex = 0;
}

mount(map) {
console.log("Mounting");
this.isMounted = true;
map.addWall(this.x, this.y);

// if we have a behavior, kick it off after a short delay
setTimeout(() => {
this.doBehaviorEvent(map);
}, 10);
}

update() {
}

async doBehaviorEvent(map) {

// maybe the game object has no current behaviour or there's a global event (like a cutscene)
if(map.isCutscenePlaying || this.behaviorLoop.length === 0) {
return;
}


// setting up the event with the relevant info
let eventConfig = this.behaviorLoop[this.behaviorLoopIndex];
eventConfig.who = this.id;

// create an event instance out of our next event config
const eventHandler = new OverworldEvent({map, event: eventConfig});
await eventHandler.init(); // wait until the event gets revolved

// setting the next event to fire
this.behaviorLoopIndex += 1;
if(this.behaviorLoopIndex === this.behaviorLoop.length) {
this.behaviorLoopIndex = 0;
}

// fire the next behavior
this.doBehaviorEvent(map);


}

Expand Down
25 changes: 21 additions & 4 deletions js/Overworld.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,23 @@ class Overworld {

init() {
this.map = new OverworldMap(window.OverworldMaps.DemoRoom);
this.map.mountObjects();

this.directionInput = new DirectionInput();
this.directionInput.init();

this.startGameLoop();
// game loop fires at 60 fps


this.map.startCutscene([
{who: "hero", type: "walk", direction: "down"},
{who: "hero", type: "walk", direction: "down"},
{who: "npcA", type: "walk", direction: "left"},
{who: "npcA", type: "walk", direction: "left"},
{who: "npcA", type: "stand", direction: "up", time: 800},

])

}

Expand All @@ -27,7 +39,9 @@ class Overworld {
// update all objects
Object.values( this.map.gameObjects ).forEach( object => {
object.update({
arrow: this.directionInput.direction
arrow: this.directionInput.direction,
map: this.map,

})
})

Expand All @@ -36,7 +50,10 @@ class Overworld {

this.map.drawLowerImage(this.context, cameraPerson);

Object.values( this.map.gameObjects ).forEach( object => {
// that sorting is done to render objects that are lower later, so that when someone walks under another person then they first person gets rendered on top
Object.values( this.map.gameObjects ).sort((a,b) => {
return a.y - b.y;
}).forEach( object => {
object.sprite.draw(this.context, cameraPerson);
})

Expand All @@ -47,7 +64,7 @@ class Overworld {
step();
});
}
console.log(performance.now());
// console.log(performance.now());
step();
}
}
56 changes: 56 additions & 0 deletions js/OverworldEvent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
class OverworldEvent {
constructor({map, event}) {
this.map = map;
this.event = event;
}

init() {
return new Promise(resolve => {
this[this.event.type](resolve)
})
}

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
})

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 // if true, then the game object retries its movement after an interrupt (get an npc to start walking again after collision with the player)
})

// Set up a handler to complete when the correct person is done walking.
// Then resolve the event
const completeHandler = (e) => {
if(e.detail.whoId === this.event.who) {
document.removeEventListener("PersonWalkingComplete", completeHandler);
resolve();
}
}
document.addEventListener("PersonWalkingComplete", completeHandler);
}
}
92 changes: 78 additions & 14 deletions js/OverworldMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ class OverworldMap {

this.lowerImage.src = config.lowerSrc; // floor
this.upperImage.src = config.upperSrc; // what is rendered above the floor (above the player) like tree tops

this.isCutscenePlaying = true;

}

drawLowerImage(context, cameraPerson) {
Expand All @@ -18,6 +21,52 @@ class OverworldMap {
context.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;

// TODO: determine if this object should be mounted or not
object.mount(this);
})
}

async startCutscene(events) {
this.isCutscenePlaying = true;

// start a loop of async events
// await each event
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;
}

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 = {
Expand All @@ -32,19 +81,37 @@ window.OverworldMaps = {
y: utils.withGrid(6)
}),

npc1: new Person({
npcA: new Person({
x: utils.withGrid(7),
y: utils.withGrid(9),
src: "./images/npc1.png"
src: "./images/npc1.png",
behaviorLoop: [
{type: "stand", direction: "left", time: 800},
{type: "stand", direction: "up", time: 800},
{type: "stand", direction: "right", time: 1200},
{type: "stand", direction: "up", time: 300}

]
}),

// walls: {
// [utils.asGridCoord(7,6)]: true,
// [utils.asGridCoord(8,6)]: true,
// [utils.asGridCoord(7,7)]: true,
// [utils.asGridCoord(8,7)]: true,

// }
npcB: new Person({
x: utils.withGrid(3),
y: utils.withGrid(7),
src: "./images/npc2.png",
behaviorLoop: [
{type: "walk", direction: "left"},
{type: "stand", direction: "left", time: 800},
{type: "walk", direction: "up"},
{type: "walk", direction: "right"},
{type: "walk", direction: "down"}
]
}),
},
walls: {
[utils.asGridCoord(7,6)]: true,
[utils.asGridCoord(8,6)]: true,
[utils.asGridCoord(7,7)]: true,
[utils.asGridCoord(8,7)]: true,
}
},

Expand All @@ -57,20 +124,17 @@ window.OverworldMaps = {
y: 5,
}),

npc1: new GameObject({
npcA: new GameObject({
x: 9,
y: 6,
src: "./images/npc1.png"
}),

npc2: new GameObject({
npcB: new GameObject({
x: 10,
y: 8,
src: "./images/npc2.png"
})
}
},

}


Loading

0 comments on commit 4bfee38

Please sign in to comment.