Update templates/index.html

#2
by zxciop - opened
Files changed (1) hide show
  1. templates/index.html +94 -15
templates/index.html CHANGED
@@ -25,7 +25,7 @@
25
  .game-ui {
26
  position: absolute;
27
  padding: 10px;
28
- background-color: rgba(0, 20, 0, 0.9);
29
  border: 1px solid #0f0;
30
  border-radius: 5px;
31
  font-size: 1.2em;
@@ -52,7 +52,7 @@
52
  flex-direction: column;
53
  justify-content: center;
54
  align-items: center;
55
- background-color: rgba(0, 10, 0, 0.0);
56
  z-index: 10;
57
  }
58
  #startScreen, #gameOverScreen {
@@ -91,9 +91,9 @@
91
  pointer-events: auto;
92
  }
93
  .button:hover {
94
- background-color: rgba(0, 120, 0, 0.9);
95
  transform: translateY(-5px);
96
- box-shadow: 0px 2px 10px #2eff00;
97
  }
98
  .controls {
99
  margin-top: 20px;
@@ -121,12 +121,12 @@
121
  display: none; /* Hidden by default, shown on mobile */
122
  }
123
  .touchBtn {
124
- width: 60px;
125
- height: 60px;
126
  background-color: rgba(0, 120, 0, 0.7);
127
- border: 1px solid #0f0;
128
  border-radius: 50%;
129
- margin: 5px;
130
  display: inline-flex;
131
  justify-content: center;
132
  align-items: center;
@@ -233,6 +233,7 @@
233
  'HARD': { speedMultiplier: 0.7, obstacleMultiplier: 1.5 }
234
  },
235
  MAX_OBSTACLE_COUNT: 10, // Maximum number of obstacles
 
236
  FOOD_TYPES: [
237
  { type: 'regular', color: 0x00ff00, points: 1, speedEffect: 0 },
238
  { type: 'special', color: 0x00ffff, points: 5, speedEffect: -10 },
@@ -256,7 +257,7 @@
256
  const material = new THREE.MeshBasicMaterial({
257
  color: color || 0x00ff00,
258
  transparent: true,
259
- opacity: 0.8
260
  });
261
  const particle = new THREE.Mesh(this.geometry, material);
262
  particle.position.copy(position);
@@ -446,6 +447,7 @@
446
  this.snake = [];
447
  this.food = null;
448
  this.obstacles = [];
 
449
  this.direction = new THREE.Vector3(CONFIG.CELL_SIZE, 0, 0);
450
  this.nextDirection = new THREE.Vector3(CONFIG.CELL_SIZE, 0, 0);
451
  this.score = 0;
@@ -457,6 +459,7 @@
457
  this.gameLoopId = null;
458
  this.bounds = Math.floor(CONFIG.GRID_SIZE / 2) * CONFIG.CELL_SIZE;
459
  this.obstacleCount = CONFIG.MAX_OBSTACLE_COUNT;
 
460
  this.comboCount = 0;
461
  this.lastFoodTime = 0;
462
  this.currentDifficulty = 'NORMAL';
@@ -473,14 +476,18 @@
473
  obstacle: new THREE.MeshStandardMaterial({ // Changed to Standard for lighting
474
  color: 0xff0000, emissive: 0x550000, roughness: 0.3, metalness: 1, wireframe: false
475
  }),
 
 
 
476
  // Food materials defined per type in chooseFoodType
477
  };
478
  this.geometries = {
479
  segment: new THREE.BoxGeometry(CONFIG.CELL_SIZE, CONFIG.CELL_SIZE, CONFIG.CELL_SIZE),
480
  foodBox: new THREE.BoxGeometry(CONFIG.CELL_SIZE * 0.8, CONFIG.CELL_SIZE * 0.8, CONFIG.CELL_SIZE * 0.8),
481
- foodSphere: new THREE.SphereGeometry(CONFIG.CELL_SIZE * 0.5, 16, 12),
482
  foodTetrahedron: new THREE.TetrahedronGeometry(CONFIG.CELL_SIZE * 0.6, 0),
483
- obstacle: new THREE.BoxGeometry(CONFIG.CELL_SIZE * 0.9, CONFIG.CELL_SIZE * 1.5, CONFIG.CELL_SIZE * 0.9) // Taller obstacles
 
484
  };
485
 
486
  this.segmentPool = new ObjectPool(() => {
@@ -495,6 +502,12 @@
495
  return obstacle;
496
  }, CONFIG.MAX_OBSTACLE_COUNT * 1.5);
497
 
 
 
 
 
 
 
498
  this.init(); // Call init before matrixRain if matrixRain depends on game elements
499
  this.matrixRain = new MatrixRain(); // Initialize after main game setup if it interacts
500
  this.setupEventListeners();
@@ -524,9 +537,9 @@
524
  // Post-processing for bloom
525
  const renderPass = new RenderPass(this.scene, this.camera);
526
  const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.2, 0.8, 0.75);
527
- bloomPass.threshold = 0.0;
528
- bloomPass.strength = 1.3; // Play with these
529
- bloomPass.radius = 0.3;
530
 
531
  this.composer = new EffectComposer(this.renderer);
532
  this.composer.addPass(renderPass);
@@ -586,8 +599,12 @@
586
  let collisionWithObstacle = this.obstacles.some(obstacle =>
587
  obstacle.position.distanceToSquared(foodPos) < (CONFIG.CELL_SIZE * 0.9)**2
588
  );
 
 
 
 
589
 
590
- validPosition = !collisionWithSnake && !collisionWithObstacle;
591
  attempts++;
592
  }
593
 
@@ -652,6 +669,54 @@
652
  }
653
  }
654
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
655
  clearGameObjects() {
656
  this.snake.forEach(segment => {
657
  this.scene.remove(segment);
@@ -671,6 +736,12 @@
671
  });
672
  this.obstacles = [];
673
 
 
 
 
 
 
 
674
  this.particleSystem.clear();
675
  }
676
 
@@ -712,6 +783,13 @@
712
  }
713
  }
714
 
 
 
 
 
 
 
 
715
  const newHead = this.segmentPool.get();
716
  newHead.position.copy(newHeadPos);
717
  newHead.material = this.materials.snakeHead; // Head material
@@ -778,6 +856,7 @@
778
  }
779
  }
780
 
 
781
  chooseFoodType() {
782
  const rand = Math.random();
783
  let foodTypeData;
 
25
  .game-ui {
26
  position: absolute;
27
  padding: 10px;
28
+ background-color: rgba(0, 0, 20, 0.9);
29
  border: 1px solid #0f0;
30
  border-radius: 5px;
31
  font-size: 1.2em;
 
52
  flex-direction: column;
53
  justify-content: center;
54
  align-items: center;
55
+ background-color: rgba(0, 10, 50, 0.2);
56
  z-index: 10;
57
  }
58
  #startScreen, #gameOverScreen {
 
91
  pointer-events: auto;
92
  }
93
  .button:hover {
94
+ background-color: rgba(0, 120, 0, 0.7);
95
  transform: translateY(-5px);
96
+ box-shadow: 0px 2px 10px #2eff00, 0 7px 14px rgba(0, 255, 0.1, 0.9), 3px 3px 6px rgba(0, 255, 0.1, 0.3);
97
  }
98
  .controls {
99
  margin-top: 20px;
 
121
  display: none; /* Hidden by default, shown on mobile */
122
  }
123
  .touchBtn {
124
+ width: 80px;
125
+ height: 80px;
126
  background-color: rgba(0, 120, 0, 0.7);
127
+ border: 10px solid #0f0;
128
  border-radius: 50%;
129
+ margin: 15px;
130
  display: inline-flex;
131
  justify-content: center;
132
  align-items: center;
 
233
  'HARD': { speedMultiplier: 0.7, obstacleMultiplier: 1.5 }
234
  },
235
  MAX_OBSTACLE_COUNT: 10, // Maximum number of obstacles
236
+ MAX_OBSTACLEB_COUNT: 3, // Maximum number of obstacles
237
  FOOD_TYPES: [
238
  { type: 'regular', color: 0x00ff00, points: 1, speedEffect: 0 },
239
  { type: 'special', color: 0x00ffff, points: 5, speedEffect: -10 },
 
257
  const material = new THREE.MeshBasicMaterial({
258
  color: color || 0x00ff00,
259
  transparent: true,
260
+ opacity: 0.7
261
  });
262
  const particle = new THREE.Mesh(this.geometry, material);
263
  particle.position.copy(position);
 
447
  this.snake = [];
448
  this.food = null;
449
  this.obstacles = [];
450
+ this.obstaclesB = [];
451
  this.direction = new THREE.Vector3(CONFIG.CELL_SIZE, 0, 0);
452
  this.nextDirection = new THREE.Vector3(CONFIG.CELL_SIZE, 0, 0);
453
  this.score = 0;
 
459
  this.gameLoopId = null;
460
  this.bounds = Math.floor(CONFIG.GRID_SIZE / 2) * CONFIG.CELL_SIZE;
461
  this.obstacleCount = CONFIG.MAX_OBSTACLE_COUNT;
462
+ this.obstacleBCount = CONFIG.MAX_OBSTACLEB_COUNT;
463
  this.comboCount = 0;
464
  this.lastFoodTime = 0;
465
  this.currentDifficulty = 'NORMAL';
 
476
  obstacle: new THREE.MeshStandardMaterial({ // Changed to Standard for lighting
477
  color: 0xff0000, emissive: 0x550000, roughness: 0.3, metalness: 1, wireframe: false
478
  }),
479
+ obstacleB: new THREE.MeshStandardMaterial({ // Changed to Standard for lighting
480
+ color: 0xff0069, emissive: 0x550000, roughness: 0.9, metalness: 0.1, wireframe: false
481
+ }),
482
  // Food materials defined per type in chooseFoodType
483
  };
484
  this.geometries = {
485
  segment: new THREE.BoxGeometry(CONFIG.CELL_SIZE, CONFIG.CELL_SIZE, CONFIG.CELL_SIZE),
486
  foodBox: new THREE.BoxGeometry(CONFIG.CELL_SIZE * 0.8, CONFIG.CELL_SIZE * 0.8, CONFIG.CELL_SIZE * 0.8),
487
+ foodSphere: new THREE.SphereGeometry(CONFIG.CELL_SIZE * 0.5, 6, 12),
488
  foodTetrahedron: new THREE.TetrahedronGeometry(CONFIG.CELL_SIZE * 0.6, 0),
489
+ obstacle: new THREE.BoxGeometry(CONFIG.CELL_SIZE * 0.9, CONFIG.CELL_SIZE * 1.5, CONFIG.CELL_SIZE * 0.9), // Taller obstacles
490
+ obstacleB: new THREE.BoxGeometry(CONFIG.CELL_SIZE * 0.8, CONFIG.CELL_SIZE * 1.25, CONFIG.CELL_SIZE * 0.7) // Taller obstacles
491
  };
492
 
493
  this.segmentPool = new ObjectPool(() => {
 
502
  return obstacle;
503
  }, CONFIG.MAX_OBSTACLE_COUNT * 1.5);
504
 
505
+ this.obstacleBPool = new ObjectPool(() => {
506
+ const obstacleB = new THREE.Mesh(this.geometries.obstacleB, this.materials.obstacleB.clone());
507
+ obstacleB.castShadow = true; // If using shadows
508
+ return obstacleB;
509
+ }, CONFIG.MAX_OBSTACLEB_COUNT * 1.2);
510
+
511
  this.init(); // Call init before matrixRain if matrixRain depends on game elements
512
  this.matrixRain = new MatrixRain(); // Initialize after main game setup if it interacts
513
  this.setupEventListeners();
 
537
  // Post-processing for bloom
538
  const renderPass = new RenderPass(this.scene, this.camera);
539
  const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.2, 0.8, 0.75);
540
+ bloomPass.threshold = 0.2;
541
+ bloomPass.strength = 1.4; // Play with these
542
+ bloomPass.radius = 0.2;
543
 
544
  this.composer = new EffectComposer(this.renderer);
545
  this.composer.addPass(renderPass);
 
599
  let collisionWithObstacle = this.obstacles.some(obstacle =>
600
  obstacle.position.distanceToSquared(foodPos) < (CONFIG.CELL_SIZE * 0.9)**2
601
  );
602
+
603
+ let collisionWithObstacleB = this.obstacles.some(obstacle =>
604
+ obstacleB.position.distanceToSquared(foodPos) < (CONFIG.CELL_SIZE * 0.9)**2
605
+ );
606
 
607
+ validPosition = !collisionWithSnake && !collisionWithObstacle && !collisionWithObstacleB;
608
  attempts++;
609
  }
610
 
 
669
  }
670
  }
671
 
672
+ createObstacleBs() {
673
+ this.obstacleBs.forEach(obstacleB => {
674
+ this.scene.remove(obstacleB);
675
+ this.obstacleBPool.release(obstacleB);
676
+ });
677
+ this.obstacleBs = [];
678
+
679
+ const numCells = CONFIG.GRID_SIZE;
680
+
681
+ for (let i = 0; i < this.obstacleBCount; i++) {
682
+ let obstaclePos;
683
+ let validPosition = false;
684
+ let attempts = 0;
685
+ const maxAttempts = 50;
686
+
687
+ while (!validPosition && attempts < maxAttempts) {
688
+ const xIndex = Math.floor(Math.random() * numCells) - Math.floor((numCells - 1) / 2);
689
+ const zIndex = Math.floor(Math.random() * numCells) - Math.floor((numCells - 1) / 2);
690
+ obstacleBPos = new THREE.Vector3(
691
+ xIndex * CONFIG.CELL_SIZE,
692
+ 0, // Obstacles on the grid plane, but mesh is taller
693
+ zIndex * CONFIG.CELL_SIZE
694
+ );
695
+
696
+ let tooCloseToStart = obstacleBPos.lengthSq() < (CONFIG.CELL_SIZE * 4)**2; // Check squared length
697
+
698
+ let collisionWithSnake = this.snake.some(segment =>
699
+ segment.position.distanceToSquared(obstacleBPos) < (CONFIG.CELL_SIZE * 2)**2
700
+ );
701
+
702
+ let collisionWithOtherObstacleB = this.obstacleBs.some(existingObstacleB =>
703
+ existingObstacleB.position.distanceToSquared(obstacleBPos) < (CONFIG.CELL_SIZE * 1.5)**2 // Ensure spacing
704
+ );
705
+
706
+ validPosition = !tooCloseToStart && !collisionWithSnake && !collisionWithOtherObstacle;
707
+ attempts++;
708
+ }
709
+
710
+ if (validPosition) {
711
+ const obstacleB = this.obstacleBPool.get();
712
+ obstacleB.position.copy(obstacleBPos);
713
+ obstacle.position.y = (CONFIG.CELL_SIZE * 1.5 - CONFIG.CELL_SIZE) / 2 - CONFIG.CELL_SIZE / 2; // Adjust Y to sit on grid
714
+ this.obstacleBs.push(obstacleB);
715
+ this.scene.add(obstacleB);
716
+ }
717
+ }
718
+ }
719
+
720
  clearGameObjects() {
721
  this.snake.forEach(segment => {
722
  this.scene.remove(segment);
 
736
  });
737
  this.obstacles = [];
738
 
739
+ this.obstacleBs.forEach(obstacleB => {
740
+ this.scene.remove(obstacleB);
741
+ this.obstacleBPool.release(obstacleB);
742
+ });
743
+ this.obstacleBs = [];
744
+
745
  this.particleSystem.clear();
746
  }
747
 
 
783
  }
784
  }
785
 
786
+ for (const obstacleB of this.obstacleBs) {
787
+ if (newHeadPos.distanceToSquared(obstacleB.position) < (CONFIG.CELL_SIZE * 0.75)**2) { // Check collision with obstacle
788
+ this.triggerGameOver();
789
+ return;
790
+ }
791
+ }
792
+
793
  const newHead = this.segmentPool.get();
794
  newHead.position.copy(newHeadPos);
795
  newHead.material = this.materials.snakeHead; // Head material
 
856
  }
857
  }
858
 
859
+
860
  chooseFoodType() {
861
  const rand = Math.random();
862
  let foodTypeData;