KBLLR commited on
Commit
d05a6a1
·
verified ·
1 Parent(s): ee6e524

Promote version e676143 to main

Browse files

Promoted commit e676143bd4b8302eb130f3aef07fddd1104d1b17 to main branch

Files changed (1) hide show
  1. index.html +39 -77
index.html CHANGED
@@ -4,9 +4,10 @@
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>3D Character World</title>
 
7
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
8
- <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/controls/OrbitControls.min.js"></script>
9
- <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/loaders/GLTFLoader.min.js"></script>
10
  <style>
11
  body {
12
  margin: 0;
@@ -187,20 +188,9 @@
187
  </div>
188
  </div>
189
  </div>
190
- <!-- Modal for alerts -->
191
- <div id="modal-overlay" class="fixed inset-0 bg-black/80 backdrop-blur-sm flex items-center justify-center z-50 opacity-0 pointer-events-none transition-all">
192
- <div class="bg-gray-900/90 border border-white/10 rounded-xl p-6 max-w-md mx-4 shadow-2xl">
193
- <h3 id="modal-title" class="text-xl font-bold text-white mb-2"></h3>
194
- <p id="modal-message" class="text-gray-300 mb-4"></p>
195
- <button id="modal-close" class="w-full bg-gradient-to-r from-purple-600 to-blue-600 text-white py-2 rounded-lg font-semibold hover:from-purple-700 hover:to-blue-700 transition-all">
196
- OK
197
- </button>
198
- </div>
199
- </div>
200
-
201
  <!-- Game UI -->
202
  <div id="game-ui" class="fixed inset-0 pointer-events-none z-20 opacity-0 transition-all">
203
- <div class="absolute bottom-4 left-4 bg-gray-800 bg-opacity-70 p-4 rounded-lg">
204
  <div class="flex items-center space-x-2">
205
  <div class="w-3 h-3 rounded-full bg-green-500"></div>
206
  <span>WASD: Move</span>
@@ -379,45 +369,25 @@
379
 
380
  // Initialize audio context on user interaction
381
  document.addEventListener('click', initializeAudio, { once: true });
382
- // Check if Three.js is loaded
383
- if (typeof THREE === 'undefined') {
384
- console.error('Three.js not loaded');
385
- // Fallback to loading from CDN
386
- const script = document.createElement('script');
387
- script.src = 'https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js';
388
- script.onload = () => {
389
- console.log('Three.js loaded via fallback');
390
- // Now load the modules
391
  loadThreeJSModules();
392
- };
393
- document.head.appendChild(script);
394
- } else {
395
- // Three.js is loaded, check if modules are available
396
- loadThreeJSModules();
397
- }
398
- });
399
  // Function to dynamically load Three.js modules if needed
400
  function loadThreeJSModules() {
401
  // Check if OrbitControls is available
402
  if (typeof THREE.OrbitControls === 'undefined') {
403
- console.log('Loading OrbitControls...');
404
- const orbitScript = document.createElement('script');
405
- orbitScript.src = 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/controls/OrbitControls.min.js';
406
- orbitScript.onload = () => {
407
- console.log('OrbitControls loaded');
408
- };
409
- document.head.appendChild(orbitScript);
410
  }
411
 
412
  // Check if GLTFLoader is available
413
  if (typeof THREE.GLTFLoader === 'undefined') {
414
- console.log('Loading GLTFLoader...');
415
- const gltfScript = document.createElement('script');
416
- gltfScript.src = 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/loaders/GLTFLoader.min.js';
417
- gltfScript.onload = () => {
418
- console.log('GLTFLoader loaded');
419
- };
420
- document.head.appendChild(gltfScript);
421
  }
422
  }
423
  function initializeAudio() {
@@ -511,11 +481,11 @@ function showCharacterSelection() {
511
  }
512
  function startGame() {
513
  if (gameState.selectedWorldCharacters.length < 2) {
514
- // Use a custom modal instead of alert for better UX
515
- showModal('Selection Required', 'Please select 2 characters for your world!');
516
  return;
517
  }
518
- // Ensure audio is initialized when game starts
 
519
  if (!audioContext) {
520
  initializeAudio();
521
  }
@@ -612,26 +582,18 @@ card.addEventListener('click', () => {
612
  function initThreeJS() {
613
  if (typeof THREE === 'undefined') {
614
  console.error('Three.js is not loaded properly');
615
- // Try to load Three.js dynamically
616
- const script = document.createElement('script');
617
- script.src = 'https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js';
618
- script.onload = () => {
619
- console.log('Three.js loaded, retrying initialization...');
620
- initThreeJS(); // Retry initialization
621
- };
622
- document.head.appendChild(script);
623
  return;
624
  }
625
 
626
- // Check if required modules are available
627
- if (typeof THREE.OrbitControls === 'undefined') {
628
- console.warn('OrbitControls not available, using fallback camera controls');
629
- }
630
-
631
- if (typeof THREE.GLTFLoader === 'undefined') {
632
- console.warn('GLTFLoader not available, using fallback geometry');
633
- }
634
- try {
635
  // Set up Three.js scene
636
  scene = new THREE.Scene();
637
  scene.background = new THREE.Color(0x87CEEB); // Sky blue
@@ -714,23 +676,23 @@ try {
714
 
715
  // Add some environment objects
716
  addEnvironmentObjects();
 
717
  // Initialize OrbitControls with fallback
718
- let controls;
719
  if (typeof THREE.OrbitControls !== 'undefined') {
720
  controls = new THREE.OrbitControls(camera, renderer.domElement);
721
  controls.enableDamping = true;
722
  controls.dampingFactor = 0.05;
723
  controls.enabled = false; // Start with controls disabled for follow camera
724
  } else {
725
- console.warn('OrbitControls not available, using fallback camera controls');
726
  controls = {
727
  enabled: false,
728
  update: () => {},
729
  target: new THREE.Vector3()
730
  };
731
  }
732
- window.controls = controls; // Make globally available
733
- // Load player character
734
  loadPlayerCharacter();
735
 
736
  // Load NPC characters
@@ -748,8 +710,8 @@ try {
748
  } catch (error) {
749
  console.error('Error initializing Three.js:', error);
750
  // Show user-friendly error message
751
- showModal('3D Graphics Error', 'Error initializing 3D graphics. Please check your browser supports WebGL and try refreshing the page.');
752
- }
753
  }
754
  function addEnvironmentObjects() {
755
  // Add some trees
@@ -786,9 +748,8 @@ function addEnvironmentObjects() {
786
  }
787
  }
788
  function loadPlayerCharacter() {
789
- if (typeof THREE.GLTFLoader !== 'undefined') {
790
- const loader = new THREE.GLTFLoader();
791
- loader.load(gameState.selectedCharacter.modelUrl, (gltf) => {
792
  const model = gltf.scene;
793
  // Scale and position the RPM avatar model - adjusted for human proportions
794
  model.scale.set(0.8, 0.8, 0.8);
@@ -842,10 +803,9 @@ loader.load(gameState.selectedCharacter.modelUrl, (gltf) => {
842
  });
843
  } else {
844
  // GLTFLoader not available, use fallback
845
- console.warn('GLTFLoader not available, using fallback character');
846
  loadPlayerCharacterFallback();
847
  }
848
- }
849
  function loadPlayerCharacterFallback() {
850
  const group = new THREE.Group();
851
 
@@ -1054,7 +1014,7 @@ scene.add(group);
1054
  // Update camera based on mode
1055
  updateCamera(delta);
1056
  // Update OrbitControls if enabled
1057
- if (controls && controls.enabled && typeof controls.update === 'function') {
1058
  controls.update();
1059
  }
1060
  renderer.render(scene, camera);
@@ -1207,11 +1167,13 @@ function handlePlayerMovement(delta) {
1207
  // Update UI display
1208
  document.getElementById('camera-mode-display').textContent =
1209
  gameState.cameraMode.charAt(0).toUpperCase() + gameState.cameraMode.slice(1);
 
1210
  // Enable/disable OrbitControls based on mode
1211
  if (controls && typeof controls.enabled !== 'undefined') {
1212
  controls.enabled = (gameState.cameraMode === 'orbit');
1213
  }
1214
- // Reset camera position for first-person mode
 
1215
  if (gameState.cameraMode === 'first-person') {
1216
  camera.rotation.set(0, 0, 0);
1217
  }
 
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>3D Character World</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/controls/OrbitControls.js"></script>
10
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/loaders/GLTFLoader.js"></script>
11
  <style>
12
  body {
13
  margin: 0;
 
188
  </div>
189
  </div>
190
  </div>
 
 
 
 
 
 
 
 
 
 
 
191
  <!-- Game UI -->
192
  <div id="game-ui" class="fixed inset-0 pointer-events-none z-20 opacity-0 transition-all">
193
+ <div class="absolute bottom-4 left-4 bg-gray-800 bg-opacity-70 p-4 rounded-lg">
194
  <div class="flex items-center space-x-2">
195
  <div class="w-3 h-3 rounded-full bg-green-500"></div>
196
  <span>WASD: Move</span>
 
369
 
370
  // Initialize audio context on user interaction
371
  document.addEventListener('click', initializeAudio, { once: true });
372
+
373
+ // Check if Three.js modules are available
374
+ if (typeof THREE === 'undefined') {
375
+ console.error('Three.js not loaded');
376
+ // Try to load modules dynamically if needed
 
 
 
 
377
  loadThreeJSModules();
378
+ }
379
+ });
380
+
 
 
 
 
381
  // Function to dynamically load Three.js modules if needed
382
  function loadThreeJSModules() {
383
  // Check if OrbitControls is available
384
  if (typeof THREE.OrbitControls === 'undefined') {
385
+ console.warn('OrbitControls not available, using fallback controls');
 
 
 
 
 
 
386
  }
387
 
388
  // Check if GLTFLoader is available
389
  if (typeof THREE.GLTFLoader === 'undefined') {
390
+ console.warn('GLTFLoader not available, using fallback geometry');
 
 
 
 
 
 
391
  }
392
  }
393
  function initializeAudio() {
 
481
  }
482
  function startGame() {
483
  if (gameState.selectedWorldCharacters.length < 2) {
484
+ alert('Please select 2 characters for your world!');
 
485
  return;
486
  }
487
+
488
+ // Ensure audio is initialized when game starts
489
  if (!audioContext) {
490
  initializeAudio();
491
  }
 
582
  function initThreeJS() {
583
  if (typeof THREE === 'undefined') {
584
  console.error('Three.js is not loaded properly');
585
+ // Try to reload or show error
586
+ setTimeout(() => {
587
+ if (typeof THREE === 'undefined') {
588
+ alert('Three.js failed to load. Please refresh the page.');
589
+ } else {
590
+ initThreeJS(); // Retry initialization
591
+ }
592
+ }, 100);
593
  return;
594
  }
595
 
596
+ try {
 
 
 
 
 
 
 
 
597
  // Set up Three.js scene
598
  scene = new THREE.Scene();
599
  scene.background = new THREE.Color(0x87CEEB); // Sky blue
 
676
 
677
  // Add some environment objects
678
  addEnvironmentObjects();
679
+
680
  // Initialize OrbitControls with fallback
 
681
  if (typeof THREE.OrbitControls !== 'undefined') {
682
  controls = new THREE.OrbitControls(camera, renderer.domElement);
683
  controls.enableDamping = true;
684
  controls.dampingFactor = 0.05;
685
  controls.enabled = false; // Start with controls disabled for follow camera
686
  } else {
687
+ console.warn('OrbitControls not available, using fallback');
688
  controls = {
689
  enabled: false,
690
  update: () => {},
691
  target: new THREE.Vector3()
692
  };
693
  }
694
+
695
+ // Load player character
696
  loadPlayerCharacter();
697
 
698
  // Load NPC characters
 
710
  } catch (error) {
711
  console.error('Error initializing Three.js:', error);
712
  // Show user-friendly error message
713
+ alert('Error initializing 3D graphics. Please check your browser supports WebGL.');
714
+ }
715
  }
716
  function addEnvironmentObjects() {
717
  // Add some trees
 
748
  }
749
  }
750
  function loadPlayerCharacter() {
751
+ if (loader && typeof THREE.GLTFLoader !== 'undefined') {
752
+ loader.load(gameState.selectedCharacter.modelUrl, (gltf) => {
 
753
  const model = gltf.scene;
754
  // Scale and position the RPM avatar model - adjusted for human proportions
755
  model.scale.set(0.8, 0.8, 0.8);
 
803
  });
804
  } else {
805
  // GLTFLoader not available, use fallback
 
806
  loadPlayerCharacterFallback();
807
  }
808
+ }
809
  function loadPlayerCharacterFallback() {
810
  const group = new THREE.Group();
811
 
 
1014
  // Update camera based on mode
1015
  updateCamera(delta);
1016
  // Update OrbitControls if enabled
1017
+ if (controls && controls.enabled) {
1018
  controls.update();
1019
  }
1020
  renderer.render(scene, camera);
 
1167
  // Update UI display
1168
  document.getElementById('camera-mode-display').textContent =
1169
  gameState.cameraMode.charAt(0).toUpperCase() + gameState.cameraMode.slice(1);
1170
+
1171
  // Enable/disable OrbitControls based on mode
1172
  if (controls && typeof controls.enabled !== 'undefined') {
1173
  controls.enabled = (gameState.cameraMode === 'orbit');
1174
  }
1175
+
1176
+ // Reset camera position for first-person mode
1177
  if (gameState.cameraMode === 'first-person') {
1178
  camera.rotation.set(0, 0, 0);
1179
  }