package ocelot.desktop.node import ocelot.desktop.color.RGBAColorNorm import ocelot.desktop.geometry.{Size2D, Vector2D} import ocelot.desktop.graphics.{Graphics, IconSource} import ocelot.desktop.node.SmokeParticleNode._ import ocelot.desktop.ui.UiHandler import ocelot.desktop.ui.particle.Particle import ocelot.desktop.util.Spritesheet import scala.util.Random trait SmokeParticleNode extends Node { protected def emitSmoke(): Unit = synchronized { for (_ <- 1 to randomCount) { UiHandler.root.workspaceView.particleSystem.add(new SmokeParticle) } } private class SmokeParticle extends Particle(ttl = randomDuration) { private val color: RGBAColorNorm = randomColor private var velocity: Vector2D = Vector2D(randomVelocityComponent, randomVelocityComponent) private var offset: Vector2D = Vector2D(0, 0) override def update(dt: Float): Unit = { time += dt offset += (velocity + SmokeParticleVolatilizationSpeed) * dt * speed velocity *= math.pow(SmokeParticleVelocityDamping, dt).toFloat } override def draw(g: Graphics): Unit = { val spriteRect = Spritesheet.sprites(IconSource.Particles.Smoke.path) val animationFrameCount = spriteRect.h / spriteRect.w val animationFrame = (time / ttl * animationFrameCount).toInt val particlePosition = bounds.center + offset - SmokeParticleSize.toVector * .5f g.sprite( IconSource.Particles.Smoke.path, particlePosition.x, particlePosition.y, SmokeParticleSize.width, SmokeParticleSize.height, color, Some(spriteRect.copy( y = spriteRect.y + animationFrame * spriteRect.w, h = spriteRect.w, )), ) } } } private object SmokeParticleNode { private final val SmokeParticleSize: Size2D = Size2D(32, 32) private final val SmokeParticleVelocityRange: Float = 300 private final val SmokeParticleVolatilizationSpeed: Vector2D = Vector2D(0, -50) private final val SmokeParticleVelocityDamping: Float = .1f private final val SmokeParticleCount: (Int, Int) = (10, 20) private final val SmokeParticleAnimationDuration: (Float, Float) = (1f, 4f) private def randomVelocityComponent: Float = Random.between( -SmokeParticleVelocityRange, SmokeParticleVelocityRange, ) private def randomColor: RGBAColorNorm = { val channel = Random.between(.5f, .9f) RGBAColorNorm(channel, channel, channel) } private def randomDuration: Float = Random.between( SmokeParticleAnimationDuration._1, SmokeParticleAnimationDuration._2, ) private def randomCount: Int = Random.between( SmokeParticleCount._1, SmokeParticleCount._2, ) }