Tune steel wall density and use health state

main
darcy 4 weeks ago
parent a258454ff2
commit f9496cd628

@ -23,8 +23,8 @@
<strong id="score">0</strong> <strong id="score">0</strong>
</div> </div>
<div class="hud-item"> <div class="hud-item">
<span>Lives</span> <span>Health</span>
<strong id="lives">3</strong> <strong id="lives">100%</strong>
</div> </div>
<div class="hud-item"> <div class="hud-item">
<span>Enemies</span> <span>Enemies</span>

@ -34,7 +34,7 @@
hud.style.cssText = hud.style.cssText =
"width:800px;max-width:100%;margin:8px auto;color:#e8eadf;font:16px/1.4 system-ui,sans-serif;display:flex;gap:18px;flex-wrap:wrap;"; "width:800px;max-width:100%;margin:8px auto;color:#e8eadf;font:16px/1.4 system-ui,sans-serif;display:flex;gap:18px;flex-wrap:wrap;";
hud.innerHTML = hud.innerHTML =
'Score: <span id="score">0</span> Lives: <span id="lives">3</span> Enemies: <span id="enemies">0</span>'; 'Score: <span id="score">0</span> Health: <span id="lives">100%</span> Enemies: <span id="enemies">0</span>';
canvas.parentNode.insertBefore(hud, canvas.nextSibling); canvas.parentNode.insertBefore(hud, canvas.nextSibling);
} }
@ -80,6 +80,8 @@
const FIRE_COOLDOWN = 0.34; const FIRE_COOLDOWN = 0.34;
const ENEMY_FIRE_COOLDOWN = 1.35; const ENEMY_FIRE_COOLDOWN = 1.35;
const BRICK_SIZE = 20; const BRICK_SIZE = 20;
const PLAYER_MAX_HEALTH = 100;
const PLAYER_HIT_DAMAGE = 34;
const DIRS = { const DIRS = {
up: { x: 0, y: -1 }, up: { x: 0, y: -1 },
down: { x: 0, y: 1 }, down: { x: 0, y: 1 },
@ -90,7 +92,7 @@
const keys = new Set(); const keys = new Set();
let state = "menu"; let state = "menu";
let score = 0; let score = 0;
let lives = 3; let health = PLAYER_MAX_HEALTH;
let player; let player;
let enemies = []; let enemies = [];
let bullets = []; let bullets = [];
@ -147,14 +149,15 @@
// Generate a handful of vertical/horizontal steel segments at random tile // Generate a handful of vertical/horizontal steel segments at random tile
// positions, skipping any that overlap a spawn keep-out zone. // positions, skipping any that overlap a spawn keep-out zone.
const pieces = []; const pieces = [];
const count = 3 + Math.floor(Math.random() * 3); // 3-5 steel walls const segmentCount = 5 + Math.floor(Math.random() * 3); // 5-7 steel wall segments
const cols = Math.floor(WIDTH / TILE); const cols = Math.floor(WIDTH / TILE);
const rows = Math.floor(HEIGHT / TILE); const rows = Math.floor(HEIGHT / TILE);
let placedSegments = 0;
let attempts = 0; let attempts = 0;
while (pieces.length < count && attempts < count * 20) { while (placedSegments < segmentCount && attempts < segmentCount * 30) {
attempts += 1; attempts += 1;
const vertical = Math.random() < 0.5; const vertical = Math.random() < 0.5;
const length = (2 + Math.floor(Math.random() * 2)) * TILE; // 2-3 tiles long const length = (2 + Math.floor(Math.random() * 3)) * TILE; // 2-4 tiles long
const x = Math.floor(Math.random() * cols) * TILE; const x = Math.floor(Math.random() * cols) * TILE;
const y = Math.floor(Math.random() * rows) * TILE; const y = Math.floor(Math.random() * rows) * TILE;
const w = vertical ? TILE : length; const w = vertical ? TILE : length;
@ -165,6 +168,7 @@
if (occupied.some((area) => intersects(candidate, area))) continue; if (occupied.some((area) => intersects(candidate, area))) continue;
pieces.push(...steelWall(x, y, w, h)); pieces.push(...steelWall(x, y, w, h));
occupied.push(candidate); occupied.push(candidate);
placedSegments += 1;
} }
return pieces; return pieces;
} }
@ -213,7 +217,7 @@
function resetGame() { function resetGame() {
score = 0; score = 0;
lives = 3; health = PLAYER_MAX_HEALTH;
bullets = []; bullets = [];
particles = []; particles = [];
regenerateWalls(); regenerateWalls();
@ -278,7 +282,7 @@
function updateHud() { function updateHud() {
scoreEl.textContent = score; scoreEl.textContent = score;
livesEl.textContent = lives; livesEl.textContent = `${health}%`;
enemiesEl.textContent = enemies.filter((enemy) => enemy.alive).length; enemiesEl.textContent = enemies.filter((enemy) => enemy.alive).length;
} }
@ -445,9 +449,9 @@
continue; continue;
} }
} else if (intersects(bullet, player)) { } else if (intersects(bullet, player)) {
lives -= 1; health = Math.max(0, health - PLAYER_HIT_DAMAGE);
spark(player.x + player.w / 2, player.y + player.h / 2, "#77b255"); spark(player.x + player.w / 2, player.y + player.h / 2, "#77b255");
if (lives <= 0) { if (health <= 0) {
player.alive = false; player.alive = false;
setState("gameOver"); setState("gameOver");
} else { } else {
@ -551,13 +555,13 @@
let glowColor, glowBlur, outerColor, innerColor, coreColor; let glowColor, glowBlur, outerColor, innerColor, coreColor;
if (isPlayer) { if (isPlayer) {
if (lives >= 3) { if (health > 66) {
glowColor = "rgba(132, 238, 212, 0.75)"; glowColor = "rgba(132, 238, 212, 0.75)";
glowBlur = 12; glowBlur = 12;
outerColor = "#e8fff7"; outerColor = "#e8fff7";
innerColor = "#102822"; innerColor = "#102822";
coreColor = entity.color; coreColor = entity.color;
} else if (lives === 2) { } else if (health > 33) {
glowColor = "rgba(240, 182, 70, 0.45)"; glowColor = "rgba(240, 182, 70, 0.45)";
glowBlur = 8; glowBlur = 8;
outerColor = "#c8c0a0"; outerColor = "#c8c0a0";
@ -585,7 +589,7 @@
ctx.fillStyle = "rgba(255,255,255,0.18)"; ctx.fillStyle = "rgba(255,255,255,0.18)";
ctx.fillRect(-7, -8, 14, 16); ctx.fillRect(-7, -8, 14, 16);
if (isPlayer && lives === 2) { if (isPlayer && health <= 66 && health > 33) {
ctx.strokeStyle = "rgba(30, 20, 10, 0.55)"; ctx.strokeStyle = "rgba(30, 20, 10, 0.55)";
ctx.lineWidth = 2; ctx.lineWidth = 2;
ctx.beginPath(); ctx.beginPath();
@ -601,7 +605,7 @@
ctx.fillRect(5, -4, 4, 4); ctx.fillRect(5, -4, 4, 4);
} }
if (isPlayer && lives <= 1) { if (isPlayer && health <= 33) {
ctx.strokeStyle = "rgba(80, 10, 10, 0.6)"; ctx.strokeStyle = "rgba(80, 10, 10, 0.6)";
ctx.lineWidth = 2; ctx.lineWidth = 2;
ctx.beginPath(); ctx.beginPath();
@ -623,7 +627,7 @@
} }
ctx.fillStyle = isPlayer ? "#f4fff8" : "#1b0805"; ctx.fillStyle = isPlayer ? "#f4fff8" : "#1b0805";
if (isPlayer && lives <= 1 && Math.floor(Date.now() / 300) % 2 === 0) { if (isPlayer && health <= 33 && Math.floor(Date.now() / 300) % 2 === 0) {
ctx.globalAlpha = 0.3; ctx.globalAlpha = 0.3;
} }
ctx.fillRect(-4, -26, 8, 20); ctx.fillRect(-4, -26, 8, 20);
@ -633,7 +637,7 @@
ctx.fillRect(-10, -2, 20, 4); ctx.fillRect(-10, -2, 20, 4);
ctx.fillStyle = "#79e5c9"; ctx.fillStyle = "#79e5c9";
ctx.fillRect(-5, -5, 10, 10); ctx.fillRect(-5, -5, 10, 10);
if (lives <= 1 && Math.floor(Date.now() / 300) % 2 === 0) { if (health <= 33 && Math.floor(Date.now() / 300) % 2 === 0) {
ctx.fillStyle = "rgba(212, 93, 69, 0.7)"; ctx.fillStyle = "rgba(212, 93, 69, 0.7)";
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(0, -14); ctx.moveTo(0, -14);

Loading…
Cancel
Save