CodeWalrus

Development => Calculators => Calc Projects, Programming & Tutorials => Topic started by: Zeda on June 26, 2018, 04:25:27 am

Title: Fire Animation
Post by: Zeda on June 26, 2018, 04:25:27 am
A fascination with fire is nothing new for humans, or even programmers. With that in mind, I wanted to give some insight into how to create your very own fire animations, like this:
(https://i.imgur.com/tJUrnLi.gif)
In that program, I basically started from the top of the screen, working downward. I'd copy from the pixel below, with a 12.5% chance of the copy "burning up" and thus failing. To cause a perpetual burn, I then OR the original image back to the buffer and run the next iteration. If I didn't do this, then the image would disintegrate after a few seconds (which is cool, too).

Now of course, this is Assembly, which is fast, but it's also the Z80, so not that fast. Instead of operating on one pixel at a time, it's faster if we can operate on 8 pixels at a time (represented by 1 byte). Copying the pixels is easy-- if DE points to the current byte of pixels, and HL points to the byte of pixels below, then we can do ld a,(hl) \ ld (de),a (or ldi). The tricky part is coming up with some chance of messing with those pixels.

We want it to appear random or chaotic, so we need an RNG of some kind, in this case a Pseudo-Random Number Generator. Ideally, we also want it to be fast. If our PRNG returns numbers with the property that each bit is chaotic, but has a 50% chance of being 0 or 1, then we can apply some probability tricks. For example, if we OR three pseudo-random numbers, then the result has bits with probability 1/8 being 0, 7/8 being 1. Armed with this knowledge, if we then AND this with the pixels to copy, we have a 12.5% chance of turning any ON pixels to OFF.

This assumes the 'flames' are black. If we want white flames, AND three numbers from the PRNG and OR the result with the pixels to copy. This has a 12.5% chance of turning a pixel ON.

If we want more complicated probabilities, we can change the sequence of ANDs and ORs. For example, if we OR two PRNs and AND a third, the bit probabilities are 37.5% being 1, 62.5% being 0.
Just note that if we change the order, then the probabilities change! If we AND to PRNs and then OR a third, we have a 62.5% being 0 and 37.5% being 1.

To calculate, we start with p0=50%.
If we OR with a PRN, then pi+1=(1+pi)/2
If we AND with a PRN, then pi+1=pi/2

For example, if we AND/OR/AND/OR, we have:
p0=.5
p1=.5/2 = .25
p2=(1+.25)/2 = .625
p3=.625/2 = .3125
p4=(1+.3125)/2 = .65625


With my example, I wanted it to be easy, so I just went with ORing three pseudo-random numbers to generate a bitmask. I created a 24-bit PRNG with the necessary qualities (and as a bonus, it passed a suite of randomness tests), so by calling it once and ORing each of the bytes together, I can make a mask.

For those who might be able to follow Axe code a little better:
Code: [Select]
StorePic
While getKey(15)=0
L3->W
For(Z,L6,L6+767)
{Z} or {W}->{Z}
W+1->W
End
L6->Z+12->W
For(K,0,755)
rand or rand or rand or {W}->{Z}
W+1->W
Z+1->Z
End
DispGraph
End
Title: Re: Fire Animation
Post by: 123outerme on June 26, 2018, 04:36:28 am
Wow, that looks really good! The grayscale in the screenshot really sells the fire for me, although I'm not sure if it's actual grayscale or just an emulator-only thing. Either way, nice work! I don't really use animations that alter the individual pixels, this has convinced me for magic, fire, etc. animations, that sort of animation would work out really well!
Title: Re: Fire Animation
Post by: Zeda on June 26, 2018, 12:51:43 pm
I usually don't like to enable grayscale in my animations for size reasons (that was .5MB !), but in this case, it was the most faithful to how my physical calculators displayed it. In the download there are also 15MHz versions that are kinda too fast :P The gray is even more apparent there because basically everything turns gray with how fast pixels are changing state.