chore: scaffold Dino Land with canvas base game loop

This commit is contained in:
OpenClaw Engineer 2026-03-03 20:39:07 -06:00
commit 93958c02a4
3 changed files with 110 additions and 0 deletions

34
index.php Normal file
View File

@ -0,0 +1,34 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Dino Land</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div id="hud">
<div id="hearts"></div>
<div id="score">Score: 0</div>
</div>
<canvas id="game" width="960" height="540" aria-label="Dino Land game canvas"></canvas>
<div id="deathScreen" class="hidden">
<div class="panel">
<h1>TRex Down!</h1>
<p id="finalScore"></p>
<h2>Top 10</h2>
<ol id="leaderboard"></ol>
<form id="saveScoreForm" class="hidden">
<label for="playerName">You made top 10! Enter name:</label>
<input id="playerName" maxlength="20" required />
<button type="submit">Save Score</button>
</form>
<button id="restartBtn">Play Again</button>
</div>
</div>
<script src="js/game.js"></script>
</body>
</html>

28
js/game.js Normal file
View File

@ -0,0 +1,28 @@
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const state = {
running: true,
lastTs: performance.now()
};
function drawBackground() {
ctx.fillStyle = '#88d34f';
ctx.fillRect(0, 420, canvas.width, 120);
}
function tick(ts) {
if (!state.running) return;
const dt = Math.min((ts - state.lastTs) / 1000, 0.05);
state.lastTs = ts;
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBackground();
requestAnimationFrame(tick);
}
requestAnimationFrame((ts) => {
state.lastTs = ts;
requestAnimationFrame(tick);
});

48
styles.css Normal file
View File

@ -0,0 +1,48 @@
* { box-sizing: border-box; }
body {
margin: 0;
font-family: Arial, sans-serif;
background: linear-gradient(#6fd3ff, #d7f7ff);
color: #102026;
}
#hud {
position: fixed;
top: 12px;
left: 12px;
right: 12px;
display: flex;
justify-content: space-between;
font-size: 24px;
font-weight: 700;
pointer-events: none;
z-index: 2;
}
#game {
display: block;
margin: 0 auto;
width: min(100vw, 1200px);
height: auto;
border: 2px solid #1b3a47;
background: #b5ecff;
}
#deathScreen {
position: fixed;
inset: 0;
background: rgba(0,0,0,0.65);
display: grid;
place-items: center;
z-index: 4;
}
.panel {
background: #fff;
border-radius: 12px;
padding: 20px;
width: min(92vw, 460px);
}
.hidden { display: none !important; }
button, input {
font-size: 16px;
padding: 8px 10px;
margin-top: 8px;
}
ol { padding-left: 22px; }