Luis-Filipe commited on
Commit
c655c61
·
verified ·
1 Parent(s): 05ada9a

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +414 -587
index.html CHANGED
@@ -3,696 +3,523 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Space Invaders Arcade</title>
7
  <style>
 
 
8
  * {
9
  margin: 0;
10
  padding: 0;
11
  box-sizing: border-box;
12
  }
13
-
14
  body {
15
- background: linear-gradient(135deg, #0f0c29, #302b63, #24243e);
16
- font-family: 'Courier New', monospace;
 
17
  display: flex;
18
  justify-content: center;
19
  align-items: center;
20
  min-height: 100vh;
21
  overflow: hidden;
22
- color: white;
23
- user-select: none;
24
- }
25
-
26
- .game-container {
27
- position: relative;
28
- width: 800px;
29
- height: 600px;
30
- box-shadow: 0 0 40px rgba(0, 255, 255, 0.5);
31
- border-radius: 15px;
32
- overflow: hidden;
33
- background: #000;
34
  }
35
-
36
- #game-canvas {
37
- background-color: #000;
38
- display: block;
 
 
39
  }
40
-
41
- .screen {
42
- position: absolute;
43
- top: 0;
44
- left: 0;
45
- width: 100%;
46
- height: 100%;
47
  display: flex;
48
- flex-direction: column;
49
- justify-content: center;
50
  align-items: center;
51
- background: rgba(0, 0, 0, 0.9);
52
- z-index: 10;
 
 
 
53
  }
54
-
55
- .hidden {
56
- display: none;
 
57
  }
58
-
59
- h1 {
60
- font-size: 4rem;
61
- margin-bottom: 1rem;
62
- color: #00FF00;
63
- text-shadow: 0 0 20px #00FF00, 0 0 30px #00FF00;
64
- letter-spacing: 3px;
65
- font-weight: 800;
66
- }
67
-
68
- h2 {
69
- font-size: 2.5rem;
70
- margin-bottom: 2rem;
71
- color: #00FFFF;
72
- text-shadow: 0 0 10px rgba(0, 255, 255, 0.7);
73
- }
74
-
75
- .subtitle {
76
- font-size: 1.2rem;
77
- margin-bottom: 2rem;
78
- text-align: center;
79
- max-width: 80%;
80
- line-height: 1.6;
81
- color: #FF6B6B;
82
  }
83
-
84
- .btn {
85
- background: linear-gradient(45deg, #00FFFF, #00FF00);
86
- color: #000;
87
- border: none;
88
- padding: 15px 40px;
89
- font-size: 1.3rem;
90
- font-weight: bold;
91
- border-radius: 50px;
92
- cursor: pointer;
93
- margin: 10px;
94
- transition: all 0.3s ease;
95
- box-shadow: 0 5px 15px rgba(0, 255, 255, 0.4);
96
- border: 3px solid rgba(255, 255, 255, 0.3);
97
- font-family: 'Courier New', monospace;
98
- }
99
-
100
- .btn:hover {
101
- transform: translateY(-3px) scale(1.05);
102
- box-shadow: 0 8px 25px rgba(0, 255, 255, 0.6);
103
- }
104
-
105
- .btn:active {
106
- transform: translateY(1px);
107
- }
108
-
109
- .controls {
110
- display: flex;
111
- gap: 20px;
112
- margin-top: 20px;
113
  }
114
-
115
- .key {
116
- background: rgba(255, 255, 255, 0.1);
117
- border: 2px solid #00FFFF;
118
- border-radius: 10px;
119
- padding: 15px;
120
- text-align: center;
121
- min-width: 80px;
122
  }
123
-
124
- .key kbd {
 
125
  display: block;
126
- font-size: 2rem;
127
- margin-bottom: 5px;
128
- color: #00FF00;
129
  }
130
-
131
- .ui-panel {
 
 
 
 
 
132
  position: absolute;
133
- top: 15px;
134
- left: 15px;
135
- right: 15px;
136
- display: flex;
137
- justify-content: space-between;
138
- z-index: 5;
139
- background: rgba(0, 0, 0, 0.7);
140
- padding: 10px 20px;
141
  border-radius: 10px;
142
- border: 2px solid #00FFFF;
143
- }
144
-
145
- .score, .lives {
146
- font-size: 1.5rem;
147
- font-weight: bold;
148
- }
149
-
150
- .score {
151
- color: #00FF00;
152
- }
153
-
154
- .lives {
155
- color: #FF6B6B;
156
- }
157
-
158
- .ship-life {
159
- display: inline-block;
160
- width: 20px;
161
- height: 15px;
162
- background-color: #00FF00;
163
- clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
164
- margin-left: 5px;
165
- }
166
-
167
- .game-title {
168
- display: flex;
169
- align-items: center;
170
- gap: 15px;
171
  }
172
-
173
- .game-title span {
174
- color: #00FFFF;
 
 
175
  }
176
-
177
- .instructions {
178
- background: rgba(255, 255, 255, 0.1);
179
- padding: 20px;
180
- border-radius: 10px;
181
- margin: 20px 0;
182
- text-align: center;
183
- border: 1px solid #00FFFF;
184
- max-width: 80%;
185
- }
186
-
187
- .highlight {
188
- color: #00FF00;
189
- font-weight: bold;
190
- }
191
-
192
- .final-score {
193
- font-size: 3rem;
194
- color: #00FF00;
195
- margin: 20px 0;
196
- text-shadow: 0 0 20px #00FF00;
197
- }
198
-
199
- .game-over-text {
200
- color: #FF0000;
201
- text-shadow: 0 0 20px #FF0000;
202
- }
203
-
204
- .level-indicator {
205
  position: absolute;
206
  top: 50%;
207
  left: 50%;
208
  transform: translate(-50%, -50%);
209
- font-size: 3rem;
210
- color: #FFFF00;
211
- text-shadow: 0 0 20px #FFFF00;
212
- z-index: 20;
213
- opacity: 0;
214
- transition: opacity 0.5s;
 
 
 
 
 
 
 
 
 
 
 
 
215
  }
216
  </style>
217
  </head>
218
  <body>
219
- <div class="game-container">
220
- <div class="ui-panel">
221
- <div class="game-title">
222
- <h3>SPACE <span>INVADERS</span></h3>
223
- </div>
224
- <div class="score">SCORE: <span id="score-value">0000</span></div>
225
- <div class="lives">SHIPS: <span id="lives-value"></span></div>
226
- </div>
227
-
228
- <div id="level-indicator" class="level-indicator">LEVEL 1</div>
229
-
230
- <canvas id="game-canvas" width="800" height="600"></canvas>
231
-
232
- <div id="start-screen" class="screen">
233
- <h1>SPACE INVADERS</h1>
234
- <h2>ARCADE CLASSIC</h2>
235
- <div class="instructions">
236
- <p>Use <span class="highlight">ARROW KEYS</span> to move your ship</p>
237
- <p>Press <span class="highlight">SPACEBAR</span> to fire lasers</p>
238
- <p>Destroy all aliens before they reach Earth!</p>
239
- </div>
240
-
241
- <button id="start-btn" class="btn">START MISSION</button>
242
-
243
- <div class="controls">
244
- <div class="key">
245
- <kbd>←</kbd>
246
- <div>LEFT</div>
247
- </div>
248
- <div class="key">
249
- <kbd>→</kbd>
250
- <div>RIGHT</div>
251
- </div>
252
- <div class="key">
253
- <kbd>SPACE</kbd>
254
- <div>FIRE</div>
255
- </div>
256
- </div>
257
  </div>
258
-
259
- <div id="game-over-screen" class="screen hidden">
260
- <h1 class="game-over-text">MISSION FAILED</h1>
261
- <div class="final-score">FINAL SCORE: <span id="final-score">0000</span></div>
262
- <button id="restart-btn" class="btn">NEW MISSION</button>
263
  </div>
264
  </div>
265
-
 
 
 
 
 
 
 
 
 
 
 
 
 
266
  <script>
267
- // Game constants
268
- const SHIP_SPEED = 8;
269
- const ALIEN_SPEED = 1;
270
- const BULLET_SPEED = 10;
271
- const ALIEN_BULLET_SPEED = 5;
272
- const ALIEN_ROWS = 5;
273
- const ALIEN_COLS = 10;
274
- const ALIEN_WIDTH = 40;
275
- const ALIEN_HEIGHT = 30;
276
- const ALIEN_SPACING = 15;
277
- const LINE_ADVANCE_TIME = 1000; // 1 second
278
-
279
  // Game state
 
 
280
  let score = 0;
281
  let lives = 3;
282
- let gameRunning = false;
283
- let aliens = [];
284
- let bullets = [];
285
- let alienBullets = [];
286
- let alienDirection = 1;
287
- let alienMoveTimer = 0;
288
- let alienShootTimer = 0;
289
- let keys = {};
290
- let lastFireTime = 0;
291
- let fireCooldown = 150; // milliseconds
292
  let level = 1;
293
- let lastLineAdvance = 0;
294
-
295
- // Canvas setup
296
- const canvas = document.getElementById('game-canvas');
297
- const ctx = canvas.getContext('2d');
298
- const levelIndicator = document.getElementById('level-indicator');
299
-
300
- // DOM elements
301
- const startScreen = document.getElementById('start-screen');
302
- const gameOverScreen = document.getElementById('game-over-screen');
303
- const startBtn = document.getElementById('start-btn');
304
- const restartBtn = document.getElementById('restart-btn');
305
- const scoreValue = document.getElementById('score-value');
306
- const livesValue = document.getElementById('lives-value');
307
- const finalScore = document.getElementById('final-score');
308
-
309
- // Ship object
310
- let ship = {
311
  x: canvas.width / 2 - 25,
312
- y: canvas.height - 50,
313
  width: 50,
314
  height: 30,
315
- speed: SHIP_SPEED
316
  };
317
-
318
- // Prevent arrow keys from scrolling the page
319
- window.addEventListener('keydown', function(e) {
320
- if(['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', ' '].includes(e.key)) {
321
- e.preventDefault();
 
 
 
 
 
 
 
322
  }
323
- keys[e.key] = true;
324
- }, false);
325
-
326
- window.addEventListener('keyup', function(e) {
327
- keys[e.key] = false;
328
- }, false);
329
-
330
- // Initialize game
331
- function initGame() {
332
- score = 0;
333
- lives = 3;
334
- gameRunning = true;
335
- level = 1;
336
- aliens = [];
337
- bullets = [];
338
- alienBullets = [];
339
- alienDirection = 1;
340
- alienMoveTimer = 0;
341
- alienShootTimer = 0;
342
- keys = {};
343
- lastFireTime = 0;
344
- lastLineAdvance = performance.now();
345
-
346
- // Create aliens
347
- createAliens();
348
-
349
- // Reset ship position
350
- ship.x = canvas.width / 2 - 25;
351
- ship.y = canvas.height - 50;
352
-
353
- updateUI();
354
- showLevelIndicator(level);
355
- startScreen.classList.add('hidden');
356
- gameOverScreen.classList.add('hidden');
357
- }
358
-
359
- // Create aliens
360
- function createAliens() {
361
- aliens = [];
362
- for (let row = 0; row < ALIEN_ROWS; row++) {
363
- for (let col = 0; col < ALIEN_COLS; col++) {
364
- aliens.push({
365
- x: col * (ALIEN_WIDTH + ALIEN_SPACING) + 100,
366
- y: row * (ALIEN_HEIGHT + ALIEN_SPACING) + 50,
367
- width: ALIEN_WIDTH,
368
- height: ALIEN_HEIGHT,
369
- alive: true
370
  });
371
  }
372
  }
373
  }
374
-
375
- // Show level indicator
376
- function showLevelIndicator(levelNum) {
377
- levelIndicator.textContent = `LEVEL ${levelNum}`;
378
- levelIndicator.style.opacity = '1';
379
-
380
- setTimeout(() => {
381
- levelIndicator.style.opacity = '0';
382
- }, 1500);
383
- }
384
-
385
- // Update UI elements
386
- function updateUI() {
387
- scoreValue.textContent = score.toString().padStart(4, '0');
388
-
389
- // Update lives display
390
- livesValue.innerHTML = '';
391
- for (let i = 0; i < lives; i++) {
392
- const life = document.createElement('span');
393
- life.className = 'ship-life';
394
- livesValue.appendChild(life);
395
  }
396
  }
397
-
398
- // Draw ship
399
- function drawShip() {
400
- ctx.fillStyle = '#00FF00';
401
- // Ship body
402
- ctx.beginPath();
403
- ctx.moveTo(ship.x, ship.y + ship.height);
404
- ctx.lineTo(ship.x + ship.width / 2, ship.y);
405
- ctx.lineTo(ship.x + ship.width, ship.y + ship.height);
406
- ctx.closePath();
407
- ctx.fill();
408
 
409
- // Ship details
410
- ctx.fillStyle = '#008800';
411
- ctx.fillRect(ship.x + 15, ship.y + 20, 20, 10);
412
- }
413
-
414
- // Draw aliens
415
- function drawAliens() {
416
- aliens.forEach(alien => {
417
- if (alien.alive) {
418
- // Alien body
419
- ctx.fillStyle = '#FF0000';
420
- ctx.fillRect(alien.x, alien.y, alien.width, alien.height);
421
-
422
- // Alien details
423
- ctx.fillStyle = '#FF6666';
424
- ctx.fillRect(alien.x + 5, alien.y + 5, 10, 10);
425
- ctx.fillRect(alien.x + 25, alien.y + 5, 10, 10);
426
- ctx.fillRect(alien.x + 15, alien.y + 20, 10, 5);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
427
  }
 
 
 
 
 
 
 
 
 
428
  });
429
  }
430
-
431
- // Draw bullets
432
- function drawBullets() {
433
- // Player bullets
434
- ctx.fillStyle = '#00FF00';
435
- bullets.forEach(bullet => {
436
- ctx.fillRect(bullet.x, bullet.y, 3, 15);
437
- });
438
 
439
- // Alien bullets
440
- ctx.fillStyle = '#FF0000';
441
- alienBullets.forEach(bullet => {
442
- ctx.fillRect(bullet.x, bullet.y, 3, 15);
443
- });
444
- }
445
-
446
- // Move ship
447
- function moveShip() {
448
- if (keys['ArrowLeft'] && ship.x > 0) {
449
- ship.x -= ship.speed;
450
  }
451
- if (keys['ArrowRight'] && ship.x < canvas.width - ship.width) {
452
- ship.x += ship.speed;
453
  }
454
- }
455
-
456
- // Fire bullet
457
- function fireBullet() {
458
- const now = performance.now();
459
- if (now - lastFireTime > fireCooldown) {
460
- bullets.push({
461
- x: ship.x + ship.width / 2 - 1.5,
462
- y: ship.y,
463
- width: 3,
464
- height: 15
465
- });
466
- lastFireTime = now;
467
- }
468
- }
469
-
470
- // Move bullets
471
- function moveBullets() {
472
- // Move player bullets
473
- for (let i = bullets.length - 1; i >= 0; i--) {
474
- bullets[i].y -= BULLET_SPEED;
475
- if (bullets[i].y < 0) {
476
- bullets.splice(i, 1);
477
  }
478
  }
479
 
480
- // Move alien bullets
481
- for (let i = alienBullets.length - 1; i >= 0; i--) {
482
- alienBullets[i].y += ALIEN_BULLET_SPEED;
483
- if (alienBullets[i].y > canvas.height) {
484
- alienBullets.splice(i, 1);
485
  }
486
- }
487
- }
488
-
489
- // Move aliens
490
- function moveAliens() {
491
- alienMoveTimer++;
492
- if (alienMoveTimer >= Math.max(3, 15 - level * 1)) { // Speed up with level
493
- alienMoveTimer = 0;
494
-
495
- let moveDown = false;
496
-
497
- // Check if aliens need to change direction
498
- for (let alien of aliens) {
499
- if (alien.alive) {
500
- if ((alienDirection === 1 && alien.x + alien.width >= canvas.width - 20) ||
501
- (alienDirection === -1 && alien.x <= 20)) {
502
- moveDown = true;
503
- break;
504
- }
505
- }
506
  }
 
 
 
 
 
 
507
 
508
- if (moveDown) {
509
- alienDirection *= -1;
510
- aliens.forEach(alien => {
511
- if (alien.alive) {
512
- alien.y += 8;
513
- }
514
- });
515
- } else {
516
- aliens.forEach(alien => {
517
- if (alien.alive) {
518
- alien.x += (ALIEN_SPEED + level * 0.3) * alienDirection;
519
- }
520
- });
521
  }
522
- }
523
- }
524
-
525
- // Line advance every 1 second
526
- function advanceAlienLine() {
527
- const now = performance.now();
528
- if (now - lastLineAdvance > LINE_ADVANCE_TIME) {
529
- aliens.forEach(alien => {
530
- if (alien.alive) {
531
- alien.y += 3;
532
- }
533
  });
534
- lastLineAdvance = now;
535
  }
536
- }
537
-
538
- // Alien shooting
539
- function alienShoot() {
540
- alienShootTimer++;
541
- if (alienShootTimer >= Math.max(15, 45 - level * 3)) { // Shoot more frequently with level
542
- alienShootTimer = 0;
543
-
544
- // Find alive aliens in the bottom row
545
- let bottomAliens = [];
546
- for (let col = 0; col < ALIEN_COLS; col++) {
547
- for (let row = ALIEN_ROWS - 1; row >= 0; row--) {
548
- let index = row * ALIEN_COLS + col;
549
- if (index < aliens.length && aliens[index].alive) {
550
- bottomAliens.push(aliens[index]);
551
- break;
552
- }
553
- }
554
- }
555
-
556
- // Randomly select one to shoot
557
- if (bottomAliens.length > 0) {
558
- let shooter = bottomAliens[Math.floor(Math.random() * bottomAliens.length)];
559
- alienBullets.push({
560
- x: shooter.x + shooter.width / 2 - 1.5,
561
- y: shooter.y + shooter.height,
562
- width: 3,
563
- height: 15
564
- });
565
- }
566
  }
567
- }
568
-
569
- // Check collisions
570
- function checkCollisions() {
571
- // Bullet vs Alien collisions
572
- for (let i = bullets.length - 1; i >= 0; i--) {
573
- for (let j = 0; j < aliens.length; j++) {
574
- if (aliens[j].alive &&
575
- bullets[i].x < aliens[j].x + aliens[j].width &&
576
- bullets[i].x + bullets[i].width > aliens[j].x &&
577
- bullets[i].y < aliens[j].y + aliens[j].height &&
578
- bullets[i].y + bullets[i].height > aliens[j].y) {
579
 
580
- aliens[j].alive = false;
581
- bullets.splice(i, 1);
582
- score += 100;
 
583
  updateUI();
584
- break;
585
  }
586
- }
587
- }
588
 
589
- // Alien bullet vs Ship collisions
590
- for (let i = alienBullets.length - 1; i >= 0; i--) {
591
- if (alienBullets[i].x < ship.x + ship.width &&
592
- alienBullets[i].x + alienBullets[i].width > ship.x &&
593
- alienBullets[i].y < ship.y + ship.height &&
594
- alienBullets[i].y + alienBullets[i].height > ship.y) {
595
 
596
- alienBullets.splice(i, 1);
 
597
  lives--;
598
  updateUI();
599
 
600
  if (lives <= 0) {
601
  gameOver();
602
  }
603
- break;
604
  }
605
- }
606
 
607
- // Check if aliens reached the bottom
608
- for (let alien of aliens) {
609
- if (alien.alive && alien.y + alien.height >= ship.y) {
610
  gameOver();
611
- return;
612
- }
613
- }
614
- }
615
-
616
- // Check win condition
617
- function checkWin() {
618
- for (let alien of aliens) {
619
- if (alien.alive) {
620
- return false;
621
  }
 
 
 
 
 
622
  }
623
- return true;
624
  }
625
-
626
- // Next level
627
- function nextLevel() {
628
- level++;
629
- createAliens();
630
- showLevelIndicator(level);
631
- lastLineAdvance = performance.now();
632
- }
633
-
634
- // Draw game
635
- function draw() {
636
  // Clear canvas
637
- ctx.clearRect(0, 0, canvas.width, canvas.height);
 
638
 
639
- // Draw stars background
640
- ctx.fillStyle = '#FFFFFF';
641
- for (let i = 0; i < 100; i++) {
642
- let x = Math.random() * canvas.width;
643
- let y = Math.random() * canvas.height;
644
- let size = Math.random() * 2;
645
- ctx.fillRect(x, y, size, size);
646
  }
647
 
648
- drawShip();
649
- drawAliens();
650
- drawBullets();
 
 
 
 
 
 
 
 
 
 
 
 
651
  }
652
-
653
  // Game loop
654
- function gameLoop() {
655
- if (!gameRunning) return;
656
-
657
- moveShip();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
658
 
659
- if (keys[' ']) {
660
- fireBullet();
661
- }
 
 
 
662
 
663
- moveBullets();
664
- moveAliens();
665
- advanceAlienLine();
666
- alienShoot();
667
- checkCollisions();
668
 
669
- if (checkWin()) {
670
- score += level * 1000;
671
- updateUI();
672
- nextLevel();
673
- }
674
 
675
- draw();
676
- requestAnimationFrame(gameLoop);
677
  }
678
-
 
 
 
 
 
 
 
 
679
  // Game over
680
  function gameOver() {
681
  gameRunning = false;
682
- finalScore.textContent = score.toString().padStart(4, '0');
683
- gameOverScreen.classList.remove('hidden');
684
  }
685
-
686
- // Event listeners
687
- startBtn.addEventListener('click', () => {
688
- initGame();
689
- requestAnimationFrame(gameLoop);
690
- });
691
-
692
- restartBtn.addEventListener('click', () => {
693
- initGame();
694
- requestAnimationFrame(gameLoop);
695
- });
696
  </script>
697
  </body>
698
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Space Invaders - Arcade Edition</title>
7
  <style>
8
+ @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&display=swap');
9
+
10
  * {
11
  margin: 0;
12
  padding: 0;
13
  box-sizing: border-box;
14
  }
 
15
  body {
16
+ background: #000;
17
+ color: #0f0;
18
+ font-family: 'Orbitron', monospace;
19
  display: flex;
20
  justify-content: center;
21
  align-items: center;
22
  min-height: 100vh;
23
  overflow: hidden;
 
 
 
 
 
 
 
 
 
 
 
 
24
  }
25
+ .arcade-container {
26
+ background: #111;
27
+ border: 4px solid #333;
28
+ border-radius: 10px;
29
+ padding: 20px;
30
+ box-shadow: 0 0 30px rgba(0, 255, 0, 0.3);
31
  }
32
+ .game-header {
 
 
 
 
 
 
33
  display: flex;
34
+ justify-content: space-between;
 
35
  align-items: center;
36
+ margin-bottom: 15px;
37
+ padding: 10px;
38
+ background: #222;
39
+ border: 2px solid #444;
40
+ border-radius: 5px;
41
  }
42
+ .score-display, .lives-display, .level-display {
43
+ font-size: 18px;
44
+ font-weight: 700;
45
+ text-shadow: 0 0 10px currentColor;
46
  }
47
+ .score-display {
48
+ color: #0ff;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  }
50
+ .lives-display {
51
+ color: #f0f;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  }
53
+ .level-display {
54
+ color: #ff0;
 
 
 
 
 
 
55
  }
56
+ #gameCanvas {
57
+ border: 3px solid #0f0;
58
+ background: #000;
59
  display: block;
60
+ image-rendering: pixelated;
61
+ image-rendering: -moz-crisp-edges;
62
+ image-rendering: crisp-edges;
63
  }
64
+ .controls {
65
+ margin-top: 15px;
66
+ text-align: center;
67
+ font-size: 14px;
68
+ color: #888;
69
+ }
70
+ .game-over {
71
  position: absolute;
72
+ top: 50%;
73
+ left: 50%;
74
+ transform: translate(-50%, -50%);
75
+ background: rgba(0, 0, 0, 0.9);
76
+ border: 3px solid #f00;
 
 
 
77
  border-radius: 10px;
78
+ padding: 30px;
79
+ text-align: center;
80
+ display: none;
81
+ z-index: 1000;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  }
83
+ .game-over h2 {
84
+ color: #f00;
85
+ font-size: 32px;
86
+ margin-bottom: 20px;
87
+ text-shadow: 0 0 20px currentColor;
88
  }
89
+ .game-over p {
90
+ color: #0f0;
91
+ font-size: 20px;
92
+ margin-bottom: 20px;
93
+ }
94
+ .restart-btn {
95
+ background: #0f0;
96
+ color: #000;
97
+ border: none;
98
+ padding: 15px 30px;
99
+ font-family: 'Orbitron', monospace;
100
+ font-size: 18px;
101
+ font-weight: 700;
102
+ border-radius: 5px;
103
+ cursor: pointer;
104
+ transition: all 0.3s;
105
+ }
106
+ .restart-btn:hover {
107
+ background: #0ff;
108
+ box-shadow: 0 0 20px rgba(0, 255, 255, 0.5);
109
+ }
110
+ .start-screen {
 
 
 
 
 
 
 
111
  position: absolute;
112
  top: 50%;
113
  left: 50%;
114
  transform: translate(-50%, -50%);
115
+ background: rgba(0, 0, 0, 0.95);
116
+ border: 3px solid #0f0;
117
+ border-radius: 10px;
118
+ padding: 40px;
119
+ text-align: center;
120
+ z-index: 1000;
121
+ }
122
+ .start-screen h1 {
123
+ color: #0f0;
124
+ font-size: 36px;
125
+ margin-bottom: 20px;
126
+ text-shadow: 0 0 30px currentColor;
127
+ }
128
+ .start-screen p {
129
+ color: #0ff;
130
+ font-size: 16px;
131
+ margin-bottom: 30px;
132
+ line-height: 1.6;
133
  }
134
  </style>
135
  </head>
136
  <body>
137
+ <div class="arcade-container">
138
+ <div class="game-header">
139
+ <div class="score-display">SCORE: <span id="score">0</span></div>
140
+ <div class="level-display">LEVEL: <span id="level">1</span></div>
141
+ <div class="lives-display">LIVES: <span id="lives">3</span></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  </div>
143
+
144
+ <canvas id="gameCanvas" width="800" height="600"></canvas>
145
+
146
+ <div class="controls">
147
+ Use ARROWS to move • SPACEBAR to shoot • ENTER to start/pause
148
  </div>
149
  </div>
150
+ <div class="start-screen" id="startScreen">
151
+ <h1>SPACE INVADERS</h1>
152
+ <p>
153
+ Defend Earth from alien invasion!<br>
154
+ Destroy all invaders before they reach you.<br>
155
+ Each level gets faster and more challenging.
156
+ </p>
157
+ <button class="restart-btn" onclick="startGame()">START GAME</button>
158
+ </div>
159
+ <div class="game-over" id="gameOverScreen">
160
+ <h2>GAME OVER</h2>
161
+ <p>Final Score: <span id="finalScore">0</span></p>
162
+ <button class="restart-btn" onclick="restartGame()">PLAY AGAIN</button>
163
+ </div>
164
  <script>
165
+ const canvas = document.getElementById('gameCanvas');
166
+ const ctx = canvas.getContext('2d');
167
+
 
 
 
 
 
 
 
 
 
168
  // Game state
169
+ let gameRunning = false;
170
+ let gamePaused = false;
171
  let score = 0;
172
  let lives = 3;
 
 
 
 
 
 
 
 
 
 
173
  let level = 1;
174
+ let invaderDirection = 1;
175
+ let invaderSpeed = 0.5;
176
+ let lastTime = 0;
177
+
178
+ // Game objects
179
+ const player = {
 
 
 
 
 
 
 
 
 
 
 
 
180
  x: canvas.width / 2 - 25,
181
+ y: canvas.height - 60,
182
  width: 50,
183
  height: 30,
184
+ speed: 5
185
  };
186
+ const bullets = [];
187
+ const invaderBullets = [];
188
+ const invaders = [];
189
+ const particles = [];
190
+
191
+ // Input handling
192
+ const keys = {};
193
+ document.addEventListener('keydown', (e) => {
194
+ keys[e.code] = true;
195
+ if (e.code === 'Enter') {
196
+ if (!gameRunning) startGame();
197
+ else gamePaused = !gamePaused;
198
  }
199
+ });
200
+ document.addEventListener('keyup', (e) => {
201
+ keys[e.code] = false;
202
+ });
203
+
204
+ // Initialize invaders
205
+ function createInvaders() {
206
+ invaders.length = 0;
207
+ const rows = 5;
208
+ const cols = 11;
209
+ const invaderWidth = 40;
210
+ const invaderHeight = 30;
211
+ const spacing = 15;
212
+ const startX = 50;
213
+ const startY = 50;
214
+ for (let row = 0; row < rows; row++) {
215
+ for (let col = 0; col < cols; col++) {
216
+ invaders.push({
217
+ x: startX + col * (invaderWidth + spacing),
218
+ y: startY + row * (invaderHeight + spacing),
219
+ width: invaderWidth,
220
+ height: invaderHeight,
221
+ type: row < 2 ? 'strong' : 'normal',
222
+ points: row < 2 ? 20 : 10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  });
224
  }
225
  }
226
  }
227
+
228
+ // Create particle effect
229
+ function createParticles(x, y, color) {
230
+ for (let i = 0; i < 8; i++) {
231
+ particles.push({
232
+ x: x,
233
+ y: y,
234
+ vx: (Math.random() - 0.5) * 6,
235
+ vy: (Math.random() - 0.5) * 6,
236
+ life: 30,
237
+ color: color
238
+ });
 
 
 
 
 
 
 
 
 
239
  }
240
  }
241
+
242
+ // Draw player
243
+ function drawPlayer() {
244
+ ctx.fillStyle = '#0f0';
245
+ // Player ship design
246
+ ctx.fillRect(player.x + 20, player.y, 10, 20);
247
+ ctx.fillRect(player.x + 10, player.y + 10, 30, 15);
248
+ ctx.fillRect(player.x, player.y + 20, 50, 10);
 
 
 
249
 
250
+ // Add glow effect
251
+ ctx.shadowColor = '#0f0';
252
+ ctx.shadowBlur = 10;
253
+ ctx.fillRect(player.x + 20, player.y + 5, 10, 5);
254
+ ctx.shadowBlur = 0;
255
+ }
256
+
257
+ // Draw invader
258
+ function drawInvader(invader) {
259
+ ctx.fillStyle = invader.type === 'strong' ? '#f0f' : '#0ff';
260
+
261
+ // Simple invader design
262
+ const centerX = invader.x + invader.width / 2;
263
+ const centerY = invader.y + invader.height / 2;
264
+
265
+ // Body
266
+ ctx.fillRect(invader.x + 5, invader.y + 5, invader.width - 10, invader.height - 10);
267
+
268
+ // Eyes
269
+ ctx.fillStyle = '#000';
270
+ ctx.fillRect(invader.x + 10, invader.y + 10, 8, 8);
271
+ ctx.fillRect(invader.x + invader.width - 18, invader.y + 10, 8, 8);
272
+
273
+ // Antennas
274
+ ctx.strokeStyle = invader.type === 'strong' ? '#f0f' : '#0ff';
275
+ ctx.lineWidth = 2;
276
+ ctx.beginPath();
277
+ ctx.moveTo(invader.x + 10, invader.y);
278
+ ctx.lineTo(invader.x + 5, invader.y - 5);
279
+ ctx.moveTo(invader.x + invader.width - 10, invader.y);
280
+ ctx.lineTo(invader.x + invader.width - 5, invader.y - 5);
281
+ ctx.stroke();
282
+ }
283
+
284
+ // Draw bullet
285
+ function drawBullet(bullet, isPlayer = true) {
286
+ ctx.fillStyle = isPlayer ? '#ff0' : '#f00';
287
+ ctx.shadowColor = isPlayer ? '#ff0' : '#f00';
288
+ ctx.shadowBlur = 5;
289
+ ctx.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
290
+ ctx.shadowBlur = 0;
291
+ }
292
+
293
+ // Draw particles
294
+ function drawParticles() {
295
+ particles.forEach((particle, index) => {
296
+ if (particle.life <= 0) {
297
+ particles.splice(index, 1);
298
+ return;
299
  }
300
+
301
+ ctx.fillStyle = particle.color;
302
+ ctx.globalAlpha = particle.life / 30;
303
+ ctx.fillRect(particle.x, particle.y, 3, 3);
304
+ ctx.globalAlpha = 1;
305
+
306
+ particle.x += particle.vx;
307
+ particle.y += particle.vy;
308
+ particle.life--;
309
  });
310
  }
311
+
312
+ // Update game logic
313
+ function update(deltaTime) {
314
+ if (!gameRunning || gamePaused) return;
 
 
 
 
315
 
316
+ // Player movement
317
+ if (keys['ArrowLeft'] && player.x > 0) {
318
+ player.x -= player.speed;
 
 
 
 
 
 
 
 
319
  }
320
+ if (keys['ArrowRight'] && player.x < canvas.width - player.width) {
321
+ player.x += player.speed;
322
  }
323
+
324
+ // Player shooting
325
+ if (keys['Space']) {
326
+ if (bullets.length === 0 || bullets[bullets.length - 1].y < player.y - 50) {
327
+ bullets.push({
328
+ x: player.x + player.width / 2 - 2,
329
+ y: player.y,
330
+ width: 4,
331
+ height: 10,
332
+ speed: 8
333
+ });
 
 
 
 
 
 
 
 
 
 
 
 
334
  }
335
  }
336
 
337
+ // Update bullets
338
+ bullets.forEach((bullet, index) => {
339
+ bullet.y -= bullet.speed;
340
+ if (bullet.y < 0) {
341
+ bullets.splice(index, 1);
342
  }
343
+ });
344
+
345
+ // Update invader bullets
346
+ invaderBullets.forEach((bullet, index) => {
347
+ bullet.y += bullet.speed;
348
+ if (bullet.y > canvas.height) {
349
+ invaderBullets.splice(index, 1);
 
 
 
 
 
 
 
 
 
 
 
 
 
350
  }
351
+ });
352
+
353
+ // Update invaders
354
+ let shouldDrop = false;
355
+ invaders.forEach(invader => {
356
+ invader.x += invaderDirection * invaderSpeed;
357
 
358
+ if (invader.x <= 0 || invader.x + invader.width >= canvas.width) {
359
+ shouldDrop = true;
 
 
 
 
 
 
 
 
 
 
 
360
  }
361
+ });
362
+
363
+ if (shouldDrop) {
364
+ invaderDirection *= -1;
365
+ invaders.forEach(invader => {
366
+ invader.y += 20;
 
 
 
 
 
367
  });
 
368
  }
369
+
370
+ // Invader shooting
371
+ if (Math.random() < 0.001 * level && invaders.length > 0) {
372
+ const shooter = invaders[Math.floor(Math.random() * invaders.length)];
373
+ invaderBullets.push({
374
+ x: shooter.x + shooter.width / 2 - 2,
375
+ y: shooter.y + shooter.height,
376
+ width: 4,
377
+ height: 8,
378
+ speed: 3
379
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
380
  }
381
+
382
+ // Collision detection - bullets vs invaders
383
+ bullets.forEach((bullet, bulletIndex) => {
384
+ invaders.forEach((invader, invaderIndex) => {
385
+ if (bullet.x < invader.x + invader.width &&
386
+ bullet.x + bullet.width > invader.x &&
387
+ bullet.y < invader.y + invader.height &&
388
+ bullet.y + bullet.height > invader.y) {
 
 
 
 
389
 
390
+ createParticles(invader.x + invader.width / 2, invader.y + invader.height / 2, '#0ff');
391
+ bullets.splice(bulletIndex, 1);
392
+ invaders.splice(invaderIndex, 1);
393
+ score += invader.points;
394
  updateUI();
 
395
  }
396
+ });
397
+ });
398
 
399
+ // Collision detection - invader bullets vs player
400
+ invaderBullets.forEach((bullet, index) => {
401
+ if (bullet.x < player.x + player.width &&
402
+ bullet.x + bullet.width > player.x &&
403
+ bullet.y < player.y + player.height &&
404
+ bullet.y + bullet.height > player.y) {
405
 
406
+ createParticles(player.x + player.width / 2, player.y + player.height / 2, '#0f0');
407
+ invaderBullets.splice(index, 1);
408
  lives--;
409
  updateUI();
410
 
411
  if (lives <= 0) {
412
  gameOver();
413
  }
 
414
  }
415
+ });
416
 
417
+ // Check if invaders reached player
418
+ invaders.forEach(invader => {
419
+ if (invader.y + invader.height >= player.y) {
420
  gameOver();
 
 
 
 
 
 
 
 
 
 
421
  }
422
+ });
423
+
424
+ // Check if all invaders destroyed
425
+ if (invaders.length === 0) {
426
+ nextLevel();
427
  }
 
428
  }
429
+
430
+ // Render game
431
+ function render() {
 
 
 
 
 
 
 
 
432
  // Clear canvas
433
+ ctx.fillStyle = '#000';
434
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
435
 
436
+ // Draw stars
437
+ ctx.fillStyle = '#fff';
438
+ for (let i = 0; i < 50; i++) {
439
+ const x = (i * 137.5) % canvas.width;
440
+ const y = (i * 234.7) % canvas.height;
441
+ ctx.fillRect(x, y, 1, 1);
 
442
  }
443
 
444
+ // Draw game objects
445
+ drawPlayer();
446
+ invaders.forEach(drawInvader);
447
+ bullets.forEach(bullet => drawBullet(bullet, true));
448
+ invaderBullets.forEach(bullet => drawBullet(bullet, false));
449
+ drawParticles();
450
+
451
+ // Draw pause text
452
+ if (gamePaused) {
453
+ ctx.fillStyle = '#0f0';
454
+ ctx.font = '48px Orbitron';
455
+ ctx.textAlign = 'center';
456
+ ctx.fillText('PAUSED', canvas.width / 2, canvas.height / 2);
457
+ ctx.textAlign = 'left';
458
+ }
459
  }
460
+
461
  // Game loop
462
+ function gameLoop(currentTime) {
463
+ const deltaTime = currentTime - lastTime;
464
+ lastTime = currentTime;
465
+ update(deltaTime);
466
+ render();
467
+ requestAnimationFrame(gameLoop);
468
+ }
469
+
470
+ // Update UI
471
+ function updateUI() {
472
+ document.getElementById('score').textContent = score;
473
+ document.getElementById('lives').textContent = lives;
474
+ document.getElementById('level').textContent = level;
475
+ }
476
+
477
+ // Start game
478
+ function startGame() {
479
+ document.getElementById('startScreen').style.display = 'none';
480
+ document.getElementById('gameOverScreen').style.display = 'none';
481
 
482
+ gameRunning = true;
483
+ gamePaused = false;
484
+ score = 0;
485
+ lives = 3;
486
+ level = 1;
487
+ invaderSpeed = 0.5;
488
 
489
+ bullets.length = 0;
490
+ invaderBullets.length = 0;
491
+ particles.length = 0;
 
 
492
 
493
+ player.x = canvas.width / 2 - 25;
494
+ player.y = canvas.height - 60;
 
 
 
495
 
496
+ createInvaders();
497
+ updateUI();
498
  }
499
+
500
+ // Next level
501
+ function nextLevel() {
502
+ level++;
503
+ invaderSpeed += 0.2;
504
+ createInvaders();
505
+ updateUI();
506
+ }
507
+
508
  // Game over
509
  function gameOver() {
510
  gameRunning = false;
511
+ document.getElementById('finalScore').textContent = score;
512
+ document.getElementById('gameOverScreen').style.display = 'block';
513
  }
514
+
515
+ // Restart game
516
+ function restartGame() {
517
+ startGame();
518
+ }
519
+
520
+ // Initialize game
521
+ updateUI();
522
+ requestAnimationFrame(gameLoop);
 
 
523
  </script>
524
  </body>
525
  </html>