W tym samouczku nauczysz si臋, jak stworzy膰 hipnotyzuj膮cy animowany efekt plazmy za pomoc膮 Ruby2D. Ten klasyczny efekt demoscenowy wykorzystuje funkcje matematyczne do generowania p艂ynnych, kolorowych wzor贸w, kt贸re wygl膮daj膮 jak ciek艂a plazma.
gem install ruby2d)
Efekt plazmy powstaje przez kombinowanie wielu fal sinusoidalnych, kt贸re zmieniaj膮 si臋 w przestrzeni i czasie. Rezultatem jest p艂ynna, organicznie wygl膮daj膮ca animacja z przep艂ywaj膮cymi kolorami. Jest to element grafiki komputerowej obecny w demach od lat 90-tych XX wieku.
Najpierw musimy zaimportowa膰 Ruby2D i skonfigurowa膰 nasze okno:
require 'ruby2d'
set title: "Plasma Effect"
set width: 640
set height: 480
set background: 'black'
To tworzy okno o wymiarach 640x480 pikseli z czarnym t艂em.
Zamiast oblicza膰 kolory dla ka偶dego piksela (co by艂oby wolne), tworzymy siatk臋 prostok膮t贸w:
GRID_WIDTH = 80
GRID_HEIGHT = 60
CELL_WIDTH = Window.width / GRID_WIDTH
CELL_HEIGHT = Window.height / GRID_HEIGHT
To dzieli nasze okno na siatk臋 80x60. Ka偶da kom贸rka b臋dzie mia艂a 8x8 pikseli.
Teraz tworzymy prostok膮t dla ka偶dej kom贸rki siatki:
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
To tworzy dwuwymiarow膮 tablic臋, gdzie plasma_grid[y][x] daje nam prostok膮t na pozycji (x, y).
Tutaj dzieje si臋 magia! Funkcja plazmy 艂膮czy wiele fal sinusoidalnych:
def plasma_color(x, y, time)
# Cztery r贸偶ne fale sinusoidalne
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)
# U艣redniamy je razem
value = (v1 + v2 + v3 + v4) / 4.0
# ... (konwersja koloru trwa dalej)
end
Dodaj膮c time do ka偶dej fali z r贸偶nymi pr臋dko艣ciami, animuj膮 si臋 one w r贸偶nym tempie, tworz膮c z艂o偶one wzory.
Fale sinusoidalne daj膮 nam warto艣ci mi臋dzy -1 a 1. Musimy je przekonwertowa膰 na kolory:
// Normalizacja do zakresu 0-1
hue = (value + 1.0) * 0.5
// Tworzenie kolor贸w RGB za pomoc膮 fal sinusoidalnych przesuni臋tych o 120 stopni
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] // Zwraca tablic臋 RGBA
To tworzy gradient t臋czowy poprzez przesuni臋cie kana艂贸w czerwonego, zielonego i niebieskiego.
Na koniec animujemy, aktualizuj膮c kolory w ka偶dej klatce:
time = 0.0
update do
time += 0.03 # Zwi臋kszamy czas w ka偶dej klatce
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 # Uruchamia okno
Blok update jest wykonywany w ka偶dej klatce (zazwyczaj 60 razy na sekund臋), przeliczaj膮c kolory na podstawie aktualnego czasu.
Pomy艣l o ka偶dej fali sinusoidalnej jak o zmarszczce na wodzie. Kiedy wiele zmarszczek nak艂ada si臋 na siebie, tworz膮 wzory interferencji. Efekt plazmy symuluje to poprzez 艂膮czenie fal poruszaj膮cych si臋 w r贸偶nych kierunkach i z r贸偶nymi pr臋dko艣ciami.
Zmienna time sprawia, 偶e te fale si臋 poruszaj膮, podczas gdy wsp贸艂rz臋dne x i y okre艣laj膮, kt贸r膮 cz臋艣膰 fali ogl膮damy dla ka偶dej kom贸rki siatki.
time += 0.03 # Wolniej
time += 0.1 # Szybciej
time += 0.01 # Bardzo wolno, hipnotyzuj膮co
# Wi臋cej fal = bardziej z艂o偶one wzory
v5 = Math.sin(x * 0.15 - y * 0.15 + time * 1.2)
value = (v1 + v2 + v3 + v4 + v5) / 5.0
# Kolory ognia (czerwienie i pomara艅cze)
r = value + 1.0
g = (value + 1.0) * 0.5
b = 0.0
# Kolory oceanu (b艂臋kity i zielenie)
r = 0.0
g = (value + 1.0) * 0.5
b = value + 1.0
GRID_WIDTH i GRID_HEIGHT dla lepszej wydajno艣ciTeraz, gdy rozumiesz podstawy, spr贸buj tych wyzwa艅: