🌈 Creating an Animated Plasma Effect in Ruby2D

In this tutorial, you'll learn how to create a mesmerizing animated plasma effect using Ruby2D. This classic demoscene effect uses mathematical functions to generate flowing, colorful patterns that look like liquid plasma.

Prerequisites: Basic Ruby knowledge and Ruby2D installed (gem install ruby2d)

What is a Plasma Effect?

A plasma effect is created by combining multiple sine waves that vary over space and time. The result is a smooth, organic-looking animation with flowing colors. It's been a staple of computer graphics demos since the 1990s.

Step-by-Step Implementation

1Setting Up the Window

First, we need to require Ruby2D and configure our window:

require 'ruby2d'

set title: "Plasma Effect"
set width: 640
set height: 480
set background: 'black'

This creates a 640x480 window with a black background.

2Creating the Grid

Instead of calculating colors for every pixel (which would be slow), we create a grid of rectangles:

GRID_WIDTH = 80
GRID_HEIGHT = 60
CELL_WIDTH = Window.width / GRID_WIDTH
CELL_HEIGHT = Window.height / GRID_HEIGHT

This divides our window into an 80x60 grid. Each cell will be 8x8 pixels.

💡 Tip: Lower grid dimensions = faster performance but blockier effect. Higher = smoother but slower.

3Building the Rectangle Grid

Now we create a rectangle for each grid cell:

plasma_grid = []
GRID_HEIGHT.times do |y|
  row = []
  GRID_WIDTH.times do |x|
    rect = Rectangle.new(
      x: x * CELL_WIDTH,
      y: y * CELL_HEIGHT,
      width: CELL_WIDTH,
      height: CELL_HEIGHT,
      color: 'black'
    )
    row << rect
  end
  plasma_grid << row
end

This creates a 2D array where plasma_grid[y][x] gives us the rectangle at position (x, y).

4The Heart of Plasma: The Math

This is where the magic happens! The plasma function combines multiple sine waves:

def plasma_color(x, y, time)
  # Four different sine waves
  v1 = Math.sin(x * 0.1 + time)
  v2 = Math.sin(y * 0.1 + time * 0.8)
  v3 = Math.sin((x + y) * 0.08 + time * 0.5)
  v4 = Math.sin(Math.sqrt(x * x + y * y) * 0.05 + time)
  
  # Average them together
  value = (v1 + v2 + v3 + v4) / 4.0
  
  # ... (color conversion continues)
end

Understanding Each Wave:

By adding time to each wave with different speeds, they animate at different rates, creating complex patterns.

🎨 Experiment: Try changing the coefficients (0.1, 0.8, 0.08, 0.05) to create different patterns!

5Converting Math to Colors

The sine waves give us values between -1 and 1. We need to convert these to colors:

# Normalize to 0-1 range
hue = (value + 1.0) * 0.5

# Create RGB colors using sine waves offset by 120 degrees
r = (Math.sin(hue * Math::PI * 2) * 0.5 + 0.5)
g = (Math.sin((hue + 0.33) * Math::PI * 2) * 0.5 + 0.5)
b = (Math.sin((hue + 0.66) * Math::PI * 2) * 0.5 + 0.5)

[r, g, b, 1.0]  # Return RGBA array

This creates a rainbow gradient by offsetting the red, green, and blue channels.

6Animation Loop

Finally, we animate by updating colors every frame:

time = 0.0

update do
  time += 0.03  # Increment time each frame
  
  GRID_HEIGHT.times do |y|
    GRID_WIDTH.times do |x|
      color = plasma_color(x, y, time)
      plasma_grid[y][x].color = color
    end
  end
end

show  # Start the window

The update block runs every frame (typically 60 times per second), recalculating colors based on the current time.

How It Works: The Physics

Think of each sine wave as a ripple in water. When multiple ripples overlap, they create interference patterns. The plasma effect simulates this by combining waves traveling in different directions and at different speeds.

The time variable makes these waves move, while the x and y coordinates determine which part of the wave we're looking at for each grid cell.

Customization Ideas

Speed Control

time += 0.03  # Slower
time += 0.1   # Faster
time += 0.01  # Very slow, hypnotic

Different Wave Patterns

# More waves = more complex patterns
v5 = Math.sin(x * 0.15 - y * 0.15 + time * 1.2)
value = (v1 + v2 + v3 + v4 + v5) / 5.0

Color Schemes

# Fire colors (reds and oranges)
r = value + 1.0
g = (value + 1.0) * 0.5
b = 0.0

# Ocean colors (blues and greens)
r = 0.0
g = (value + 1.0) * 0.5
b = value + 1.0

Performance Tips

Complete Code

Download plasma.rb

Further Exploration

Now that you understand the basics, try these challenges:

  1. Add mouse interaction (change wave parameters based on mouse position)
  2. Create "zoom" effects by scaling the x and y coordinates
  3. Add rotation by transforming coordinates before calculation
  4. Combine multiple plasma layers with transparency
  5. Create preset buttons to switch between different patterns

Happy coding! Share your plasma creations! 🎨✨