adrish commited on
Commit
9bff983
·
verified ·
1 Parent(s): aa6b049

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +734 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Galaxy Defender
3
- emoji: 🦀
4
- colorFrom: pink
5
  colorTo: blue
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: galaxy-defender
3
+ emoji: 🐳
4
+ colorFrom: blue
5
  colorTo: blue
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,734 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Galaxy Defender</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ background-color: #000;
16
+ overflow: hidden;
17
+ font-family: 'Orbitron', sans-serif;
18
+ color: white;
19
+ }
20
+
21
+ @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');
22
+
23
+ #gameContainer {
24
+ position: relative;
25
+ width: 100vw;
26
+ height: 100vh;
27
+ background: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiPgogIDxkZWZzPgogICAgPHBhdHRlcm4gaWQ9InBhdHRlcm4iIHBhdHRlcm5Vbml0cz0idXNlclNwYWNlT25Vc2UiIHBhdHRlcm5UcmFuc2Zvcm09InNjYWxlKDIpIHJvdGF0ZSgwKSI+CiAgICAgIDxyZWN0IHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiNmZmZmZmYiIG9wYWNpdHk9IjAuMCIvPgogICAgICA8Y2lyY2xlIGN4PSIwLjUiIGN5PSIwLjUiIHI9IjAuNSIgZmlsbD0iIzIwMjBmZiIgb3BhY2l0eT0iMC4xIi8+CiAgICA8L3BhdHRlcm4+CiAgPC9kZWZzPgogIDxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjcGF0dGVybikiLz4KPC9zdmc+') #000;
28
+ }
29
+
30
+ #gameCanvas {
31
+ position: absolute;
32
+ top: 0;
33
+ left: 0;
34
+ width: 100%;
35
+ height: 100%;
36
+ }
37
+
38
+ #startScreen, #gameOverScreen {
39
+ position: absolute;
40
+ top: 0;
41
+ left: 0;
42
+ width: 100%;
43
+ height: 100%;
44
+ display: flex;
45
+ flex-direction: column;
46
+ justify-content: center;
47
+ align-items: center;
48
+ background-color: rgba(0, 0, 0, 0.8);
49
+ z-index: 10;
50
+ }
51
+
52
+ #gameOverScreen {
53
+ display: none;
54
+ }
55
+
56
+ h1 {
57
+ font-size: 3rem;
58
+ color: #0ff;
59
+ text-shadow: 0 0 10px #0ff, 0 0 20px #0ff;
60
+ margin-bottom: 2rem;
61
+ text-align: center;
62
+ }
63
+
64
+ button {
65
+ background: none;
66
+ border: 2px solid #0ff;
67
+ color: #0ff;
68
+ padding: 1rem 2rem;
69
+ font-size: 1.5rem;
70
+ font-family: 'Orbitron', sans-serif;
71
+ cursor: pointer;
72
+ transition: all 0.3s;
73
+ margin-top: 1rem;
74
+ text-shadow: 0 0 5px #0ff;
75
+ }
76
+
77
+ button:hover {
78
+ background-color: rgba(0, 255, 255, 0.1);
79
+ box-shadow: 0 0 10px #0ff;
80
+ }
81
+
82
+ #scoreDisplay, #healthDisplay {
83
+ position: absolute;
84
+ top: 20px;
85
+ right: 20px;
86
+ z-index: 5;
87
+ font-size: 1.5rem;
88
+ color: #0ff;
89
+ text-shadow: 0 0 5px #0ff;
90
+ }
91
+
92
+ #healthDisplay {
93
+ display: flex;
94
+ align-items: center;
95
+ }
96
+
97
+ #healthBar {
98
+ width: 100px;
99
+ height: 20px;
100
+ background-color: #333;
101
+ margin-left: 10px;
102
+ border: 1px solid #0ff;
103
+ overflow: hidden;
104
+ }
105
+
106
+ #healthProgress {
107
+ height: 100%;
108
+ width: 100%;
109
+ background-color: #0f0;
110
+ transition: width 0.3s;
111
+ }
112
+
113
+ .controls {
114
+ position: absolute;
115
+ bottom: 20px;
116
+ left: 20px;
117
+ color: #0ff;
118
+ font-size: 1rem;
119
+ text-shadow: 0 0 5px #0ff;
120
+ }
121
+
122
+ #mobileControls {
123
+ display: none;
124
+ position: absolute;
125
+ bottom: 20px;
126
+ width: 100%;
127
+ justify-content: space-around;
128
+ z-index: 5;
129
+ }
130
+
131
+ .mobile-button {
132
+ width: 60px;
133
+ height: 60px;
134
+ background-color: rgba(0, 255, 255, 0.2);
135
+ border: 2px solid #0ff;
136
+ border-radius: 50%;
137
+ color: #0ff;
138
+ display: flex;
139
+ justify-content: center;
140
+ align-items: center;
141
+ font-size: 1.5rem;
142
+ user-select: none;
143
+ }
144
+
145
+ @media (max-width: 768px) {
146
+ #mobileControls {
147
+ display: flex;
148
+ }
149
+
150
+ .controls {
151
+ display: none;
152
+ }
153
+
154
+ h1 {
155
+ font-size: 2rem;
156
+ }
157
+
158
+ button {
159
+ padding: 0.8rem 1.5rem;
160
+ font-size: 1.2rem;
161
+ }
162
+ }
163
+
164
+ #stars {
165
+ position: absolute;
166
+ width: 100%;
167
+ height: 100%;
168
+ z-index: -1;
169
+ }
170
+
171
+ .star {
172
+ position: absolute;
173
+ background-color: white;
174
+ border-radius: 50%;
175
+ animation: twinkle 1s infinite alternate;
176
+ }
177
+
178
+ @keyframes twinkle {
179
+ from { opacity: 0.3; }
180
+ to { opacity: 1; }
181
+ }
182
+
183
+ .explosion {
184
+ position: absolute;
185
+ width: 30px;
186
+ height: 30px;
187
+ pointer-events: none;
188
+ background-image: radial-gradient(circle, #ff0, #f80, #f00);
189
+ border-radius: 50%;
190
+ transform: scale(0);
191
+ opacity: 1;
192
+ animation: explode 0.5s forwards;
193
+ }
194
+
195
+ @keyframes explode {
196
+ to {
197
+ transform: scale(3);
198
+ opacity: 0;
199
+ }
200
+ }
201
+ </style>
202
+ </head>
203
+ <body>
204
+ <div id="gameContainer">
205
+ <div id="stars"></div>
206
+ <canvas id="gameCanvas"></canvas>
207
+
208
+ <div id="scoreDisplay">Score: 0</div>
209
+ <div id="healthDisplay">
210
+ Health: <div id="healthBar"><div id="healthProgress"></div></div>
211
+ </div>
212
+
213
+ <div id="startScreen">
214
+ <h1>GALAXY DEFENDER</h1>
215
+ <p>Defend the sector from enemy invaders!</p>
216
+ <button id="startButton">START MISSION</button>
217
+ <div class="controls">
218
+ Controls: Arrow Keys to Move, Space to Shoot
219
+ </div>
220
+ </div>
221
+
222
+ <div id="gameOverScreen">
223
+ <h1>MISSION FAILED</h1>
224
+ <p id="finalScore">Your score: 0</p>
225
+ <button id="restartButton">TRY AGAIN</button>
226
+ </div>
227
+
228
+ <div id="mobileControls">
229
+ <div class="mobile-button" id="leftButton">←</div>
230
+ <div class="mobile-button" id="rightButton">→</div>
231
+ <div class="mobile-button" id="upButton">↑</div>
232
+ <div class="mobile-button" id="downButton">↓</div>
233
+ <div class="mobile-button" id="shootButton">💥</div>
234
+ </div>
235
+ </div>
236
+
237
+ <script>
238
+ // Game variables
239
+ const canvas = document.getElementById('gameCanvas');
240
+ const ctx = canvas.getContext('2d');
241
+ const startScreen = document.getElementById('startScreen');
242
+ const gameOverScreen = document.getElementById('gameOverScreen');
243
+ const startButton = document.getElementById('startButton');
244
+ const restartButton = document.getElementById('restartButton');
245
+ const scoreDisplay = document.getElementById('scoreDisplay');
246
+ const finalScore = document.getElementById('finalScore');
247
+ const healthProgress = document.getElementById('healthProgress');
248
+ const starsContainer = document.getElementById('stars');
249
+
250
+ // Mobile controls
251
+ const leftButton = document.getElementById('leftButton');
252
+ const rightButton = document.getElementById('rightButton');
253
+ const upButton = document.getElementById('upButton');
254
+ const downButton = document.getElementById('downButton');
255
+ const shootButton = document.getElementById('shootButton');
256
+
257
+ // Set canvas size
258
+ function resizeCanvas() {
259
+ canvas.width = window.innerWidth;
260
+ canvas.height = window.innerHeight;
261
+ }
262
+
263
+ resizeCanvas();
264
+ window.addEventListener('resize', resizeCanvas);
265
+
266
+ // Create stars
267
+ function createStars() {
268
+ starsContainer.innerHTML = '';
269
+ const starCount = Math.floor(window.innerWidth * window.innerHeight / 1000);
270
+
271
+ for (let i = 0; i < starCount; i++) {
272
+ const star = document.createElement('div');
273
+ star.className = 'star';
274
+ star.style.width = `${Math.random() * 3}px`;
275
+ star.style.height = star.style.width;
276
+ star.style.left = `${Math.random() * 100}%`;
277
+ star.style.top = `${Math.random() * 100}%`;
278
+ star.style.opacity = Math.random();
279
+ star.style.animationDelay = `${Math.random() * 2}s`;
280
+ star.style.animationDuration = `${0.5 + Math.random() * 1.5}s`;
281
+ starsContainer.appendChild(star);
282
+ }
283
+ }
284
+
285
+ createStars();
286
+
287
+ // Game objects
288
+ const player = {
289
+ x: canvas.width / 2,
290
+ y: canvas.height - 100,
291
+ width: 50,
292
+ height: 50,
293
+ speed: 8,
294
+ color: '#0ff',
295
+ health: 100,
296
+ maxHealth: 100,
297
+ isShooting: false,
298
+ shootCooldown: 0,
299
+ shootInterval: 300 // ms
300
+ };
301
+
302
+ const bullets = [];
303
+ const enemies = [];
304
+ const explosions = [];
305
+ let score = 0;
306
+ let gameRunning = false;
307
+ let enemySpawnTimer = 0;
308
+ let enemySpawnInterval = 1500; // ms
309
+ let lastTime = 0;
310
+ let animationFrameId = null;
311
+
312
+ // Input handling
313
+ const keys = {
314
+ ArrowLeft: false,
315
+ ArrowRight: false,
316
+ ArrowUp: false,
317
+ ArrowDown: false,
318
+ ' ': false
319
+ };
320
+
321
+ window.addEventListener('keydown', (e) => {
322
+ if (keys.hasOwnProperty(e.key)) {
323
+ keys[e.key] = true;
324
+ e.preventDefault();
325
+ }
326
+ });
327
+
328
+ window.addEventListener('keyup', (e) => {
329
+ if (keys.hasOwnProperty(e.key)) {
330
+ keys[e.key] = false;
331
+ e.preventDefault();
332
+ }
333
+ });
334
+
335
+ // Mobile controls
336
+ function setupMobileControls() {
337
+ const handlePress = (button, key) => {
338
+ const startPress = () => {
339
+ keys[key] = true;
340
+ button.style.backgroundColor = 'rgba(0, 255, 255, 0.4)';
341
+ };
342
+
343
+ const endPress = () => {
344
+ keys[key] = false;
345
+ button.style.backgroundColor = 'rgba(0, 255, 255, 0.2)';
346
+ };
347
+
348
+ button.addEventListener('touchstart', (e) => {
349
+ e.preventDefault();
350
+ startPress();
351
+ });
352
+
353
+ button.addEventListener('touchend', (e) => {
354
+ e.preventDefault();
355
+ endPress();
356
+ });
357
+
358
+ button.addEventListener('mousedown', startPress);
359
+ button.addEventListener('mouseup', endPress);
360
+ button.addEventListener('mouseleave', endPress);
361
+ };
362
+
363
+ handlePress(leftButton, 'ArrowLeft');
364
+ handlePress(rightButton, 'ArrowRight');
365
+ handlePress(upButton, 'ArrowUp');
366
+ handlePress(downButton, 'ArrowDown');
367
+ handlePress(shootButton, ' ');
368
+ }
369
+
370
+ setupMobileControls();
371
+
372
+ // Draw player ship
373
+ function drawPlayer() {
374
+ ctx.save();
375
+
376
+ // Ship body
377
+ ctx.fillStyle = player.color;
378
+ ctx.beginPath();
379
+ ctx.moveTo(player.x, player.y - player.height/2);
380
+ ctx.lineTo(player.x + player.width/2, player.y + player.height/2);
381
+ ctx.lineTo(player.x - player.width/2, player.y + player.height/2);
382
+ ctx.closePath();
383
+ ctx.fill();
384
+
385
+ // Ship cockpit
386
+ ctx.fillStyle = '#80f0f0';
387
+ ctx.beginPath();
388
+ ctx.arc(player.x, player.y - player.height/6, player.width/6, 0, Math.PI * 2);
389
+ ctx.fill();
390
+
391
+ // Engine glow when moving
392
+ if (keys.ArrowUp || keys.ArrowDown || keys.ArrowLeft || keys.ArrowRight) {
393
+ ctx.fillStyle = '#ff0';
394
+ ctx.beginPath();
395
+ ctx.moveTo(player.x - player.width/2 + 5, player.y + player.height/2);
396
+ ctx.lineTo(player.x + player.width/2 - 5, player.y + player.height/2);
397
+ ctx.lineTo(player.x, player.y + player.height/1.5);
398
+ ctx.closePath();
399
+ ctx.fill();
400
+ }
401
+
402
+ ctx.restore();
403
+ }
404
+
405
+ // Player shooting
406
+ function shoot() {
407
+ const bullet = {
408
+ x: player.x,
409
+ y: player.y - player.height/2, // Start from ship's nose
410
+ width: 6,
411
+ height: 20,
412
+ speed: -10, // Moving upwards (negative y direction)
413
+ color: '#0ff'
414
+ };
415
+
416
+ bullets.push(bullet);
417
+ }
418
+
419
+ // Draw and update bullets
420
+ function updateBullets() {
421
+ for (let i = bullets.length - 1; i >= 0; i--) {
422
+ const bullet = bullets[i];
423
+
424
+ // Draw bullet
425
+ ctx.fillStyle = bullet.color;
426
+ ctx.fillRect(bullet.x - bullet.width/2, bullet.y - bullet.height/2, bullet.width, bullet.height);
427
+
428
+ // Add glow effect
429
+ ctx.save();
430
+ ctx.fillStyle = '#fff';
431
+ ctx.globalAlpha = 0.5;
432
+ ctx.beginPath();
433
+ ctx.arc(bullet.x, bullet.y, bullet.width * 1.5, 0, Math.PI * 2);
434
+ ctx.fill();
435
+ ctx.restore();
436
+
437
+ // Move bullet based on its speed (negative for player, positive for enemies)
438
+ bullet.y += bullet.speed;
439
+
440
+ // Remove if off screen
441
+ if (bullet.y < -bullet.height || bullet.y > canvas.height + bullet.height) {
442
+ bullets.splice(i, 1);
443
+ }
444
+ }
445
+ }
446
+
447
+ // Spawn enemies
448
+ function spawnEnemy() {
449
+ const size = 30 + Math.random() * 20;
450
+ const enemy = {
451
+ x: Math.random() * (canvas.width - size) + size/2,
452
+ y: -size,
453
+ width: size,
454
+ height: size,
455
+ speedX: (Math.random() - 0.5) * 2,
456
+ speedY: 1 + Math.random() * 2, // Slower enemy speed
457
+ color: `hsl(${Math.random() * 60}, 100%, 50%)`,
458
+ health: Math.ceil(size / 15), // More balanced health
459
+ lastShootTime: 0,
460
+ shootInterval: 2500 + Math.random() * 3000,
461
+ value: Math.floor(size / 5)
462
+ };
463
+
464
+ enemies.push(enemy);
465
+ }
466
+
467
+ // Draw and update enemies
468
+ function updateEnemies() {
469
+ for (let i = enemies.length - 1; i >= 0; i--) {
470
+ const enemy = enemies[i];
471
+
472
+ // Draw enemy ship
473
+ ctx.save();
474
+ ctx.fillStyle = enemy.color;
475
+ ctx.beginPath();
476
+ ctx.moveTo(enemy.x, enemy.y + enemy.height/2);
477
+ ctx.lineTo(enemy.x + enemy.width/2, enemy.y - enemy.height/2);
478
+ ctx.lineTo(enemy.x - enemy.width/2, enemy.y - enemy.height/2);
479
+ ctx.closePath();
480
+ ctx.fill();
481
+
482
+ // Enemy cockpit
483
+ ctx.fillStyle = '#ff0';
484
+ ctx.beginPath();
485
+ ctx.arc(enemy.x, enemy.y - enemy.height/6, enemy.width/6, 0, Math.PI * 2);
486
+ ctx.fill();
487
+ ctx.restore();
488
+
489
+ // Move enemy
490
+ enemy.x += enemy.speedX;
491
+ enemy.y += enemy.speedY;
492
+
493
+ // Change direction near edges
494
+ if (enemy.x < enemy.width/2 || enemy.x > canvas.width - enemy.width/2) {
495
+ enemy.speedX *= -1;
496
+ }
497
+
498
+ // Enemy shooting
499
+ const now = Date.now();
500
+ if (now - enemy.lastShootTime > enemy.shootInterval) {
501
+ enemy.lastShootTime = now;
502
+ const enemyBullet = {
503
+ x: enemy.x,
504
+ y: enemy.y + enemy.height/2,
505
+ width: 6,
506
+ height: 20,
507
+ speed: 5, // Positive speed moves bullets downward
508
+ color: enemy.color
509
+ };
510
+ bullets.push(enemyBullet);
511
+ }
512
+
513
+ // Remove if off screen
514
+ if (enemy.y > canvas.height + enemy.height) {
515
+ enemies.splice(i, 1);
516
+ }
517
+ }
518
+ }
519
+
520
+ // Collision detection
521
+ function checkCollisions() {
522
+ // Player bullets hitting enemies
523
+ for (let i = bullets.length - 1; i >= 0; i--) {
524
+ const bullet = bullets[i];
525
+
526
+ // Skip enemy bullets (positive speed)
527
+ if (bullet.speed > 0) continue;
528
+
529
+ for (let j = enemies.length - 1; j >= 0; j--) {
530
+ const enemy = enemies[j];
531
+
532
+ if (
533
+ bullet.x + bullet.width/2 > enemy.x - enemy.width/2 &&
534
+ bullet.x - bullet.width/2 < enemy.x + enemy.width/2 &&
535
+ bullet.y - bullet.height/2 < enemy.y + enemy.height/2 &&
536
+ bullet.y + bullet.height/2 > enemy.y - enemy.height/2
537
+ ) {
538
+ // Hit detected
539
+ createExplosion(enemy.x, enemy.y, enemy.color);
540
+ enemy.health--;
541
+
542
+ // Remove bullet
543
+ bullets.splice(i, 1);
544
+
545
+ // Remove enemy if health is 0 and add score
546
+ if (enemy.health <= 0) {
547
+ enemies.splice(j, 1);
548
+ score += enemy.value;
549
+ scoreDisplay.textContent = `Score: ${score}`;
550
+ }
551
+
552
+ break;
553
+ }
554
+ }
555
+ }
556
+
557
+ // Enemy bullets hitting player
558
+ for (let i = bullets.length - 1; i >= 0; i--) {
559
+ const bullet = bullets[i];
560
+
561
+ // Skip player bullets (negative speed)
562
+ if (bullet.speed < 0) continue;
563
+
564
+ if (
565
+ bullet.x + bullet.width/2 > player.x - player.width/2 &&
566
+ bullet.x - bullet.width/2 < player.x + player.width/2 &&
567
+ bullet.y - bullet.height/2 < player.y + player.height/2 &&
568
+ bullet.y + bullet.height/2 > player.y - player.height/2
569
+ ) {
570
+ // Hit detected
571
+ createExplosion(bullet.x, bullet.y, '#f00');
572
+ player.health -= 10;
573
+ updateHealthBar();
574
+
575
+ // Remove bullet
576
+ bullets.splice(i, 1);
577
+
578
+ // Check if player is dead
579
+ if (player.health <= 0) {
580
+ gameOver();
581
+ }
582
+ }
583
+ }
584
+
585
+ // Enemies hitting player
586
+ for (let i = enemies.length - 1; i >= 0; i--) {
587
+ const enemy = enemies[i];
588
+
589
+ if (
590
+ player.x < enemy.x + enemy.width/2 &&
591
+ player.x > enemy.x - enemy.width/2 &&
592
+ player.y < enemy.y + enemy.height/2 &&
593
+ player.y > enemy.y - enemy.height/2
594
+ ) {
595
+ // Collision detected
596
+ createExplosion(enemy.x, enemy.y, enemy.color);
597
+ player.health -= 20;
598
+ updateHealthBar();
599
+ enemies.splice(i, 1);
600
+
601
+ // Check if player is dead
602
+ if (player.health <= 0) {
603
+ gameOver();
604
+ }
605
+ }
606
+ }
607
+ }
608
+
609
+ // Create explosion effect
610
+ function createExplosion(x, y, color) {
611
+ const explosion = document.createElement('div');
612
+ explosion.className = 'explosion';
613
+ explosion.style.left = `${x - 15}px`;
614
+ explosion.style.top = `${y - 15}px`;
615
+ explosion.style.backgroundColor = color;
616
+ document.getElementById('gameContainer').appendChild(explosion);
617
+
618
+ // Remove after animation
619
+ setTimeout(() => {
620
+ explosion.remove();
621
+ }, 500);
622
+ }
623
+
624
+ // Update health bar display
625
+ function updateHealthBar() {
626
+ const percent = (player.health / player.maxHealth) * 100;
627
+ healthProgress.style.width = `${percent}%`;
628
+
629
+ // Change color based on health
630
+ if (percent > 60) {
631
+ healthProgress.style.backgroundColor = '#0f0';
632
+ } else if (percent > 30) {
633
+ healthProgress.style.backgroundColor = '#ff0';
634
+ } else {
635
+ healthProgress.style.backgroundColor = '#f00';
636
+ }
637
+ }
638
+
639
+ // Game over
640
+ function gameOver() {
641
+ gameRunning = false;
642
+ finalScore.textContent = `Your score: ${score}`;
643
+ gameOverScreen.style.display = 'flex';
644
+ if (animationFrameId) {
645
+ cancelAnimationFrame(animationFrameId);
646
+ }
647
+ }
648
+
649
+ // Reset game
650
+ function resetGame() {
651
+ player.x = canvas.width / 2;
652
+ player.y = canvas.height - 100;
653
+ player.health = player.maxHealth;
654
+ bullets.length = 0;
655
+ enemies.length = 0;
656
+ score = 0;
657
+ scoreDisplay.textContent = `Score: ${score}`;
658
+ updateHealthBar();
659
+ enemySpawnInterval = 1500;
660
+ enemySpawnTimer = 0;
661
+ }
662
+
663
+ // Game loop
664
+ function gameLoop(timestamp) {
665
+ if (!gameRunning) return;
666
+
667
+ if (!lastTime) lastTime = timestamp;
668
+ const deltaTime = timestamp - lastTime;
669
+ lastTime = timestamp;
670
+
671
+ // Clear canvas
672
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
673
+
674
+ // Update player position
675
+ if (keys.ArrowLeft && player.x > player.width/2) {
676
+ player.x -= player.speed;
677
+ }
678
+ if (keys.ArrowRight && player.x < canvas.width - player.width/2) {
679
+ player.x += player.speed;
680
+ }
681
+ if (keys.ArrowUp && player.y > player.height/2) {
682
+ player.y -= player.speed;
683
+ }
684
+ if (keys.ArrowDown && player.y < canvas.height - player.height/2) {
685
+ player.y += player.speed;
686
+ }
687
+
688
+ // Handle shooting
689
+ if (keys[' '] && player.shootCooldown <= 0) {
690
+ shoot();
691
+ player.shootCooldown = player.shootInterval;
692
+ }
693
+ player.shootCooldown -= deltaTime;
694
+
695
+ // Spawn enemies
696
+ enemySpawnTimer += deltaTime;
697
+ if (enemySpawnTimer >= enemySpawnInterval) {
698
+ enemySpawnTimer = 0;
699
+ spawnEnemy();
700
+
701
+ // Slightly increase spawn rate over time
702
+ enemySpawnInterval = Math.max(1000, 1500 - score * 0.5);
703
+ }
704
+
705
+ // Update game objects
706
+ drawPlayer();
707
+ updateBullets();
708
+ updateEnemies();
709
+ checkCollisions();
710
+
711
+ // Continue game loop
712
+ animationFrameId = requestAnimationFrame(gameLoop);
713
+ }
714
+
715
+ // Start game
716
+ startButton.addEventListener('click', () => {
717
+ resetGame();
718
+ startScreen.style.display = 'none';
719
+ gameRunning = true;
720
+ lastTime = 0; // Reset lastTime
721
+ animationFrameId = requestAnimationFrame(gameLoop);
722
+ });
723
+
724
+ // Restart game
725
+ restartButton.addEventListener('click', () => {
726
+ resetGame();
727
+ gameOverScreen.style.display = 'none';
728
+ gameRunning = true;
729
+ lastTime = 0; // Reset lastTime
730
+ animationFrameId = requestAnimationFrame(gameLoop);
731
+ });
732
+ </script>
733
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <a href="https://enzostvs-deepsite.hf.space" style="color: #fff;" target="_blank" >DeepSite</a> <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;"></p></body>
734
+ </html>