| <!DOCTYPE html> |
| <html> |
| <head> |
| <style> |
| body { margin: 0; overflow: hidden; background: #000; } |
| #ui { |
| position: fixed; |
| top: 10px; |
| left: 10px; |
| color: #0f0; |
| background: rgba(0,20,0,0.7); |
| padding: 15px; |
| border: 1px solid #0f0; |
| font-family: monospace; |
| z-index: 100; |
| } |
| .control { margin: 10px 0; } |
| #matrix { |
| position: fixed; |
| top: 0; |
| left: 0; |
| z-index: -1; |
| color: #0f0; |
| font-family: monospace; |
| font-size: 12px; |
| opacity: 0.2; |
| } |
| </style> |
| </head> |
| <body> |
| <div id="ui"> |
| <div class="control"> |
| <button onclick="initAudio()">Start Audio</button> |
| </div> |
| <div class="control"> |
| <label>Particle Speed: <input type="range" id="speed" min="1" max="200" value="100"></label> |
| </div> |
| <div class="control"> |
| <label>Energy Level: <input type="range" id="energy" min="1" max="100" value="50"></label> |
| </div> |
| <div class="control"> |
| <label>Power: <input type="range" id="power" min="1" max="100" value="75"></label> |
| </div> |
| <div class="control"> |
| <button onclick="addParticle()">Add Particle</button> |
| <button onclick="addDarkMatter()">Add Dark Matter</button> |
| </div> |
| <div>Particles: <span id="particleCount">0</span></div> |
| </div> |
| <div id="matrix"></div> |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> |
| <script> |
| let scene, camera, renderer, particles = [], darkMatter = [], plasmaParticles = []; |
| let audioContext; |
| const TUBE_RADIUS = 20; |
| |
| function initAudio() { |
| audioContext = new (window.AudioContext || window.webkitAudioContext)(); |
| } |
| |
| function playCollisionSound() { |
| const oscillator1 = audioContext.createOscillator(); |
| const oscillator2 = audioContext.createOscillator(); |
| const gainNode = audioContext.createGain(); |
| |
| oscillator1.connect(gainNode); |
| oscillator2.connect(gainNode); |
| gainNode.connect(audioContext.destination); |
| |
| oscillator1.frequency.setValueAtTime(440 + Math.random() * 220, audioContext.currentTime); |
| oscillator2.frequency.setValueAtTime(220 + Math.random() * 110, audioContext.currentTime); |
| |
| oscillator1.type = 'sine'; |
| oscillator2.type = 'square'; |
| |
| gainNode.gain.setValueAtTime(0.2, audioContext.currentTime); |
| gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.3); |
| |
| oscillator1.start(); |
| oscillator2.start(); |
| oscillator1.stop(audioContext.currentTime + 0.3); |
| oscillator2.stop(audioContext.currentTime + 0.3); |
| } |
| |
| function init() { |
| initAudio(); |
| scene = new THREE.Scene(); |
| camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); |
| renderer = new THREE.WebGLRenderer({ antialias: true }); |
| renderer.setSize(window.innerWidth, window.innerHeight); |
| document.body.appendChild(renderer.domElement); |
| |
| |
| const tubeGeometry = new THREE.TorusGeometry(TUBE_RADIUS, 2, 32, 100); |
| const tubeMaterial = new THREE.MeshPhongMaterial({ |
| color: 0x00ff00, |
| transparent: true, |
| opacity: 0.3, |
| wireframe: true |
| }); |
| const tube = new THREE.Mesh(tubeGeometry, tubeMaterial); |
| scene.add(tube); |
| |
| |
| const light = new THREE.PointLight(0xffffff, 1); |
| light.position.set(0, 0, 50); |
| scene.add(light); |
| scene.add(new THREE.AmbientLight(0x404040)); |
| |
| camera.position.z = 50; |
| |
| |
| initMatrix(); |
| } |
| |
| function initMatrix() { |
| const matrix = document.getElementById('matrix'); |
| const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%^&*()"; |
| setInterval(() => { |
| let str = ''; |
| for(let i = 0; i < 50; i++) { |
| for(let j = 0; j < 100; j++) { |
| str += chars[Math.floor(Math.random() * chars.length)]; |
| } |
| str += '\n'; |
| } |
| matrix.textContent = str; |
| }, 50); |
| } |
| |
| function addParticle() { |
| const geometry = new THREE.SphereGeometry(0.3, 16, 16); |
| const material = new THREE.MeshPhongMaterial({ |
| color: 0x00ff00, |
| emissive: 0x00ff00, |
| emissiveIntensity: 0.5 |
| }); |
| |
| const particle = new THREE.Mesh(geometry, material); |
| particle.userData = { |
| angle: Math.random() * Math.PI * 2, |
| speed: Math.random() * 0.02 + 0.01, |
| direction: Math.random() > 0.5 ? 1 : -1, |
| phase: Math.random() * Math.PI * 2, |
| energy: 100 |
| }; |
| |
| particles.push(particle); |
| scene.add(particle); |
| updateParticleCount(); |
| } |
| |
| function addDarkMatter() { |
| const geometry = new THREE.SphereGeometry(1, 32, 32); |
| const material = new THREE.MeshPhongMaterial({ |
| color: 0x000066, |
| transparent: true, |
| opacity: 0.3 |
| }); |
| |
| const dm = new THREE.Mesh(geometry, material); |
| dm.position.set( |
| (Math.random() - 0.5) * TUBE_RADIUS * 2, |
| (Math.random() - 0.5) * TUBE_RADIUS * 2, |
| (Math.random() - 0.5) * TUBE_RADIUS * 2 |
| ); |
| |
| darkMatter.push(dm); |
| scene.add(dm); |
| } |
| |
| function createPlasmaExplosion(position) { |
| const particleCount = 30; |
| for(let i = 0; i < particleCount; i++) { |
| const geometry = new THREE.SphereGeometry(0.1, 8, 8); |
| const material = new THREE.MeshPhongMaterial({ |
| color: 0x00ff00, |
| emissive: 0x00ff00, |
| emissiveIntensity: 1 |
| }); |
| |
| const plasma = new THREE.Mesh(geometry, material); |
| plasma.position.copy(position); |
| |
| const velocity = new THREE.Vector3( |
| (Math.random() - 0.5) * 0.5, |
| (Math.random() - 0.5) * 0.5, |
| (Math.random() - 0.5) * 0.5 |
| ); |
| |
| plasma.userData = { |
| velocity: velocity, |
| lifetime: 100, |
| maxLifetime: 100 |
| }; |
| |
| plasmaParticles.push(plasma); |
| scene.add(plasma); |
| } |
| } |
| |
| function updateParticles() { |
| const speed = document.getElementById('speed').value / 50; |
| const energy = document.getElementById('energy').value / 100; |
| const power = document.getElementById('power').value / 100; |
| |
| |
| particles.forEach((particle, index) => { |
| particle.userData.angle += particle.userData.speed * speed * particle.userData.direction; |
| |
| particle.position.x = Math.cos(particle.userData.angle) * TUBE_RADIUS; |
| particle.position.y = Math.sin(particle.userData.angle) * TUBE_RADIUS; |
| particle.position.z = Math.sin(particle.userData.phase) * 2; |
| |
| particle.userData.phase += 0.01 * particle.userData.direction; |
| |
| |
| for(let i = index + 1; i < particles.length; i++) { |
| const other = particles[i]; |
| if(particle.position.distanceTo(other.position) < 0.6) { |
| createPlasmaExplosion(particle.position); |
| particle.userData.energy -= power * 10; |
| other.userData.energy -= power * 10; |
| playCollisionSound(); |
| } |
| } |
| |
| if(particle.userData.energy <= 0) { |
| scene.remove(particle); |
| particles.splice(index, 1); |
| updateParticleCount(); |
| } |
| }); |
| |
| |
| plasmaParticles.forEach((plasma, index) => { |
| plasma.position.add(plasma.userData.velocity); |
| plasma.userData.lifetime--; |
| plasma.material.opacity = plasma.userData.lifetime / plasma.userData.maxLifetime; |
| |
| if(plasma.userData.lifetime <= 0) { |
| scene.remove(plasma); |
| plasmaParticles.splice(index, 1); |
| } |
| }); |
| } |
| |
| function updateParticleCount() { |
| document.getElementById('particleCount').textContent = particles.length; |
| } |
| |
| function animate() { |
| requestAnimationFrame(animate); |
| updateParticles(); |
| renderer.render(scene, camera); |
| } |
| |
| init(); |
| animate(); |
| </script> |
| </body> |
| </html> |