import * as THREE from 'three'; import * as Calc from './utils/calc'; import * as Ease from './utils/ease'; import { Drop } from './drop'; import { Loader } from './loader'; import { Particle } from './particle'; import { Ripple } from './ripple'; function hexToInt(rrggbb: string): number { if (rrggbb.startsWith('#')) rrggbb = rrggbb.substr(1); return parseInt(rrggbb, 16); } export class System { public loader: Loader; private drops: Drop[] = []; private ripples: Ripple[] = []; private particles: Particle[] = []; public sphereGeometry: THREE.SphereGeometry; public boxGeometry: THREE.BoxGeometry; private center: THREE.Vector3; private particleGroup: THREE.Object3D; private size = 96; private cols = 32; private rows = 32; private tick: number = 0; private dropTick = 0; private dropTickMin = 25; private dropTickMax = 30; private particleColor: number; private rippleColor: number; private dropColor: number; constructor(loader, config: { particleColor: string; rippleColor: string; dropColor: string; }) { this.loader = loader; this.particleColor = hexToInt(config.particleColor); this.rippleColor = hexToInt(config.rippleColor); this.dropColor = hexToInt(config.dropColor); this.sphereGeometry = new THREE.SphereGeometry(1, 16, 16); this.boxGeometry = new THREE.BoxGeometry(1, 1, 1); this.center = new THREE.Vector3(); this.loader.camera.lookAt(this.center); this.particleGroup = new THREE.Object3D(); this.particleGroup.scale.set(1, 1, 1); this.loader.scene.add(this.particleGroup); for(let col = 0; col < this.cols; col++) { for(let row = 0; row < this.rows; row++) { let x = Calc.map(col, 0, this.cols - 1, -this.size / 2, this.size / 2); let y = 0; let z = Calc.map(row, 0, this.rows - 1, -this.size / 2, this.size / 2); this.particles.push(new Particle({ group: this.particleGroup, x: x, y: y, z: z, size: 0.01, color: this.particleColor, opacity: 0.01 }, this)); } } } createDrop(x?, y?, z?, strength?) { this.drops.push(new Drop({ array: this.drops, group: this.particleGroup, x: x === undefined ? Calc.rand(-this.size / 2, this.size / 2) : x, y: y === undefined ? Calc.rand(30, 50) : y, z: z === undefined ? Calc.rand(-this.size / 2, this.size / 2) : z, size: 0.15, color: this.dropColor, opacity: 0, strength: strength }, this)); } updateDrops() { let i = this.drops.length; while(i--) { this.drops[i].update(i); } } createRipple(x, z, strength) { this.ripples.push(new Ripple({ array: this.ripples, group: this.particleGroup, x: x, y: -0.1, z: z, color: this.rippleColor, strength: strength }, this)); } updateRipples() { let i = this.ripples.length; while(i--) { this.ripples[i].update(i); } } update() { { let i = this.particles.length; while(i--) { this.particles[i].update(); } } if(this.tick >= this.dropTick) { this.createDrop(); this.dropTick = Calc.randInt(this.dropTickMin, this.dropTickMax); this.tick = 0; } this.updateDrops(); this.updateRipples(); { let i = this.particles.length; while(i--) { let j = this.ripples.length; while(j--) { let particle = this.particles[i]; let ripple = this.ripples[j]; let influence = ripple.getInfluenceVector(particle.base); influence.setX(0); influence.setZ(0); particle.velocity.add(influence); } } } this.particleGroup.rotation.x = Math.cos(this.loader.elapsedMilliseconds * 0.0005) * 0.1; this.particleGroup.rotation.y = Math.PI * 0.25 + Math.sin(this.loader.elapsedMilliseconds * 0.0005) * -0.2; this.tick += this.loader.deltaTimeNormal; } }