Skip to content

Commit 9ce427e

Browse files
authored
feat: local multi + hitboxes
1 parent 66f421c commit 9ce427e

3 files changed

Lines changed: 259 additions & 76 deletions

File tree

data/game.js

Lines changed: 133 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -4,108 +4,165 @@ const ctx = canvas.getContext("2d");
44
canvas.width = 800;
55
canvas.height = 600;
66

7-
let ship = {
8-
x: canvas.width / 2,
9-
y: canvas.height - 50,
10-
width: 30,
11-
height: 30,
12-
speed: 5
13-
};
14-
15-
let bullets = [];
16-
let enemies = [];
17-
let lastShotTime = 0;
18-
19-
function createEnemies() {
20-
const rows = 2;
21-
const cols = 6;
22-
const spacing = 60;
7+
const playerColors = ["white", "lime", "cyan", "orange", "violet"];
8+
const enemyTypes = ["vi", "vim", "neovim"];
9+
10+
class Player {
11+
constructor(x, color) {
12+
this.x = x;
13+
this.y = canvas.height - 50;
14+
this.width = 30;
15+
this.height = 30;
16+
this.speed = 7;
17+
this.color = color;
18+
this.bullets = [];
19+
this.lastShot = 0;
20+
this.active = false;
21+
}
2322

24-
enemies = [];
23+
draw() {
24+
if (this.active) {
25+
ctx.fillStyle = this.color;
26+
ctx.fillRect(this.x - this.width / 2, this.y, this.width, this.height);
27+
}
28+
}
2529

26-
for (let row = 0; row < rows; row++) {
27-
for (let col = 0; col < cols; col++) {
28-
enemies.push({
29-
x: 100 + col * spacing,
30-
y: 50 + row * spacing,
31-
dx: 1,
32-
type: ["vi", "vim", "neovim"][Math.floor(Math.random() * 3)]
33-
});
30+
shoot() {
31+
const now = Date.now();
32+
if (now - this.lastShot > 1000 && this.active) {
33+
this.bullets.push({ x: this.x, y: this.y });
34+
this.lastShot = now;
3435
}
3536
}
36-
}
3737

38-
function drawShip() {
39-
ctx.fillStyle = "white";
40-
ctx.fillRect(ship.x - ship.width / 2, ship.y, ship.width, ship.height);
38+
updateBullets() {
39+
this.bullets = this.bullets.filter(b => b.y > 0);
40+
this.bullets.forEach(b => b.y -= 7);
41+
ctx.fillStyle = this.color;
42+
this.bullets.forEach(b => ctx.fillRect(b.x - 2, b.y, 4, 10));
43+
}
4144
}
4245

43-
function drawBullets() {
44-
ctx.fillStyle = "cyan";
45-
bullets.forEach(b => ctx.fillRect(b.x - 2, b.y, 4, 10));
46-
}
46+
class Enemy {
47+
constructor(x, y, type) {
48+
this.x = x;
49+
this.y = y;
50+
this.dx = 1;
51+
this.type = type;
52+
}
4753

48-
function drawEnemies() {
49-
ctx.fillStyle = "red";
50-
ctx.font = "16px monospace";
51-
enemies.forEach(e => ctx.fillText(e.type, e.x, e.y));
52-
}
54+
draw() {
55+
ctx.fillStyle = "red";
56+
ctx.font = "16px monospace";
57+
ctx.fillText(this.type, this.x, this.y);
58+
}
5359

54-
function updateBullets() {
55-
bullets = bullets.filter(b => b.y > 0);
56-
bullets.forEach(b => b.y -= 7);
60+
update() {
61+
this.x += this.dx;
62+
if (this.x < 0 || this.x > canvas.width - 30) {
63+
this.dx *= -1;
64+
this.y += 10;
65+
}
66+
}
5767
}
5868

59-
function updateEnemies() {
60-
enemies.forEach(e => {
61-
e.x += e.dx;
62-
if (e.x < 0 || e.x > canvas.width - 30) {
63-
e.dx *= -1;
64-
e.y += 10;
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+
72+
let enemies = [];
73+
74+
function createEnemies() {
75+
enemies = [];
76+
for (let row = 0; row < 2; row++) {
77+
for (let col = 0; col < 6; col++) {
78+
enemies.push(new Enemy(100 + col * 60, 50 + row * 50, enemyTypes[Math.floor(Math.random() * 3)]));
6579
}
66-
});
80+
}
6781
}
6882

69-
function shoot() {
70-
const now = Date.now();
71-
if (now - lastShotTime >= 1000) {
72-
bullets.push({ x: ship.x, y: ship.y });
73-
lastShotTime = now;
74-
}
83+
function checkCollisions(player) {
84+
player.bullets.forEach((b, i) => {
85+
enemies.forEach((e, j) => {
86+
if (
87+
b.x > e.x - 10 &&
88+
b.x < e.x + 30 &&
89+
b.y < e.y + 16 &&
90+
b.y > e.y
91+
) {
92+
// trafienie
93+
enemies.splice(j, 1);
94+
player.bullets.splice(i, 1);
95+
}
96+
});
97+
});
7598
}
7699

77100
function draw() {
78101
ctx.clearRect(0, 0, canvas.width, canvas.height);
79-
drawShip();
80-
drawEnemies();
81-
drawBullets();
82-
updateBullets();
83-
updateEnemies();
102+
103+
player1.draw();
104+
player1.updateBullets();
105+
checkCollisions(player1);
106+
107+
if (player2.active) {
108+
player2.draw();
109+
player2.updateBullets();
110+
checkCollisions(player2);
111+
}
112+
113+
enemies.forEach(e => {
114+
e.update();
115+
e.draw();
116+
});
117+
84118
requestAnimationFrame(draw);
85119
}
86120

87-
// Keyboard input
88-
document.addEventListener("keydown", e => {
89-
if (e.key === "a") ship.x -= ship.speed;
90-
if (e.key === "d") ship.x += ship.speed;
91-
if (e.key === " ") shoot();
121+
createEnemies();
122+
draw();
123+
124+
// Klawiatura – player 1: A/D/Spacja
125+
document.addEventListener("keydown", (e) => {
126+
if (e.key === "a") {
127+
player1.x -= player1.speed;
128+
player1.active = true;
129+
}
130+
if (e.key === "d") {
131+
player1.x += player1.speed;
132+
player1.active = true;
133+
}
134+
if (e.key === " ") {
135+
player1.shoot();
136+
player1.active = true;
137+
}
138+
139+
// Klawiatura – player 2: ←/→/Enter
140+
if (e.key === "ArrowLeft") {
141+
player2.x -= player2.speed;
142+
player2.active = true;
143+
}
144+
if (e.key === "ArrowRight") {
145+
player2.x += player2.speed;
146+
player2.active = true;
147+
}
148+
if (e.key === "Enter") {
149+
player2.shoot();
150+
player2.active = true;
151+
}
92152
});
93153

94-
// Touch input (left/right/center = shoot)
95-
canvas.addEventListener("touchstart", e => {
154+
// Dotyk (prosty) – steruje player1
155+
canvas.addEventListener("touchstart", (e) => {
96156
e.preventDefault();
97157
const x = e.touches[0].clientX;
98-
const canvasX = canvas.getBoundingClientRect().left;
99-
const relativeX = x - canvasX;
158+
const relX = x - canvas.getBoundingClientRect().left;
100159

101-
if (relativeX < canvas.width / 3) {
102-
ship.x -= ship.speed * 2;
103-
} else if (relativeX > 2 * canvas.width / 3) {
104-
ship.x += ship.speed * 2;
160+
player1.active = true;
161+
if (relX < canvas.width / 3) {
162+
player1.x -= player1.speed * 1.5;
163+
} else if (relX > 2 * canvas.width / 3) {
164+
player1.x += player1.speed * 1.5;
105165
} else {
106-
shoot();
166+
player1.shoot();
107167
}
108168
}, { passive: false });
109-
110-
createEnemies();
111-
draw();

data/game.js.bak

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
const canvas = document.getElementById("gameCanvas");
2+
const ctx = canvas.getContext("2d");
3+
4+
canvas.width = 800;
5+
canvas.height = 600;
6+
7+
let ship = {
8+
x: canvas.width / 2,
9+
y: canvas.height - 50,
10+
width: 30,
11+
height: 30,
12+
speed: 5
13+
};
14+
15+
let bullets = [];
16+
let enemies = [];
17+
let lastShotTime = 0;
18+
19+
function createEnemies() {
20+
const rows = 2;
21+
const cols = 6;
22+
const spacing = 60;
23+
24+
enemies = [];
25+
26+
for (let row = 0; row < rows; row++) {
27+
for (let col = 0; col < cols; col++) {
28+
enemies.push({
29+
x: 100 + col * spacing,
30+
y: 50 + row * spacing,
31+
dx: 1,
32+
type: ["vi", "vim", "neovim"][Math.floor(Math.random() * 3)]
33+
});
34+
}
35+
}
36+
}
37+
38+
function drawShip() {
39+
ctx.fillStyle = "white";
40+
ctx.fillRect(ship.x - ship.width / 2, ship.y, ship.width, ship.height);
41+
}
42+
43+
function drawBullets() {
44+
ctx.fillStyle = "cyan";
45+
bullets.forEach(b => ctx.fillRect(b.x - 2, b.y, 4, 10));
46+
}
47+
48+
function drawEnemies() {
49+
ctx.fillStyle = "red";
50+
ctx.font = "16px monospace";
51+
enemies.forEach(e => ctx.fillText(e.type, e.x, e.y));
52+
}
53+
54+
function updateBullets() {
55+
bullets = bullets.filter(b => b.y > 0);
56+
bullets.forEach(b => b.y -= 7);
57+
}
58+
59+
function updateEnemies() {
60+
enemies.forEach(e => {
61+
e.x += e.dx;
62+
if (e.x < 0 || e.x > canvas.width - 30) {
63+
e.dx *= -1;
64+
e.y += 10;
65+
}
66+
});
67+
}
68+
69+
function shoot() {
70+
const now = Date.now();
71+
if (now - lastShotTime >= 1000) {
72+
bullets.push({ x: ship.x, y: ship.y });
73+
lastShotTime = now;
74+
}
75+
}
76+
77+
function draw() {
78+
ctx.clearRect(0, 0, canvas.width, canvas.height);
79+
drawShip();
80+
drawEnemies();
81+
drawBullets();
82+
updateBullets();
83+
updateEnemies();
84+
requestAnimationFrame(draw);
85+
}
86+
87+
// Keyboard input
88+
document.addEventListener("keydown", e => {
89+
if (e.key === "a") ship.x -= ship.speed;
90+
if (e.key === "d") ship.x += ship.speed;
91+
if (e.key === " ") shoot();
92+
});
93+
94+
// Touch input (left/right/center = shoot)
95+
canvas.addEventListener("touchstart", e => {
96+
e.preventDefault();
97+
const x = e.touches[0].clientX;
98+
const canvasX = canvas.getBoundingClientRect().left;
99+
const relativeX = x - canvasX;
100+
101+
if (relativeX < canvas.width / 3) {
102+
ship.x -= ship.speed * 2;
103+
} else if (relativeX > 2 * canvas.width / 3) {
104+
ship.x += ship.speed * 2;
105+
} else {
106+
shoot();
107+
}
108+
}, { passive: false });
109+
110+
createEnemies();
111+
draw();

data/style.css.bak

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
body {
2+
margin: 0;
3+
background: black;
4+
display: flex;
5+
justify-content: center;
6+
align-items: center;
7+
height: 100vh;
8+
overflow: hidden;
9+
touch-action: manipulation; /* zapobiega zoomowaniu */
10+
}
11+
12+
canvas {
13+
border: 2px solid white;
14+
touch-action: none; /* ważne dla sterowania dotykiem */
15+
}

0 commit comments

Comments
 (0)