giseldo commited on
Commit
ac3c319
·
verified ·
1 Parent(s): a29b598

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +544 -94
index.html CHANGED
@@ -1,94 +1,544 @@
1
- <style>
2
- body { margin: 0; overflow: hidden; }
3
- canvas { display: block; }
4
- #ui {
5
- position: absolute;
6
- top: 10px;
7
- left: 10px;
8
- color: white;
9
- font-family: Arial, sans-serif;
10
- display: none;
11
- }
12
- #center-ui {
13
- position: absolute;
14
- top: 10px;
15
- left: 50%;
16
- transform: translateX(-50%);
17
- color: white;
18
- font-family: Arial, sans-serif;
19
- text-align: center;
20
- display: none;
21
- }
22
- #deaths-ui {
23
- position: absolute;
24
- top: 10px;
25
- right: 10px;
26
- color: white;
27
- font-family: Arial, sans-serif;
28
- text-align: right;
29
- display: none;
30
- }
31
- #gameOver {
32
- position: absolute;
33
- top: 50%;
34
- left: 50%;
35
- transform: translate(-50%, -50%);
36
- color: white;
37
- font-family: Arial, sans-serif;
38
- text-align: center;
39
- display: none;
40
- }
41
- #gameOver button {
42
- font-size: 32px; /* Aumenta o tamanho da fonte */
43
- padding: 15px 30px; /* Aumenta o preenchimento */
44
- cursor: pointer;
45
- border: none; /* Opcional: remove borda padrão */
46
- background-color: #ff0000; /* Opcional: fundo vermelho */
47
- color: white; /* Opcional: texto branco */
48
- border-radius: 5px; /* Opcional: bordas arredondadas */
49
- }
50
- #gameOver button:hover {
51
- background-color: #cc0000; /* Opcional: cor ao passar o mouse */
52
- }
53
- #startScreen {
54
- position: absolute;
55
- top: 50%;
56
- left: 50%;
57
- transform: translate(-50%, -50%);
58
- color: white;
59
- font-family: Arial, sans-serif;
60
- text-align: center;
61
- display: block;
62
- }
63
- #startScreen h1 {
64
- font-size: 48px;
65
- margin-bottom: 20px;
66
- }
67
- #startScreen p {
68
- font-size: 24px;
69
- margin: 10px 0;
70
- }
71
- #startScreen button {
72
- font-size: 24px;
73
- padding: 10px 20px;
74
- cursor: pointer;
75
- }
76
- #pausedScreen {
77
- position: absolute;
78
- top: 50%;
79
- left: 50%;
80
- transform: translate(-50%, -50%);
81
- color: white;
82
- font-family: Arial, sans-serif;
83
- text-align: center;
84
- display: none;
85
- }
86
- #pausedScreen h1 {
87
- font-size: 48px;
88
- margin-bottom: 20px;
89
- }
90
- #pausedScreen p {
91
- font-size: 24px;
92
- margin: 10px 0;
93
- }
94
- </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="pt-BR">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Space Invaders com Three.js</title>
6
+ <style>
7
+ body { margin: 0; overflow: hidden; }
8
+ canvas { display: block; }
9
+ #ui {
10
+ position: absolute;
11
+ top: 10px;
12
+ left: 10px;
13
+ color: white;
14
+ font-family: Arial, sans-serif;
15
+ display: none;
16
+ }
17
+ #center-ui {
18
+ position: absolute;
19
+ top: 10px;
20
+ left: 50%;
21
+ transform: translateX(-50%);
22
+ color: white;
23
+ font-family: Arial, sans-serif;
24
+ text-align: center;
25
+ display: none;
26
+ }
27
+ #deaths-ui {
28
+ position: absolute;
29
+ top: 10px;
30
+ right: 10px;
31
+ color: white;
32
+ font-family: Arial, sans-serif;
33
+ text-align: right;
34
+ display: none;
35
+ }
36
+ #gameOver {
37
+ position: absolute;
38
+ top: 50%;
39
+ left: 50%;
40
+ transform: translate(-50%, -50%);
41
+ color: white;
42
+ font-family: Arial, sans-serif;
43
+ text-align: center;
44
+ display: none;
45
+ }
46
+ #startScreen {
47
+ position: absolute;
48
+ top: 50%;
49
+ left: 50%;
50
+ transform: translate(-50%, -50%);
51
+ color: white;
52
+ font-family: Arial, sans-serif;
53
+ text-align: center;
54
+ display: block;
55
+ }
56
+ #startScreen h1 {
57
+ font-size: 48px;
58
+ margin-bottom: 20px;
59
+ }
60
+ #startScreen p {
61
+ font-size: 24px;
62
+ margin: 10px 0;
63
+ }
64
+ #startScreen button {
65
+ font-size: 24px;
66
+ padding: 10px 20px;
67
+ cursor: pointer;
68
+ }
69
+ #pausedScreen {
70
+ position: absolute;
71
+ top: 50%;
72
+ left: 50%;
73
+ transform: translate(-50%, -50%);
74
+ color: white;
75
+ font-family: Arial, sans-serif;
76
+ text-align: center;
77
+ display: none;
78
+ }
79
+ #pausedScreen h1 {
80
+ font-size: 48px;
81
+ margin-bottom: 20px;
82
+ }
83
+ #pausedScreen p {
84
+ font-size: 24px;
85
+ margin: 10px 0;
86
+ }
87
+ </style>
88
+ </head>
89
+ <body>
90
+ <div id="ui">
91
+ <p>Score: <span id="score">0</span></p>
92
+ <p>Planet: <span id="level">1</span></p>
93
+ </div>
94
+ <div id="center-ui">
95
+ <p>Hi-Score: <span id="hiScore">0</span></p>
96
+ <p>Hi-Planet: <span id="hiPlanet">1</span></p>
97
+ </div>
98
+ <div id="deaths-ui">
99
+ <p>Mortes: <span id="deaths">0</span></p>
100
+ <p>Próximo Power-Up: <span id="nextPowerUp">Planet 2</span></p>
101
+ </div>
102
+ <div id="gameOver">
103
+ <h1>Game Over</h1>
104
+ <button onclick="retry()">Tentar Novamente</button>
105
+ </div>
106
+ <div id="pausedScreen">
107
+ <h1>PAUSED</h1>
108
+ <p>Pressione R para reiniciar</p>
109
+ </div>
110
+ <div id="startScreen">
111
+ <h1>Space Invaders</h1>
112
+ <p>Espaço para atirar</p>
113
+ <p>P para pausar</p>
114
+ <p>R para reiniciar</p>
115
+ <button onclick="startGame()">Iniciar</button>
116
+ </div>
117
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"></script>
118
+ <script>
119
+ // Configuração da cena
120
+ const scene = new THREE.Scene();
121
+ const camera = new THREE.OrthographicCamera(-8, 8, 8, -8, 0.1, 100);
122
+ camera.position.z = 10;
123
+ const renderer = new THREE.WebGLRenderer();
124
+ renderer.setSize(window.innerWidth, window.innerHeight);
125
+ document.body.appendChild(renderer.domElement);
126
+
127
+ // Variáveis do jogo
128
+ let player, enemies = [], bullets = [], enemyBullets = [], shields = [], explosions = [];
129
+ let score = 0, hiScore = 0, level = 1, hiPlanet = 1, deaths = 0;
130
+ let unlockedPowerUps = [0]; // Começa com tiro simples
131
+ let isPaused = false, gameOver = false, isGameStarted = false;
132
+ let enemyDirection = 1, enemySpeed = 0.01;
133
+ let lastShotTime = 0, tapShotDelay = 200, holdShotDelay = 500;
134
+ let isSpacePressed = false;
135
+ const colors = [0xff0000, 0x00ff00, 0x0000ff, 0xffff00]; // Cores por fase
136
+
137
+ // Jogador
138
+ function createPlayer() {
139
+ const geometry = new THREE.BoxGeometry(0.5, 0.5, 0.5);
140
+ const material = new THREE.MeshBasicMaterial({ color: 0xffffff });
141
+ player = new THREE.Mesh(geometry, material);
142
+ player.position.set(0, -6, 0);
143
+ scene.add(player);
144
+ }
145
+
146
+ // Inimigos
147
+ function createEnemies() {
148
+ enemies = [];
149
+ const color = colors[(level - 1) % colors.length];
150
+ for (let x = -6; x <= 6; x += 1.5) {
151
+ for (let y = 4; y <= 7; y += 1.5) {
152
+ const geometry = new THREE.BoxGeometry(0.3, 0.3, 0.3);
153
+ const material = new THREE.MeshBasicMaterial({ color });
154
+ const enemy = new THREE.Mesh(geometry, material);
155
+ enemy.position.set(x, y, 0);
156
+ enemies.push(enemy);
157
+ scene.add(enemy);
158
+ }
159
+ }
160
+ }
161
+
162
+ // Proteções
163
+ function createShields() {
164
+ shields = [];
165
+ let positions;
166
+ if (deaths === 0) {
167
+ positions = [-6, -2, 2, 6]; // 4 barreiras
168
+ } else if (deaths === 1) {
169
+ positions = [-4, 0, 4]; // 3 barreiras
170
+ } else if (deaths === 2) {
171
+ positions = [-2, 2]; // 2 barreiras
172
+ } else if (deaths === 3) {
173
+ positions = [0]; // 1 barreira
174
+ } else {
175
+ positions = []; // 0 barreiras
176
+ }
177
+ positions.forEach(x => {
178
+ const geometry = new THREE.BoxGeometry(1, 0.5, 0.5);
179
+ const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
180
+ const shield = new THREE.Mesh(geometry, material);
181
+ shield.position.set(x, -4, 0);
182
+ shield.health = 30;
183
+ shields.push(shield);
184
+ scene.add(shield);
185
+ });
186
+ }
187
+
188
+ // Atualizar visual da proteção
189
+ function updateShieldVisual(shield) {
190
+ if (shield.health <= 22) {
191
+ shield.scale.set(0.8, 0.8, 0.8);
192
+ shield.material.color.set(0xffff00); // Amarelo
193
+ } else if (shield.health <= 14) {
194
+ shield.scale.set(0.6, 0.6, 0.6);
195
+ shield.material.color.set(0xffa500); // Laranja
196
+ } else if (shield.health <= 7) {
197
+ shield.scale.set(0.4, 0.4, 0.4);
198
+ shield.material.color.set(0xff0000); // Vermelho
199
+ }
200
+ }
201
+
202
+ // Tiro do jogador
203
+ function shoot(isTap = false) {
204
+ const now = Date.now();
205
+ const delay = isTap ? tapShotDelay : holdShotDelay;
206
+ if (now - lastShotTime < delay) return;
207
+ lastShotTime = now;
208
+
209
+ unlockedPowerUps.forEach(powerUp => {
210
+ if (powerUp >= 5) {
211
+ const offsets = powerUp === 5 ? [0] : powerUp === 6 ? [-0.3, 0.3] : [-0.5, 0, 0.5];
212
+ offsets.forEach(offset => {
213
+ const bulletLeft = createBullet(offset);
214
+ bulletLeft.velocity = new THREE.Vector3(-0.075, 0.1, 0);
215
+ bulletLeft.isDiagonal = true;
216
+ bullets.push(bulletLeft);
217
+ scene.add(bulletLeft);
218
+ const bulletRight = createBullet(offset);
219
+ bulletRight.velocity = new THREE.Vector3(0.075, 0.1, 0);
220
+ bulletRight.isDiagonal = true;
221
+ bullets.push(bulletRight);
222
+ scene.add(bulletRight);
223
+ });
224
+ } else if (powerUp >= 3) {
225
+ const offsets = powerUp === 3 ? [0] : [-0.3, 0.3];
226
+ offsets.forEach(offset => {
227
+ const geometry = new THREE.SphereGeometry(0.3, 8, 8);
228
+ const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
229
+ const bomb = new THREE.Mesh(geometry, material);
230
+ bomb.position.set(player.position.x + offset, player.position.y, 0);
231
+ bomb.velocity = new THREE.Vector3(0, 0.1, 0);
232
+ bomb.isBomb = true;
233
+ bullets.push(bomb);
234
+ scene.add(bomb);
235
+ });
236
+ } else {
237
+ const offsets = powerUp === 0 ? [0] : powerUp === 1 ? [-0.3, 0.3] : [-0.5, 0, 0.5];
238
+ offsets.forEach(offset => {
239
+ const bullet = createBullet(offset);
240
+ bullet.velocity = new THREE.Vector3(0, 0.1, 0);
241
+ bullet.isNormal = true;
242
+ bullets.push(bullet);
243
+ scene.add(bullet);
244
+ });
245
+ }
246
+ });
247
+
248
+ function createBullet(offset) {
249
+ const geometry = new THREE.BoxGeometry(0.1, 0.3, 0.1);
250
+ const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
251
+ const bullet = new THREE.Mesh(geometry, material);
252
+ bullet.position.set(player.position.x + offset, player.position.y, 0);
253
+ return bullet;
254
+ }
255
+ }
256
+
257
+ // Tiro dos inimigos
258
+ function enemyShoot(enemy) {
259
+ const geometry = new THREE.BoxGeometry(0.1, 0.3, 0.1);
260
+ const material = new THREE.MeshBasicMaterial({ color: 0x800080 });
261
+ const bullet = new THREE.Mesh(geometry, material);
262
+ bullet.position.set(enemy.position.x, enemy.position.y - 0.3, 0);
263
+ bullet.velocity = new THREE.Vector3(0, -0.05, 0);
264
+ enemyBullets.push(bullet);
265
+ scene.add(bullet);
266
+ }
267
+
268
+ // Explosão
269
+ function createExplosion(x, y) {
270
+ const geometry = new THREE.SphereGeometry(0.3, 8, 8);
271
+ const material = new THREE.MeshBasicMaterial({ color: 0xffa500 });
272
+ const explosion = new THREE.Mesh(geometry, material);
273
+ explosion.position.set(x, y, 0);
274
+ explosion.scale.set(0.1, 0.1, 0.1);
275
+ explosion.life = 0;
276
+ explosions.push(explosion);
277
+ scene.add(explosion);
278
+ }
279
+
280
+ // Atualizar UI
281
+ function updateUI() {
282
+ document.getElementById('score').textContent = score;
283
+ document.getElementById('hiScore').textContent = hiScore;
284
+ document.getElementById('level').textContent = level;
285
+ document.getElementById('hiPlanet').textContent = hiPlanet;
286
+ document.getElementById('deaths').textContent = deaths;
287
+ const nextPowerUpPhase = unlockedPowerUps.length + 1;
288
+ document.getElementById('nextPowerUp').textContent =
289
+ nextPowerUpPhase <= 8 ? `Planet ${nextPowerUpPhase}` : 'Todos Desbloqueados';
290
+ }
291
+
292
+ // Iniciar o jogo
293
+ function startGame() {
294
+ isGameStarted = true;
295
+ document.getElementById('startScreen').style.display = 'none';
296
+ document.getElementById('ui').style.display = 'block';
297
+ document.getElementById('center-ui').style.display = 'block';
298
+ document.getElementById('deaths-ui').style.display = 'block';
299
+ createPlayer();
300
+ createEnemies();
301
+ createShields();
302
+ updateUI();
303
+ }
304
+
305
+ // Próxima fase
306
+ function nextLevel() {
307
+ level++;
308
+ hiPlanet = Math.max(hiPlanet, level);
309
+ if (!unlockedPowerUps.includes(level - 1)) {
310
+ unlockedPowerUps.push(level - 1);
311
+ }
312
+ enemySpeed += 0.005;
313
+ enemyBullets.forEach(bullet => scene.remove(bullet));
314
+ enemyBullets = [];
315
+ createEnemies();
316
+ updateUI();
317
+ }
318
+
319
+ // Game Over
320
+ function endGame() {
321
+ deaths++;
322
+ gameOver = true;
323
+ updateUI();
324
+ document.getElementById('gameOver').style.display = 'block';
325
+ }
326
+
327
+ // Reinício completo (novo jogo, usado por tecla R)
328
+ function restartGame() {
329
+ // Resetar todas as variáveis para um novo jogo
330
+ score = 0;
331
+ hiScore = 0;
332
+ level = 1;
333
+ hiPlanet = 1;
334
+ deaths = 0;
335
+ unlockedPowerUps = [0]; // Reseta power-ups
336
+ enemySpeed = 0.01;
337
+ // Limpar cena
338
+ enemies.forEach(enemy => scene.remove(enemy));
339
+ bullets.forEach(bullet => scene.remove(bullet));
340
+ enemyBullets.forEach(bullet => scene.remove(bullet));
341
+ shields.forEach(shield => scene.remove(shield));
342
+ explosions.forEach(explosion => scene.remove(explosion));
343
+ if (player) scene.remove(player);
344
+ // Limpar arrays
345
+ enemies = [];
346
+ bullets = [];
347
+ enemyBullets = [];
348
+ shields = [];
349
+ explosions = [];
350
+ player = null;
351
+ // Resetar estados
352
+ gameOver = false;
353
+ isPaused = false;
354
+ document.getElementById('gameOver').style.display = 'none';
355
+ document.getElementById('pausedScreen').style.display = 'none';
356
+ // Recriar elementos
357
+ createPlayer();
358
+ createEnemies();
359
+ createShields(); // Cria 4 barreiras, pois deaths = 0
360
+ updateUI();
361
+ }
362
+
363
+ // Tentar novamente (mantém power-ups, usado por Game Over)
364
+ window.retry = function() {
365
+ // Resetar variáveis, mas manter power-ups
366
+ score = 0;
367
+ level = 1;
368
+ enemySpeed = 0.01;
369
+ // Limpar cena
370
+ enemies.forEach(enemy => scene.remove(enemy));
371
+ bullets.forEach(bullet => scene.remove(bullet));
372
+ enemyBullets.forEach(bullet => scene.remove(bullet));
373
+ shields.forEach(shield => scene.remove(shield));
374
+ explosions.forEach(explosion => scene.remove(explosion));
375
+ if (player) scene.remove(player);
376
+ // Limpar arrays
377
+ enemies = [];
378
+ bullets = [];
379
+ enemyBullets = [];
380
+ shields = [];
381
+ explosions = [];
382
+ player = null;
383
+ // Resetar estados
384
+ gameOver = false;
385
+ isPaused = false;
386
+ document.getElementById('gameOver').style.display = 'none';
387
+ document.getElementById('pausedScreen').style.display = 'none';
388
+ // Recriar elementos
389
+ createPlayer();
390
+ createEnemies();
391
+ createShields(); // Cria barreiras com base em deaths
392
+ updateUI();
393
+ };
394
+
395
+ // Controles
396
+ const keys = {};
397
+ document.addEventListener('keydown', e => {
398
+ if (e.code === 'KeyR') {
399
+ if (isGameStarted && !gameOver) {
400
+ restartGame();
401
+ }
402
+ return;
403
+ }
404
+ if (!isGameStarted || gameOver) return;
405
+ keys[e.code] = true;
406
+ if (e.code === 'Space' && !isSpacePressed) {
407
+ isSpacePressed = true;
408
+ shoot(true);
409
+ } else if (e.code === 'KeyP') {
410
+ isPaused = !isPaused;
411
+ document.getElementById('pausedScreen').style.display = isPaused ? 'block' : 'none';
412
+ }
413
+ });
414
+ document.addEventListener('keyup', e => {
415
+ keys[e.code] = false;
416
+ if (e.code === 'Space') {
417
+ isSpacePressed = false;
418
+ }
419
+ });
420
+
421
+ // Animação
422
+ function animate() {
423
+ if (!isGameStarted || gameOver) {
424
+ renderer.render(scene, camera);
425
+ requestAnimationFrame(animate);
426
+ return;
427
+ }
428
+
429
+ if (isPaused) {
430
+ document.getElementById('pausedScreen').style.display = 'block';
431
+ renderer.render(scene, camera);
432
+ requestAnimationFrame(animate);
433
+ return;
434
+ }
435
+
436
+ document.getElementById('pausedScreen').style.display = 'none';
437
+
438
+ // Movimento do jogador
439
+ if (keys['ArrowLeft'] && player.position.x > -7.5) {
440
+ player.position.x -= 0.05;
441
+ }
442
+ if (keys['ArrowRight'] && player.position.x < 7.5) {
443
+ player.position.x += 0.05;
444
+ }
445
+ if (keys['Space'] && isSpacePressed) {
446
+ shoot(false);
447
+ }
448
+
449
+ // Movimento dos inimigos
450
+ let moveDown = false;
451
+ enemies.forEach(enemy => {
452
+ enemy.position.x += enemySpeed * enemyDirection;
453
+ if (enemy.position.x > 7.5 || enemy.position.x < -7.5) moveDown = true;
454
+ if (enemy.position.y < -5.5) endGame();
455
+ if (Math.random() < 0.005) {
456
+ enemyShoot(enemy);
457
+ }
458
+ });
459
+ if (moveDown) {
460
+ enemyDirection *= -1;
461
+ enemies.forEach(enemy => enemy.position.y -= 0.5);
462
+ }
463
+
464
+ // Movimento dos tiros do jogador
465
+ bullets.forEach((bullet, bIndex) => {
466
+ bullet.position.add(bullet.velocity);
467
+ if (bullet.position.y > 8 || bullet.position.x < -8 || bullet.position.x > 8) {
468
+ scene.remove(bullet);
469
+ bullets.splice(bIndex, 1);
470
+ }
471
+ });
472
+
473
+ // Movimento dos tiros dos inimigos
474
+ enemyBullets.forEach((bullet, bIndex) => {
475
+ bullet.position.add(bullet.velocity);
476
+ if (bullet.position.y < -8) {
477
+ scene.remove(bullet);
478
+ enemyBullets.splice(bIndex, 1);
479
+ }
480
+ });
481
+
482
+ // Colisões jogador-inimigos
483
+ bullets.forEach((bullet, bIndex) => {
484
+ enemies.forEach((enemy, eIndex) => {
485
+ if (bullet.position.distanceTo(enemy.position) < 0.3) {
486
+ createExplosion(enemy.position.x, enemy.position.y);
487
+ scene.remove(enemy);
488
+ enemies.splice(eIndex, 1);
489
+ if (!bullet.isBomb) {
490
+ scene.remove(bullet);
491
+ bullets.splice(bIndex, 1);
492
+ }
493
+ score += 10;
494
+ hiScore = Math.max(hiScore, score);
495
+ updateUI();
496
+ }
497
+ });
498
+ });
499
+
500
+ // Colisões inimigos-jogador
501
+ enemyBullets.forEach((bullet, bIndex) => {
502
+ shields.forEach((shield, sIndex) => {
503
+ if (bullet.position.distanceTo(shield.position) < 0.5) {
504
+ shield.health--;
505
+ if (shield.health <= 0) {
506
+ scene.remove(shield);
507
+ shields.splice(sIndex, 1);
508
+ } else {
509
+ updateShieldVisual(shield);
510
+ }
511
+ scene.remove(bullet);
512
+ enemyBullets.splice(bIndex, 1);
513
+ return;
514
+ }
515
+ });
516
+ if (bullet.position.distanceTo(player.position) < 0.3) {
517
+ scene.remove(bullet);
518
+ enemyBullets.splice(bIndex, 1);
519
+ endGame();
520
+ }
521
+ });
522
+
523
+ // Explosões
524
+ explosions.forEach((explosion, index) => {
525
+ explosion.scale.multiplyScalar(1.1);
526
+ explosion.life += 0.1;
527
+ if (explosion.life > 0.5) {
528
+ scene.remove(explosion);
529
+ explosions.splice(index, 1);
530
+ }
531
+ });
532
+
533
+ // Verificar próxima fase
534
+ if (enemies.length === 0) nextLevel();
535
+
536
+ renderer.render(scene, camera);
537
+ requestAnimationFrame(animate);
538
+ }
539
+
540
+ // Inicialização
541
+ animate();
542
+ </script>
543
+ </body>
544
+ </html>