Metapod Madness is a 4-player minigame drawing inspiration from the N64 classic, Pokemon Stadium, remastered in the form of a web application. Avoid damage from the boulders being launched at your cuddly cocoon pokemon by using its only move, Harden. However, be careful about overusing Harden since it will gradually drain your HP. Compete with your friends to see whose coordination is the fittest... last one standing wins!
- JavaScript
- HTML5
- CSS3
The animate(time)
method in the GameView
class minimizes graphic rendering lag through usage of HTML5 Canvas and recursively looping the requestAnimationFrame
method until the game is complete.
Click to expand code snippet
animate(time) {
const timeDelta = time - this.lastTime;
this.game.step(timeDelta);
this.game.draw(this.ctx);
this.lastTime = time;
this.gameOver = this.game.over;
if (!this.paused) {
requestAnimationFrame(this.animate);
if (this.gameOver) {
this.paused = true;
setTimeout(() => this.end(), 1000);
};
};
};
Click to expand code snippet
bindKeyHandlers () {
const keys = this.keys;
const keyDownHandler = (e) => {
for (let i = 0; i < 4; i++) {
if (e.key == keys[i]) {
this.game.metapodsHardened[i] = true;
};
};
};
const keyUpHandler = (e) => {
for (let i = 0; i < 4; i++) {
if (e.key == keys[i]) {
this.game.metapodsHardened[i] = false;
};
};
};
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
};
Though I initially planned to utilize three.js
for this project, using diagonal lines as diminishing scale, I was able to reconfigure my Boulder
and Shadow
classes to craft the illusion of depth.
With each iteration of boulders that are added to the game, the shadows follow fixed vectors that uniformly spawn below their respective boulders, traverse diagonally toward their respective Metapods, and reach their final destination as the boulders fall to collide with the Metapods.
Click to expand code snippet
const shadowVelocities = [
[-0.62, 1.3],
[-0.28, 1.3],
[0.12, 1.3],
[0.48, 1.3],
];
The boulders spawn at various points closer to the vertical center of the canvas. They travel parallel to each other upwards, and upon reaching a fixed height, they grow in size and horizontally adjust to different points directly above their respective Metapod character models.
Click to expand code snippet
move(timeDelta) {
if (this.pos[1] < -500) {
this.width *= 1.5;
this.height *= 1.5;
this.vel = [0, 16];
switch (this.idx) {
case 0:
this.pos[0] = this.game.dimensionX * (1 / 8) - 60
break;
case 1:
this.pos[0] = this.game.dimensionX * (3 / 8) - 60
break;
case 2:
this.pos[0] = this.game.dimensionX * (5 / 8) - 60
break;
case 3:
this.pos[0] = this.game.dimensionX * (7 / 8) - 60
break;
default:
break;
};
};
super.move(timeDelta)
};
Click to expand code snippet
isCollidedWith(otherObject) {
const pos1 = this.pos;
const pos2 = otherObject.pos;
const centerDist = Math.sqrt(
Math.pow(pos1[0] - pos2[0], 2) + Math.pow(pos1[1] - pos2[1], 2)
);
const distance = (this.width / 2 + otherObject.width / 2);
return (centerDist < distance + 5 && centerDist > distance - 5);
};
An issue that I came across with using HTML5 Canvas was layering my Canvas element with the game's menu and victory screens. To solve this, I weaved a state attribute into my GameView
constructor function, initializing state accordingly: this.state = "menu";
Each state is tied to different absolutely positioned z-index planes which allow for a more holistic gaming experience.
Upon clicking "Start Game" on the menu screen, this.state = "game";
which introduces the main Canvas element displaying all the Metapods and launching boulders. Once at least 3 Metapods have fainted, this.state = "victory";
which then transitions the game into the victory screen.
Some ideas that I would love to implement in time:
- Allow users to select number of AI players with varying difficulties for additional flexibility
- Additional objects being launched at the Metapods, such as berries which could provide healing
- Single-player mode with high score rankings
If you have any feedback for patches or improvement, please feel free to share!