const VELOCITY = [0.002, 0.0001]; const SHOOT_PROBABILITY = 0.0007; class Cloud extends Entity { static shootProbability = SHOOT_PROBABILITY; constructor(...args) { super(...args); this.particles = new Set(); for (let i = 0; i < 3; i++) { const cloudParticle = { w: randRange(0.3, 0.8), h: randRange(0.3, 0.8), x: randRange(0.2, 0.8), y: randRange(0.2, 0.8), r: randRange(-Math.PI, Math.PI), n: randRange(-10000, 10000), } this.particles.add(cloudParticle); } this.sound = new Audio(); this.sound.src = 'snd/click.ogg'; } draw() { const { x, y, w, h } = this.getScreenCoords(); for (let particle of this.particles) { const px = x + particle.x * w; const py = y + particle.y * h; const pw = particle.w * w; const ph = particle.h * w; const now = Date.now() / 1000; const a = mapNumber( noise.simplex3(particle.n, now / 2, 0), -1, 1, 0, 0.7, ); const r = mapNumber( noise.simplex3(particle.n, now / 10, 1), -1, 1, 0, Math.PI, ); const z = mapNumber( noise.simplex3(particle.n, now / 2, 2), -1, 1, 0.5, 1.5, ); CTX.fillStyle = `rgba(255, 255, 255, ${a})`; CTX.beginPath(); CTX.ellipse(px, py, pw / 2 * z, ph / 2 * z, particle.r + r, 0, 2 * Math.PI); CTX.fill(); } } static reset() { this.shootProbability = SHOOT_PROBABILITY; } update(direction) { if (this.alive) { this.x += VELOCITY[0] * direction; this.y += VELOCITY[1]; if (Math.random() < Cloud.shootProbability) { const raindrop = new RainDrop(this.x, this.y + 0.009); bullets.add(raindrop); if (soundEnabled) { this.sound.currentTime = 0; this.sound.play().catch(() => { }); } } } } destroy() { super.destroy(); Cloud.shootProbability += 0.0001; } }