ProPerNounpYK commited on
Commit
f55aec5
ยท
verified ยท
1 Parent(s): 4b2b7da

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +524 -245
index.html CHANGED
@@ -1,269 +1,548 @@
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>Interactive Animation & Game</title>
7
- <style>
8
- body {
9
- margin: 0;
10
- overflow: hidden;
11
- background: #1a1a1a;
12
- display: flex;
13
- justify-content: center;
14
- align-items: center;
15
- min-height: 100vh;
16
- }
17
- canvas {
18
- cursor: pointer;
19
- }
20
- #gameCanvas {
21
- background-image: url('stage 1.jpg');
22
- background-size: cover;
23
- }
24
- #message {
25
- position: fixed;
26
- bottom: 550px;
27
- left: 0;
28
- width: 100%;
29
- color: white;
30
- text-align: center;
31
- font-size: 30px;
32
- font-family: Arial;
33
- }
34
- #stats {
35
- position: fixed;
36
- top: 20px;
37
- left: 20px;
38
- color: white;
39
- font-family: Arial;
40
- font-size: 28px;
41
- }
42
- #villainCount {
43
- position: fixed;
44
- top: 20px;
45
- right: 20px;
46
- color: white;
47
- font-family: Arial;
48
- font-size: 28px;
49
- }
50
- #healthBar {
51
- width: 300px;
52
- height: 30px;
53
- background: #333;
54
- margin-top: 5px;
55
- }
56
- #healthFill {
57
- width: 100%;
58
- height: 100%;
59
- background: red;
60
- transition: width 0.3s;
61
- }
62
- #bulletCount, #enemyCount {
63
- font-size: 28px;
64
- }
65
- #replayButton {
66
- position: fixed;
67
- top: 50%;
68
- left: 50%;
69
- transform: translate(-50%, -50%);
70
- padding: 15px 30px;
71
- font-size: 20px;
72
- font-family: Arial;
73
- background-color: white;
74
- color: black;
75
- border: none;
76
- border-radius: 5px;
77
- display: none;
78
- cursor: pointer;
79
- }
80
- #replayButton:hover {
81
- background-color: lightgray;
82
- }
83
- </style>
 
 
 
 
 
 
 
 
 
 
 
84
  </head>
85
  <body>
86
- <canvas id="canvas"></canvas>
87
- <canvas id="gameCanvas"></canvas>
88
- <div id="message"></div>
89
- <div id="stats">
90
- Health: <div id="healthBar"><div id="healthFill"></div></div>
91
- Bullets: <span id="bulletCount">35</span>
92
- </div>
93
- <div id="villainCount">Villains: <span id="enemyCount">30</span></div>
94
- <button id="replayButton">Replay</button>
95
- <audio id="bgMusic" src="cinematic-time-lapse-115672.mp3" loop></audio>
96
- <audio id="playerShootSound" src="Maincharactergunsound.mp3"></audio>
97
- <audio id="enemyShootSound" src="Renovatorsgunshot.mp3"></audio>
98
- <audio id="playerHitSound" src="Maincharactershot.mp3"></audio>
99
- <audio id="enemyHitSound" src="Renovatorsgetshot.mp3"></audio>
100
-
101
- <script>
102
- // Part 1 - Animation and Particle Effects
103
-
104
- const canvas = document.getElementById('canvas');
105
- const ctx = canvas.getContext('2d');
106
- let particles = [];
107
- const phrases = [
108
- { text: 'Hello everyone.', size: 65, duration: 5000 },
109
- { text: 'You have been selected as the next\nTimewalker for our team of Space Guardians.', size: 50, duration: 7000 },
110
- { text: 'Repair the collapsing timelines\nand return safely.', size: 55, duration: 6000 },
111
- { text: 'Good luck.\n- From the Space Guardians Leader', sizes: [65, 45], spacing: 45, duration: 6000 },
112
- { text: 'TimeWalker', size: 65, duration: 3000 },
113
- { text: 'Chapter 1', size: 65, duration: null }
114
- ];
115
-
116
- let currentPhraseIndex = 0;
117
- let animationFrame;
118
- let mouseX = 0;
119
- let mouseY = 0;
120
-
121
- canvas.width = window.innerWidth;
122
- canvas.height = window.innerHeight;
123
-
124
- class Particle {
125
- constructor(x, y, targetX, targetY) {
126
- this.x = Math.random() * canvas.width;
127
- this.y = Math.random() * canvas.height;
128
- this.targetX = targetX;
129
- this.targetY = targetY;
130
- this.dx = (Math.random() - 0.5) * 8;
131
- this.dy = (Math.random() - 0.5) * 8;
132
- this.radius = 2;
133
- this.alpha = 1;
134
- this.fadeSpeed = 0.02;
135
- }
136
 
137
- draw() {
138
- ctx.beginPath();
139
- ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
140
- ctx.fillStyle = `rgba(255, 255, 255, ${this.alpha})`;
141
- ctx.fill();
142
- ctx.closePath();
143
- }
 
 
144
 
145
- update() {
146
- const distance = Math.hypot(mouseX - this.x, mouseY - this.y);
147
- if(distance < 100) {
148
- this.x += this.dx;
149
- this.y += this.dy;
150
- } else {
151
- this.x += (this.targetX - this.x) * 0.1;
152
- this.y += (this.targetY - this.y) * 0.1;
153
- }
154
- }
155
- }
156
 
157
- function createParticles(phrase) {
158
- let newParticles = [];
159
- ctx.clearRect(0, 0, canvas.width, canvas.height);
160
-
161
- const lines = phrase.text.split('\n');
162
-
163
- lines.forEach((line, index) => {
164
- const size = phrase.sizes ? phrase.sizes[index] : phrase.size;
165
- ctx.font = `${size}px Arial`;
166
- ctx.fillStyle = 'white';
167
- ctx.textAlign = 'center';
168
- ctx.textBaseline = 'middle';
169
-
170
- const spacing = phrase.spacing || size * 1.2;
171
- const y = (canvas.height / 2 - 20) + (index - (lines.length - 1) / 2) * spacing;
172
- ctx.fillText(line, canvas.width / 2, y);
173
- });
174
-
175
- const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
176
-
177
- for(let y = 0; y < canvas.height; y += 4) {
178
- for(let x = 0; x < canvas.width; x += 4) {
179
- const index = (y * canvas.width + x) * 4;
180
- const alpha = imageData[index + 3];
181
- if(alpha > 128) {
182
- newParticles.push(new Particle(x, y, x, y));
183
- }
184
- }
185
- }
186
-
187
- ctx.clearRect(0, 0, canvas.width, canvas.height);
188
- return newParticles;
189
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
- function transition() {
192
- if(currentPhraseIndex < phrases.length - 1) {
193
- currentPhraseIndex++;
194
- const currentPhrase = phrases[currentPhraseIndex];
195
-
196
- particles.forEach(particle => {
197
- particle.dx = (Math.random() - 0.5) * 20;
198
- particle.dy = (Math.random() - 0.5) * 20;
199
- const fadeOut = setInterval(() => {
200
- particle.alpha -= particle.fadeSpeed;
201
- if(particle.alpha <= 0) clearInterval(fadeOut);
202
- }, 50);
203
- });
 
 
 
204
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  setTimeout(() => {
206
- particles = createParticles(currentPhrase);
207
- particles.forEach(particle => {
208
- particle.alpha = 0;
209
- const fadeIn = setInterval(() => {
210
- particle.alpha += particle.fadeSpeed;
211
- if(particle.alpha >= 1) clearInterval(fadeIn);
212
- }, 50);
213
- });
214
- }, 800);
215
-
216
- if(currentPhrase.duration) {
217
- setTimeout(transition, currentPhrase.duration);
218
- }
219
- }
 
 
220
  }
221
 
222
- function animate() {
223
- ctx.clearRect(0, 0, canvas.width, canvas.height);
224
- particles.forEach(particle => {
225
- particle.update();
226
- particle.draw();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
  });
228
- animationFrame = requestAnimationFrame(animate);
 
229
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
 
231
- canvas.addEventListener('mousemove', (e) => {
232
- mouseX = e.clientX;
233
- mouseY = e.clientY;
 
 
234
  });
235
 
236
- window.addEventListener('resize', () => {
237
- canvas.width = window.innerWidth;
238
- canvas.height = window.innerHeight;
239
- particles = createParticles(phrases[currentPhraseIndex]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
240
  });
241
 
242
- particles = createParticles(phrases[0]);
243
- particles.forEach(particle => {
244
- particle.alpha = 0;
245
- const fadeIn = setInterval(() => {
246
- particle.alpha += particle.fadeSpeed;
247
- if(particle.alpha >= 1) clearInterval(fadeIn);
248
- }, 50);
 
 
249
  });
250
- animate();
251
- transition();
252
 
253
- // Part 2 - Game Logic
254
- function gameStart() {
255
- setTimeout(() => {
256
- document.getElementById('gameCanvas').style.display = 'block';
257
- document.getElementById('stats').style.display = 'block';
258
- document.getElementById('message').style.display = 'none';
259
- document.getElementById('bgMusic').play();
260
- // Additional game logic can start here
261
- }, 1000); // Wait for 1 second before starting the game
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  }
 
263
 
264
- // Once animation part completes or after transition, start the game logic
265
- gameStart();
 
 
 
266
 
267
- </script>
268
- </body>
269
- </html>
 
 
 
 
 
 
 
 
 
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
+ }