You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
3.1 KiB
134 lines
3.1 KiB
import * as THREE from 'three/build/three.module'; |
|
import { Ship } from './Ship'; |
|
import { Laser } from './Laser'; |
|
|
|
export const scene = ({ ref }) => { |
|
// TODO: add waves of ships |
|
// TODO: add stars |
|
// TODO: use aspect ratio to determine space docking point |
|
|
|
let t = 0.01; |
|
const shipInterval = 1; |
|
let nextShip = shipInterval; |
|
|
|
var scene = new THREE.Scene(); |
|
|
|
let renderer = null; |
|
try { |
|
renderer = new THREE.WebGLRenderer({ antialias: true }); |
|
} catch (error) { |
|
console.log('Problem creating WebGLRenderer:', error); |
|
return; |
|
} |
|
|
|
const width = ref.current.clientWidth; |
|
const height = ref.current.clientHeight; |
|
|
|
renderer.setSize(width, height); |
|
|
|
const camera = new THREE.PerspectiveCamera(65, width / height, 0.01, 1000000); |
|
|
|
camera.position.set(5, 2, 1); |
|
camera.lookAt(new THREE.Vector3(0, 0, 0)); |
|
scene.add(camera); |
|
|
|
ref.current.appendChild(renderer.domElement); |
|
|
|
const light1 = new THREE.DirectionalLight('#fff', 1); |
|
light1.position.x = 3; |
|
light1.position.z = 1; |
|
scene.add(light1); |
|
|
|
const light2 = new THREE.PointLight('#fff', 2); |
|
light2.position.x = 5; |
|
light2.position.y = 5; |
|
light2.position.z = 1; |
|
scene.add(light2); |
|
|
|
const star_material = new THREE.MeshBasicMaterial( { side: THREE.DoubleSide, color: 0xaaaaaa } ); |
|
let stars = []; |
|
|
|
for (let i = 0; i < 200; i++) { |
|
const star_geometry = new THREE.CircleGeometry( Math.random() * 200 + 100, 8 ); |
|
const star_circle = new THREE.Mesh( star_geometry, star_material ); |
|
scene.add(star_circle); |
|
//star_circle.rotation.y = Math.PI / 2; |
|
const u = Math.random() - 0.5; |
|
const v = Math.random() - 0.5; |
|
star_circle.position.set(-100000*Math.sin(v*Math.PI+Math.PI/2), 300000*u, 100000*Math.cos(v*Math.PI+Math.PI/2)); |
|
star_circle.lookAt(camera.position); |
|
stars.push(star_circle); |
|
} |
|
|
|
|
|
let ships = []; |
|
let bolts = []; |
|
|
|
window.addEventListener('resize', () => { |
|
camera.updateProjectionMatrix(); |
|
renderer.setSize(ref.current.clientWidth, ref.current.clientHeight); |
|
}); |
|
|
|
ref.current.addEventListener('mousemove', (e) => { |
|
const x = e.clientX; |
|
const ratio = x / ref.current.clientWidth; |
|
camera.position.set(5, 2, ratio * 4 - 2); |
|
camera.lookAt(new THREE.Vector3(0, 0, 0)); |
|
}); |
|
|
|
const animate = () => { |
|
const deltaTime = 0.075; |
|
t += deltaTime; |
|
|
|
const direction = Math.random() > 0.5 ? 1 : -1; |
|
|
|
if (t > nextShip) { |
|
const ship = new Ship(direction); |
|
scene.add(ship.mesh); |
|
ships.push(ship); |
|
nextShip += shipInterval + (Math.random() - 0.5) * 2; |
|
} |
|
|
|
for (const ship of ships) { |
|
ship.update({ deltaTime }); |
|
|
|
if (ship.firing) { |
|
const bolt = new Laser(ship); |
|
|
|
bolts.push(bolt); |
|
scene.add(bolt.mesh); |
|
ship.firing = false; |
|
} |
|
|
|
if (ship.kill) { |
|
scene.remove(ship.mesh); |
|
} |
|
} |
|
|
|
for (const bolt of bolts) { |
|
bolt.update({ deltaTime }); |
|
|
|
if (bolt.kill) { |
|
scene.remove(bolt.mesh); |
|
} |
|
} |
|
|
|
ships = ships.filter((s) => !s.kill); |
|
bolts = bolts.filter((s) => !s.kill); |
|
|
|
try { |
|
requestAnimationFrame(animate); |
|
renderer.render(scene, camera); |
|
} catch(err) { |
|
return; |
|
} |
|
}; |
|
|
|
try { |
|
animate(); |
|
renderer.render(scene, camera); |
|
} catch(err) { |
|
renderer.dispose(); |
|
return; |
|
} |
|
};
|
|
|