Archived

This topic is now archived and is closed to further replies.

yue feng

Fire effect

Recommended Posts

I have read the tutorial provided by this website and tried to create a fire effect. However, the code seems not running right,there is no fire at all. Can someone please check my code and tell me why? Here is my code: void CDirectDraw::DrawFire() { int fireoffset = 0; int firevalue = 0; FillPalleteInfo();//here, i set up my own pallete unsigned char *double_buffer = NULL; double_buffer = (unsigned char *)malloc(307200); unsigned char *fire_buffer = NULL; fire_buffer = (unsigned char *)malloc(307200); //here i setup my "hot spots" for(int x = 1; x < 637; x++) { if(rand() % 2) fire_buffer[640*480 + x] = 0; else fire_buffer[640*480 + x] = 255; } //CALCULATE THE SURROUNDING PIXELS for(int y = 0; y < 480; y++) { for(int x = 0; x < 640; x++) { fireoffset = (y*640) + x; firevalue = ((fire_buffer[fireoffset-640] + fire_buffer[fireoffset+640] + fire_buffer[fireoffset+1] + fire_buffer[fireoffset-1] + fire_buffer[fireoffset-641] + fire_buffer[fireoffset-639] + fire_buffer[fireoffset+641] + fire_buffer[fireoffset+639]) / 8); if(firevalue != 0) // is it black? { firevalue++; fire_buffer[fireoffset+640] = firevalue; // Plot that new color } } } double_buffer = Lock_Back_Buffer(); memcpy(double_buffer, fire_buffer, (640*480)); // Copy fire buffer to the screen m_lpDDSBack->Unlock(NULL); // Unlock! Important! you have no idear! m_lpDDSPrimary->Flip(NULL,0); }

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You should always consider the pitch. In fact, because of the pitch, you must copy each line individually.
DDSURFACEDESC.lPitch

Also, just remember that at position (0,0) there is no defined value for (-1,0) and such.

Hope it helps.

Share this post


Link to post
Share on other sites
Thanks for your advice first!

But these code is copied out from the tutorial which says such way will be working fine. In fact, Your worries are mine,too. Now, I am just hoping that someone can offer me the revised code which will be greatly appreciated!

Share this post


Link to post
Share on other sites
I had been playing with fire recently. I have an algo that makes a fire that is resizeable. It is currently in 32 bit colour mode with a 768 colour palette and 8 different pixel averaging routines to make differnt kinds of fires.

Heres a quick pic. This is the fastest averaging routine using only 2 pixels. The picture does not have smoke. The newer version does. More work as to be done in that area.



My attempt at a FIRE TUTORIAL

You can pick up a zip file with fire.h, fire.cpp, README.TXT HERE

[EDIT] Clipping added. Default to 800 X 600. Can be set. [/EDIT]

Guy


"Who lives in a pineapple under the sea ?"

[edited by - Arion on March 18, 2002 2:39:24 PM]

Share this post


Link to post
Share on other sites
A few things of note with your algo.

(1)

You are loading your palette each frame, it only needs to be loaded once upon initialization.

(2)

You are re-allocating memory in the buffers each frame.
Allocate those buffers once upon initialization.

(3)

You are averaging down the screen. You have to start at the end and average upwards.

for ( y = 0 ; y < 480 ; y++ )

should be:

for ( y = 479 ; y > 0 ; y-- )

This will average you hot spots upwards towards the top of the screen instead of downwads to the bottom.

Guy


"Who lives in a pineapple under the sea ?"

Share this post


Link to post
Share on other sites
I have read a lot of fire tutorials in which one thing is always unexplained.(or I never get)That is when you average the surrounding pixels, whon''t you get an unexpected different effect for pixels that are on the edge? Can anyone answer me please?( I have been suffering from the flame effect for days, now it is still not working out )

Thanks to anyone reply

Share this post


Link to post
Share on other sites
Edge pixels can be a problem. You don''t want the fire to go out of bounds of the rectangle. It loses the effect.

What I do is have a pixel buffer of say 8 pixels on the left and right side of the fire. I lay hot and cold spots between the two buffers. This stops the fire from getting odd effects at the sides. I also make sure that I decrease the colour of pixels as the fire heads upward. You would do this if the fire was going over the top of the rectangle. So now the fire is in full view not obstructed by the edges or top.

Guy


"Who lives in a pineapple under the sea ?"

Share this post


Link to post
Share on other sites
hello Arion:

You have no idea how much I am suffering from this damn fire. My program seems to have more than just one problem in it. But I did create a little fancy funky fire on the very bottom. NOT TO MENTION THE WHOLE LOT OF MESS IN THE REST OF THE PLACE!!! Now, I am just hoping that some experienced god of fire can get my code, look through it and help me out. Are you willing to do that? If so, please give me your e-mail, icq or whatever,i can send my code to you. That will be greatly appreciated!!!!!!!!

Ji

Share this post


Link to post
Share on other sites
finally, I have got my fire going but i don''t know why the height of the fire is very low. Dose anyone have any sugestions?

Share this post


Link to post
Share on other sites
The fire can be low at times. The colour palette may limit how high you fire can go. That''s why I use a 768 custom colour palette.

A solution would be to average less pixels, especially the pixels above the one you are trying to average for.

Try this:

Take Out: (Or rem out)

fire_buffer[fireoffset-640]
fire_buffer[fireoffset-641]
fire_buffer[fireoffset-639]

Then divide by 5.
That should get your fire to be higher because it is not throwing in as many dark pixels into the averaging algo.

Guy


"Who lives in a pineapple under the sea ?"

Share this post


Link to post
Share on other sites
quote:
Original post by Arion
Try this:

Take Out: (Or rem out)

fire_buffer[fireoffset-640]
fire_buffer[fireoffset-641]
fire_buffer[fireoffset-639]

Then divide by 5.

Try to stick with powers of two when you're doing the averaging. That means you can avoid divisions per pixel (yuck!), using >> right bit-shifting instead - your computer will thank you for it, trust me!

As a test, I took some unoptimised code I did a while back and replaced a "shr 2" (it's in Delphi, in case you're wondering) with a "div 5". Now, ignoring the obvious visual difference (smaller fire), it whacked 40 frames per second off (and if I'd optimised it, that would get even larger)!

The compiler is probably smart enough to catch dividing with powers-of-two and turn it into shift code, so you don't even need to do much to get the benefits other than use the right numbers.

[edited by - Alimonster on March 19, 2002 6:44:44 PM]

Share this post


Link to post
Share on other sites
Good point Alimonster.
But it is not always so easy to get the desired effect.
It sometimes takes trial and error.

I guess you could take out
fire_buffer[fireoffset+640]
and divide by four.

If you take too many pixels out,
the fire looses it''s effect.

One thing I did to average three pixels was:

( x + (y<<1) + z ) >>2;
Where y was the pixel under the one I was averaging for.
It turned out pretty good, and fairly fast. That would be
fire_buffer[fireoffset+640] in that algo. The other two would be the ones to the left and right of that pixel.

Guy


"Who lives in a pineapple under the sea ?"

Share this post


Link to post
Share on other sites