ProPerNounpYK commited on
Commit
6f7e03f
·
verified ·
1 Parent(s): 47654c5

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +316 -513
index.html CHANGED
@@ -1,551 +1,354 @@
1
  <!DOCTYPE html>
2
  <html>
3
  <head>
4
- <style>
5
- body {
6
- margin: 0;
7
- overflow: hidden;
8
- background: #1a1a1a;
9
- display: flex;
10
- justify-content: center;
11
- align-items: center;
12
- min-height: 100vh;
13
- }
14
-
15
- #introCanvas {
16
- cursor: pointer;
17
- }
18
-
19
- #gameCanvas {
20
- display: none;
21
- background-image: url('stage 1.jpg');
22
- background-size: cover;
23
- }
24
-
25
- #message {
26
- position: fixed;
27
- bottom: 550px;
28
- left: 0;
29
- width: 100%;
30
- color: white;
31
- text-align: center;
32
- font-size: 30px;
33
- font-family: Arial;
34
- display: none;
35
- }
36
-
37
- #stats {
38
- position: fixed;
39
- top: 20px;
40
- left: 20px;
41
- color: white;
42
- font-family: Arial;
43
- font-size: 28px;
44
- display: none;
45
- }
46
-
47
- #villainCount {
48
- position: fixed;
49
- top: 20px;
50
- right: 20px;
51
- color: white;
52
- font-family: Arial;
53
- font-size: 28px;
54
- display: none;
55
- }
56
-
57
- #healthBar {
58
- width: 300px;
59
- height: 30px;
60
- background: #333;
61
- margin-top: 5px;
62
- }
63
-
64
- #healthFill {
65
- width: 100%;
66
- height: 100%;
67
- background: red;
68
- transition: width 0.3s;
69
- }
70
-
71
- #bulletCount, #enemyCount {
72
- font-size: 28px;
73
- }
74
-
75
- #replayButton {
76
- position: fixed;
77
- top: 50%;
78
- left: 50%;
79
- transform: translate(-50%, -50%);
80
- padding: 15px 30px;
81
- font-size: 20px;
82
- font-family: Arial;
83
- background-color: white;
84
- color: black;
85
- border: none;
86
- border-radius: 5px;
87
- display: none;
88
- cursor: pointer;
89
- }
90
-
91
- #replayButton:hover {
92
- background-color: lightgray;
93
- }
94
- </style>
95
  </head>
96
  <body>
97
- <canvas id="introCanvas"></canvas>
98
- <canvas id="gameCanvas"></canvas>
99
- <div id="message"></div>
100
- <div id="stats">
101
- Health:<div id="healthBar"><div id="healthFill"></div></div>
102
- Bullets: <span id="bulletCount">35</span>
103
- </div>
104
- <div id="villainCount">Villains: <span id="enemyCount">30</span></div>
105
- <button id="replayButton">Replay</button>
106
-
107
- <audio id="bgMusic" src="cinematic-time-lapse-115672.mp3" loop></audio>
108
- <audio id="playerShootSound" src="Maincharactergunsound.mp3"></audio>
109
- <audio id="enemyShootSound" src="Renovatorsgunshot.mp3"></audio>
110
- <audio id="playerHitSound" src="Maincharactershot.mp3"></audio>
111
- <audio id="enemyHitSound" src="Renovatorsgetshot.mp3"></audio>
112
- <script>
113
-
114
- const introCanvas = document.getElementById('introCanvas');
115
- const ctx = introCanvas.getContext('2d');
116
-
117
- let particles = [];
118
- const phrases = [
119
- { text: 'Hello everyone.', size: 65, duration: 5000 },
120
- { text: 'You have been selected as the next\nTimewalker for our team of Space Guardians.', size: 50, duration: 7000 },
121
- { text: 'Repair the collapsing timelines\nand return safely.', size: 55, duration: 6000 },
122
- { text: 'Good luck.\n- From the Space Guardians Leader', sizes: [65, 45], spacing: 45, duration: 6000 },
123
- { text: 'TimeWalker', size: 65, duration: 3000 },
124
- { text: 'Chapter 1', size: 65, duration: null }
125
- ];
126
-
127
- let currentPhraseIndex = 0;
128
- let animationFrame;
129
- let mouseX = 0;
130
- let mouseY = 0;
131
-
132
- introCanvas.width = window.innerWidth;
133
- introCanvas.height = window.innerHeight;
134
-
135
- class Particle {
136
- constructor(x, y, targetX, targetY) {
137
- this.x = Math.random() * introCanvas.width;
138
- this.y = Math.random() * introCanvas.height;
139
- this.targetX = targetX;
140
- this.targetY = targetY;
141
- this.dx = (Math.random() - 0.5) * 8;
142
- this.dy = (Math.random() - 0.5) * 8;
143
- this.radius = 2;
144
- this.alpha = 1;
145
- this.fadeSpeed = 0.02;
146
- }
147
-
148
- draw() {
149
- ctx.beginPath();
150
- ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
151
- ctx.fillStyle = rgba(255, 255, 255, ${this.alpha});
152
- ctx.fill();
153
- ctx.closePath();
154
- }
155
-
156
- update() {
157
- const distance = Math.hypot(mouseX - this.x, mouseY - this.y);
158
-
159
- if(distance < 100) {
160
- this.x += this.dx;
161
- this.y += this.dy;
162
- } else {
163
- this.x += (this.targetX - this.x) * 0.1;
164
- this.y += (this.targetY - this.y) * 0.1;
165
  }
166
- }
167
- }
168
 
169
- function createParticles(phrase) {
170
- let newParticles = [];
171
- ctx.clearRect(0, 0, introCanvas.width, introCanvas.height);
172
-
173
- const lines = phrase.text.split('\n');
174
-
175
- lines.forEach((line, index) => {
176
- const size = phrase.sizes ? phrase.sizes[index] : phrase.size;
177
- ctx.font = ${size}px Arial;
178
- ctx.fillStyle = 'white';
179
- ctx.textAlign = 'center';
180
- ctx.textBaseline = 'middle';
181
-
182
- const spacing = phrase.spacing || size * 1.2;
183
- const y = (introCanvas.height/2 - 20) + (index - (lines.length-1)/2) * spacing;
184
- ctx.fillText(line, introCanvas.width/2, y);
185
- });
186
-
187
- const imageData = ctx.getImageData(0, 0, introCanvas.width, introCanvas.height).data;
188
-
189
- for(let y = 0; y < introCanvas.height; y += 4) {
190
- for(let x = 0; x < introCanvas.width; x += 4) {
191
- const index = (y * introCanvas.width + x) * 4;
192
- const alpha = imageData[index + 3];
193
-
194
- if(alpha > 128) {
195
- newParticles.push(new Particle(x, y, x, y));
196
- }
197
  }
198
- }
199
-
200
- ctx.clearRect(0, 0, introCanvas.width, introCanvas.height);
201
- return newParticles;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  }
203
- function transition() {
204
- if(currentPhraseIndex < phrases.length - 1) {
205
- currentPhraseIndex++;
206
- const currentPhrase = phrases[currentPhraseIndex];
207
-
208
- particles.forEach(particle => {
209
- particle.dx = (Math.random() - 0.5) * 20;
210
- particle.dy = (Math.random() - 0.5) * 20;
211
- const fadeOut = setInterval(() => {
212
- particle.alpha -= particle.fadeSpeed;
213
- if(particle.alpha <= 0) clearInterval(fadeOut);
214
- }, 50);
215
  });
216
 
217
- setTimeout(() => {
218
- particles = createParticles(currentPhrase);
219
- particles.forEach(particle => {
220
- particle.alpha = 0;
221
- const fadeIn = setInterval(() => {
222
- particle.alpha += particle.fadeSpeed;
223
- if(particle.alpha >= 1) clearInterval(fadeIn);
224
- }, 50);
225
- });
226
- }, 800);
 
 
 
 
 
 
 
227
 
228
- if(currentPhrase.duration) {
229
- setTimeout(transition, currentPhrase.duration);
230
- }
231
- } else {
232
- // 마지막 문구가 표시된 1초 후에 게임 시작
233
- setTimeout(() => {
234
- cancelAnimationFrame(animationFrame); // 인트로 애니메이션 중지
235
- introCanvas.style.display = 'none';
236
- document.getElementById('gameCanvas').style.display = 'block';
237
- document.getElementById('stats').style.display = 'block';
238
- document.getElementById('villainCount').style.display = 'block';
239
- document.getElementById('message').style.display = 'block';
240
- startGame(); // 게임 시작
241
- }, 1000);
242
- }
243
- }
 
 
244
 
245
- function animate() {
246
- ctx.clearRect(0, 0, introCanvas.width, introCanvas.height);
247
- particles.forEach(particle => {
248
- particle.update();
249
- particle.draw();
250
- });
251
- animationFrame = requestAnimationFrame(animate);
252
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
 
254
- introCanvas.addEventListener('mousemove', (e) => {
255
- mouseX = e.clientX;
256
- mouseY = e.clientY;
257
- });
258
-
259
- window.addEventListener('resize', () => {
260
- introCanvas.width = window.innerWidth;
261
- introCanvas.height = window.innerHeight;
262
- particles = createParticles(phrases[currentPhraseIndex]);
263
- });
264
-
265
- // 인트로 애니메이션 시작
266
- particles = createParticles(phrases[0]);
267
- particles.forEach(particle => {
268
- particle.alpha = 0;
269
- const fadeIn = setInterval(() => {
270
- particle.alpha += particle.fadeSpeed;
271
- if(particle.alpha >= 1) clearInterval(fadeIn);
272
- }, 50);
273
- });
274
-
275
- animate();
276
- setTimeout(transition, phrases[0].duration);
277
- playAudioForDuration('reflected-light-147979.mp3', 31000);
278
-
279
- function startGame() {
280
- // 여기서부터 게임 코드 시작
281
- const gameCanvas = document.getElementById('gameCanvas');
282
- const gameCtx = gameCanvas.getContext('2d');
283
-
284
- // ... [이전에 보여드린 게임 코드 전체]
285
  }
286
- function startGame() {
287
- const gameCanvas = document.getElementById('gameCanvas');
288
- const gameCtx = gameCanvas.getContext('2d');
289
-
290
- // 게임 상태 변수
291
- let enemies = [];
292
- let bullets = [];
293
- let enemyBullets = [];
294
- let enemiesRemaining = 30;
295
- let mouseX = 0;
296
- let gameStarted = false;
297
- let gameOver = false;
298
-
299
- // 플레이어 객체 초기화
300
- const player = {
301
- x: gameCanvas.width / 2.3,
302
- y: gameCanvas.height - 260,
303
- width: 250,
304
- height: 250,
305
- speed: 10,
306
- health: 10,
307
- bullets: 35,
308
- direction: 1,
309
- image: new Image(),
310
- imageLeft: 'Maincharacterdefaultleft.png',
311
- imageRight: 'Maincharacterdefaultright.png',
312
- imageShootLeft: 'gunshotleft.png',
313
- imageShootRight: 'gunshotright.png',
314
- imageHitLeft: 'ExplosionLeft.png',
315
- imageHitRight: 'ExplosionRight.png'
316
- };
317
- player.image.src = player.imageRight;
318
-
319
- // 게임 시작 메시지 시퀀스
320
- setTimeout(() => {
321
- message.textContent = "Click on the character";
322
  setTimeout(() => {
323
- message.textContent = "You can move your character using the arrow keys.";
324
  setTimeout(() => {
325
- message.textContent = "The character's direction follows the mouse cursor.";
326
  setTimeout(() => {
327
- message.textContent = "Press the space bar to shoot a bullet.";
328
  setTimeout(() => {
329
- message.textContent = "Your mission is to defeat the Renovators who have attacked New York. Defeat them all and save New York in 2030!";
330
  setTimeout(() => {
331
- message.textContent = "";
332
- gameStarted = true;
333
- }, 5000);
334
- }, 3000);
 
 
 
335
  }, 4000);
336
  }, 4000);
337
- }, 4000);
338
- }, 0);
339
- // 적 생성 함수
340
- function spawnEnemy() {
341
- if (!gameStarted || gameOver) {
342
- return;
343
- }
344
-
345
- if (enemies.length >= 10) {
346
- return;
347
- }
348
-
349
- const side = Math.random() < 0.5 ? 0 : gameCanvas.width;
350
- const enemy = {
351
- x: side,
352
- y: Math.random() * (gameCanvas.height - 150),
353
- width: 250,
354
- height: 250,
355
- speed: side === 0 ? 1 : -1,
356
- image: new Image(),
357
- imageLeft: 'Renovators Default Right.png',
358
- imageRight: 'RenovatorsDefaultLeft.png',
359
- imageShootLeft: 'RenovatorsgunLeft.png',
360
- imageShootRight: 'RenovatorsGunRight.png',
361
- imageHitLeft: 'RenovatorsExplodeLeft.png',
362
- imageHitRight: 'RenovatorsExplodeRight.png',
363
- lastShootTime: Date.now()
364
- };
365
- enemy.image.src = side === 0 ? enemy.imageLeft : enemy.imageRight;
366
- enemies.push(enemy);
367
- }
368
 
369
- // 총알 발사 함수
370
- function enemyShoot(enemy) {
371
- const now = Date.now();
372
- if (now - enemy.lastShootTime >= 3000 && !gameOver) {
373
- enemy.image.src = enemy.speed > 0 ? enemy.imageShootRight : enemy.imageShootLeft;
374
- enemyBullets.push({
375
- x: enemy.x + enemy.width / 2,
376
- y: enemy.y + enemy.height / 2.5,
377
- width: 10,
378
- height: 5,
379
- speed: enemy.speed > 0 ? 5 : -5
380
- });
381
- enemy.lastShootTime = now;
382
- enemyShootSound.play();
383
  }
384
- }
385
-
386
- // 충돌 감지 함수
387
- function checkCollision(rect1, rect2) {
388
- return (
389
- rect1.x + rect1.width * 0.2 < rect2.x + rect2.width * 0.8 &&
390
- rect1.x + rect1.width * 0.8 > rect2.x + rect2.width * 0.2 &&
391
- rect1.y + rect1.height * 0.2 < rect2.y + rect2.height * 0.8 &&
392
- rect1.y + rect1.height * 0.8 > rect2.y + rect2.height * 0.2
393
- );
394
- }
395
- // 메인 게임 업데이트 루프
396
- function updateGame() {
397
- gameCtx.clearRect(0, 0, gameCanvas.width, gameCanvas.height);
398
-
399
- // 플레이어 업데이트
400
- player.direction = mouseX > player.x ? 1 : -1;
401
- player.image.src = player.direction === 1 ? player.imageRight : player.imageLeft;
402
- gameCtx.drawImage(player.image, player.x, player.y, player.width, player.height);
403
-
404
- // 총알 업데이트
405
- bullets.forEach((bullet, index) => {
406
- bullet.x += bullet.speed;
407
- gameCtx.fillStyle = 'yellow';
408
- gameCtx.fillRect(bullet.x, bullet.y, 10, 5);
409
- });
410
-
411
- // 적 업데이트
412
- enemies.forEach((enemy, enemyIndex) => {
413
- enemy.x += enemy.speed;
414
- gameCtx.drawImage(enemy.image, enemy.x, enemy.y, enemy.width, enemy.height);
415
-
416
- // 충돌 체크 및 처리
417
- if (checkCollision(player, enemy)) {
418
- handlePlayerEnemyCollision(enemy, enemyIndex);
419
  }
 
420
 
421
- // 총알 충돌 체크
422
- bullets.forEach((bullet, bulletIndex) => {
423
- if (checkCollision(bullet, enemy)) {
424
- handleBulletEnemyCollision(bullet, bulletIndex, enemy, enemyIndex);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
425
  }
426
- });
427
-
428
- enemyShoot(enemy);
429
- });
430
-
431
- // 적 총알 업데이트
432
- enemyBullets.forEach((bullet, index) => {
433
- bullet.x += bullet.speed;
434
- gameCtx.fillStyle = 'orange';
435
- gameCtx.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
436
-
437
- if (checkBulletPlayerCollision(bullet)) {
438
- handleBulletPlayerCollision(bullet, index);
439
  }
440
  });
441
 
442
- // 화면 총알 제거
443
- cleanupBullets();
444
-
445
- // 게임 상태 체크
446
- if (!gameOver) {
447
- requestAnimationFrame(updateGame);
448
- }
449
- }
450
-
451
- // 이벤트 리스너
452
- window.addEventListener('keydown', handleKeyPress);
453
- window.addEventListener('mousemove', (e) => {
454
- mouseX = e.clientX;
455
- });
456
-
457
- replayButton.addEventListener('click', () => {
458
- location.reload();
459
- });
460
-
461
- // 게임 시작
462
- setInterval(spawnEnemy, 2000);
463
- bgMusic.play();
464
- updateGame();
465
- }
466
- // 충돌 처리 헬퍼 함수들
467
- function handlePlayerEnemyCollision(enemy, enemyIndex) {
468
- player.health--;
469
- healthFill.style.width = (player.health / 5 * 100) + '%';
470
- player.image.src = player.direction === 1 ? player.imageHitRight : player.imageHitLeft;
471
- enemies.splice(enemyIndex, 1);
472
- playerHitSound.play();
473
-
474
- if (player.health <= 0) {
475
- endGame("Game Over! Go back to the past and change the current result!");
476
- }
477
- }
478
-
479
- function handleBulletEnemyCollision(bullet, bulletIndex, enemy, enemyIndex) {
480
- enemy.image.src = enemy.speed > 0 ? enemy.imageHitRight : enemy.imageHitLeft;
481
- setTimeout(() => {
482
- enemies.splice(enemyIndex, 1);
483
- bullets.splice(bulletIndex, 1);
484
- enemiesRemaining--;
485
- enemyCount.textContent = enemiesRemaining;
486
-
487
- if (enemiesRemaining <= 0) {
488
- endGame("You have successfully protected New York. Return to the time machine.");
489
- }
490
- }, 100);
491
- enemyHitSound.play();
492
- }
493
-
494
- function handleKeyPress(e) {
495
- if (!gameOver) {
496
- switch (e.key) {
497
- case 'ArrowUp':
498
- if (player.y > 0) player.y -= player.speed;
499
- break;
500
- case 'ArrowDown':
501
- if (player.y < gameCanvas.height - player.height) player.y += player.speed;
502
- break;
503
- case 'ArrowLeft':
504
- if (player.x > 0) player.x -= player.speed;
505
- break;
506
- case 'ArrowRight':
507
- if (player.x < gameCanvas.width - player.width) player.x += player.speed;
508
- break;
509
- case ' ':
510
- handlePlayerShoot();
511
- break;
512
- }
513
- }
514
- }
515
-
516
- function handlePlayerShoot() {
517
- if (player.bullets > 0) {
518
- player.image.src = player.direction === 1 ? player.imageShootRight : player.imageShootLeft;
519
- bullets.push({
520
- x: player.x + player.width / 2,
521
- y: player.y + player.height / 2.5,
522
- width: 10,
523
- height: 5,
524
- speed: player.direction * 10
525
- });
526
- player.bullets--;
527
- bulletCount.textContent = player.bullets;
528
- playerShootSound.play();
529
- }
530
- }
531
 
532
- function endGame(messageText) {
533
- gameOver = true;
534
- message.textContent = messageText;
535
- replayButton.style.display = 'block';
536
- }
537
 
538
- // 인트로 애니메이션이 완료된 후 게임 시작
539
- function startGameAfterIntro() {
540
- document.getElementById('introCanvas').style.display = 'none';
541
- document.getElementById('gameCanvas').style.display = 'block';
542
- document.getElementById('message').style.display = 'block';
543
- document.getElementById('stats').style.display = 'block';
544
- document.getElementById('villainCount').style.display = 'block';
545
  bgMusic.play();
546
  updateGame();
547
- setInterval(spawnEnemy, 2000);}
548
-
549
  </script>
550
  </body>
551
  </html>
 
1
  <!DOCTYPE html>
2
  <html>
3
  <head>
4
+ <style>
5
+ body {
6
+ margin: 0;
7
+ overflow: hidden;
8
+ background: black;
9
+ }
10
+ #gameCanvas {
11
+ background-image: url('stage 1.jpg');
12
+ background-size: cover;
13
+ }
14
+ #message {
15
+ position: fixed;
16
+ bottom: 550px;
17
+ left: 0;
18
+ width: 100%;
19
+ color: white;
20
+ text-align: center;
21
+ font-size: 30px;
22
+ font-family: Arial;
23
+ }
24
+ #stats {
25
+ position: fixed;
26
+ top: 20px;
27
+ left: 20px;
28
+ color: white;
29
+ font-family: Arial;
30
+ font-size: 28px;
31
+ }
32
+ #villainCount {
33
+ position: fixed;
34
+ top: 20px;
35
+ right: 20px;
36
+ color: white;
37
+ font-family: Arial;
38
+ font-size: 28px;
39
+ }
40
+ #healthBar {
41
+ width: 300px;
42
+ height: 30px;
43
+ background: #333;
44
+ margin-top: 5px;
45
+ }
46
+ #healthFill {
47
+ width: 100%;
48
+ height: 100%;
49
+ background: red;
50
+ transition: width 0.3s;
51
+ }
52
+ #bulletCount, #enemyCount {
53
+ font-size: 28px;
54
+ }
55
+ #replayButton {
56
+ position: fixed;
57
+ top: 50%;
58
+ left: 50%;
59
+ transform: translate(-50%, -50%);
60
+ padding: 15px 30px;
61
+ font-size: 20px;
62
+ font-family: Arial;
63
+ background-color: white;
64
+ color: black;
65
+ border: none;
66
+ border-radius: 5px;
67
+ display: none;
68
+ cursor: pointer;
69
+ }
70
+ #replayButton:hover {
71
+ background-color: lightgray;
72
+ }
73
+ </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  </head>
75
  <body>
76
+ <canvas id="gameCanvas"></canvas>
77
+ <div id="message"></div>
78
+ <div id="stats">
79
+ Health:<div id="healthBar"><div id="healthFill"></div></div>
80
+ Bullets: <span id="bulletCount">35</span>
81
+ </div>
82
+ <div id="villainCount">Villains: <span id="enemyCount">30</span></div>
83
+ <button id="replayButton">Replay</button>
84
+ <audio id="bgMusic" src="cinematic-time-lapse-115672.mp3" loop></audio>
85
+ <audio id="playerShootSound" src="Maincharactergunsound.mp3"></audio>
86
+ <audio id="enemyShootSound" src="Renovatorsgunshot.mp3"></audio>
87
+ <audio id="playerHitSound" src="Maincharactershot.mp3"></audio>
88
+ <audio id="enemyHitSound" src="Renovatorsgetshot.mp3"></audio>
89
+
90
+ <script>
91
+ const canvas = document.getElementById('gameCanvas');
92
+ const ctx = canvas.getContext('2d');
93
+ const message = document.getElementById('message');
94
+ const healthFill = document.getElementById('healthFill');
95
+ const bulletCount = document.getElementById('bulletCount');
96
+ const enemyCount = document.getElementById('enemyCount');
97
+ const bgMusic = document.getElementById('bgMusic');
98
+ const replayButton = document.getElementById('replayButton');
99
+ const playerShootSound = document.getElementById('playerShootSound');
100
+ const enemyShootSound = document.getElementById('enemyShootSound');
101
+ const playerHitSound = document.getElementById('playerHitSound');
102
+ const enemyHitSound = document.getElementById('enemyHitSound');
103
+
104
+ canvas.width = window.innerWidth;
105
+ canvas.height = window.innerHeight;
106
+
107
+ const player = {
108
+ x: canvas.width / 2.3,
109
+ y: canvas.height - 260,
110
+ width: 250,
111
+ height: 250,
112
+ speed: 10,
113
+ health: 10,
114
+ bullets: 35,
115
+ direction: 1,
116
+ image: new Image(),
117
+ imageLeft: 'Maincharacterdefaultleft.png',
118
+ imageRight: 'Maincharacterdefaultright.png',
119
+ imageShootLeft: 'gunshotleft.png',
120
+ imageShootRight: 'gunshotright.png',
121
+ imageHitLeft: 'ExplosionLeft.png',
122
+ imageHitRight: 'ExplosionRight.png'
123
+ };
124
+ player.image.src = player.imageRight;
125
+
126
+ let enemies = [];
127
+ let bullets = [];
128
+ let enemyBullets = [];
129
+ let enemiesRemaining = 30;
130
+ let mouseX = 0;
131
+ let gameStarted = false;
132
+ let gameOver = false;
133
+
134
+ function spawnEnemy() {
135
+ if (!gameStarted || gameOver) {
136
+ return;
 
 
 
 
 
 
 
137
  }
 
 
138
 
139
+ if (enemies.length >= 10) { // 동시에 존재할 수 있는 적의 수 제한
140
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  }
142
+
143
+ const side = Math.random() < 0.5 ? 0 : canvas.width;
144
+ const enemy = {
145
+ x: side,
146
+ y: Math.random() * (canvas.height - 150),
147
+ width: 250,
148
+ height: 250,
149
+ speed: side === 0 ? 1 : -1,
150
+ image: new Image(),
151
+ imageLeft: 'Renovators Default Right.png',
152
+ imageRight: 'RenovatorsDefaultLeft.png',
153
+ imageShootLeft: 'RenovatorsgunLeft.png',
154
+ imageShootRight: 'RenovatorsGunRight.png',
155
+ imageHitLeft: 'RenovatorsExplodeLeft.png',
156
+ imageHitRight: 'RenovatorsExplodeRight.png',
157
+ lastShootTime: Date.now()
158
+ };
159
+ enemy.image.src = side === 0 ? enemy.imageLeft : enemy.imageRight;
160
+ enemies.push(enemy);
161
  }
162
+ function updateGame() {
163
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
164
+
165
+ player.direction = mouseX > player.x ? 1 : -1;
166
+ player.image.src = player.direction === 1 ? player.imageRight : player.imageLeft;
167
+ ctx.drawImage(player.image, player.x, player.y, player.width, player.height);
168
+
169
+ // 플레이어가 발사한 총알 처리
170
+ bullets.forEach((bullet, index) => {
171
+ bullet.x += bullet.speed;
172
+ ctx.fillStyle = 'yellow';
173
+ ctx.fillRect(bullet.x, bullet.y, 10, 5);
174
  });
175
 
176
+ // 처리
177
+ enemies.forEach((enemy, enemyIndex) => {
178
+ enemy.x += enemy.speed;
179
+ ctx.drawImage(enemy.image, enemy.x, enemy.y, enemy.width, enemy.height);
180
+
181
+ // 플레이어와 적이 충돌했을 경우 처리
182
+ if (checkCollision(player, enemy)) {
183
+ player.health--;
184
+ healthFill.style.width = (player.health / 5 * 100) + '%';
185
+ player.image.src = player.direction === 1 ? player.imageHitRight : player.imageHitLeft;
186
+ enemies.splice(enemyIndex, 1); // 적 제거
187
+ playerHitSound.play();
188
+
189
+ if (player.health <= 0) {
190
+ endGame("Game Over! Go back to the past and change the current result!");
191
+ }
192
+ }
193
 
194
+ // 플레이어의 총알이 적을 맞췄을 경우 처리
195
+ bullets.forEach((bullet, bulletIndex) => {
196
+ if (checkCollision(bullet, enemy)) {
197
+ // 총알이 적을 맞췄을 때 처리
198
+ enemy.image.src = enemy.speed > 0 ? enemy.imageHitRight : enemy.imageHitLeft;
199
+ setTimeout(() => {
200
+ enemies.splice(enemyIndex, 1); // 제거
201
+ bullets.splice(bulletIndex, 1); // 총알 제거
202
+ enemiesRemaining--;
203
+ enemyCount.textContent = enemiesRemaining;
204
+ }, 100);
205
+ enemyHitSound.play();
206
+
207
+ if (enemiesRemaining <= 0) {
208
+ endGame("You have successfully protected New York. Return to the time machine.");
209
+ }
210
+ }
211
+ });
212
 
213
+ // 적의 총알 발사
214
+ enemyShoot(enemy);
215
+ });
216
+ if (enemiesRemaining <= 0 && enemies.length === 0) {
217
+ endGame("You have successfully protected New York. Return to the time machine.");
218
+ return; // 게임 종료 후 더 이상 업데이트하지 않음
 
219
  }
220
+ // 적의 총알 처리
221
+ enemyBullets.forEach((bullet, index) => {
222
+ bullet.x += bullet.speed;
223
+ ctx.fillStyle = 'orange';
224
+ ctx.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
225
+
226
+ // 총알이 플레이어와 충돌했을 경우 처리
227
+ if (
228
+ bullet.x < player.x + player.width - 30 &&
229
+ bullet.x + bullet.width > player.x + 30 &&
230
+ bullet.y < player.y + player.height - 30 &&
231
+ bullet.y + bullet.height > player.y + 30
232
+ ) {
233
+ player.health--;
234
+ healthFill.style.width = (player.health / 5 * 100) + '%';
235
+ player.image.src = player.direction === 1 ? player.imageHitRight : player.imageHitLeft;
236
+ enemyBullets.splice(index, 1); // 총알 제거
237
+ playerHitSound.play();
238
+
239
+ if (player.health <= 0) {
240
+ endGame("Game Over! Go back to the past and change the current result!");
241
+ }
242
+ }
243
+ });
244
 
245
+ // 화면 밖으로 나간 총알 제거
246
+ bullets = bullets.filter(bullet =>
247
+ bullet.x >= 0 && bullet.x <= canvas.width
248
+ );
249
+ enemyBullets = enemyBullets.filter(bullet =>
250
+ bullet.x >= 0 && bullet.x <= canvas.width
251
+ );
252
+
253
+ // 게임이 종료되지 않으면 계속 업데이트
254
+ if (!gameOver) {
255
+ requestAnimationFrame(updateGame);
256
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  setTimeout(() => {
259
+ message.textContent = "Click on the character";
260
  setTimeout(() => {
261
+ message.textContent = "You can move your character using the arrow keys.";
262
  setTimeout(() => {
263
+ message.textContent = "The character's direction follows the mouse cursor.";
264
  setTimeout(() => {
265
+ message.textContent = "Press the space bar to shoot a bullet.";
266
  setTimeout(() => {
267
+ message.textContent = "Your mission is to defeat the Renovators who have attacked New York. Defeat them all and save New York in 2030!";
268
+ setTimeout(() => {
269
+ message.textContent = "";
270
+ gameStarted = true;
271
+ }, 5000);
272
+ }, 3000);
273
+ }, 4000);
274
  }, 4000);
275
  }, 4000);
276
+ }, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
 
278
+ function endGame(messageText) {
279
+ gameOver = true;
280
+ message.textContent = messageText;
281
+ replayButton.style.display = 'block';
 
 
 
 
 
 
 
 
 
 
282
  }
283
+ function checkCollision(rect1, rect2) {
284
+ return (
285
+ rect1.x + rect1.width * 0.2 < rect2.x + rect2.width * 0.8 &&
286
+ rect1.x + rect1.width * 0.8 > rect2.x + rect2.width * 0.2 &&
287
+ rect1.y + rect1.height * 0.2 < rect2.y + rect2.height * 0.8 &&
288
+ rect1.y + rect1.height * 0.8 > rect2.y + rect2.height * 0.2
289
+ );
290
+ }
291
+ function enemyShoot(enemy) {
292
+ const now = Date.now();
293
+ if (now - enemy.lastShootTime >= 3000 && !gameOver) {
294
+ enemy.image.src = enemy.speed > 0 ? enemy.imageShootRight : enemy.imageShootLeft;
295
+ enemyBullets.push({
296
+ x: enemy.x + enemy.width / 2,
297
+ y: enemy.y + enemy.height / 2.5,
298
+ width: 10,
299
+ height: 5,
300
+ speed: enemy.speed > 0 ? 5 : -5
301
+ });
302
+ enemy.lastShootTime = now; // Update the last shoot time
303
+ enemyShootSound.play();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
304
  }
305
+ }
306
 
307
+ window.addEventListener('keydown', (e) => {
308
+ if (!gameOver) {
309
+ switch (e.key) {
310
+ case 'ArrowUp':
311
+ if (player.y > 0) player.y -= player.speed;
312
+ break;
313
+ case 'ArrowDown':
314
+ if (player.y < canvas.height - player.height) player.y += player.speed;
315
+ break;
316
+ case 'ArrowLeft':
317
+ if (player.x > 0) player.x -= player.speed;
318
+ break;
319
+ case 'ArrowRight':
320
+ if (player.x < canvas.width - player.width) player.x += player.speed;
321
+ break;
322
+ case ' ':
323
+ if (player.bullets > 0) {
324
+ player.image.src = player.direction === 1 ? player.imageShootRight : player.imageShootLeft;
325
+ bullets.push({
326
+ x: player.x + player.width / 2,
327
+ y: player.y + player.height / 2.5,
328
+ width: 10,
329
+ height: 5,
330
+ speed: player.direction * 10
331
+ });
332
+ player.bullets--;
333
+ bulletCount.textContent = player.bullets;
334
+ playerShootSound.play();
335
+ }
336
+ break;
337
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
338
  }
339
  });
340
 
341
+ window.addEventListener('mousemove', (e) => {
342
+ mouseX = e.clientX;
343
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344
 
345
+ replayButton.addEventListener('click', () => {
346
+ location.reload();
347
+ });
 
 
348
 
349
+ setInterval(spawnEnemy, 2000);
 
 
 
 
 
 
350
  bgMusic.play();
351
  updateGame();
 
 
352
  </script>
353
  </body>
354
  </html>