I wanted to use multiple LEDs to simulate water level warning lights around Lionel swing bridge. My solution was to use an Arduino (I used a NANO, but same code will work on UNO) as it has 6 output pins that have Pulse Width Modulation (PWM) control. Each pin can source/sink 20ma, so can drive one LED directly. I used standard 2.0VDC drop Red LED in series with 150ohm resistor. LED connected to Arduino output such that a 1 on the output turns the LED on.
First, I played with trying to blink one LED so that it looks like it is an incandescent bulb, i.e., rather quick turn on, slow turn off. I came up will 11 PWM values between 0% and 100% modulation, and 11 delay values between 15milliseconds and 1 second. Once I liked the way blinking of a single LED looked, I attacked the problem of getting all 6 PWM outputs follow my on/off ramps, but added the requirement that the 6 LEDs would not be in sync, and in fact, keep "rolling" their individual flashes past each other, giving the look not being in sync with each other.
I decided using arrays was the way to go. For you non-programmers, an array is like a drawer you divide into sections and name each section 0 through X (so if you have 6 sections, they would be 0 through 5). You can then ask someone to go to the drawer and get (or put) something into a section of the drawer based on its name (number).
Reading the code is probably clearer than me trying to explain in words every step. But in general, first everything is initialized. You read the present time, and compare it (on an LED by LED basis) to when the next change to an LED is required. If change is required, write out the next PWM value, setup the time when the next change is required. If the next change for a LED is to be off, the next change time is influenced by the addition of a "prime number" number of milliseconds to achieve the not in sync look.
.jpg of code listing and Arduino .ino file included with this post.