The plasma effect is a visual effect created by applying various functions, notably sine and cosine, to the color values of screen pixels. When animated (not a task requirement) the effect may give the impression of a colorful flowing liquid.



Task
Create a plasma effect.




See also
 Computer Graphics Tutorial (lodev.org)
 Plasma (bidouille.org)


 
uses javax.swing.*
uses java.awt.*
uses java.awt.image.*
uses java.awt.event.ActionEvent
uses java.awt.image.BufferedImage#*
uses java.lang.Math#*
 
var size = 400
EventQueue.invokeLater(\ -> showPlasma())
 
function showPlasma() {
  var frame = new JFrame("Plasma") {:Resizable = false, :DefaultCloseOperation = JFrame.EXIT_ON_CLOSE}
  frame.add(new Plasma(), BorderLayout.CENTER)
  frame.pack()
  frame.setLocationRelativeTo(null)
  frame.Visible = true 
}
 
class Plasma extends JPanel  {
  var hueShift: float
  property get plasma: float[][] = createPlasma(size, size)
  property get img: BufferedImage = new BufferedImage(size, size, TYPE_INT_RGB)
 
  construct() {
    PreferredSize = new Dimension(size, size)
    new Timer(50, \ e -> {hueShift+=0.02 repaint()}).start()
  }
 
  private function createPlasma(w: int, h: int): float[][] {
    var buffer = new float[h][w]
    for(y in 0..|h)
      for(x in 0..|w) {
        var value = (sin(x / 16) + sin(y / 8) + sin((x + y) / 16) + sin(sqrt(x * x + y * y) / 8) + 4) / 8
        buffer[y][x] = value as float
      }
    return buffer
  }
 
  override function paintComponent(g: Graphics) {
    for(y in 0..|plasma.length)
      for(x in 0..|plasma[0].length)
        img.setRGB(x, y, Color.HSBtoRGB(hueShift + plasma[y][x], 1, 1))
    g.drawImage(img, 0, 0, null)
  }
}
 