|
|
|
|
@ -79,6 +79,7 @@
|
|
|
|
|
const BULLET_SIZE = 6;
|
|
|
|
|
const FIRE_COOLDOWN = 0.34;
|
|
|
|
|
const ENEMY_FIRE_COOLDOWN = 1.35;
|
|
|
|
|
const BRICK_SIZE = 20;
|
|
|
|
|
const DIRS = {
|
|
|
|
|
up: { x: 0, y: -1 },
|
|
|
|
|
down: { x: 0, y: 1 },
|
|
|
|
|
@ -97,20 +98,38 @@
|
|
|
|
|
let lastTime = 0;
|
|
|
|
|
|
|
|
|
|
const walls = [
|
|
|
|
|
rect(120, 80, TILE, TILE * 3),
|
|
|
|
|
rect(240, 120, TILE * 4, TILE),
|
|
|
|
|
rect(520, 80, TILE, TILE * 3),
|
|
|
|
|
rect(640, 160, TILE * 2, TILE),
|
|
|
|
|
rect(80, 320, TILE * 3, TILE),
|
|
|
|
|
rect(280, 280, TILE, TILE * 3),
|
|
|
|
|
rect(400, 360, TILE * 4, TILE),
|
|
|
|
|
rect(640, 360, TILE, TILE * 3),
|
|
|
|
|
rect(160, 480, TILE * 2, TILE),
|
|
|
|
|
rect(480, 500, TILE * 3, TILE),
|
|
|
|
|
...brickWall(120, 80, TILE, TILE * 3),
|
|
|
|
|
...brickWall(240, 120, TILE * 4, TILE),
|
|
|
|
|
...steelWall(520, 80, TILE, TILE * 3),
|
|
|
|
|
...brickWall(640, 160, TILE * 2, TILE),
|
|
|
|
|
...brickWall(80, 320, TILE * 3, TILE),
|
|
|
|
|
...brickWall(280, 280, TILE, TILE * 3),
|
|
|
|
|
...brickWall(400, 360, TILE * 4, TILE),
|
|
|
|
|
...steelWall(640, 360, TILE, TILE * 3),
|
|
|
|
|
...brickWall(160, 480, TILE * 2, TILE),
|
|
|
|
|
...brickWall(480, 500, TILE * 3, TILE),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
function rect(x, y, w, h) {
|
|
|
|
|
return { x, y, w, h };
|
|
|
|
|
function rect(x, y, w, h, type = "brick") {
|
|
|
|
|
return { x, y, w, h, type, destructible: type === "brick" };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function brickWall(x, y, w, h) {
|
|
|
|
|
return splitWall(x, y, w, h, "brick");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function steelWall(x, y, w, h) {
|
|
|
|
|
return splitWall(x, y, w, h, "steel");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function splitWall(x, y, w, h, type) {
|
|
|
|
|
const pieces = [];
|
|
|
|
|
for (let py = y; py < y + h; py += BRICK_SIZE) {
|
|
|
|
|
for (let px = x; px < x + w; px += BRICK_SIZE) {
|
|
|
|
|
pieces.push(rect(px, py, Math.min(BRICK_SIZE, x + w - px), Math.min(BRICK_SIZE, y + h - py), type));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return pieces;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function tank(x, y, color, dir = "up", team = "enemy") {
|
|
|
|
|
@ -340,8 +359,11 @@
|
|
|
|
|
const out =
|
|
|
|
|
bullet.x < -20 || bullet.y < -20 || bullet.x > WIDTH + 20 || bullet.y > HEIGHT + 20;
|
|
|
|
|
if (out) continue;
|
|
|
|
|
if (walls.some((wall) => intersects(bullet, wall))) {
|
|
|
|
|
spark(bullet.x, bullet.y, "#f0c451");
|
|
|
|
|
const wallIndex = walls.findIndex((wall) => intersects(bullet, wall));
|
|
|
|
|
if (wallIndex !== -1) {
|
|
|
|
|
const wall = walls[wallIndex];
|
|
|
|
|
spark(bullet.x, bullet.y, wall.destructible ? "#b86d3d" : "#c4c8bd");
|
|
|
|
|
if (wall.destructible) walls.splice(wallIndex, 1);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (bullet.owner === "player") {
|
|
|
|
|
@ -430,12 +452,22 @@
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function drawWall(wall) {
|
|
|
|
|
ctx.fillStyle = "#5d5540";
|
|
|
|
|
ctx.fillRect(wall.x, wall.y, wall.w, wall.h);
|
|
|
|
|
ctx.fillStyle = "rgba(255,255,255,0.08)";
|
|
|
|
|
for (let y = wall.y + 4; y < wall.y + wall.h; y += 12) {
|
|
|
|
|
ctx.fillRect(wall.x + 4, y, wall.w - 8, 3);
|
|
|
|
|
if (wall.type === "steel") {
|
|
|
|
|
ctx.fillStyle = "#6f7770";
|
|
|
|
|
ctx.fillRect(wall.x, wall.y, wall.w, wall.h);
|
|
|
|
|
ctx.fillStyle = "rgba(255,255,255,0.22)";
|
|
|
|
|
ctx.fillRect(wall.x + 3, wall.y + 3, wall.w - 6, 3);
|
|
|
|
|
ctx.fillStyle = "rgba(0,0,0,0.24)";
|
|
|
|
|
ctx.fillRect(wall.x + 3, wall.y + wall.h - 6, wall.w - 6, 3);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ctx.fillStyle = "#8e5a3d";
|
|
|
|
|
ctx.fillRect(wall.x, wall.y, wall.w, wall.h);
|
|
|
|
|
ctx.strokeStyle = "rgba(40,24,16,0.58)";
|
|
|
|
|
ctx.lineWidth = 1;
|
|
|
|
|
ctx.strokeRect(wall.x + 0.5, wall.y + 0.5, wall.w - 1, wall.h - 1);
|
|
|
|
|
ctx.fillStyle = "rgba(255,220,150,0.1)";
|
|
|
|
|
ctx.fillRect(wall.x + 3, wall.y + 3, wall.w - 6, 3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function drawTank(entity) {
|
|
|
|
|
|