Sushil kumar commited on
Commit
1ce99fc
·
verified ·
1 Parent(s): 6e9d686

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +1238 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Space
3
- emoji: 👁
4
  colorFrom: green
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: space
3
+ emoji: 🐳
4
  colorFrom: green
5
+ colorTo: yellow
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,1238 @@
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>Galactic Defender</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ body {
11
+ margin: 0;
12
+ overflow: hidden;
13
+ background-color: #111;
14
+ font-family: 'Arial', sans-serif;
15
+ }
16
+ #gameCanvas {
17
+ display: block;
18
+ margin: 0 auto;
19
+ background-color: #000;
20
+ }
21
+ #gameContainer {
22
+ position: relative;
23
+ width: 100vw;
24
+ height: 100vh;
25
+ display: flex;
26
+ justify-content: center;
27
+ align-items: center;
28
+ }
29
+ #startScreen, #gameOverScreen, #pauseScreen {
30
+ position: absolute;
31
+ width: 100%;
32
+ height: 100%;
33
+ display: flex;
34
+ flex-direction: column;
35
+ justify-content: center;
36
+ align-items: center;
37
+ background-color: rgba(0, 0, 0, 0.8);
38
+ color: white;
39
+ z-index: 10;
40
+ }
41
+ #gameOverScreen, #pauseScreen {
42
+ display: none;
43
+ }
44
+ .btn {
45
+ background: linear-gradient(135deg, #6e8efb, #a777e3);
46
+ border: none;
47
+ color: white;
48
+ padding: 12px 24px;
49
+ margin: 10px;
50
+ border-radius: 30px;
51
+ font-size: 18px;
52
+ cursor: pointer;
53
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
54
+ transition: all 0.3s ease;
55
+ }
56
+ .btn:hover {
57
+ transform: translateY(-3px);
58
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
59
+ }
60
+ .btn:active {
61
+ transform: translateY(1px);
62
+ }
63
+ .title {
64
+ font-size: 48px;
65
+ margin-bottom: 20px;
66
+ background: linear-gradient(135deg, #6e8efb, #a777e3);
67
+ -webkit-background-clip: text;
68
+ background-clip: text;
69
+ color: transparent;
70
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
71
+ }
72
+ .score-display {
73
+ font-size: 24px;
74
+ margin-bottom: 30px;
75
+ }
76
+ .powerup {
77
+ position: absolute;
78
+ font-size: 24px;
79
+ animation: float 2s infinite ease-in-out;
80
+ }
81
+ @keyframes float {
82
+ 0%, 100% { transform: translateY(0); }
83
+ 50% { transform: translateY(-10px); }
84
+ }
85
+ .leaderboard {
86
+ background: rgba(0, 0, 0, 0.6);
87
+ padding: 20px;
88
+ border-radius: 10px;
89
+ margin-top: 20px;
90
+ max-height: 200px;
91
+ overflow-y: auto;
92
+ }
93
+ .leaderboard-item {
94
+ display: flex;
95
+ justify-content: space-between;
96
+ padding: 5px 10px;
97
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
98
+ }
99
+ .difficulty-selector {
100
+ margin: 20px 0;
101
+ display: flex;
102
+ gap: 10px;
103
+ }
104
+ .difficulty-btn {
105
+ padding: 8px 16px;
106
+ border-radius: 20px;
107
+ cursor: pointer;
108
+ transition: all 0.3s;
109
+ }
110
+ .difficulty-btn.active {
111
+ background: linear-gradient(135deg, #6e8efb, #a777e3);
112
+ box-shadow: 0 0 10px rgba(110, 142, 251, 0.5);
113
+ }
114
+ </style>
115
+ </head>
116
+ <body>
117
+ <div id="gameContainer">
118
+ <canvas id="gameCanvas"></canvas>
119
+
120
+ <div id="startScreen">
121
+ <h1 class="title">GALACTIC DEFENDER</h1>
122
+ <p class="text-white mb-8 text-lg">Defend the galaxy from alien invaders!</p>
123
+
124
+ <div class="difficulty-selector">
125
+ <div class="difficulty-btn active" data-difficulty="easy">Easy</div>
126
+ <div class="difficulty-btn" data-difficulty="medium">Medium</div>
127
+ <div class="difficulty-btn" data-difficulty="hard">Hard</div>
128
+ </div>
129
+
130
+ <button id="startBtn" class="btn">
131
+ <i class="fas fa-play mr-2"></i> START GAME
132
+ </button>
133
+
134
+ <div class="mt-8 text-gray-400 text-center">
135
+ <p class="font-bold mb-2">Controls:</p>
136
+ <p><i class="fas fa-arrow-left mr-2"></i> <i class="fas fa-arrow-right mr-2"></i> Move</p>
137
+ <p><i class="fas fa-arrow-up mr-2"></i> <i class="fas fa-arrow-down mr-2"></i> Move</p>
138
+ <p><i class="fas fa-space-shuttle mr-2"></i> Shoot</p>
139
+ <p><i class="fas fa-pause mr-2"></i> Pause</p>
140
+ </div>
141
+
142
+ <div class="leaderboard mt-8 w-64">
143
+ <h3 class="text-center mb-2">TOP SCORES</h3>
144
+ <div id="leaderboardList">
145
+ <!-- Leaderboard items will be added here -->
146
+ </div>
147
+ </div>
148
+ </div>
149
+
150
+ <div id="gameOverScreen">
151
+ <h1 class="title">MISSION FAILED</h1>
152
+ <p id="finalScore" class="score-display">Score: 0</p>
153
+ <p id="highScore" class="text-gray-400 mb-4">High Score: 0</p>
154
+ <button id="restartBtn" class="btn">
155
+ <i class="fas fa-redo mr-2"></i> TRY AGAIN
156
+ </button>
157
+ <button id="menuBtn" class="btn mt-4">
158
+ <i class="fas fa-home mr-2"></i> MAIN MENU
159
+ </button>
160
+ </div>
161
+
162
+ <div id="pauseScreen">
163
+ <h1 class="title">GAME PAUSED</h1>
164
+ <p class="text-white mb-8">Current Score: <span id="pauseScore">0</span></p>
165
+ <button id="resumeBtn" class="btn">
166
+ <i class="fas fa-play mr-2"></i> RESUME
167
+ </button>
168
+ <button id="quitBtn" class="btn mt-4">
169
+ <i class="fas fa-sign-out-alt mr-2"></i> QUIT
170
+ </button>
171
+ </div>
172
+ </div>
173
+
174
+ <audio id="shootSound" src="https://assets.mixkit.co/sfx/preview/mixkit-laser-weapon-shot-1681.mp3" preload="auto"></audio>
175
+ <audio id="explosionSound" src="https://assets.mixkit.co/sfx/preview/mixkit-explosion-impact-1684.mp3" preload="auto"></audio>
176
+ <audio id="powerupSound" src="https://assets.mixkit.co/sfx/preview/mixkit-power-up-electricity-2580.mp3" preload="auto"></audio>
177
+ <audio id="bgMusic" loop src="https://assets.mixkit.co/music/preview/mixkit-game-show-idea-229.mp3" preload="auto"></audio>
178
+
179
+ <script>
180
+ // Game variables
181
+ const canvas = document.getElementById('gameCanvas');
182
+ const ctx = canvas.getContext('2d');
183
+ const startScreen = document.getElementById('startScreen');
184
+ const gameOverScreen = document.getElementById('gameOverScreen');
185
+ const pauseScreen = document.getElementById('pauseScreen');
186
+ const startBtn = document.getElementById('startBtn');
187
+ const restartBtn = document.getElementById('restartBtn');
188
+ const menuBtn = document.getElementById('menuBtn');
189
+ const resumeBtn = document.getElementById('resumeBtn');
190
+ const quitBtn = document.getElementById('quitBtn');
191
+ const finalScore = document.getElementById('finalScore');
192
+ const highScore = document.getElementById('highScore');
193
+ const pauseScore = document.getElementById('pauseScore');
194
+ const leaderboardList = document.getElementById('leaderboardList');
195
+ const difficultyBtns = document.querySelectorAll('.difficulty-btn');
196
+
197
+ // Sound elements
198
+ const shootSound = document.getElementById('shootSound');
199
+ const explosionSound = document.getElementById('explosionSound');
200
+ const powerupSound = document.getElementById('powerupSound');
201
+ const bgMusic = document.getElementById('bgMusic');
202
+
203
+ // Set canvas size
204
+ canvas.width = window.innerWidth * 0.9;
205
+ canvas.height = window.innerHeight * 0.9;
206
+
207
+ // Game state
208
+ let gameRunning = false;
209
+ let gamePaused = false;
210
+ let score = 0;
211
+ let lives = 3;
212
+ let level = 1;
213
+ let difficulty = 'easy';
214
+ let asteroids = [];
215
+ let bullets = [];
216
+ let explosions = [];
217
+ let powerups = [];
218
+ let enemies = [];
219
+ let stars = [];
220
+ let lastAsteroidTime = 0;
221
+ let asteroidInterval = 2000; // ms
222
+ let keys = {};
223
+ let leaderboard = JSON.parse(localStorage.getItem('spaceShooterLeaderboard')) || [];
224
+ let playerPowerups = {
225
+ rapidFire: false,
226
+ tripleShot: false,
227
+ shield: false
228
+ };
229
+ let powerupEndTime = 0;
230
+
231
+ // Player object
232
+ const player = {
233
+ x: canvas.width / 2,
234
+ y: canvas.height - 60,
235
+ width: 40,
236
+ height: 60,
237
+ speed: 5,
238
+ color: '#6e8efb',
239
+ lastShot: 0,
240
+ shootDelay: 300, // ms
241
+ draw() {
242
+ ctx.save();
243
+
244
+ // Draw shield if active
245
+ if (playerPowerups.shield) {
246
+ ctx.beginPath();
247
+ ctx.arc(this.x, this.y, this.width + 15, 0, Math.PI * 2);
248
+ ctx.strokeStyle = 'rgba(100, 200, 255, 0.7)';
249
+ ctx.lineWidth = 3;
250
+ ctx.stroke();
251
+ }
252
+
253
+ // Draw spaceship (triangle)
254
+ ctx.fillStyle = this.color;
255
+ ctx.beginPath();
256
+ ctx.moveTo(this.x, this.y - this.height/2);
257
+ ctx.lineTo(this.x - this.width/2, this.y + this.height/2);
258
+ ctx.lineTo(this.x + this.width/2, this.y + this.height/2);
259
+ ctx.closePath();
260
+ ctx.fill();
261
+
262
+ // Draw cockpit
263
+ ctx.fillStyle = '#a777e3';
264
+ ctx.beginPath();
265
+ ctx.arc(this.x, this.y - 10, 10, 0, Math.PI * 2);
266
+ ctx.fill();
267
+
268
+ // Draw engine glow
269
+ if (keys['ArrowUp'] || keys['ArrowLeft'] || keys['ArrowRight'] || keys['ArrowDown']) {
270
+ ctx.fillStyle = '#ff5555';
271
+ ctx.beginPath();
272
+ ctx.moveTo(this.x - this.width/3, this.y + this.height/2);
273
+ ctx.lineTo(this.x + this.width/3, this.y + this.height/2);
274
+ ctx.lineTo(this.x, this.y + this.height/2 + 15);
275
+ ctx.closePath();
276
+ ctx.fill();
277
+ }
278
+
279
+ ctx.restore();
280
+ },
281
+ update() {
282
+ if (keys['ArrowLeft'] && this.x > this.width/2) {
283
+ this.x -= this.speed;
284
+ }
285
+ if (keys['ArrowRight'] && this.x < canvas.width - this.width/2) {
286
+ this.x += this.speed;
287
+ }
288
+ if (keys['ArrowUp'] && this.y > this.height/2) {
289
+ this.y -= this.speed;
290
+ }
291
+ if (keys['ArrowDown'] && this.y < canvas.height - this.height/2) {
292
+ this.y += this.speed;
293
+ }
294
+ },
295
+ shoot() {
296
+ const now = Date.now();
297
+ if (now - this.lastShot > (playerPowerups.rapidFire ? this.shootDelay / 2 : this.shootDelay)) {
298
+ if (playerPowerups.tripleShot) {
299
+ // Triple shot
300
+ bullets.push({
301
+ x: this.x - 15,
302
+ y: this.y - this.height/2,
303
+ radius: 5,
304
+ speed: 10,
305
+ color: '#ff5555',
306
+ angle: -0.2
307
+ });
308
+ bullets.push({
309
+ x: this.x,
310
+ y: this.y - this.height/2,
311
+ radius: 5,
312
+ speed: 10,
313
+ color: '#ff5555',
314
+ angle: 0
315
+ });
316
+ bullets.push({
317
+ x: this.x + 15,
318
+ y: this.y - this.height/2,
319
+ radius: 5,
320
+ speed: 10,
321
+ color: '#ff5555',
322
+ angle: 0.2
323
+ });
324
+ } else {
325
+ // Single shot
326
+ bullets.push({
327
+ x: this.x,
328
+ y: this.y - this.height/2,
329
+ radius: 5,
330
+ speed: 10,
331
+ color: '#ff5555',
332
+ angle: 0
333
+ });
334
+ }
335
+ this.lastShot = now;
336
+
337
+ // Play shoot sound
338
+ playSound('shoot');
339
+ }
340
+ }
341
+ };
342
+
343
+ // Create stars for background
344
+ function createStars() {
345
+ stars = [];
346
+ for (let i = 0; i < 200; i++) {
347
+ stars.push({
348
+ x: Math.random() * canvas.width,
349
+ y: Math.random() * canvas.height,
350
+ radius: Math.random() * 2,
351
+ speed: Math.random() * 0.5 + 0.1,
352
+ alpha: Math.random() * 0.5 + 0.5
353
+ });
354
+ }
355
+ }
356
+
357
+ // Draw stars
358
+ function drawStars() {
359
+ ctx.save();
360
+ stars.forEach(star => {
361
+ ctx.beginPath();
362
+ ctx.arc(star.x, star.y, star.radius, 0, Math.PI * 2);
363
+ ctx.fillStyle = `rgba(255, 255, 255, ${star.alpha})`;
364
+ ctx.fill();
365
+
366
+ // Move stars
367
+ star.y += star.speed;
368
+ if (star.y > canvas.height) {
369
+ star.y = 0;
370
+ star.x = Math.random() * canvas.width;
371
+ }
372
+ });
373
+ ctx.restore();
374
+ }
375
+
376
+ // Create asteroid
377
+ function createAsteroid() {
378
+ const size = Math.random() * 30 + 20;
379
+ const x = Math.random() * (canvas.width - size * 2) + size;
380
+ asteroids.push({
381
+ x: x,
382
+ y: -size,
383
+ size: size,
384
+ speed: Math.random() * 2 + 1 + level * 0.2,
385
+ rotation: 0,
386
+ rotationSpeed: Math.random() * 0.02 - 0.01,
387
+ vertices: Math.floor(Math.random() * 5) + 5,
388
+ offset: Array.from({length: Math.floor(Math.random() * 5) + 5}, () => Math.random() * 10 - 5),
389
+ health: Math.floor(size / 10)
390
+ });
391
+ }
392
+
393
+ // Create enemy ship
394
+ function createEnemyShip() {
395
+ const types = ['basic', 'shooter', 'fast'];
396
+ const type = types[Math.floor(Math.random() * types.length)];
397
+ const size = 40;
398
+ const x = Math.random() * (canvas.width - size * 2) + size;
399
+
400
+ let enemy = {
401
+ x: x,
402
+ y: -size,
403
+ width: size,
404
+ height: size,
405
+ speed: 1 + level * 0.1,
406
+ type: type,
407
+ lastShot: 0,
408
+ shootDelay: 2000,
409
+ health: type === 'basic' ? 1 : (type === 'shooter' ? 2 : 1),
410
+ color: type === 'basic' ? '#ff5555' : (type === 'shooter' ? '#55ff55' : '#5555ff')
411
+ };
412
+
413
+ // Adjust properties based on type
414
+ if (type === 'fast') {
415
+ enemy.speed *= 2;
416
+ }
417
+
418
+ enemies.push(enemy);
419
+ }
420
+
421
+ // Create powerup
422
+ function createPowerup(x, y) {
423
+ const types = ['rapidFire', 'tripleShot', 'shield', 'extraLife'];
424
+ const type = types[Math.floor(Math.random() * types.length)];
425
+
426
+ powerups.push({
427
+ x: x,
428
+ y: y,
429
+ type: type,
430
+ radius: 15,
431
+ speed: 2,
432
+ color: getPowerupColor(type)
433
+ });
434
+ }
435
+
436
+ // Get powerup color by type
437
+ function getPowerupColor(type) {
438
+ switch(type) {
439
+ case 'rapidFire': return '#ffcc00';
440
+ case 'tripleShot': return '#00ccff';
441
+ case 'shield': return '#00ffcc';
442
+ case 'extraLife': return '#ff00cc';
443
+ default: return '#ffffff';
444
+ }
445
+ }
446
+
447
+ // Get powerup icon by type
448
+ function getPowerupIcon(type) {
449
+ switch(type) {
450
+ case 'rapidFire': return 'fa-bolt';
451
+ case 'tripleShot': return 'fa-crosshairs';
452
+ case 'shield': return 'fa-shield-alt';
453
+ case 'extraLife': return 'fa-heart';
454
+ default: return 'fa-star';
455
+ }
456
+ }
457
+
458
+ // Draw asteroid
459
+ function drawAsteroid(asteroid) {
460
+ ctx.save();
461
+ ctx.translate(asteroid.x, asteroid.y);
462
+ ctx.rotate(asteroid.rotation);
463
+
464
+ ctx.beginPath();
465
+ for (let i = 0; i < asteroid.vertices; i++) {
466
+ const angle = (i / asteroid.vertices) * Math.PI * 2;
467
+ const radius = asteroid.size + asteroid.offset[i % asteroid.offset.length];
468
+ const x = Math.cos(angle) * radius;
469
+ const y = Math.sin(angle) * radius;
470
+
471
+ if (i === 0) {
472
+ ctx.moveTo(x, y);
473
+ } else {
474
+ ctx.lineTo(x, y);
475
+ }
476
+ }
477
+ ctx.closePath();
478
+
479
+ ctx.fillStyle = '#888';
480
+ ctx.fill();
481
+ ctx.strokeStyle = '#555';
482
+ ctx.lineWidth = 2;
483
+ ctx.stroke();
484
+
485
+ // Draw health bar if asteroid has health > 1
486
+ if (asteroid.health > 1) {
487
+ const healthPercent = asteroid.health / Math.floor(asteroid.size / 10);
488
+ ctx.fillStyle = 'red';
489
+ ctx.fillRect(-asteroid.size/2, -asteroid.size/2 - 10, asteroid.size, 5);
490
+ ctx.fillStyle = 'lime';
491
+ ctx.fillRect(-asteroid.size/2, -asteroid.size/2 - 10, asteroid.size * healthPercent, 5);
492
+ }
493
+
494
+ ctx.restore();
495
+ }
496
+
497
+ // Draw enemy ship
498
+ function drawEnemyShip(enemy) {
499
+ ctx.save();
500
+ ctx.translate(enemy.x, enemy.y);
501
+
502
+ // Draw different enemy types
503
+ if (enemy.type === 'basic') {
504
+ // Basic triangle enemy
505
+ ctx.fillStyle = enemy.color;
506
+ ctx.beginPath();
507
+ ctx.moveTo(0, -enemy.height/2);
508
+ ctx.lineTo(-enemy.width/2, enemy.height/2);
509
+ ctx.lineTo(enemy.width/2, enemy.height/2);
510
+ ctx.closePath();
511
+ ctx.fill();
512
+
513
+ // Draw cockpit
514
+ ctx.fillStyle = '#ffffff';
515
+ ctx.beginPath();
516
+ ctx.arc(0, -5, 5, 0, Math.PI * 2);
517
+ ctx.fill();
518
+ }
519
+ else if (enemy.type === 'shooter') {
520
+ // Shooter enemy (rectangle with turret)
521
+ ctx.fillStyle = enemy.color;
522
+ ctx.fillRect(-enemy.width/2, -enemy.height/2, enemy.width, enemy.height);
523
+
524
+ // Draw turret
525
+ ctx.fillStyle = '#ffffff';
526
+ ctx.fillRect(-5, -enemy.height/2 - 10, 10, 10);
527
+ }
528
+ else if (enemy.type === 'fast') {
529
+ // Fast enemy (small and sleek)
530
+ ctx.fillStyle = enemy.color;
531
+ ctx.beginPath();
532
+ ctx.moveTo(0, -enemy.height/2);
533
+ ctx.lineTo(-enemy.width/3, enemy.height/2);
534
+ ctx.lineTo(enemy.width/3, enemy.height/2);
535
+ ctx.closePath();
536
+ ctx.fill();
537
+
538
+ // Draw engine glow
539
+ ctx.fillStyle = '#ffffff';
540
+ ctx.beginPath();
541
+ ctx.moveTo(-enemy.width/4, enemy.height/2);
542
+ ctx.lineTo(enemy.width/4, enemy.height/2);
543
+ ctx.lineTo(0, enemy.height/2 + 8);
544
+ ctx.closePath();
545
+ ctx.fill();
546
+ }
547
+
548
+ // Draw health bar if enemy has health > 1
549
+ if (enemy.health > 1) {
550
+ const healthPercent = enemy.type === 'shooter' ? enemy.health / 2 : enemy.health;
551
+ ctx.fillStyle = 'red';
552
+ ctx.fillRect(-enemy.width/2, -enemy.height/2 - 10, enemy.width, 5);
553
+ ctx.fillStyle = 'lime';
554
+ ctx.fillRect(-enemy.width/2, -enemy.height/2 - 10, enemy.width * healthPercent, 5);
555
+ }
556
+
557
+ ctx.restore();
558
+ }
559
+
560
+ // Draw bullet
561
+ function drawBullet(bullet) {
562
+ ctx.save();
563
+ ctx.fillStyle = bullet.color;
564
+
565
+ // If bullet has angle (for triple shot), adjust position
566
+ if (bullet.angle) {
567
+ bullet.x += Math.sin(bullet.angle) * 2;
568
+ }
569
+
570
+ ctx.beginPath();
571
+ ctx.arc(bullet.x, bullet.y, bullet.radius, 0, Math.PI * 2);
572
+ ctx.fill();
573
+ ctx.restore();
574
+ }
575
+
576
+ // Draw enemy bullet
577
+ function drawEnemyBullet(bullet) {
578
+ ctx.save();
579
+ ctx.fillStyle = '#ff00ff';
580
+ ctx.beginPath();
581
+ ctx.arc(bullet.x, bullet.y, bullet.radius, 0, Math.PI * 2);
582
+ ctx.fill();
583
+
584
+ // Add glow effect
585
+ ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
586
+ ctx.beginPath();
587
+ ctx.arc(bullet.x, bullet.y, bullet.radius + 2, 0, Math.PI * 2);
588
+ ctx.fill();
589
+ ctx.restore();
590
+ }
591
+
592
+ // Draw powerup
593
+ function drawPowerup(powerup) {
594
+ ctx.save();
595
+
596
+ // Draw outer circle
597
+ ctx.beginPath();
598
+ ctx.arc(powerup.x, powerup.y, powerup.radius, 0, Math.PI * 2);
599
+ ctx.fillStyle = powerup.color;
600
+ ctx.fill();
601
+
602
+ // Draw inner circle
603
+ ctx.beginPath();
604
+ ctx.arc(powerup.x, powerup.y, powerup.radius - 5, 0, Math.PI * 2);
605
+ ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
606
+ ctx.fill();
607
+
608
+ ctx.restore();
609
+
610
+ // Draw icon using DOM element (since we can't draw Font Awesome icons on canvas)
611
+ const icon = document.createElement('div');
612
+ icon.className = `powerup fas ${getPowerupIcon(powerup.type)}`;
613
+ icon.style.color = 'white';
614
+ icon.style.left = `${powerup.x - 12}px`;
615
+ icon.style.top = `${powerup.y - 12}px`;
616
+ icon.style.zIndex = '5';
617
+ document.getElementById('gameContainer').appendChild(icon);
618
+
619
+ // Remove icon after animation frame
620
+ setTimeout(() => {
621
+ if (icon.parentNode) {
622
+ icon.parentNode.removeChild(icon);
623
+ }
624
+ }, 16);
625
+ }
626
+
627
+ // Draw explosion
628
+ function drawExplosion(explosion) {
629
+ ctx.save();
630
+ ctx.globalAlpha = explosion.alpha;
631
+ ctx.fillStyle = explosion.color;
632
+
633
+ for (let i = 0; i < explosion.particles; i++) {
634
+ const angle = (i / explosion.particles) * Math.PI * 2;
635
+ const distance = explosion.radius * (1 - explosion.progress);
636
+ const x = explosion.x + Math.cos(angle) * distance;
637
+ const y = explosion.y + Math.sin(angle) * distance;
638
+
639
+ ctx.beginPath();
640
+ ctx.arc(x, y, explosion.particleSize, 0, Math.PI * 2);
641
+ ctx.fill();
642
+ }
643
+
644
+ ctx.restore();
645
+ }
646
+
647
+ // Check collision between two objects
648
+ function checkCollision(obj1, obj2) {
649
+ // Simple circle collision detection
650
+ const dx = obj1.x - obj2.x;
651
+ const dy = obj1.y - obj2.y;
652
+ const distance = Math.sqrt(dx * dx + dy * dy);
653
+
654
+ if (obj1.radius && obj2.radius) {
655
+ return distance < obj1.radius + obj2.radius;
656
+ }
657
+
658
+ // For player (triangle) vs asteroid/enemy
659
+ if (obj1 === player || obj2 === player) {
660
+ const playerObj = obj1 === player ? obj1 : obj2;
661
+ const otherObj = obj1 === player ? obj2 : obj1;
662
+
663
+ // Simplified collision - check if object center is within player bounds
664
+ return (
665
+ otherObj.x > playerObj.x - playerObj.width/2 &&
666
+ otherObj.x < playerObj.x + playerObj.width/2 &&
667
+ otherObj.y > playerObj.y - playerObj.height/2 &&
668
+ otherObj.y < playerObj.y + playerObj.height/2
669
+ );
670
+ }
671
+
672
+ // For bullet vs asteroid/enemy
673
+ if (obj1.radius && (obj2.size || obj2.width)) {
674
+ const bullet = obj1.radius ? obj1 : obj2;
675
+ const target = obj1.radius ? obj2 : obj1;
676
+
677
+ if (target.size) {
678
+ // Asteroid
679
+ return distance < bullet.radius + target.size;
680
+ } else {
681
+ // Enemy ship
682
+ return (
683
+ bullet.x > target.x - target.width/2 &&
684
+ bullet.x < target.x + target.width/2 &&
685
+ bullet.y > target.y - target.height/2 &&
686
+ bullet.y < target.y + target.height/2
687
+ );
688
+ }
689
+ }
690
+
691
+ return false;
692
+ }
693
+
694
+ // Create explosion
695
+ function createExplosion(x, y, color = '#ff5555', size = 30) {
696
+ explosions.push({
697
+ x: x,
698
+ y: y,
699
+ radius: size,
700
+ particles: 12,
701
+ particleSize: 3,
702
+ color: color,
703
+ alpha: 1,
704
+ progress: 0,
705
+ speed: 0.05
706
+ });
707
+
708
+ // Play explosion sound
709
+ playSound('explosion');
710
+ }
711
+
712
+ // Play sound
713
+ function playSound(type) {
714
+ try {
715
+ switch(type) {
716
+ case 'shoot':
717
+ shootSound.currentTime = 0;
718
+ shootSound.play();
719
+ break;
720
+ case 'explosion':
721
+ explosionSound.currentTime = 0;
722
+ explosionSound.play();
723
+ break;
724
+ case 'powerup':
725
+ powerupSound.currentTime = 0;
726
+ powerupSound.play();
727
+ break;
728
+ }
729
+ } catch(e) {
730
+ console.log('Error playing sound:', e);
731
+ }
732
+ }
733
+
734
+ // Draw HUD
735
+ function drawHUD() {
736
+ ctx.save();
737
+ ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
738
+ ctx.fillRect(10, 10, 200, 110);
739
+
740
+ ctx.fillStyle = 'white';
741
+ ctx.font = '20px Arial';
742
+ ctx.textAlign = 'left';
743
+ ctx.fillText(`Score: ${score}`, 20, 40);
744
+ ctx.fillText(`Lives: ${lives}`, 20, 70);
745
+ ctx.fillText(`Level: ${level}`, 20, 100);
746
+
747
+ // Draw powerup indicators
748
+ if (playerPowerups.rapidFire || playerPowerups.tripleShot || playerPowerups.shield) {
749
+ ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
750
+ ctx.fillRect(canvas.width - 160, 10, 150, 50);
751
+
752
+ ctx.fillStyle = 'white';
753
+ ctx.font = '14px Arial';
754
+ ctx.textAlign = 'right';
755
+
756
+ const remainingTime = Math.max(0, Math.ceil((powerupEndTime - Date.now()) / 1000));
757
+
758
+ if (playerPowerups.rapidFire) {
759
+ ctx.fillStyle = '#ffcc00';
760
+ ctx.fillText(`Rapid Fire: ${remainingTime}s`, canvas.width - 20, 30);
761
+ }
762
+ if (playerPowerups.tripleShot) {
763
+ ctx.fillStyle = '#00ccff';
764
+ ctx.fillText(`Triple Shot: ${remainingTime}s`, canvas.width - 20, 50);
765
+ }
766
+ if (playerPowerups.shield) {
767
+ ctx.fillStyle = '#00ffcc';
768
+ ctx.fillText(`Shield: ${remainingTime}s`, canvas.width - 20, 30);
769
+ }
770
+ }
771
+
772
+ ctx.restore();
773
+ }
774
+
775
+ // Update game state
776
+ function update() {
777
+ if (!gameRunning || gamePaused) return;
778
+
779
+ // Update player
780
+ player.update();
781
+
782
+ // Check powerup expiration
783
+ if (playerPowerups.rapidFire || playerPowerups.tripleShot || playerPowerups.shield) {
784
+ if (Date.now() > powerupEndTime) {
785
+ playerPowerups.rapidFire = false;
786
+ playerPowerups.tripleShot = false;
787
+ playerPowerups.shield = false;
788
+ }
789
+ }
790
+
791
+ // Create asteroids and enemies
792
+ const now = Date.now();
793
+ if (now - lastAsteroidTime > asteroidInterval) {
794
+ if (Math.random() < 0.7) {
795
+ createAsteroid();
796
+ } else {
797
+ createEnemyShip();
798
+ }
799
+ lastAsteroidTime = now;
800
+
801
+ // Decrease interval over time to make game harder
802
+ asteroidInterval = Math.max(500, 2000 - level * 100);
803
+
804
+ // Random chance to spawn powerup
805
+ if (Math.random() < 0.1) {
806
+ createPowerup(Math.random() * (canvas.width - 30) + 15, -30);
807
+ }
808
+ }
809
+
810
+ // Update asteroids
811
+ asteroids.forEach((asteroid, index) => {
812
+ asteroid.y += asteroid.speed;
813
+ asteroid.rotation += asteroid.rotationSpeed;
814
+
815
+ // Check if asteroid is out of screen
816
+ if (asteroid.y > canvas.height + asteroid.size) {
817
+ asteroids.splice(index, 1);
818
+ }
819
+
820
+ // Check collision with player
821
+ if (checkCollision(player, asteroid)) {
822
+ if (playerPowerups.shield) {
823
+ playerPowerups.shield = false;
824
+ createExplosion(asteroid.x, asteroid.y, '#ffff55', asteroid.size);
825
+ asteroids.splice(index, 1);
826
+ } else {
827
+ asteroids.splice(index, 1);
828
+ lives--;
829
+ createExplosion(asteroid.x, asteroid.y, '#ff5555', asteroid.size);
830
+
831
+ if (lives <= 0) {
832
+ gameOver();
833
+ }
834
+ }
835
+ }
836
+ });
837
+
838
+ // Update enemies
839
+ enemies.forEach((enemy, index) => {
840
+ enemy.y += enemy.speed;
841
+
842
+ // Enemy specific behavior
843
+ if (enemy.type === 'shooter' && now - enemy.lastShot > enemy.shootDelay) {
844
+ // Shoot at player
845
+ bullets.push({
846
+ x: enemy.x,
847
+ y: enemy.y + enemy.height/2,
848
+ radius: 5,
849
+ speed: -7,
850
+ color: '#ff00ff',
851
+ isEnemy: true
852
+ });
853
+ enemy.lastShot = now;
854
+ }
855
+
856
+ // Check if enemy is out of screen
857
+ if (enemy.y > canvas.height + enemy.height) {
858
+ enemies.splice(index, 1);
859
+ }
860
+
861
+ // Check collision with player
862
+ if (checkCollision(player, enemy)) {
863
+ if (playerPowerups.shield) {
864
+ playerPowerups.shield = false;
865
+ createExplosion(enemy.x, enemy.y, '#ffff55', enemy.width);
866
+ enemies.splice(index, 1);
867
+ } else {
868
+ enemies.splice(index, 1);
869
+ lives--;
870
+ createExplosion(enemy.x, enemy.y, '#ff5555', enemy.width);
871
+
872
+ if (lives <= 0) {
873
+ gameOver();
874
+ }
875
+ }
876
+ }
877
+ });
878
+
879
+ // Update bullets
880
+ bullets.forEach((bullet, index) => {
881
+ if (bullet.isEnemy) {
882
+ // Enemy bullets move down
883
+ bullet.y -= bullet.speed;
884
+ } else {
885
+ // Player bullets move up
886
+ bullet.y += bullet.speed;
887
+ }
888
+
889
+ // Check if bullet is out of screen
890
+ if (bullet.y < 0 || bullet.y > canvas.height) {
891
+ bullets.splice(index, 1);
892
+ return;
893
+ }
894
+
895
+ // Check collision with asteroids
896
+ asteroids.forEach((asteroid, aIndex) => {
897
+ if (checkCollision(bullet, asteroid)) {
898
+ // Reduce asteroid health
899
+ asteroid.health--;
900
+
901
+ if (asteroid.health <= 0) {
902
+ // Remove asteroid
903
+ asteroids.splice(aIndex, 1);
904
+
905
+ // Add score
906
+ score += Math.floor(asteroid.size);
907
+
908
+ // Random chance to drop powerup
909
+ if (Math.random() < 0.2) {
910
+ createPowerup(asteroid.x, asteroid.y);
911
+ }
912
+
913
+ // Create explosion
914
+ createExplosion(asteroid.x, asteroid.y, '#ffff55', asteroid.size);
915
+ }
916
+
917
+ // Remove bullet unless it's a piercing shot (future feature)
918
+ bullets.splice(index, 1);
919
+ }
920
+ });
921
+
922
+ // Check collision with enemies
923
+ enemies.forEach((enemy, eIndex) => {
924
+ if (checkCollision(bullet, enemy)) {
925
+ // Reduce enemy health
926
+ enemy.health--;
927
+
928
+ if (enemy.health <= 0) {
929
+ // Remove enemy
930
+ enemies.splice(eIndex, 1);
931
+
932
+ // Add score based on enemy type
933
+ score += enemy.type === 'basic' ? 50 : (enemy.type === 'shooter' ? 100 : 75);
934
+
935
+ // Random chance to drop powerup
936
+ if (Math.random() < 0.3) {
937
+ createPowerup(enemy.x, enemy.y);
938
+ }
939
+
940
+ // Create explosion
941
+ createExplosion(enemy.x, enemy.y, '#ffff55', enemy.width);
942
+ }
943
+
944
+ // Remove bullet
945
+ bullets.splice(index, 1);
946
+ }
947
+ });
948
+ });
949
+
950
+ // Update powerups
951
+ powerups.forEach((powerup, index) => {
952
+ powerup.y += powerup.speed;
953
+
954
+ // Check if powerup is out of screen
955
+ if (powerup.y > canvas.height + powerup.radius) {
956
+ powerups.splice(index, 1);
957
+ return;
958
+ }
959
+
960
+ // Check collision with player
961
+ if (checkCollision(player, powerup)) {
962
+ // Apply powerup effect
963
+ applyPowerup(powerup.type);
964
+ powerups.splice(index, 1);
965
+
966
+ // Play powerup sound
967
+ playSound('powerup');
968
+ }
969
+ });
970
+
971
+ // Update explosions
972
+ explosions.forEach((explosion, index) => {
973
+ explosion.progress += explosion.speed;
974
+ explosion.alpha = 1 - explosion.progress;
975
+
976
+ if (explosion.progress >= 1) {
977
+ explosions.splice(index, 1);
978
+ }
979
+ });
980
+
981
+ // Level up every 500 points
982
+ if (score > 0 && score % 500 === 0 && score / 500 >= level) {
983
+ level++;
984
+ createExplosion(canvas.width / 2, canvas.height / 2, '#ffffff', 100);
985
+ }
986
+ }
987
+
988
+ // Apply powerup effect
989
+ function applyPowerup(type) {
990
+ // Set powerup duration (10 seconds)
991
+ powerupEndTime = Date.now() + 10000;
992
+
993
+ switch(type) {
994
+ case 'rapidFire':
995
+ playerPowerups.rapidFire = true;
996
+ break;
997
+ case 'tripleShot':
998
+ playerPowerups.tripleShot = true;
999
+ break;
1000
+ case 'shield':
1001
+ playerPowerups.shield = true;
1002
+ break;
1003
+ case 'extraLife':
1004
+ lives++;
1005
+ break;
1006
+ }
1007
+ }
1008
+
1009
+ // Draw game
1010
+ function draw() {
1011
+ // Clear canvas
1012
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
1013
+
1014
+ // Draw background
1015
+ drawStars();
1016
+
1017
+ // Draw game objects
1018
+ player.draw();
1019
+ asteroids.forEach(drawAsteroid);
1020
+ enemies.forEach(drawEnemyShip);
1021
+ bullets.forEach(bullet => bullet.isEnemy ? drawEnemyBullet(bullet) : drawBullet(bullet));
1022
+ powerups.forEach(drawPowerup);
1023
+ explosions.forEach(drawExplosion);
1024
+
1025
+ // Draw HUD
1026
+ drawHUD();
1027
+ }
1028
+
1029
+ // Game loop
1030
+ function gameLoop() {
1031
+ update();
1032
+ draw();
1033
+ requestAnimationFrame(gameLoop);
1034
+ }
1035
+
1036
+ // Update leaderboard
1037
+ function updateLeaderboard() {
1038
+ leaderboardList.innerHTML = '';
1039
+
1040
+ // Add current score to leaderboard
1041
+ if (score > 0) {
1042
+ leaderboard.push({
1043
+ score: score,
1044
+ date: new Date().toLocaleDateString(),
1045
+ difficulty: difficulty
1046
+ });
1047
+ }
1048
+
1049
+ // Sort by score (descending)
1050
+ leaderboard.sort((a, b) => b.score - a.score);
1051
+
1052
+ // Keep only top 10 scores
1053
+ leaderboard = leaderboard.slice(0, 10);
1054
+
1055
+ // Save to localStorage
1056
+ localStorage.setItem('spaceShooterLeaderboard', JSON.stringify(leaderboard));
1057
+
1058
+ // Display leaderboard
1059
+ leaderboard.forEach((entry, index) => {
1060
+ const item = document.createElement('div');
1061
+ item.className = 'leaderboard-item';
1062
+ item.innerHTML = `
1063
+ <span>${index + 1}. ${entry.score}</span>
1064
+ <span class="text-gray-400 text-sm">${entry.difficulty}</span>
1065
+ `;
1066
+ leaderboardList.appendChild(item);
1067
+ });
1068
+ }
1069
+
1070
+ // Start game
1071
+ function startGame() {
1072
+ // Reset game state
1073
+ score = 0;
1074
+ lives = difficulty === 'easy' ? 5 : (difficulty === 'medium' ? 3 : 1);
1075
+ level = 1;
1076
+ asteroids = [];
1077
+ bullets = [];
1078
+ explosions = [];
1079
+ powerups = [];
1080
+ enemies = [];
1081
+ playerPowerups = {
1082
+ rapidFire: false,
1083
+ tripleShot: false,
1084
+ shield: false
1085
+ };
1086
+
1087
+ // Reposition player
1088
+ player.x = canvas.width / 2;
1089
+ player.y = canvas.height - 60;
1090
+
1091
+ // Set asteroid interval based on difficulty
1092
+ asteroidInterval = difficulty === 'easy' ? 2000 : (difficulty === 'medium' ? 1500 : 1000);
1093
+
1094
+ // Hide screens
1095
+ startScreen.style.display = 'none';
1096
+ gameOverScreen.style.display = 'none';
1097
+ pauseScreen.style.display = 'none';
1098
+
1099
+ // Start game
1100
+ gameRunning = true;
1101
+ gamePaused = false;
1102
+
1103
+ // Create stars
1104
+ createStars();
1105
+
1106
+ // Play background music
1107
+ try {
1108
+ bgMusic.volume = 0.3;
1109
+ bgMusic.currentTime = 0;
1110
+ bgMusic.play();
1111
+ } catch(e) {
1112
+ console.log('Error playing music:', e);
1113
+ }
1114
+
1115
+ // Start game loop
1116
+ gameLoop();
1117
+ }
1118
+
1119
+ // Game over
1120
+ function gameOver() {
1121
+ gameRunning = false;
1122
+ finalScore.textContent = `Score: ${score}`;
1123
+
1124
+ // Update high score display
1125
+ const highScoreValue = leaderboard.length > 0 ? Math.max(...leaderboard.map(e => e.score)) : 0;
1126
+ highScore.textContent = `High Score: ${highScoreValue}`;
1127
+
1128
+ // Update leaderboard
1129
+ updateLeaderboard();
1130
+
1131
+ // Show game over screen
1132
+ gameOverScreen.style.display = 'flex';
1133
+
1134
+ // Stop background music
1135
+ try {
1136
+ bgMusic.pause();
1137
+ } catch(e) {
1138
+ console.log('Error stopping music:', e);
1139
+ }
1140
+ }
1141
+
1142
+ // Pause game
1143
+ function pauseGame() {
1144
+ if (!gameRunning) return;
1145
+
1146
+ gamePaused = !gamePaused;
1147
+
1148
+ if (gamePaused) {
1149
+ pauseScreen.style.display = 'flex';
1150
+ pauseScore.textContent = score;
1151
+
1152
+ // Pause background music
1153
+ try {
1154
+ bgMusic.pause();
1155
+ } catch(e) {
1156
+ console.log('Error pausing music:', e);
1157
+ }
1158
+ } else {
1159
+ pauseScreen.style.display = 'none';
1160
+
1161
+ // Resume background music
1162
+ try {
1163
+ bgMusic.play();
1164
+ } catch(e) {
1165
+ console.log('Error resuming music:', e);
1166
+ }
1167
+ }
1168
+ }
1169
+
1170
+ // Event listeners
1171
+ startBtn.addEventListener('click', startGame);
1172
+ restartBtn.addEventListener('click', startGame);
1173
+
1174
+ menuBtn.addEventListener('click', () => {
1175
+ gameOverScreen.style.display = 'none';
1176
+ startScreen.style.display = 'flex';
1177
+ updateLeaderboard();
1178
+ });
1179
+
1180
+ resumeBtn.addEventListener('click', pauseGame);
1181
+ quitBtn.addEventListener('click', () => {
1182
+ pauseScreen.style.display = 'none';
1183
+ startScreen.style.display = 'flex';
1184
+ gameRunning = false;
1185
+ updateLeaderboard();
1186
+ });
1187
+
1188
+ // Difficulty selection
1189
+ difficultyBtns.forEach(btn => {
1190
+ btn.addEventListener('click', () => {
1191
+ difficultyBtns.forEach(b => b.classList.remove('active'));
1192
+ btn.classList.add('active');
1193
+ difficulty = btn.dataset.difficulty;
1194
+ });
1195
+ });
1196
+
1197
+ window.addEventListener('keydown', (e) => {
1198
+ keys[e.key] = true;
1199
+
1200
+ if (e.key === ' ' && gameRunning && !gamePaused) {
1201
+ player.shoot();
1202
+ }
1203
+
1204
+ if (e.key === 'Escape') {
1205
+ pauseGame();
1206
+ }
1207
+
1208
+ // Prevent default for arrow keys and space
1209
+ if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', ' '].includes(e.key)) {
1210
+ e.preventDefault();
1211
+ }
1212
+ });
1213
+
1214
+ window.addEventListener('keyup', (e) => {
1215
+ keys[e.key] = false;
1216
+ });
1217
+
1218
+ // Handle window resize
1219
+ window.addEventListener('resize', () => {
1220
+ canvas.width = window.innerWidth * 0.9;
1221
+ canvas.height = window.innerHeight * 0.9;
1222
+
1223
+ // Reposition player
1224
+ player.x = canvas.width / 2;
1225
+ player.y = canvas.height - 60;
1226
+
1227
+ // Recreate stars
1228
+ createStars();
1229
+ });
1230
+
1231
+ // Initialize leaderboard
1232
+ updateLeaderboard();
1233
+
1234
+ // Start game loop (even when game not running to show start screen)
1235
+ gameLoop();
1236
+ </script>
1237
+ <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 <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=SushilAI/space" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1238
+ </html>