feat: add ants with stomp-crush and collision heart damage

This commit is contained in:
OpenClaw Engineer 2026-03-03 20:40:41 -06:00
parent 5de53553ca
commit 85e6d8290f

View File

@ -25,6 +25,13 @@ const state = {
stepCarry: 0, stepCarry: 0,
cameraX: 0, cameraX: 0,
hearts: 3, hearts: 3,
hitCooldown: 0,
ants: [
{ x: 1000, y: groundY - 20, width: 22, height: 20, vx: -65, alive: true },
{ x: 1750, y: groundY - 20, width: 22, height: 20, vx: -70, alive: true },
{ x: 2600, y: groundY - 20, width: 22, height: 20, vx: -80, alive: true },
{ x: 3400, y: groundY - 20, width: 22, height: 20, vx: -75, alive: true }
],
player: { player: {
x: 160, x: 160,
y: 0, y: 0,
@ -79,6 +86,22 @@ function drawTRex(p) {
ctx.fillRect(sx + p.width - 24, p.y + p.height - 8, 14, 8); ctx.fillRect(sx + p.width - 24, p.y + p.height - 8, 14, 8);
} }
function drawAnts() {
ctx.fillStyle = '#5a1e0d';
for (const ant of state.ants) {
if (!ant.alive) continue;
const sx = ant.x - state.cameraX;
if (sx + ant.width < 0 || sx > canvas.width) continue;
ctx.fillRect(sx, ant.y, ant.width, ant.height);
ctx.fillRect(sx - 4, ant.y + 6, 4, 4);
ctx.fillRect(sx + ant.width, ant.y + 6, 4, 4);
}
}
function intersects(a, b) {
return a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y;
}
function updateHeartsUI() { function updateHeartsUI() {
heartsEl.textContent = '❤'.repeat(state.hearts) + '🖤'.repeat(Math.max(0, 3 - state.hearts)); heartsEl.textContent = '❤'.repeat(state.hearts) + '🖤'.repeat(Math.max(0, 3 - state.hearts));
} }
@ -89,11 +112,44 @@ function kill(reason) {
state.deadReason = reason; state.deadReason = reason;
} }
function applyHit(reason) {
if (state.hitCooldown > 0 || state.dead) return;
state.hearts -= 1;
state.hitCooldown = 1.0;
if (state.hearts <= 0) {
kill(reason);
}
}
function isOverWater(player) { function isOverWater(player) {
const centerX = player.x + player.width / 2; const centerX = player.x + player.width / 2;
return waterGaps.some((g) => centerX >= g.x && centerX <= g.x + g.width); return waterGaps.some((g) => centerX >= g.x && centerX <= g.x + g.width);
} }
function updateAnts(dt) {
const p = state.player;
const prevBottom = p.y + p.height - p.vy * dt;
for (const ant of state.ants) {
if (!ant.alive) continue;
ant.x += ant.vx * dt;
if (ant.x < 200) ant.vx = Math.abs(ant.vx);
if (ant.x > worldWidth - 200) ant.vx = -Math.abs(ant.vx);
if (intersects(p, ant)) {
const playerBottom = p.y + p.height;
const stomped = p.vy > 0 && prevBottom <= ant.y + 4 && playerBottom >= ant.y;
if (stomped) {
ant.alive = false;
p.vy = -380;
} else {
applyHit('A swarm of ants got you.');
}
}
}
}
function updatePlayer(dt) { function updatePlayer(dt) {
const p = state.player; const p = state.player;
let move = 0; let move = 0;
@ -153,10 +209,15 @@ function tick(ts) {
const dt = Math.min((ts - state.lastTs) / 1000, 0.05); const dt = Math.min((ts - state.lastTs) / 1000, 0.05);
state.lastTs = ts; state.lastTs = ts;
if (state.running) updatePlayer(dt); if (state.running) {
state.hitCooldown = Math.max(0, state.hitCooldown - dt);
updatePlayer(dt);
updateAnts(dt);
}
ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBackground(); drawBackground();
drawAnts();
drawTRex(state.player); drawTRex(state.player);
drawDeathText(); drawDeathText();