Skip to content

Instantly share code, notes, and snippets.

@jonurry
Last active March 28, 2018 13:52
Show Gist options
  • Save jonurry/f118b887c19e0b96f7396c923d97b480 to your computer and use it in GitHub Desktop.
Save jonurry/f118b887c19e0b96f7396c923d97b480 to your computer and use it in GitHub Desktop.
16.3 A Monster (Eloquent JavaScript Solutions)
<link rel="stylesheet" href="css/game.css">
<style>.monster { background: purple }</style>
<body>
<script>
// Complete the constructor, update, and collide methods
class Monster {
constructor(pos, speed, chase) {
this.pos = pos;
this.speed = speed;
this.chase = chase;
}
get type() { return "monster"; }
static create(pos, ch) {
if (ch == 'm') {
// monster that moves back and forth
return new Monster(pos.plus(new Vec(0, -1)), new Vec(3, 0), false);
} else { // 'M'
// monster that chases player
return new Monster(pos.plus(new Vec(0, -1)), new Vec(3, 0), true);
}
}
update(time, state) {
let newPos;
if (this.chase) {
if (state.player.pos.x < this.pos.x) {
this.speed = new Vec(-3, 0);
} else {
this.speed = new Vec(3, 0);
}
}
newPos = this.pos.plus(this.speed.times(time));
if (!state.level.touches(newPos, this.size, "wall")) {
return new Monster(newPos, this.speed, this.chase);
} else {
return new Monster(this.pos, this.speed.times(-1), this.chase);
}
}
collide(state) {
let player = state.player;
let monster = this;
if (monster.pos.y - player.pos.y > 1) {
let filtered = state.actors.filter(a => a != this);
return new State(state.level, filtered, state.status);
} else {
return new State(state.level, state.actors, 'lost');
}
}
}
Monster.prototype.size = new Vec(1.2, 2);
levelChars["m"] = Monster;
levelChars["M"] = Monster;
runLevel(new Level(`
..................................
.################################.
.#..............................#.
.#..............................#.
.#..............................#.
.#...........................o..#.
.#..@...........................#.
.##########..............########.
..........#..o..o..o..o..#........
..........#..m........M..#........
..........################........
..................................
`), DOMDisplay);
</script>
</body>
@jonurry
Copy link
Author

jonurry commented Mar 28, 2018

16.3 A Monster

It is traditional for platform games to have enemies that you can jump on top of to defeat. This exercise asks you to add such an actor type to the game.

We’ll call it a monster. Monsters move only horizontally. You can make them move in the direction of the player, or bounce back and forth like horizontal lava, or have any movement pattern you want. The class doesn’t have to handle falling, but it should make sure the monster doesn’t walk through walls.

When a monster touches the player, the effect depends on whether the player is jumping on top of them or not. You can approximate this by checking whether the player’s bottom is near the monster’s top. If this is the case, the monster disappears. If not, the game is lost.

@jonurry
Copy link
Author

jonurry commented Mar 28, 2018

Hints

If you want to implement a type of motion that is stateful, such as bouncing, make sure you store the necessary state in the actor object—include it as a constructor argument and add it as a property.

Remember that update returns a new object, rather than changing the old one.

When handling collision, find the player in state.actors and compare its position to the monster’s position. To get the bottom of the player, you have to add its vertical size to its vertical position. The creation of an updated state will resemble either Coin’s collide method (removing the actor) or Lava’s (changing the status to "lost"), depending on the player position.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment