Simulating candle flickering with a simple RNG
While preparing to attach the electrical candles to the christmas tree, a question popped into my mind.
There are electrical candles that simulate the flickering of real candles. How complex would an algorithm have to be to be convincing?
I wrote a quick proof of concept in Ruby for a script running in the terminal which just randomly chooses a grey value to display.
#!/usr/bin/env ruby
require 'io/console'
lines, cols = $stdout.winsize
rnd = 0
loop {
rnd = (rnd * 5 + 17) % 256
lines.times {
puts "\e[48;2;#{rnd};#{rnd};#{rnd}m" + (" " * cols) + "\e[0m"
}
sleep(0.11)
}
It uses a simple linear congruential generator as random number generator with a period of 256. This period is already large enough for the repetition to be not noticeable for a human being.
But there were obvious improvements, like using a better color and smoothing the transition from one color to the next.
I think given its simplicity it already works quite well. But the color transitions are quite harsh so for the second version I restricted the color value range, varied only one color channel, and added some ASCII art.
function updateFlameColor() {
rnd = (rnd * 5 + 17) % 256;
// mapping the random value onto a color range from yellow to orange
const r = 255;
const g = 100 + rnd / 2; // 100..228
const b = 0;
flameEl.style.color = `rgb(${r},${g},${b})`;
setTimeout(updateFlameColor, 110);
}
This results in this cozy animation:
O | ===