Skip to content

Commit e3a0370

Browse files
authored
Add files via upload
1 parent 4056258 commit e3a0370

2 files changed

Lines changed: 290 additions & 62 deletions

File tree

data/game.js

Lines changed: 161 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ canvas.height = 600;
66

77
const playerColors = ["white", "lime", "cyan", "orange", "violet"];
88
const enemyTypes = ["vi", "vim", "neovim"];
9+
let enemyBullets = [];
10+
let gameOver = false;
11+
let level = 1;
912

1013
class Player {
1114
constructor(x, color) {
@@ -18,18 +21,28 @@ class Player {
1821
this.bullets = [];
1922
this.lastShot = 0;
2023
this.active = false;
24+
this.lives = 3;
25+
this.score = 0;
26+
this.alive = true;
27+
this.respawnTimer = 0;
28+
this.respawnCountdown = null;
2129
}
2230

2331
draw() {
24-
if (this.active) {
32+
if (this.active && this.alive) {
2533
ctx.fillStyle = this.color;
2634
ctx.fillRect(this.x - this.width / 2, this.y, this.width, this.height);
35+
} else if (!this.alive && this.lives > 0) {
36+
const secondsLeft = Math.ceil((5000 - (Date.now() - this.respawnTimer)) / 1000);
37+
ctx.fillStyle = "white";
38+
ctx.font = "14px sans-serif";
39+
ctx.fillText(`P${this === player1 ? 1 : 2} respawn in ${secondsLeft}`, this.x - 40, this.y - 10);
2740
}
2841
}
2942

3043
shoot() {
3144
const now = Date.now();
32-
if (now - this.lastShot > 1000 && this.active) {
45+
if (now - this.lastShot > 1000 && this.active && this.alive) {
3346
this.bullets.push({ x: this.x, y: this.y });
3447
this.lastShot = now;
3548
}
@@ -41,6 +54,22 @@ class Player {
4154
ctx.fillStyle = this.color;
4255
this.bullets.forEach(b => ctx.fillRect(b.x - 2, b.y, 4, 10));
4356
}
57+
58+
takeHit() {
59+
if (!this.alive || this.lives <= 0) return;
60+
this.lives -= 1;
61+
this.alive = false;
62+
this.respawnTimer = Date.now();
63+
}
64+
65+
updateRespawn() {
66+
if (!this.alive && this.lives > 0) {
67+
const now = Date.now();
68+
if (now - this.respawnTimer >= 5000) {
69+
this.alive = true;
70+
}
71+
}
72+
}
4473
}
4574

4675
class Enemy {
@@ -63,100 +92,145 @@ class Enemy {
6392
this.dx *= -1;
6493
this.y += 10;
6594
}
66-
}
67-
}
68-
69-
const player1 = new Player(canvas.width / 2 - 60, playerColors[Math.floor(Math.random() * playerColors.length)]);
70-
const player2 = new Player(canvas.width / 2 + 60, playerColors[Math.floor(Math.random() * playerColors.length)]);
71-
7295

73-
const ws = new WebSocket("ws://" + location.hostname + "/ws");
74-
75-
ws.onmessage = (event) => {
76-
const data = JSON.parse(event.data);
77-
78-
// joystick 1
79-
if (data.j1x < 1500) {
80-
player1.x -= player1.speed;
81-
player1.active = true;
82-
} else if (data.j1x > 3500) {
83-
player1.x += player1.speed;
84-
player1.active = true;
85-
}
86-
if (data.j1f) {
87-
player1.shoot();
88-
player1.active = true;
89-
}
90-
91-
// joystick 2
92-
if (data.j2x < 1500) {
93-
player2.x -= player2.speed;
94-
player2.active = true;
95-
} else if (data.j2x > 3500) {
96-
player2.x += player2.speed;
97-
player2.active = true;
98-
}
99-
if (data.j2f) {
100-
player2.shoot();
101-
player2.active = true;
96+
if (this.y > canvas.height - 100 && !gameOver) {
97+
gameOver = true;
98+
setTimeout(() => alert("Game Over – wróg dotarł do bazy!"), 10);
99+
}
102100
}
103-
};
101+
}
104102

103+
let player1, player2;
104+
let enemies = [];
105105

106+
function newGame() {
107+
player1 = new Player(canvas.width / 2 - 60, randomColor());
108+
player2 = new Player(canvas.width / 2 + 60, randomColor());
109+
enemyBullets = [];
110+
level = 1;
111+
gameOver = false;
112+
createEnemies();
113+
}
106114

107-
let enemies = [];
115+
function randomColor() {
116+
return playerColors[Math.floor(Math.random() * playerColors.length)];
117+
}
108118

109119
function createEnemies() {
110120
enemies = [];
111-
for (let row = 0; row < 2; row++) {
112-
for (let col = 0; col < 6; col++) {
113-
enemies.push(new Enemy(100 + col * 60, 50 + row * 50, enemyTypes[Math.floor(Math.random() * 3)]));
121+
const rows = 2 + level;
122+
const cols = 4 + level;
123+
for (let row = 0; row < rows; row++) {
124+
for (let col = 0; col < cols; col++) {
125+
enemies.push(new Enemy(60 + col * 60, 50 + row * 40, enemyTypes[Math.floor(Math.random() * 3)]));
114126
}
115127
}
116128
}
117129

118130
function checkCollisions(player) {
119131
player.bullets.forEach((b, i) => {
120132
enemies.forEach((e, j) => {
121-
if (
122-
b.x > e.x - 10 &&
123-
b.x < e.x + 30 &&
124-
b.y < e.y + 16 &&
125-
b.y > e.y
126-
) {
127-
// trafienie
133+
if (b.x > e.x - 10 && b.x < e.x + 30 && b.y < e.y + 16 && b.y > e.y) {
128134
enemies.splice(j, 1);
129135
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);
130144
}
131145
});
132146
});
133147
}
134148

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+
});
171+
}
172+
173+
function enemyFire() {
174+
if (enemies.length === 0 || gameOver) return;
175+
const shooter = enemies[Math.floor(Math.random() * enemies.length)];
176+
enemyBullets.push({ x: shooter.x + 10, y: shooter.y + 10 });
177+
}
178+
179+
function drawHUD() {
180+
ctx.fillStyle = "white";
181+
ctx.font = "16px monospace";
182+
ctx.fillText(`P1: x${player1.lives} (${player1.score})`, 20, 20);
183+
ctx.fillText(`P2: x${player2.lives} (${player2.score})`, canvas.width - 180, 20);
184+
ctx.fillText(`Level: ${level}`, canvas.width / 2 - 30, 20);
185+
}
186+
135187
function draw() {
136188
ctx.clearRect(0, 0, canvas.width, canvas.height);
137189

190+
if (gameOver) {
191+
ctx.fillStyle = "red";
192+
ctx.font = "30px sans-serif";
193+
ctx.fillText("GAME OVER", canvas.width / 2 - 100, canvas.height / 2);
194+
return;
195+
}
196+
197+
player1.updateRespawn();
198+
player2.updateRespawn();
199+
138200
player1.draw();
139201
player1.updateBullets();
140202
checkCollisions(player1);
203+
checkPlayerHit(player1);
141204

142205
if (player2.active) {
143206
player2.draw();
144207
player2.updateBullets();
145208
checkCollisions(player2);
209+
checkPlayerHit(player2);
146210
}
147211

148212
enemies.forEach(e => {
149213
e.update();
150214
e.draw();
151215
});
152216

217+
updateEnemyBullets();
218+
drawHUD();
219+
220+
// Level progression
221+
if (enemies.length === 0 && !gameOver) {
222+
level++;
223+
createEnemies();
224+
}
225+
153226
requestAnimationFrame(draw);
154227
}
155228

156-
createEnemies();
229+
setInterval(enemyFire, 1500);
230+
newGame();
157231
draw();
158232

159-
// Klawiatura – player 1: A/D/Spacja
233+
// Input: keyboard
160234
document.addEventListener("keydown", (e) => {
161235
if (e.key === "a") {
162236
player1.x -= player1.speed;
@@ -171,7 +245,6 @@ document.addEventListener("keydown", (e) => {
171245
player1.active = true;
172246
}
173247

174-
// Klawiatura – player 2: ←/→/Enter
175248
if (e.key === "ArrowLeft") {
176249
player2.x -= player2.speed;
177250
player2.active = true;
@@ -180,13 +253,17 @@ document.addEventListener("keydown", (e) => {
180253
player2.x += player2.speed;
181254
player2.active = true;
182255
}
183-
if (e.key === "Enter") {
256+
if (e.key === "ArrowUp") {
184257
player2.shoot();
185258
player2.active = true;
186259
}
260+
261+
if (e.key === "r") {
262+
newGame();
263+
}
187264
});
188265

189-
// Dotyk (prosty) – steruje player1
266+
// Input: touch
190267
canvas.addEventListener("touchstart", (e) => {
191268
e.preventDefault();
192269
const x = e.touches[0].clientX;
@@ -201,3 +278,33 @@ canvas.addEventListener("touchstart", (e) => {
201278
player1.shoot();
202279
}
203280
}, { passive: false });
281+
282+
// Input: joystick (WebSocket)
283+
const ws = new WebSocket("ws://" + location.hostname + "/ws");
284+
ws.onmessage = (event) => {
285+
const data = JSON.parse(event.data);
286+
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+
}
310+
};

0 commit comments

Comments
 (0)