yokoha/Particle-Accelerator-Simulation
1
1<!DOCTYPE html>2<html>3<head>4 <style>5 body { margin: 0; overflow: hidden; background: #000; }6 #ui {7 position: fixed;8 top: 10px;9 left: 10px;10 color: #0f0;11 background: rgba(0,20,0,0.7);12 padding: 15px;13 border: 1px solid #0f0;14 font-family: monospace;15 z-index: 100;16 }17 .control { margin: 10px 0; }18 #matrix {19 position: fixed;20 top: 0;21 left: 0;22 z-index: -1;23 color: #0f0;24 font-family: monospace;25 font-size: 12px;26 opacity: 0.2;27 }28 </style>29</head>30<body>31 <div id="ui">32 <div class="control">33 <button onclick="initAudio()">Start Audio</button>34 </div>35 <div class="control">36 <label>Particle Speed: <input type="range" id="speed" min="1" max="200" value="100"></label>37 </div>38 <div class="control">39 <label>Energy Level: <input type="range" id="energy" min="1" max="100" value="50"></label>40 </div>41 <div class="control">42 <label>Power: <input type="range" id="power" min="1" max="100" value="75"></label>43 </div>44 <div class="control">45 <button onclick="addParticle()">Add Particle</button>46 <button onclick="addDarkMatter()">Add Dark Matter</button>47 </div>48 <div>Particles: <span id="particleCount">0</span></div>49 </div>50 <div id="matrix"></div>51 <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>52 <script>53 let scene, camera, renderer, particles = [], darkMatter = [], plasmaParticles = [];54 let audioContext;55 const TUBE_RADIUS = 20;56 57 function initAudio() {58 audioContext = new (window.AudioContext || window.webkitAudioContext)();59 }60 61 function playCollisionSound() {62 const oscillator1 = audioContext.createOscillator();63 const oscillator2 = audioContext.createOscillator();64 const gainNode = audioContext.createGain();65 66 oscillator1.connect(gainNode);67 oscillator2.connect(gainNode);68 gainNode.connect(audioContext.destination);69 70 oscillator1.frequency.setValueAtTime(440 + Math.random() * 220, audioContext.currentTime);71 oscillator2.frequency.setValueAtTime(220 + Math.random() * 110, audioContext.currentTime);72 73 oscillator1.type = 'sine';74 oscillator2.type = 'square';75 76 gainNode.gain.setValueAtTime(0.2, audioContext.currentTime);77 gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.3);78 79 oscillator1.start();80 oscillator2.start();81 oscillator1.stop(audioContext.currentTime + 0.3);82 oscillator2.stop(audioContext.currentTime + 0.3);83 }84 85 function init() {86 initAudio();87 scene = new THREE.Scene();88 camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);89 renderer = new THREE.WebGLRenderer({ antialias: true });90 renderer.setSize(window.innerWidth, window.innerHeight);91 document.body.appendChild(renderer.domElement);92 93 // Torus (Accelerator Tube)94 const tubeGeometry = new THREE.TorusGeometry(TUBE_RADIUS, 2, 32, 100);95 const tubeMaterial = new THREE.MeshPhongMaterial({96 color: 0x00ff00,97 transparent: true,98 opacity: 0.3,99 wireframe: true100 });101 const tube = new THREE.Mesh(tubeGeometry, tubeMaterial);102 scene.add(tube);103 104 // Lighting105 const light = new THREE.PointLight(0xffffff, 1);106 light.position.set(0, 0, 50);107 scene.add(light);108 scene.add(new THREE.AmbientLight(0x404040));109 110 camera.position.z = 50;111 112 // Matrix Rain113 initMatrix();114 }115 116 function initMatrix() {117 const matrix = document.getElementById('matrix');118 const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%^&*()";119 setInterval(() => {120 let str = '';121 for(let i = 0; i < 50; i++) {122 for(let j = 0; j < 100; j++) {123 str += chars[Math.floor(Math.random() * chars.length)];124 }125 str += '\n';126 }127 matrix.textContent = str;128 }, 50);129 }130 131 function addParticle() {132 const geometry = new THREE.SphereGeometry(0.3, 16, 16);133 const material = new THREE.MeshPhongMaterial({134 color: 0x00ff00,135 emissive: 0x00ff00,136 emissiveIntensity: 0.5137 });138 139 const particle = new THREE.Mesh(geometry, material);140 particle.userData = {141 angle: Math.random() * Math.PI * 2,142 speed: Math.random() * 0.02 + 0.01,143 direction: Math.random() > 0.5 ? 1 : -1,144 phase: Math.random() * Math.PI * 2,145 energy: 100146 };147 148 particles.push(particle);149 scene.add(particle);150 updateParticleCount();151 }152 153 function addDarkMatter() {154 const geometry = new THREE.SphereGeometry(1, 32, 32);155 const material = new THREE.MeshPhongMaterial({156 color: 0x000066,157 transparent: true,158 opacity: 0.3159 });160 161 const dm = new THREE.Mesh(geometry, material);162 dm.position.set(163 (Math.random() - 0.5) * TUBE_RADIUS * 2,164 (Math.random() - 0.5) * TUBE_RADIUS * 2,165 (Math.random() - 0.5) * TUBE_RADIUS * 2166 );167 168 darkMatter.push(dm);169 scene.add(dm);170 }171 172 function createPlasmaExplosion(position) {173 const particleCount = 30;174 for(let i = 0; i < particleCount; i++) {175 const geometry = new THREE.SphereGeometry(0.1, 8, 8);176 const material = new THREE.MeshPhongMaterial({177 color: 0x00ff00,178 emissive: 0x00ff00,179 emissiveIntensity: 1180 });181 182 const plasma = new THREE.Mesh(geometry, material);183 plasma.position.copy(position);184 185 const velocity = new THREE.Vector3(186 (Math.random() - 0.5) * 0.5,187 (Math.random() - 0.5) * 0.5,188 (Math.random() - 0.5) * 0.5189 );190 191 plasma.userData = {192 velocity: velocity,193 lifetime: 100,194 maxLifetime: 100195 };196 197 plasmaParticles.push(plasma);198 scene.add(plasma);199 }200 }201 202 function updateParticles() {203 const speed = document.getElementById('speed').value / 50;204 const energy = document.getElementById('energy').value / 100;205 const power = document.getElementById('power').value / 100;206 207 // Update particles208 particles.forEach((particle, index) => {209 particle.userData.angle += particle.userData.speed * speed * particle.userData.direction;210 211 particle.position.x = Math.cos(particle.userData.angle) * TUBE_RADIUS;212 particle.position.y = Math.sin(particle.userData.angle) * TUBE_RADIUS;213 particle.position.z = Math.sin(particle.userData.phase) * 2;214 215 particle.userData.phase += 0.01 * particle.userData.direction;216 217 // Collision detection218 for(let i = index + 1; i < particles.length; i++) {219 const other = particles[i];220 if(particle.position.distanceTo(other.position) < 0.6) {221 createPlasmaExplosion(particle.position);222 particle.userData.energy -= power * 10;223 other.userData.energy -= power * 10;224 playCollisionSound();225 }226 }227 228 if(particle.userData.energy <= 0) {229 scene.remove(particle);230 particles.splice(index, 1);231 updateParticleCount();232 }233 });234 235 // Update plasma particles236 plasmaParticles.forEach((plasma, index) => {237 plasma.position.add(plasma.userData.velocity);238 plasma.userData.lifetime--;239 plasma.material.opacity = plasma.userData.lifetime / plasma.userData.maxLifetime;240 241 if(plasma.userData.lifetime <= 0) {242 scene.remove(plasma);243 plasmaParticles.splice(index, 1);244 }245 });246 }247 248 function updateParticleCount() {249 document.getElementById('particleCount').textContent = particles.length;250 }251 252 function animate() {253 requestAnimationFrame(animate);254 updateParticles();255 renderer.render(scene, camera);256 }257 258 init();259 animate();260 </script>261</body>262</html>