Source: view/World.js

  1. import { Events } from "../controller/Utils/Events";
  2. import SceneEnvironment from "./SceneEnvironment";
  3. import SubmarineView from "./SubmarineView";
  4. import * as EnvView from "./environment/EnvView.js";
  5. import Debug from "./Debug";
  6. import * as THREE from 'three';
  7. import { ResourceNames } from '../model/Utils/Resources/ResourcesNames';
  8. import { enableEnvironmentSound } from "./environment/scripts/Debug.js";
  9. /**
  10. * World class is responsible for managing the overall scene, including initialization
  11. * and updating of different components such as the environment.
  12. *
  13. * @class
  14. */
  15. class World {
  16. /**
  17. * Constructor for the World class.
  18. * Initializes the simulator, scene, and resources.
  19. * Sets up the environment after resources are loaded.
  20. * Initializes the SubmarineView after resources are loaded.
  21. *
  22. * @param {Simulator} simulator - The simulator instance.
  23. */
  24. constructor(simulator) {
  25. this.simulator = simulator;
  26. this.scene = this.simulator.scene;
  27. this.resources = this.simulator.resources;
  28. // Wait for resources to be ready before setting up the environment
  29. this.resources.on(Events.ResourcesReady, () => {
  30. this.simulator.controlGUI = new Debug({
  31. title: "Controls",
  32. top: "50px",
  33. bottom: "auto",
  34. left: "auth",
  35. right: "10px",
  36. width: 320,
  37. });
  38. this.simulator.submarineAttributesGUI = new Debug({
  39. title: "Submarine Attributes",
  40. top: "400px",
  41. bottom: "auto",
  42. left: "auto",
  43. right: "10px",
  44. width: 250,
  45. });
  46. this.simulator.environmentAttributesGUI = new Debug({
  47. title: "Environment Attributes",
  48. top: "820px",
  49. bottom: "auto",
  50. left: "auto",
  51. right: "10px",
  52. width: 250,
  53. });
  54. this.simulator.forcesGUI = new Debug({
  55. title: "Forces",
  56. top: "120px",
  57. bottom: "auto",
  58. left: "10px",
  59. right: "auto",
  60. width: 200,
  61. });
  62. this.simulator.linearMotionGUI = new Debug({
  63. title: "Linear Motion",
  64. top: "250px",
  65. bottom: "auto",
  66. left: "10px",
  67. right: "auto",
  68. width: 200,
  69. });
  70. this.simulator.angularMotionGUI = new Debug({
  71. title: "Angular Motion",
  72. top: "583px",
  73. bottom: "auto",
  74. left: "10px",
  75. right: "auto",
  76. width: 200,
  77. });
  78. this.environment = new SceneEnvironment(this.simulator);
  79. this.submarineView = new SubmarineView(this.simulator);
  80. this.simulator.time.startUI();
  81. const listener = new THREE.AudioListener();
  82. const wavesSound = new THREE.Audio(listener);
  83. const underwaterSound = new THREE.Audio(listener);
  84. this.listener = listener;
  85. this.simulator.camera.instance.add(this.listener);
  86. const wavesSoundBuffer = this.resources.getResource(ResourceNames.WavesSound);
  87. wavesSound.setBuffer(wavesSoundBuffer);
  88. wavesSound.setLoop(true);
  89. wavesSound.setVolume(0.1);
  90. wavesSound.play();
  91. this.wavesSound = wavesSound;
  92. const underWaterSoundBuffer = this.resources.getResource(ResourceNames.UnderWaterSound);
  93. underwaterSound.setBuffer(underWaterSoundBuffer);
  94. underwaterSound.setLoop(true);
  95. underwaterSound.setVolume(0.1);
  96. this.underWaterSound = underwaterSound;
  97. });
  98. }
  99. /**
  100. * Ensure the AudioContext is resumed after user interaction.
  101. * Resumes the audio context if it is suspended.
  102. * @public
  103. */
  104. resumeAudioContext() {
  105. if (this.listener.context.state === 'suspended') {
  106. this.listener.context.resume();
  107. }
  108. }
  109. /**
  110. * Updates background sounds based on the submarine's position.
  111. * Plays or pauses the appropriate sound based on whether the submarine is above or below water.
  112. * @public
  113. */
  114. updateBackgroundSounds() {
  115. const yPosition = this.simulator.camera.instance.position.y; // Get the submarine's y position
  116. if (!(this.listener.context.state === 'suspended')) {
  117. if (yPosition >= 0) { // Assume y >= 0 means above water
  118. if (!this.wavesSound.isPlaying && enableEnvironmentSound) {
  119. this.wavesSound.play(); // Play waves sound if not already playing
  120. }
  121. this.underWaterSound.pause(); // Stop underwater sound
  122. } else { // Assume y < 0 means below water
  123. if (!this.underWaterSound.isPlaying && enableEnvironmentSound) {
  124. this.underWaterSound.play(); // Play underwater sound if not already playing
  125. }
  126. this.wavesSound.pause(); // Stop waves sound
  127. }
  128. }
  129. }
  130. /**
  131. * Update method to handle per-frame updates.
  132. * Called on each frame to update the components in the scene.
  133. * @public
  134. */
  135. update() {
  136. // Update logic for various components can be added here
  137. EnvView.update(this.simulator);
  138. this.submarineView.update();
  139. this.updateBackgroundSounds();
  140. }
  141. }
  142. export default World;