Skip to content

Commit b2440e7

Browse files
authored
feat: server with enemy sprites
1 parent e3a0370 commit b2440e7

5 files changed

Lines changed: 157 additions & 146 deletions

File tree

data/game.js

Lines changed: 113 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,31 @@
1+
// game.js z aktywacją gracza ruchem i wstrzymaniem wrogów przed aktywacją
2+
13
const canvas = document.getElementById("gameCanvas");
24
const ctx = canvas.getContext("2d");
3-
45
canvas.width = 800;
56
canvas.height = 600;
67

78
const playerColors = ["white", "lime", "cyan", "orange", "violet"];
8-
const enemyTypes = ["vi", "vim", "neovim"];
9+
const enemySprites = {
10+
vi: new Image(),
11+
vim: new Image(),
12+
neovim: new Image()
13+
};
14+
enemySprites.vi.src = "/sprites/vi.png";
15+
enemySprites.vim.src = "/sprites/vim.png";
16+
enemySprites.neovim.src = "/sprites/neovim.png";
17+
918
let enemyBullets = [];
1019
let gameOver = false;
1120
let level = 1;
21+
let fireInterval = 1500;
22+
let fireTimer;
23+
24+
function waitForSprites(callback) {
25+
const allLoaded = Object.values(enemySprites).every(img => img.complete && img.naturalHeight !== 0);
26+
if (allLoaded) callback();
27+
else setTimeout(() => waitForSprites(callback), 100);
28+
}
1229

1330
class Player {
1431
constructor(x, color) {
@@ -25,13 +42,17 @@ class Player {
2542
this.score = 0;
2643
this.alive = true;
2744
this.respawnTimer = 0;
28-
this.respawnCountdown = null;
2945
}
3046

3147
draw() {
3248
if (this.active && this.alive) {
49+
ctx.beginPath();
50+
ctx.moveTo(this.x, this.y);
51+
ctx.lineTo(this.x - 15, this.y + 30);
52+
ctx.lineTo(this.x + 15, this.y + 30);
53+
ctx.closePath();
3354
ctx.fillStyle = this.color;
34-
ctx.fillRect(this.x - this.width / 2, this.y, this.width, this.height);
55+
ctx.fill();
3556
} else if (!this.alive && this.lives > 0) {
3657
const secondsLeft = Math.ceil((5000 - (Date.now() - this.respawnTimer)) / 1000);
3758
ctx.fillStyle = "white";
@@ -45,6 +66,8 @@ class Player {
4566
if (now - this.lastShot > 1000 && this.active && this.alive) {
4667
this.bullets.push({ x: this.x, y: this.y });
4768
this.lastShot = now;
69+
} else if (gameOver) {
70+
newGame();
4871
}
4972
}
5073

@@ -81,22 +104,22 @@ class Enemy {
81104
}
82105

83106
draw() {
84-
ctx.fillStyle = "red";
85-
ctx.font = "16px monospace";
86-
ctx.fillText(this.type, this.x, this.y);
107+
const sprite = enemySprites[this.type];
108+
if (sprite.complete && sprite.naturalHeight !== 0) {
109+
ctx.drawImage(sprite, this.x, this.y, 30, 30);
110+
} else {
111+
ctx.fillStyle = "red";
112+
ctx.fillRect(this.x, this.y, 30, 30);
113+
}
87114
}
88115

89116
update() {
117+
if (!player1.active && !player2.active) return;
90118
this.x += this.dx;
91119
if (this.x < 0 || this.x > canvas.width - 30) {
92120
this.dx *= -1;
93121
this.y += 10;
94122
}
95-
96-
if (this.y > canvas.height - 100 && !gameOver) {
97-
gameOver = true;
98-
setTimeout(() => alert("Game Over – wróg dotarł do bazy!"), 10);
99-
}
100123
}
101124
}
102125

@@ -110,64 +133,32 @@ function newGame() {
110133
level = 1;
111134
gameOver = false;
112135
createEnemies();
136+
updateFireRate();
113137
}
114138

115-
function randomColor() {
116-
return playerColors[Math.floor(Math.random() * playerColors.length)];
139+
function updateFireRate() {
140+
clearInterval(fireTimer);
141+
fireInterval = Math.max(200, 1500 - level * 100);
142+
fireTimer = setInterval(() => {
143+
if (player1.active || player2.active) enemyFire();
144+
}, fireInterval);
117145
}
118146

119147
function createEnemies() {
120148
enemies = [];
149+
const types = ["vi", "vim", "neovim"];
121150
const rows = 2 + level;
122151
const cols = 4 + level;
123152
for (let row = 0; row < rows; row++) {
124153
for (let col = 0; col < cols; col++) {
125-
enemies.push(new Enemy(60 + col * 60, 50 + row * 40, enemyTypes[Math.floor(Math.random() * 3)]));
154+
const type = types[Math.floor(Math.random() * types.length)];
155+
enemies.push(new Enemy(60 + col * 60, 50 + row * 40, type));
126156
}
127157
}
128158
}
129159

130-
function checkCollisions(player) {
131-
player.bullets.forEach((b, i) => {
132-
enemies.forEach((e, j) => {
133-
if (b.x > e.x - 10 && b.x < e.x + 30 && b.y < e.y + 16 && b.y > e.y) {
134-
enemies.splice(j, 1);
135-
player.bullets.splice(i, 1);
136-
player.score += 1;
137-
}
138-
});
139-
140-
enemyBullets.forEach((eb, k) => {
141-
if (b.x > eb.x - 4 && b.x < eb.x + 4 && b.y < eb.y + 10 && b.y > eb.y) {
142-
enemyBullets.splice(k, 1);
143-
player.bullets.splice(i, 1);
144-
}
145-
});
146-
});
147-
}
148-
149-
function checkPlayerHit(player) {
150-
if (!player.alive) return;
151-
enemyBullets.forEach((b, i) => {
152-
if (
153-
b.x > player.x - player.width / 2 &&
154-
b.x < player.x + player.width / 2 &&
155-
b.y > player.y &&
156-
b.y < player.y + player.height
157-
) {
158-
player.takeHit();
159-
enemyBullets.splice(i, 1);
160-
}
161-
});
162-
}
163-
164-
function updateEnemyBullets() {
165-
enemyBullets = enemyBullets.filter(b => b.y < canvas.height);
166-
enemyBullets.forEach(b => {
167-
b.y += 4;
168-
ctx.fillStyle = "yellow";
169-
ctx.fillRect(b.x - 2, b.y, 4, 10);
170-
});
160+
function randomColor() {
161+
return playerColors[Math.floor(Math.random() * playerColors.length)];
171162
}
172163

173164
function enemyFire() {
@@ -186,7 +177,6 @@ function drawHUD() {
186177

187178
function draw() {
188179
ctx.clearRect(0, 0, canvas.width, canvas.height);
189-
190180
if (gameOver) {
191181
ctx.fillStyle = "red";
192182
ctx.font = "30px sans-serif";
@@ -217,94 +207,94 @@ function draw() {
217207
updateEnemyBullets();
218208
drawHUD();
219209

220-
// Level progression
221210
if (enemies.length === 0 && !gameOver) {
222211
level++;
223212
createEnemies();
213+
updateFireRate();
214+
}
215+
216+
if (!player1.alive && player1.lives === 0 && !player2.alive && player2.lives === 0) {
217+
gameOver = true;
224218
}
225219

226220
requestAnimationFrame(draw);
227221
}
228222

229-
setInterval(enemyFire, 1500);
230-
newGame();
231-
draw();
223+
function updateEnemyBullets() {
224+
enemyBullets = enemyBullets.filter(b => b.y < canvas.height);
225+
enemyBullets.forEach(b => {
226+
b.y += 4;
227+
ctx.fillStyle = "yellow";
228+
ctx.fillRect(b.x - 2, b.y, 4, 10);
229+
});
230+
}
232231

233-
// Input: keyboard
234-
document.addEventListener("keydown", (e) => {
235-
if (e.key === "a") {
236-
player1.x -= player1.speed;
237-
player1.active = true;
238-
}
239-
if (e.key === "d") {
240-
player1.x += player1.speed;
241-
player1.active = true;
242-
}
243-
if (e.key === " ") {
244-
player1.shoot();
245-
player1.active = true;
246-
}
232+
function checkCollisions(player) {
233+
player.bullets.forEach((b, i) => {
234+
enemies.forEach((e, j) => {
235+
if (b.x > e.x - 10 && b.x < e.x + 30 && b.y < e.y + 16 && b.y > e.y) {
236+
enemies.splice(j, 1);
237+
player.bullets.splice(i, 1);
238+
player.score += 1;
239+
}
240+
});
241+
enemyBullets.forEach((eb, k) => {
242+
if (b.x > eb.x - 4 && b.x < eb.x + 4 && b.y < eb.y + 10 && b.y > eb.y) {
243+
enemyBullets.splice(k, 1);
244+
player.bullets.splice(i, 1);
245+
}
246+
});
247+
});
248+
}
247249

248-
if (e.key === "ArrowLeft") {
249-
player2.x -= player2.speed;
250-
player2.active = true;
251-
}
252-
if (e.key === "ArrowRight") {
253-
player2.x += player2.speed;
254-
player2.active = true;
255-
}
256-
if (e.key === "ArrowUp") {
257-
player2.shoot();
258-
player2.active = true;
259-
}
250+
function checkPlayerHit(player) {
251+
if (!player.alive) return;
252+
enemyBullets.forEach((b, i) => {
253+
if (
254+
b.x > player.x - player.width / 2 &&
255+
b.x < player.x + player.width / 2 &&
256+
b.y > player.y &&
257+
b.y < player.y + player.height
258+
) {
259+
player.takeHit();
260+
enemyBullets.splice(i, 1);
261+
}
262+
});
263+
}
260264

261-
if (e.key === "r") {
262-
newGame();
263-
}
265+
window.addEventListener("keydown", (e) => {
266+
if (e.key === "a") { player1.x -= player1.speed; player1.active = true; }
267+
if (e.key === "d") { player1.x += player1.speed; player1.active = true; }
268+
if (e.key === " ") { player1.shoot(); player1.active = true; }
269+
if (e.key === "ArrowLeft") { player2.x -= player2.speed; player2.active = true; }
270+
if (e.key === "ArrowRight") { player2.x += player2.speed; player2.active = true; }
271+
if (e.key === "ArrowUp") { player2.shoot(); player2.active = true; }
272+
if (e.key === "r") newGame();
264273
});
265274

266-
// Input: touch
267275
canvas.addEventListener("touchstart", (e) => {
268276
e.preventDefault();
269277
const x = e.touches[0].clientX;
270278
const relX = x - canvas.getBoundingClientRect().left;
271-
272279
player1.active = true;
273-
if (relX < canvas.width / 3) {
274-
player1.x -= player1.speed * 1.5;
275-
} else if (relX > 2 * canvas.width / 3) {
276-
player1.x += player1.speed * 1.5;
277-
} else {
278-
player1.shoot();
279-
}
280+
if (relX < canvas.width / 3) player1.x -= player1.speed;
281+
else if (relX > 2 * canvas.width / 3) player1.x += player1.speed;
282+
else player1.shoot();
280283
}, { passive: false });
281284

282-
// Input: joystick (WebSocket)
283285
const ws = new WebSocket("ws://" + location.hostname + "/ws");
284286
ws.onmessage = (event) => {
285287
const data = JSON.parse(event.data);
288+
if (data.j1x < 1500) { player1.x -= player1.speed; player1.active = true; }
289+
else if (data.j1x > 3500) { player1.x += player1.speed; player1.active = true; }
290+
if (data.j1f) { player1.shoot(); player1.active = true; }
286291

287-
if (data.j1x < 1500) {
288-
player1.x -= player1.speed;
289-
player1.active = true;
290-
} else if (data.j1x > 3500) {
291-
player1.x += player1.speed;
292-
player1.active = true;
293-
}
294-
if (data.j1f) {
295-
player1.shoot();
296-
player1.active = true;
297-
}
298-
299-
if (data.j2x < 1500) {
300-
player2.x -= player2.speed;
301-
player2.active = true;
302-
} else if (data.j2x > 3500) {
303-
player2.x += player2.speed;
304-
player2.active = true;
305-
}
306-
if (data.j2f) {
307-
player2.shoot();
308-
player2.active = true;
309-
}
292+
if (data.j2x < 1500) { player2.x -= player2.speed; player2.active = true; }
293+
else if (data.j2x > 3500) { player2.x += player2.speed; player2.active = true; }
294+
if (data.j2f) { player2.shoot(); player2.active = true; }
310295
};
296+
297+
waitForSprites(() => {
298+
newGame();
299+
draw();
300+
});

0 commit comments

Comments
 (0)