<html lang="en-US">
<head>
<meta charset="utf-8" />
<title>Hamster Run</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
.absolute {
position: absolute;
}
</style>
</head>
<body>
<div id="score" class="absolute">SCORE: 0</div>
<canvas id="canvas" width="800" height="800"></canvas>
<script src="index.js"></script>
<div>
Source Code: <a href="https://github.com/jacklehamster/hamster-run">https://github.com/jacklehamster/hamster-run</a>
</div>
</body>
</html>
html: {
margin: 0;
padding: 0;
}
body {
margin: 0;
padding: 0;
overflow: hidden;
}
document.addEventListener("DOMContentLoaded", () => {
const canvas = document.querySelector("#canvas");
const ctx = canvas.getContext("2d");
const GROUND = 300;
const GRAVITY = 1;
const image = new Image();
image.src = "https://jacklehamster.github.io/hamster-run/hamster.png";
const hamster = {
x: 200,
y: 300,
dy: 0,
};
const trees = [0, 0, 0].map(() => ({
x: 800,
y: 325,
}));
function jump() {
hamster.dy = -20;
}
document.addEventListener("keydown", (e) => {
e.preventDefault();
if (gameOver) {
if (Date.now() - gameOver > 500) {
trees.forEach(tree => tree.x = 1000);
score = 0;
gameOver = false;
return;
}
} else {
if (hamster.y >= GROUND) {
jump();
}
}
});
let score = 0;
const scoreDiv = document.querySelector("#score");
let gameOver = 0;
const TREE_TOP = 170;
const skyGradient = ctx.createLinearGradient(0, 0, 0, 300);
skyGradient.addColorStop(0, "lightblue");
skyGradient.addColorStop(1, "#88aaff");
function loop() {
// Movement
if (!gameOver) {
hamster.y += hamster.dy;
hamster.dy += GRAVITY;
if (hamster.y > GROUND) {
hamster.y = GROUND;
hamster.dy = 0;
}
trees.forEach((tree) => {
tree.x -= 10;
if (tree.x < hamster.x && !tree.passed) {
if (hamster.y < TREE_TOP) {
score++;
tree.passed = true;
scoreDiv.textContent = `SCORE: ${score}`;
} else if (!gameOver) {
gameOver = Date.now();
}
}
if (tree.x < -150) {
tree.x = 800 + Math.random() * 3000;
tree.passed = false;
}
});
}
// Drawing
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = skyGradient;
ctx.fillRect(0, 0, canvas.width, 320);
ctx.fillStyle = "green";
ctx.fillRect(0, 320, canvas.width, 300);
const frame = Math.floor((Date.now() / 100) % 3);
const shake = gameOver ? 100 - 50 : 0;
ctx.drawImage(
image,
0 + frame * 512,
0,
512,
512,
hamster.x + shake * Math.random(),
hamster.y - 55 + shake * Math.random(),
100,
100
);
trees.forEach((tree) => {
ctx.drawImage(
image,
6 * 512,
0,
512,
512,
tree.x,
tree.y - TREE_TOP,
150,
200
);
});
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.