awacke1 commited on
Commit
27d34dd
·
verified ·
1 Parent(s): a75555f

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +486 -18
index.html CHANGED
@@ -1,19 +1,487 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </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>Yar's Revenge 3D</title>
7
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
8
+ <style>
9
+ body { margin: 0; overflow: hidden; font-family: 'Arial', sans-serif; background-color: #000; color: #fff; }
10
+ canvas { display: block; }
11
+ #infoPanel {
12
+ position: absolute;
13
+ top: 10px;
14
+ left: 10px;
15
+ padding: 10px;
16
+ background-color: rgba(0,0,0,0.7);
17
+ border-radius: 8px;
18
+ color: #fff;
19
+ font-size: 16px;
20
+ display: flex;
21
+ flex-direction: column;
22
+ gap: 8px;
23
+ }
24
+ .player-info {
25
+ padding: 5px;
26
+ border-radius: 4px;
27
+ }
28
+ .player1 { background-color: rgba(0, 150, 255, 0.5); }
29
+ .player2 { background-color: rgba(255, 100, 0, 0.5); }
30
+ #gameOverScreen {
31
+ position: absolute;
32
+ top: 50%;
33
+ left: 50%;
34
+ transform: translate(-50%, -50%);
35
+ padding: 30px;
36
+ background-color: rgba(20, 20, 20, 0.9);
37
+ border: 2px solid #555;
38
+ border-radius: 15px;
39
+ text-align: center;
40
+ display: none; /* Hidden by default */
41
+ z-index: 100;
42
+ }
43
+ #gameOverScreen h2 { margin-top: 0; font-size: 28px; color: #ff4444; }
44
+ #gameOverScreen p { font-size: 18px; }
45
+ #gameOverScreen button {
46
+ padding: 12px 25px;
47
+ font-size: 18px;
48
+ color: #fff;
49
+ background-color: #007bff;
50
+ border: none;
51
+ border-radius: 8px;
52
+ cursor: pointer;
53
+ margin-top: 20px;
54
+ transition: background-color 0.3s ease;
55
+ }
56
+ #gameOverScreen button:hover { background-color: #0056b3; }
57
+ </style>
58
+ </head>
59
+ <body>
60
+ <div id="infoPanel">
61
+ <div id="player1Info" class="player-info player1">Player 1 (WASD, E): Score 0 | Lives 3</div>
62
+ <div id="player2Info" class="player-info player2">Player 2 (IJKL, U): Score 0 | Lives 3</div>
63
+ <div id="qotileInfo">Qotile Health: 100</div>
64
+ </div>
65
+
66
+ <div id="gameOverScreen">
67
+ <h2>Game Over!</h2>
68
+ <p id="gameOverMessage"></p>
69
+ <button id="restartButton">Restart Game</button>
70
+ </div>
71
+
72
+ <script>
73
+ let scene, camera, renderer, clock;
74
+ let players = [];
75
+ let playerProjectiles = [];
76
+ let neutralZoneBlocks = [];
77
+ let qotile;
78
+
79
+ const keysPressed = {}; // Stores the state of currently pressed keys using event.code
80
+ const gameSettings = {
81
+ playerSpeed: 10,
82
+ projectileSpeed: 30,
83
+ playerSize: 1,
84
+ projectileSize: 0.2,
85
+ neutralZoneBlockSize: 2,
86
+ qotileSize: 4,
87
+ playAreaWidth: 30,
88
+ playAreaHeight: 20,
89
+ playerShootCooldown: 0.2, // seconds
90
+ initialPlayerLives: 3,
91
+ qotileInitialHealth: 100,
92
+ pointsPerNeutralBlock: 10,
93
+ pointsPerQotileHit: 50,
94
+ };
95
+ let gameActive = true;
96
+
97
+ // Initialization function
98
+ function init() {
99
+ gameActive = true;
100
+ // Scene
101
+ scene = new THREE.Scene();
102
+ scene.background = new THREE.Color(0x111122);
103
+
104
+ // Camera
105
+ camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
106
+ camera.position.set(0, 5, 25); // Positioned to see the play area
107
+ camera.lookAt(0, 0, 0);
108
+
109
+ // Renderer
110
+ renderer = new THREE.WebGLRenderer({ antialias: true });
111
+ renderer.setSize(window.innerWidth, window.innerHeight);
112
+ document.body.appendChild(renderer.domElement);
113
+
114
+ // Lighting
115
+ const ambientLight = new THREE.AmbientLight(0x606060);
116
+ scene.add(ambientLight);
117
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
118
+ directionalLight.position.set(5, 10, 7.5);
119
+ scene.add(directionalLight);
120
+
121
+ // Clock for delta time
122
+ clock = new THREE.Clock();
123
+
124
+ // Create game elements
125
+ createPlayers();
126
+ createNeutralZone();
127
+ createQotile();
128
+
129
+ // Event Listeners
130
+ document.addEventListener('keydown', onKeyDown);
131
+ document.addEventListener('keyup', onKeyUp);
132
+ window.addEventListener('resize', onWindowResize);
133
+ document.getElementById('restartButton').addEventListener('click', restartGame);
134
+
135
+ document.getElementById('gameOverScreen').style.display = 'none';
136
+ updateUI();
137
+ animate();
138
+ }
139
+
140
+ // Create Player objects
141
+ function createPlayers() {
142
+ players = []; // Clear existing players if any (for restart)
143
+ playerProjectiles = []; // Clear existing projectiles
144
+
145
+ const playerGeometry = new THREE.BoxGeometry(gameSettings.playerSize, gameSettings.playerSize, gameSettings.playerSize);
146
+
147
+ // Player 1
148
+ const player1Material = new THREE.MeshStandardMaterial({ color: 0x0099ff });
149
+ const player1Mesh = new THREE.Mesh(playerGeometry, player1Material);
150
+ player1Mesh.position.set(-gameSettings.playAreaWidth / 4, 0, 15);
151
+ scene.add(player1Mesh);
152
+ players.push({
153
+ mesh: player1Mesh,
154
+ isPlayer2: false,
155
+ // ******** UPDATED FIRE KEY FOR PLAYER 1 ********
156
+ controls: { up: 'KeyW', down: 'KeyS', left: 'KeyA', right: 'KeyD', shoot: 'KeyE' },
157
+ shootCooldownTimer: 0,
158
+ score: 0,
159
+ lives: gameSettings.initialPlayerLives,
160
+ projectiles: []
161
+ });
162
+
163
+ // Player 2
164
+ const player2Material = new THREE.MeshStandardMaterial({ color: 0xff6600 });
165
+ const player2Mesh = new THREE.Mesh(playerGeometry, player2Material);
166
+ player2Mesh.position.set(gameSettings.playAreaWidth / 4, 0, 15);
167
+ scene.add(player2Mesh);
168
+ players.push({
169
+ mesh: player2Mesh,
170
+ isPlayer2: true,
171
+ // ******** UPDATED FIRE KEY FOR PLAYER 2 ********
172
+ controls: { up: 'KeyI', down: 'KeyK', left: 'KeyJ', right: 'KeyL', shoot: 'KeyU' },
173
+ shootCooldownTimer: 0,
174
+ score: 0,
175
+ lives: gameSettings.initialPlayerLives,
176
+ projectiles: []
177
+ });
178
+ }
179
+
180
+ // Create Neutral Zone blocks
181
+ function createNeutralZone() {
182
+ // Remove existing blocks from scene before clearing array
183
+ neutralZoneBlocks.forEach(block => {
184
+ if (block && scene.getObjectById(block.id)) scene.remove(block);
185
+ if (block && block.geometry) block.geometry.dispose();
186
+ if (block && block.material) block.material.dispose();
187
+ });
188
+ neutralZoneBlocks = []; // Clear for restart
189
+
190
+
191
+ const blockGeometry = new THREE.BoxGeometry(
192
+ gameSettings.neutralZoneBlockSize,
193
+ gameSettings.neutralZoneBlockSize,
194
+ gameSettings.neutralZoneBlockSize / 2 // Thinner blocks
195
+ );
196
+ const blockMaterial = new THREE.MeshStandardMaterial({ color: 0x888888, roughness: 0.7, metalness: 0.3 });
197
+
198
+ const numX = Math.floor(gameSettings.playAreaWidth / gameSettings.neutralZoneBlockSize);
199
+ const numY = Math.floor(gameSettings.playAreaHeight / gameSettings.neutralZoneBlockSize);
200
+
201
+ for (let i = 0; i < numX; i++) {
202
+ for (let j = 0; j < numY; j++) {
203
+ const block = new THREE.Mesh(blockGeometry.clone(), blockMaterial.clone());
204
+ block.position.set(
205
+ (i - numX / 2 + 0.5) * gameSettings.neutralZoneBlockSize,
206
+ (j - numY / 2 + 0.5) * gameSettings.neutralZoneBlockSize,
207
+ 0 // Z-position of the neutral zone
208
+ );
209
+ block.userData = { health: 1 }; // Simple health for blocks
210
+ scene.add(block);
211
+ neutralZoneBlocks.push(block);
212
+ }
213
+ }
214
+ }
215
+
216
+ // Create Qotile (enemy base)
217
+ function createQotile() {
218
+ if (qotile && qotile.mesh) {
219
+ if (scene.getObjectById(qotile.mesh.id)) scene.remove(qotile.mesh);
220
+ if (qotile.mesh.geometry) qotile.mesh.geometry.dispose();
221
+ if (qotile.mesh.material) qotile.mesh.material.dispose();
222
+ }
223
+
224
+ const qotileGeometry = new THREE.BoxGeometry(gameSettings.qotileSize, gameSettings.qotileSize, gameSettings.qotileSize);
225
+ const qotileMaterial = new THREE.MeshStandardMaterial({ color: 0xff0000, emissive: 0x330000 });
226
+ const qotileMesh = new THREE.Mesh(qotileGeometry, qotileMaterial);
227
+ qotileMesh.position.set(0, 0, -15); // Positioned behind the neutral zone
228
+ scene.add(qotileMesh);
229
+ qotile = {
230
+ mesh: qotileMesh,
231
+ health: gameSettings.qotileInitialHealth,
232
+ hitTimer: 0 // For visual feedback on hit
233
+ };
234
+ }
235
+
236
+ // Handle player movement
237
+ function handlePlayerMovement(player, delta) {
238
+ const moveDistance = gameSettings.playerSpeed * delta;
239
+ // Check against the correct event.code strings stored in player.controls
240
+ if (keysPressed[player.controls.up]) player.mesh.position.y += moveDistance;
241
+ if (keysPressed[player.controls.down]) player.mesh.position.y -= moveDistance;
242
+ if (keysPressed[player.controls.left]) player.mesh.position.x -= moveDistance;
243
+ if (keysPressed[player.controls.right]) player.mesh.position.x += moveDistance;
244
+
245
+ // Boundary checks
246
+ const halfWidth = gameSettings.playAreaWidth / 2 - gameSettings.playerSize / 2;
247
+ const halfHeight = gameSettings.playAreaHeight / 2 - gameSettings.playerSize / 2;
248
+ player.mesh.position.x = Math.max(-halfWidth, Math.min(halfWidth, player.mesh.position.x));
249
+ player.mesh.position.y = Math.max(-halfHeight, Math.min(halfHeight, player.mesh.position.y));
250
+ }
251
+
252
+ // Handle player shooting
253
+ function handlePlayerShooting(player, delta) {
254
+ if (player.shootCooldownTimer > 0) {
255
+ player.shootCooldownTimer -= delta;
256
+ }
257
+ // Check against the correct event.code string for shooting
258
+ if (keysPressed[player.controls.shoot] && player.shootCooldownTimer <= 0) {
259
+ player.shootCooldownTimer = gameSettings.playerShootCooldown;
260
+ createProjectile(player);
261
+ }
262
+ }
263
+
264
+ // Create a projectile
265
+ function createProjectile(player) {
266
+ const projectileGeometry = new THREE.SphereGeometry(gameSettings.projectileSize, 8, 8);
267
+ const projectileMaterial = new THREE.MeshBasicMaterial({ color: player.isPlayer2 ? 0xffaa33 : 0x66ccff });
268
+ const projectile = new THREE.Mesh(projectileGeometry, projectileMaterial);
269
+
270
+ projectile.position.copy(player.mesh.position);
271
+ projectile.position.z -= gameSettings.playerSize / 2; // Start in front of player
272
+
273
+ projectile.userData = {
274
+ owner: player,
275
+ velocity: new THREE.Vector3(0, 0, -gameSettings.projectileSpeed) // Shoots "into" the screen
276
+ };
277
+
278
+ scene.add(projectile);
279
+ playerProjectiles.push(projectile);
280
+ }
281
+
282
+ // Update projectiles
283
+ function updateProjectiles(delta) {
284
+ for (let i = playerProjectiles.length - 1; i >= 0; i--) {
285
+ const projectile = playerProjectiles[i];
286
+ if (!projectile || !projectile.userData) { // Safety check
287
+ if (projectile && scene.getObjectById(projectile.id)) scene.remove(projectile); // Clean up from scene if partially added
288
+ playerProjectiles.splice(i, 1);
289
+ continue;
290
+ }
291
+ projectile.position.addScaledVector(projectile.userData.velocity, delta);
292
+
293
+ // Remove if out of bounds
294
+ if (projectile.position.z < -30 || projectile.position.z > 30 ||
295
+ Math.abs(projectile.position.x) > gameSettings.playAreaWidth / 2 + 5 || // Added some buffer
296
+ Math.abs(projectile.position.y) > gameSettings.playAreaHeight / 2 + 5) {
297
+ scene.remove(projectile);
298
+ if (projectile.geometry) projectile.geometry.dispose();
299
+ if (projectile.material) projectile.material.dispose();
300
+ playerProjectiles.splice(i, 1);
301
+ continue;
302
+ }
303
+ checkProjectileCollisions(projectile, i);
304
+ }
305
+ }
306
+
307
+ // Check projectile collisions
308
+ function checkProjectileCollisions(projectile, projectileIndex) {
309
+ if (!projectile || !projectile.userData || !projectile.userData.owner) {
310
+ if (projectile && scene.getObjectById(projectile.id)) scene.remove(projectile);
311
+ if(playerProjectiles[projectileIndex] === projectile) playerProjectiles.splice(projectileIndex, 1);
312
+ return;
313
+ }
314
+ const projectileBox = new THREE.Box3().setFromObject(projectile);
315
+
316
+ // Collision with Neutral Zone blocks
317
+ for (let j = neutralZoneBlocks.length - 1; j >= 0; j--) {
318
+ const block = neutralZoneBlocks[j];
319
+ const blockBox = new THREE.Box3().setFromObject(block);
320
+ if (projectileBox.intersectsBox(blockBox)) {
321
+ scene.remove(block);
322
+ if (block.geometry) block.geometry.dispose();
323
+ if (block.material) block.material.dispose();
324
+ neutralZoneBlocks.splice(j, 1);
325
+
326
+ scene.remove(projectile);
327
+ if (projectile.geometry) projectile.geometry.dispose();
328
+ if (projectile.material) projectile.material.dispose();
329
+ playerProjectiles.splice(projectileIndex, 1);
330
+
331
+ projectile.userData.owner.score += gameSettings.pointsPerNeutralBlock;
332
+ updateUI();
333
+ return;
334
+ }
335
+ }
336
+
337
+ // Collision with Qotile
338
+ if (qotile && qotile.mesh && qotile.health > 0) {
339
+ const qotileBox = new THREE.Box3().setFromObject(qotile.mesh);
340
+ if (projectileBox.intersectsBox(qotileBox)) {
341
+ scene.remove(projectile);
342
+ if (projectile.geometry) projectile.geometry.dispose();
343
+ if (projectile.material) projectile.material.dispose();
344
+ playerProjectiles.splice(projectileIndex, 1);
345
+
346
+ qotile.health -= 10;
347
+ qotile.mesh.material.emissive.setHex(0xffffff);
348
+ qotile.hitTimer = 0.1;
349
+ projectile.userData.owner.score += gameSettings.pointsPerQotileHit;
350
+ updateUI();
351
+
352
+ if (qotile.health <= 0) {
353
+ const winnerName = projectile.userData.owner.isPlayer2 ? "Player 2" : "Player 1";
354
+ endGame(winnerName + " destroyed the Qotile!");
355
+ }
356
+ return;
357
+ }
358
+ }
359
+ }
360
+
361
+ function updateQotile(delta) {
362
+ if (qotile && qotile.hitTimer > 0) {
363
+ qotile.hitTimer -= delta;
364
+ if (qotile.hitTimer <= 0) {
365
+ qotile.mesh.material.emissive.setHex(0x330000);
366
+ }
367
+ }
368
+ }
369
+
370
+ // Update UI elements
371
+ function updateUI() {
372
+ const p1 = players && players[0] ? players[0] : { score: 0, lives: 0 };
373
+ const p2 = players && players[1] ? players[1] : { score: 0, lives: 0 };
374
+
375
+ // ******** UPDATED UI TEXT FOR NEW FIRE KEYS ********
376
+ document.getElementById('player1Info').textContent = `Player 1 (WASD, E): Score ${p1.score} | Lives ${p1.lives}`;
377
+ document.getElementById('player2Info').textContent = `Player 2 (IJKL, U): Score ${p2.score} | Lives ${p2.lives}`;
378
+
379
+ if (qotile) {
380
+ document.getElementById('qotileInfo').textContent = `Qotile Health: ${Math.max(0, qotile.health)}`;
381
+ } else {
382
+ document.getElementById('qotileInfo').textContent = `Qotile Health: N/A`;
383
+ }
384
+ }
385
+
386
+ function checkGameOver() {
387
+ if (!gameActive) return;
388
+ }
389
+
390
+
391
+ function endGame(message) {
392
+ if (!gameActive) return;
393
+ gameActive = false;
394
+ console.log("Game Over:", message);
395
+ document.getElementById('gameOverMessage').textContent = message;
396
+ document.getElementById('gameOverScreen').style.display = 'flex';
397
+
398
+ playerProjectiles.forEach(p => {
399
+ if (p && scene.getObjectById(p.id)) scene.remove(p);
400
+ if (p && p.geometry) p.geometry.dispose();
401
+ if (p && p.material) p.material.dispose();
402
+ });
403
+ playerProjectiles = [];
404
+ }
405
+
406
+ function restartGame() {
407
+ players.forEach(p => {
408
+ if (p.mesh && scene.getObjectById(p.mesh.id)) scene.remove(p.mesh);
409
+ if (p.mesh && p.mesh.geometry) p.mesh.geometry.dispose();
410
+ if (p.mesh && p.mesh.material) p.mesh.material.dispose();
411
+ });
412
+ playerProjectiles.forEach(p => {
413
+ if (p && scene.getObjectById(p.id)) scene.remove(p);
414
+ if (p && p.geometry) p.geometry.dispose();
415
+ if (p && p.material) p.material.dispose();
416
+ });
417
+ neutralZoneBlocks.forEach(b => {
418
+ if (b && scene.getObjectById(b.id)) scene.remove(b);
419
+ if (b && b.geometry) b.geometry.dispose();
420
+ if (b && b.material) b.material.dispose();
421
+ });
422
+ if (qotile && qotile.mesh) {
423
+ if (scene.getObjectById(qotile.mesh.id)) scene.remove(qotile.mesh);
424
+ if (qotile.mesh.geometry) qotile.mesh.geometry.dispose();
425
+ if (qotile.mesh.material) qotile.mesh.material.dispose();
426
+ }
427
+
428
+ players = [];
429
+ playerProjectiles = [];
430
+ neutralZoneBlocks = [];
431
+ qotile = null;
432
+
433
+ createPlayers();
434
+ createNeutralZone();
435
+ createQotile();
436
+
437
+ gameActive = true;
438
+ document.getElementById('gameOverScreen').style.display = 'none';
439
+ updateUI();
440
+ }
441
+
442
+
443
+ // Animation loop
444
+ function animate() {
445
+ requestAnimationFrame(animate);
446
+ const delta = clock.getDelta();
447
+
448
+ if (gameActive) {
449
+ players.forEach(player => {
450
+ if (player && player.mesh) {
451
+ handlePlayerMovement(player, delta);
452
+ handlePlayerShooting(player, delta);
453
+ }
454
+ });
455
+ updateProjectiles(delta);
456
+ updateQotile(delta);
457
+ }
458
+
459
+ updateUI();
460
+ renderer.render(scene, camera);
461
+ }
462
+
463
+ // Event handlers
464
+ function onKeyDown(event) {
465
+ keysPressed[event.code] = true;
466
+
467
+ // ******** UPDATED GAMEKEYS FOR PREVENTDEFAULT ********
468
+ const gameKeys = ['KeyW', 'KeyA', 'KeyS', 'KeyD', 'KeyI', 'KeyJ', 'KeyK', 'KeyL', 'KeyE', 'KeyU', 'Space'];
469
+ if (gameKeys.includes(event.code)) {
470
+ event.preventDefault();
471
+ }
472
+ }
473
+ function onKeyUp(event) {
474
+ keysPressed[event.code] = false;
475
+ }
476
+ function onWindowResize() {
477
+ camera.aspect = window.innerWidth / window.innerHeight;
478
+ camera.updateProjectionMatrix();
479
+ renderer.setSize(window.innerWidth, window.innerHeight);
480
+ }
481
+
482
+ window.onload = function() {
483
+ init();
484
+ };
485
+ </script>
486
+ </body>
487
  </html>