Aleksmorshen commited on
Commit
cacc3d1
·
verified ·
1 Parent(s): 436fe15

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +702 -158
index.html CHANGED
@@ -1,193 +1,737 @@
1
-
2
  <!DOCTYPE html>
3
  <html lang="en">
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>Doom-like FPS Game</title>
 
 
8
  <style>
9
- body {
10
  margin: 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  overflow: hidden;
12
  }
13
- canvas {
14
- display: block;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  }
 
16
  #crosshair {
17
  position: absolute;
18
  top: 50%;
19
  left: 50%;
20
  transform: translate(-50%, -50%);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  font-size: 24px;
22
- color: white;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  pointer-events: none;
 
 
24
  }
25
- #hud {
 
26
  position: absolute;
27
- bottom: 10px;
28
- left: 10px;
29
- color: white;
30
- font-family: Arial, sans-serif;
 
 
 
 
31
  }
32
  </style>
33
- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
34
  </head>
35
  <body>
36
- <div id="crosshair">+</div>
37
- <div id="hud">Health: <span id="health">100</span> | Kills: <span id="kills">0</span></div>
38
- <script>
39
- // Scene setup
40
- const scene = new THREE.Scene();
41
- const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
42
- const renderer = new THREE.WebGLRenderer();
43
- renderer.setSize(window.innerWidth, window.innerHeight);
44
- document.body.appendChild(renderer.domElement);
45
-
46
- // Lighting
47
- const ambientLight = new THREE.AmbientLight(0x404040);
48
- scene.add(ambientLight);
49
- const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
50
- directionalLight.position.set(1, 1, 1);
51
- scene.add(directionalLight);
52
-
53
- // Floor
54
- const floorGeometry = new THREE.PlaneGeometry(100, 100);
55
- const floorMaterial = new THREE.MeshBasicMaterial({ color: 0x555555, side: THREE.DoubleSide });
56
- const floor = new THREE.Mesh(floorGeometry, floorMaterial);
57
- floor.rotation.x = Math.PI / 2;
58
- floor.position.y = -1;
59
- scene.add(floor);
60
-
61
- // Walls for a simple room
62
- const wallMaterial = new THREE.MeshBasicMaterial({ color: 0x888888 });
63
- const wall1 = new THREE.Mesh(new THREE.BoxGeometry(100, 10, 1), wallMaterial);
64
- wall1.position.set(0, 4, -50);
65
- scene.add(wall1);
66
- const wall2 = new THREE.Mesh(new THREE.BoxGeometry(100, 10, 1), wallMaterial);
67
- wall2.position.set(0, 4, 50);
68
- scene.add(wall2);
69
- const wall3 = new THREE.Mesh(new THREE.BoxGeometry(1, 10, 100), wallMaterial);
70
- wall3.position.set(-50, 4, 0);
71
- scene.add(wall3);
72
- const wall4 = new THREE.Mesh(new THREE.BoxGeometry(1, 10, 100), wallMaterial);
73
- wall4.position.set(50, 4, 0);
74
- scene.add(wall4);
75
-
76
- // Player setup
77
- camera.position.y = 1; // Eye level
78
- const playerVelocity = new THREE.Vector3();
79
- const playerDirection = new THREE.Vector3();
80
- const moveSpeed = 0.1;
81
- let health = 100;
82
- let kills = 0;
83
-
84
- // Controls
85
- const keys = {};
86
- document.addEventListener('keydown', (e) => keys[e.key.toLowerCase()] = true);
87
- document.addEventListener('keyup', (e) => keys[e.key.toLowerCase()] = false);
88
-
89
- // Mouse look
90
- let mouseX = 0, mouseY = 0;
91
- document.addEventListener('mousemove', (e) => {
92
- mouseX = e.movementX * 0.002;
93
- mouseY = e.movementY * 0.002;
94
- });
95
 
96
- // Pointer lock
97
- document.body.addEventListener('click', () => {
98
- document.body.requestPointerLock();
99
- });
100
-
101
- // Shooting
102
- const raycaster = new THREE.Raycaster();
103
- const mouse = new THREE.Vector2(0, 0); // Center for crosshair
104
- document.addEventListener('click', shoot);
105
-
106
- function shoot() {
107
- raycaster.setFromCamera(mouse, camera);
108
- const intersects = raycaster.intersectObjects(demons);
109
- if (intersects.length > 0) {
110
- const demon = intersects[0].object;
111
- scene.remove(demon);
112
- demons = demons.filter(d => d !== demon);
113
- kills++;
114
- document.getElementById('kills').innerText = kills;
115
- if (demons.length === 0) {
116
- alert('You win! All demons killed.');
117
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  }
119
  }
120
-
121
- // Demons
122
- const demonMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
123
- const demons = [];
124
- for (let i = 0; i < 5; i++) {
125
- const demon = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 32), demonMaterial);
126
- demon.position.set(Math.random() * 80 - 40, 0, Math.random() * 80 - 40);
127
- scene.add(demon);
128
- demons.push(demon);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  }
130
-
131
- // Demon AI (simple chase)
132
- function updateDemons() {
133
- demons.forEach(demon => {
134
- const direction = new THREE.Vector3();
135
- direction.subVectors(camera.position, demon.position).normalize();
136
- demon.position.add(direction.multiplyScalar(0.02));
137
-
138
- // Check collision with player
139
- if (demon.position.distanceTo(camera.position) < 1.5) {
140
- health -= 1;
141
- document.getElementById('health').innerText = health;
142
- if (health <= 0) {
143
- alert('Game Over! You died.');
144
- health = 100;
145
- kills = 0;
146
- // Reset game if needed
147
- }
148
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  }
151
-
152
- // Animation loop
 
 
 
 
 
153
  function animate() {
154
  requestAnimationFrame(animate);
155
-
156
- // Rotation (mouse look)
157
- camera.rotation.y -= mouseX;
158
- camera.rotation.x -= mouseY;
159
- camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));
160
- mouseX = 0;
161
- mouseY = 0;
162
-
163
- // Movement
164
- playerDirection.set(0, 0, 0);
165
- if (keys['w']) playerDirection.z -= 1;
166
- if (keys['s']) playerDirection.z += 1;
167
- if (keys['a']) playerDirection.x -= 1;
168
- if (keys['d']) playerDirection.x += 1;
169
- playerDirection.normalize();
170
- playerDirection.applyEuler(camera.rotation);
171
- playerVelocity.add(playerDirection.multiplyScalar(moveSpeed));
172
- playerVelocity.multiplyScalar(0.95); // Friction
173
- camera.position.add(playerVelocity);
174
-
175
- // Prevent going through walls (basic collision)
176
- camera.position.x = Math.max(-49, Math.min(49, camera.position.x));
177
- camera.position.z = Math.max(-49, Math.min(49, camera.position.z));
178
-
179
- updateDemons();
180
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  renderer.render(scene, camera);
182
  }
183
- animate();
184
-
185
- // Resize handler
186
- window.addEventListener('resize', () => {
187
- camera.aspect = window.innerWidth / window.innerHeight;
188
- camera.updateProjectionMatrix();
189
- renderer.setSize(window.innerWidth, window.innerHeight);
190
- });
191
  </script>
192
  </body>
193
- </html>
 
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Doom-Style 3D Shooter</title>
7
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/PointerLockControls.min.js"></script>
9
  <style>
10
+ * {
11
  margin: 0;
12
+ padding: 0;
13
+ box-sizing: border-box;
14
+ font-family: 'Courier New', monospace;
15
+ }
16
+
17
+ body {
18
+ overflow: hidden;
19
+ background: #000;
20
+ color: #ff5555;
21
+ height: 100vh;
22
+ perspective: 1px;
23
+ }
24
+
25
+ #gameContainer {
26
+ position: relative;
27
+ width: 100%;
28
+ height: 100vh;
29
  overflow: hidden;
30
  }
31
+
32
+ #gameCanvas {
33
+ position: absolute;
34
+ top: 0;
35
+ left: 0;
36
+ width: 100%;
37
+ height: 100%;
38
+ z-index: 1;
39
+ }
40
+
41
+ #ui {
42
+ position: absolute;
43
+ top: 0;
44
+ left: 0;
45
+ width: 100%;
46
+ height: 100%;
47
+ z-index: 2;
48
+ pointer-events: none;
49
  }
50
+
51
  #crosshair {
52
  position: absolute;
53
  top: 50%;
54
  left: 50%;
55
  transform: translate(-50%, -50%);
56
+ width: 30px;
57
+ height: 30px;
58
+ border: 2px solid #ff5555;
59
+ border-radius: 50%;
60
+ pointer-events: none;
61
+ }
62
+
63
+ #crosshair::before, #crosshair::after {
64
+ content: '';
65
+ position: absolute;
66
+ background: #ff5555;
67
+ }
68
+
69
+ #crosshair::before {
70
+ width: 2px;
71
+ height: 10px;
72
+ top: -12px;
73
+ left: 50%;
74
+ transform: translateX(-50%);
75
+ }
76
+
77
+ #crosshair::after {
78
+ width: 10px;
79
+ height: 2px;
80
+ top: 50%;
81
+ right: -12px;
82
+ transform: translateY(-50%);
83
+ }
84
+
85
+ #healthBar {
86
+ position: absolute;
87
+ bottom: 30px;
88
+ left: 30px;
89
+ width: 200px;
90
+ height: 30px;
91
+ background: rgba(0, 0, 0, 0.7);
92
+ border: 2px solid #ff5555;
93
+ border-radius: 5px;
94
+ overflow: hidden;
95
+ }
96
+
97
+ #healthFill {
98
+ height: 100%;
99
+ width: 100%;
100
+ background: linear-gradient(90deg, #ff0000, #ff5555);
101
+ transition: width 0.3s;
102
+ }
103
+
104
+ #ammoCounter {
105
+ position: absolute;
106
+ bottom: 30px;
107
+ right: 30px;
108
+ font-size: 24px;
109
+ color: #ff5555;
110
+ text-shadow: 0 0 5px #ff0000;
111
+ background: rgba(0, 0, 0, 0.7);
112
+ padding: 10px 20px;
113
+ border: 2px solid #ff5555;
114
+ border-radius: 5px;
115
+ }
116
+
117
+ #score {
118
+ position: absolute;
119
+ top: 30px;
120
+ left: 30px;
121
+ font-size: 24px;
122
+ color: #ff5555;
123
+ text-shadow: 0 0 5px #ff0000;
124
+ }
125
+
126
+ #startScreen {
127
+ position: absolute;
128
+ top: 0;
129
+ left: 0;
130
+ width: 100%;
131
+ height: 100%;
132
+ background: linear-gradient(rgba(0, 0, 0, 0.8), rgba(20, 0, 0, 0.9)),
133
+ url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><rect width="100" height="100" fill="%23110000"/><path d="M0 0L100 100M100 0L0 100" stroke="%23300" stroke-width="1"/></svg>');
134
+ display: flex;
135
+ flex-direction: column;
136
+ justify-content: center;
137
+ align-items: center;
138
+ z-index: 10;
139
+ text-align: center;
140
+ }
141
+
142
+ #title {
143
+ font-size: 72px;
144
+ margin-bottom: 30px;
145
+ text-shadow: 0 0 10px #ff0000, 0 0 20px #ff0000;
146
+ letter-spacing: 5px;
147
+ }
148
+
149
+ #subtitle {
150
+ font-size: 24px;
151
+ margin-bottom: 50px;
152
+ color: #ff9999;
153
+ }
154
+
155
+ #startButton {
156
+ background: #ff0000;
157
+ color: #fff;
158
+ border: none;
159
+ padding: 15px 50px;
160
+ font-size: 24px;
161
+ cursor: pointer;
162
+ border-radius: 5px;
163
+ text-transform: uppercase;
164
+ letter-spacing: 3px;
165
+ font-weight: bold;
166
+ box-shadow: 0 0 15px #ff0000;
167
+ transition: all 0.3s;
168
+ pointer-events: auto;
169
+ }
170
+
171
+ #startButton:hover {
172
+ background: #ff5555;
173
+ transform: scale(1.05);
174
+ box-shadow: 0 0 25px #ff0000;
175
+ }
176
+
177
+ #gameOverScreen {
178
+ position: absolute;
179
+ top: 0;
180
+ left: 0;
181
+ width: 100%;
182
+ height: 100%;
183
+ background: rgba(0, 0, 0, 0.85);
184
+ display: none;
185
+ flex-direction: column;
186
+ justify-content: center;
187
+ align-items: center;
188
+ z-index: 10;
189
+ }
190
+
191
+ #gameOverTitle {
192
+ font-size: 60px;
193
+ margin-bottom: 20px;
194
+ color: #ff0000;
195
+ text-shadow: 0 0 10px #ff0000;
196
+ }
197
+
198
+ #finalScore {
199
+ font-size: 36px;
200
+ margin-bottom: 40px;
201
+ color: #ff9999;
202
+ }
203
+
204
+ #restartButton {
205
+ background: #ff0000;
206
+ color: #fff;
207
+ border: none;
208
+ padding: 15px 50px;
209
  font-size: 24px;
210
+ cursor: pointer;
211
+ border-radius: 5px;
212
+ text-transform: uppercase;
213
+ letter-spacing: 3px;
214
+ font-weight: bold;
215
+ box-shadow: 0 0 15px #ff0000;
216
+ transition: all 0.3s;
217
+ }
218
+
219
+ #restartButton:hover {
220
+ background: #ff5555;
221
+ transform: scale(1.05);
222
+ box-shadow: 0 0 25px #ff0000;
223
+ }
224
+
225
+ #weapon {
226
+ position: absolute;
227
+ bottom: 0;
228
+ left: 50%;
229
+ transform: translateX(-50%);
230
+ width: 300px;
231
+ height: 200px;
232
+ background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 200"><rect x="50" y="100" width="200" height="30" fill="%23333"/><rect x="100" y="50" width="100" height="50" fill="%23444"/><rect x="130" y="30" width="40" height="20" fill="%23555"/><circle cx="150" cy="115" r="15" fill="%23222"/></svg>') no-repeat center bottom;
233
+ background-size: contain;
234
+ z-index: 3;
235
+ transition: transform 0.1s;
236
+ }
237
+
238
+ .hitEffect {
239
+ position: absolute;
240
+ top: 0;
241
+ left: 0;
242
+ width: 100%;
243
+ height: 100%;
244
+ background: rgba(255, 0, 0, 0.3);
245
  pointer-events: none;
246
+ opacity: 0;
247
+ z-index: 4;
248
  }
249
+
250
+ #bloodEffect {
251
  position: absolute;
252
+ top: 0;
253
+ left: 0;
254
+ width: 100%;
255
+ height: 100%;
256
+ background: radial-gradient(circle, rgba(255,0,0,0.7) 0%, rgba(255,0,0,0) 70%);
257
+ pointer-events: none;
258
+ opacity: 0;
259
+ z-index: 5;
260
  }
261
  </style>
 
262
  </head>
263
  <body>
264
+ <div id="gameContainer">
265
+ <div id="gameCanvas"></div>
266
+
267
+ <div id="ui">
268
+ <div id="crosshair"></div>
269
+ <div id="healthBar">
270
+ <div id="healthFill"></div>
271
+ </div>
272
+ <div id="ammoCounter">AMMO: 30</div>
273
+ <div id="score">SCORE: 0</div>
274
+ <div id="weapon"></div>
275
+ <div class="hitEffect" id="hitEffect"></div>
276
+ <div id="bloodEffect"></div>
277
+ </div>
278
+
279
+ <div id="startScreen">
280
+ <h1 id="title">DEMON SLAYER</h1>
281
+ <p id="subtitle">Eliminate all demons to survive</p>
282
+ <button id="startButton">START MISSION</button>
283
+ </div>
284
+
285
+ <div id="gameOverScreen">
286
+ <h1 id="gameOverTitle">MISSION FAILED</h1>
287
+ <p id="finalScore">SCORE: 0</p>
288
+ <button id="restartButton">TRY AGAIN</button>
289
+ </div>
290
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
 
292
+ <script>
293
+ // Game variables
294
+ let scene, camera, renderer, controls;
295
+ let player, enemies = [], bullets = [];
296
+ let playerHealth = 100;
297
+ let ammo = 30;
298
+ let score = 0;
299
+ let gameActive = false;
300
+ let moveForward = false;
301
+ let moveBackward = false;
302
+ let moveLeft = false;
303
+ let moveRight = false;
304
+ let canShoot = true;
305
+ let lastShotTime = 0;
306
+ let shotCooldown = 300; // ms
307
+ let enemySpawnTimer = 0;
308
+ let clock = new THREE.Clock();
309
+
310
+ // Initialize the game
311
+ function init() {
312
+ // Create scene
313
+ scene = new THREE.Scene();
314
+ scene.background = new THREE.Color(0x110000);
315
+ scene.fog = new THREE.Fog(0x110000, 10, 50);
316
+
317
+ // Create camera
318
+ camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
319
+ camera.position.y = 1.6;
320
+
321
+ // Create renderer
322
+ renderer = new THREE.WebGLRenderer({ antialias: true });
323
+ renderer.setSize(window.innerWidth, window.innerHeight);
324
+ renderer.shadowMap.enabled = true;
325
+ document.getElementById('gameCanvas').appendChild(renderer.domElement);
326
+
327
+ // Add lighting
328
+ const ambientLight = new THREE.AmbientLight(0x404040, 0.5);
329
+ scene.add(ambientLight);
330
+
331
+ const directionalLight = new THREE.DirectionalLight(0xff5555, 0.8);
332
+ directionalLight.position.set(10, 20, 10);
333
+ directionalLight.castShadow = true;
334
+ scene.add(directionalLight);
335
+
336
+ // Create floor
337
+ const floorGeometry = new THREE.PlaneGeometry(100, 100);
338
+ const floorMaterial = new THREE.MeshStandardMaterial({
339
+ color: 0x222222,
340
+ roughness: 0.8,
341
+ metalness: 0.2
342
+ });
343
+ const floor = new THREE.Mesh(floorGeometry, floorMaterial);
344
+ floor.rotation.x = -Math.PI / 2;
345
+ floor.receiveShadow = true;
346
+ scene.add(floor);
347
+
348
+ // Create walls
349
+ createWalls();
350
+
351
+ // Create pillars
352
+ createPillars();
353
+
354
+ // Create player
355
+ player = new THREE.Object3D();
356
+ player.position.set(0, 1.6, 0);
357
+ scene.add(player);
358
+ player.add(camera);
359
+
360
+ // Add pointer lock controls
361
+ controls = new THREE.PointerLockControls(camera, document.body);
362
+
363
+ // Event listeners
364
+ document.addEventListener('keydown', onKeyDown, false);
365
+ document.addEventListener('keyup', onKeyUp, false);
366
+ document.addEventListener('mousedown', onMouseDown, false);
367
+ document.addEventListener('mousemove', onMouseMove, false);
368
+ window.addEventListener('resize', onWindowResize, false);
369
+
370
+ // Start button event
371
+ document.getElementById('startButton').addEventListener('click', startGame);
372
+ document.getElementById('restartButton').addEventListener('click', restartGame);
373
+
374
+ // Start animation loop
375
+ animate();
376
+ }
377
+
378
+ function createWalls() {
379
+ const wallMaterial = new THREE.MeshStandardMaterial({
380
+ color: 0x330000,
381
+ roughness: 0.9,
382
+ metalness: 0.1
383
+ });
384
+
385
+ // Create a simple maze-like structure
386
+ const walls = [
387
+ // Outer walls
388
+ { x: 0, y: 2, z: -25, width: 50, height: 4, depth: 1 },
389
+ { x: 0, y: 2, z: 25, width: 50, height: 4, depth: 1 },
390
+ { x: -25, y: 2, z: 0, width: 1, height: 4, depth: 50 },
391
+ { x: 25, y: 2, z: 0, width: 1, height: 4, depth: 50 },
392
+
393
+ // Inner walls
394
+ { x: -10, y: 2, z: -10, width: 1, height: 4, depth: 20 },
395
+ { x: 10, y: 2, z: 10, width: 1, height: 4, depth: 20 },
396
+ { x: 0, y: 2, z: 0, width: 20, height: 4, depth: 1 },
397
+ { x: 0, y: 2, z: -20, width: 20, height: 4, depth: 1 }
398
+ ];
399
+
400
+ walls.forEach(wall => {
401
+ const wallGeometry = new THREE.BoxGeometry(wall.width, wall.height, wall.depth);
402
+ const wallMesh = new THREE.Mesh(wallGeometry, wallMaterial);
403
+ wallMesh.position.set(wall.x, wall.y, wall.z);
404
+ wallMesh.castShadow = true;
405
+ wallMesh.receiveShadow = true;
406
+ scene.add(wallMesh);
407
+ });
408
+ }
409
+
410
+ function createPillars() {
411
+ const pillarMaterial = new THREE.MeshStandardMaterial({
412
+ color: 0x440000,
413
+ roughness: 0.7,
414
+ metalness: 0.3
415
+ });
416
+
417
+ const pillarGeometry = new THREE.CylinderGeometry(1, 1, 4, 16);
418
+
419
+ const positions = [
420
+ { x: -20, z: -20 },
421
+ { x: 20, z: -20 },
422
+ { x: -20, z: 20 },
423
+ { x: 20, z: 20 },
424
+ { x: 0, z: -15 },
425
+ { x: 0, z: 15 },
426
+ { x: -15, z: 0 },
427
+ { x: 15, z: 0 }
428
+ ];
429
+
430
+ positions.forEach(pos => {
431
+ const pillar = new THREE.Mesh(pillarGeometry, pillarMaterial);
432
+ pillar.position.set(pos.x, 2, pos.z);
433
+ pillar.castShadow = true;
434
+ pillar.receiveShadow = true;
435
+ scene.add(pillar);
436
+ });
437
+ }
438
+
439
+ function spawnEnemy() {
440
+ const enemyGeometry = new THREE.ConeGeometry(1, 3, 8);
441
+ const enemyMaterial = new THREE.MeshStandardMaterial({
442
+ color: 0x880000,
443
+ roughness: 0.8,
444
+ metalness: 0.2
445
+ });
446
+
447
+ const enemy = new THREE.Mesh(enemyGeometry, enemyMaterial);
448
+ enemy.position.set(
449
+ (Math.random() - 0.5) * 40,
450
+ 1.5,
451
+ (Math.random() - 0.5) * 40
452
+ );
453
+ enemy.rotation.y = Math.random() * Math.PI * 2;
454
+ enemy.castShadow = true;
455
+ scene.add(enemy);
456
+
457
+ enemies.push({
458
+ mesh: enemy,
459
+ health: 100,
460
+ speed: 0.02 + Math.random() * 0.03,
461
+ lastAttack: 0,
462
+ attackCooldown: 1000 + Math.random() * 2000
463
+ });
464
+ }
465
+
466
+ function startGame() {
467
+ document.getElementById('startScreen').style.display = 'none';
468
+ controls.lock();
469
+ gameActive = true;
470
+
471
+ // Spawn initial enemies
472
+ for (let i = 0; i < 5; i++) {
473
+ spawnEnemy();
474
  }
475
  }
476
+
477
+ function restartGame() {
478
+ document.getElementById('gameOverScreen').style.display = 'none';
479
+ playerHealth = 100;
480
+ ammo = 30;
481
+ score = 0;
482
+ updateUI();
483
+
484
+ // Remove all enemies
485
+ enemies.forEach(enemy => {
486
+ scene.remove(enemy.mesh);
487
+ });
488
+ enemies = [];
489
+
490
+ // Remove all bullets
491
+ bullets.forEach(bullet => {
492
+ scene.remove(bullet.mesh);
493
+ });
494
+ bullets = [];
495
+
496
+ // Reset player position
497
+ player.position.set(0, 1.6, 0);
498
+
499
+ // Spawn initial enemies
500
+ for (let i = 0; i < 5; i++) {
501
+ spawnEnemy();
502
+ }
503
+
504
+ controls.lock();
505
+ gameActive = true;
506
  }
507
+
508
+ function gameOver() {
509
+ gameActive = false;
510
+ controls.unlock();
511
+ document.getElementById('finalScore').textContent = `SCORE: ${score}`;
512
+ document.getElementById('gameOverScreen').style.display = 'flex';
513
+ }
514
+
515
+ function updateUI() {
516
+ document.getElementById('healthFill').style.width = `${playerHealth}%`;
517
+ document.getElementById('ammoCounter').textContent = `AMMO: ${ammo}`;
518
+ document.getElementById('score').textContent = `SCORE: ${score}`;
519
+ }
520
+
521
+ function onKeyDown(event) {
522
+ switch (event.code) {
523
+ case 'KeyW': moveForward = true; break;
524
+ case 'KeyS': moveBackward = true; break;
525
+ case 'KeyA': moveLeft = true; break;
526
+ case 'KeyD': moveRight = true; break;
527
+ }
528
+ }
529
+
530
+ function onKeyUp(event) {
531
+ switch (event.code) {
532
+ case 'KeyW': moveForward = false; break;
533
+ case 'KeyS': moveBackward = false; break;
534
+ case 'KeyA': moveLeft = false; break;
535
+ case 'KeyD': moveRight = false; break;
536
+ }
537
+ }
538
+
539
+ function onMouseDown() {
540
+ if (!gameActive) return;
541
+
542
+ if (ammo > 0 && canShoot) {
543
+ shoot();
544
+ canShoot = false;
545
+ setTimeout(() => { canShoot = true; }, shotCooldown);
546
+ }
547
+ }
548
+
549
+ function onMouseMove(event) {
550
+ if (!gameActive) return;
551
+
552
+ // Add weapon sway effect
553
+ const weapon = document.getElementById('weapon');
554
+ const moveX = (event.movementX || 0) * 0.05;
555
+ const moveY = (event.movementY || 0) * 0.05;
556
+ weapon.style.transform = `translateX(calc(-50% + ${moveX}px)) translateY(${moveY}px)`;
557
+ }
558
+
559
+ function shoot() {
560
+ ammo--;
561
+ updateUI();
562
+
563
+ // Create bullet
564
+ const bulletGeometry = new THREE.SphereGeometry(0.1, 8, 8);
565
+ const bulletMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 });
566
+ const bullet = new THREE.Mesh(bulletGeometry, bulletMaterial);
567
+
568
+ // Position bullet at camera
569
+ bullet.position.set(0, 0, 0);
570
+ camera.getWorldPosition(bullet.position);
571
+
572
+ // Direction vector
573
+ const direction = new THREE.Vector3(0, 0, -1);
574
+ direction.applyQuaternion(camera.quaternion);
575
+
576
+ scene.add(bullet);
577
+ bullets.push({
578
+ mesh: bullet,
579
+ direction: direction,
580
+ speed: 1.0,
581
+ distance: 0
582
  });
583
+
584
+ // Weapon recoil effect
585
+ const weapon = document.getElementById('weapon');
586
+ weapon.style.transform = 'translateX(-50%) translateY(20px)';
587
+ setTimeout(() => {
588
+ weapon.style.transform = 'translateX(-50%) translateY(0)';
589
+ }, 100);
590
+
591
+ // Muzzle flash effect
592
+ const flash = document.createElement('div');
593
+ flash.style.position = 'absolute';
594
+ flash.style.width = '50px';
595
+ flash.style.height = '50px';
596
+ flash.style.background = 'radial-gradient(circle, #ffff00, #ff5500, transparent)';
597
+ flash.style.borderRadius = '50%';
598
+ flash.style.top = '50%';
599
+ flash.style.left = '50%';
600
+ flash.style.transform = 'translate(-50%, -50%)';
601
+ flash.style.pointerEvents = 'none';
602
+ flash.style.zIndex = '10';
603
+ document.getElementById('ui').appendChild(flash);
604
+
605
+ setTimeout(() => {
606
+ document.getElementById('ui').removeChild(flash);
607
+ }, 50);
608
  }
609
+
610
+ function onWindowResize() {
611
+ camera.aspect = window.innerWidth / window.innerHeight;
612
+ camera.updateProjectionMatrix();
613
+ renderer.setSize(window.innerWidth, window.innerHeight);
614
+ }
615
+
616
  function animate() {
617
  requestAnimationFrame(animate);
618
+
619
+ const delta = clock.getDelta();
620
+
621
+ if (gameActive) {
622
+ // Player movement
623
+ const speed = 0.1;
624
+ if (moveForward) player.translateZ(-speed);
625
+ if (moveBackward) player.translateZ(speed);
626
+ if (moveLeft) player.translateX(-speed);
627
+ if (moveRight) player.translateX(speed);
628
+
629
+ // Keep player within bounds
630
+ player.position.x = Math.max(-24, Math.min(24, player.position.x));
631
+ player.position.z = Math.max(-24, Math.min(24, player.position.z));
632
+
633
+ // Enemy AI
634
+ enemies.forEach((enemy, index) => {
635
+ // Move towards player
636
+ const direction = new THREE.Vector3();
637
+ direction.subVectors(player.position, enemy.mesh.position).normalize();
638
+ enemy.mesh.position.add(direction.multiplyScalar(enemy.speed));
639
+
640
+ // Rotate to face player
641
+ enemy.mesh.lookAt(player.position);
642
+ enemy.mesh.rotation.x = 0; // Keep upright
643
+ enemy.mesh.rotation.z = 0;
644
+
645
+ // Attack player if close
646
+ const distance = player.position.distanceTo(enemy.mesh.position);
647
+ if (distance < 3 && Date.now() - enemy.lastAttack > enemy.attackCooldown) {
648
+ playerHealth -= 10;
649
+ updateUI();
650
+ enemy.lastAttack = Date.now();
651
+
652
+ // Show hit effect
653
+ const hitEffect = document.getElementById('hitEffect');
654
+ hitEffect.style.opacity = '1';
655
+ setTimeout(() => {
656
+ hitEffect.style.opacity = '0';
657
+ }, 100);
658
+
659
+ // Show blood effect
660
+ const bloodEffect = document.getElementById('bloodEffect');
661
+ bloodEffect.style.opacity = '0.7';
662
+ setTimeout(() => {
663
+ bloodEffect.style.opacity = '0';
664
+ }, 200);
665
+
666
+ if (playerHealth <= 0) {
667
+ gameOver();
668
+ }
669
+ }
670
+
671
+ // Remove dead enemies
672
+ if (enemy.health <= 0) {
673
+ scene.remove(enemy.mesh);
674
+ enemies.splice(index, 1);
675
+ score += 100;
676
+ updateUI();
677
+
678
+ // Spawn new enemy
679
+ if (Math.random() > 0.7) {
680
+ spawnEnemy();
681
+ }
682
+ }
683
+ });
684
+
685
+ // Update bullets
686
+ for (let i = bullets.length - 1; i >= 0; i--) {
687
+ const bullet = bullets[i];
688
+ bullet.mesh.position.add(bullet.direction.clone().multiplyScalar(bullet.speed));
689
+ bullet.distance += bullet.speed;
690
+
691
+ // Remove bullets that travel too far
692
+ if (bullet.distance > 50) {
693
+ scene.remove(bullet.mesh);
694
+ bullets.splice(i, 1);
695
+ continue;
696
+ }
697
+
698
+ // Check for collisions with enemies
699
+ for (let j = enemies.length - 1; j >= 0; j--) {
700
+ const enemy = enemies[j];
701
+ const distance = bullet.mesh.position.distanceTo(enemy.mesh.position);
702
+
703
+ if (distance < 1.5) {
704
+ // Hit enemy
705
+ enemy.health -= 25;
706
+ scene.remove(bullet.mesh);
707
+ bullets.splice(i, 1);
708
+
709
+ // Enemy hit effect
710
+ enemy.mesh.material.color.set(0xff0000);
711
+ setTimeout(() => {
712
+ if (enemy.mesh) {
713
+ enemy.mesh.material.color.set(0x880000);
714
+ }
715
+ }, 100);
716
+
717
+ break;
718
+ }
719
+ }
720
+ }
721
+
722
+ // Spawn enemies periodically
723
+ enemySpawnTimer += delta;
724
+ if (enemySpawnTimer > 5) {
725
+ spawnEnemy();
726
+ enemySpawnTimer = 0;
727
+ }
728
+ }
729
+
730
  renderer.render(scene, camera);
731
  }
732
+
733
+ // Initialize the game when the page loads
734
+ window.onload = init;
 
 
 
 
 
735
  </script>
736
  </body>
737
+ </html>