// This is an old FIRE effect from The Demo Effect Collection // Converted from SDL to SDL2 on the 8-May-2024 // Fixed few bugs // Original author: W.P. van Paassen // https://demo-effects.sourceforge.net/ // Functions like TDEC_set_video() and TDEC_init_timer() from "COMMON/tdec.h" are not used // No SDL2 renderer used #include #include #include #define EXE_NAME "TDEC_fire" #define FIRE_HEIGHT 80 // Screen dimension constants #define SCREEN_WIDTH 480 #define SCREEN_HEIGHT 360 static SDL_Color colors[256]; SDL_Surface *paletSurface; void init() { int i; /* create a suitable fire palette, this is crucial for a good effect */ /* black to blue, blue to red, red to yellow, yellow to white */ for (i = 0; i < 32; i++) { /* black to blue, 32 values */ colors[i].r = 0; colors[i].g = 0; colors[i].b = i << 1; /* blue to red, 32 values */ colors[i + 32].r = i << 3; colors[i + 32].g = 0; colors[i + 32].b = 64 - (i << 1); /* red to yellow, 32 values */ colors[i + 64].r = 255; colors[i + 64].g = i << 3; colors[i + 64].b = 0; /* yellow to white, 162 */ colors[i + 96].r = 255; colors[i + 96].g = 255; colors[i + 96].b = i << 2; colors[i + 128].r = 255; colors[i + 128].g = 255; colors[i + 128].b = 64 + (i << 2); colors[i + 160].r = 255; colors[i + 160].g = 255; colors[i + 160].b = 128 + (i << 2); colors[i + 192].r = 255; colors[i + 192].g = 255; colors[i + 192].b = 192 + i; colors[i + 224].r = 255; colors[i + 224].g = 255; colors[i + 224].b = 224 + i; } //SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL, colors, 0, 256); SDL_SetPaletteColors(paletSurface->format->palette, colors, 0, 256); } int process_events( void ) { SDL_Event myEvent; while( SDL_PollEvent( &myEvent ) ) { switch( myEvent.type ) { case SDL_QUIT: // SDL_QUIT technically means pressing window's closing gadget return(1); case SDL_KEYDOWN: if(myEvent.key.keysym.sym==SDLK_ESCAPE) { return(1); } } } return(0); } int main( int argc, char* args[] ) { int x, y, oldtime, newtime, fps; Uint8 *myImage; Uint16 temp; Uint32 color; SDL_Window *myWindow; SDL_Surface *screenSurface; SDL_Rect srect, drect; unsigned int framecount; struct timeval tv; if (argc > 1) { printf("Retro Fire Effect - W.P. van Paassen - 2002\n"); exit(EXIT_SUCCESS); } // Initialize SDL if( SDL_Init( SDL_INIT_VIDEO|SDL_INIT_TIMER) < 0 ) { fprintf(stderr,"%s: SDL could not initialize! SDL_Error: %s\n", EXE_NAME, SDL_GetError() ); exit(EXIT_FAILURE); } // As far as I know, it's not possible to open a palettized window directly // We have to create a window, then create a palettized surface and copy // it's contents to the window surface each frame myWindow = SDL_CreateWindow(EXE_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN ); if(myWindow==NULL) { fprintf(stderr,"%s: Window could not be created! SDL_Error: %s\n", EXE_NAME, SDL_GetError() ); SDL_Quit(); exit(EXIT_FAILURE); } // Get window surface screenSurface=SDL_GetWindowSurface(myWindow); printf("Window surface format name: %s\n",SDL_GetPixelFormatName(screenSurface->format->format)); // Black color color=SDL_MapRGB(screenSurface->format,0x00,0x00,0x00); // Fill the whole surface SDL_FillRect(screenSurface,NULL,color); paletSurface=SDL_CreateRGBSurface(SDL_SWSURFACE,SCREEN_WIDTH,SCREEN_HEIGHT,8,0,0,0,0); // 8 bits mean a palettized surface if(paletSurface==NULL) { fprintf(stderr,"%s: Can't initialize a SDL2 surface!\n",EXE_NAME); SDL_DestroyWindow(myWindow); SDL_Quit(); exit(EXIT_FAILURE); } printf("Palette surface format name: %s\n",SDL_GetPixelFormatName(paletSurface->format->format)); printf("Number of palette colors: %d\n",paletSurface->format->palette->ncolors); // Black color color=SDL_MapRGB(paletSurface->format,0x00,0x00,0x00); // Fill the whole surface SDL_FillRect(paletSurface,NULL,color); init(); printf("Palette surface lock: "); if(SDL_MUSTLOCK(paletSurface)) { printf("needed\n"); SDL_LockSurface(paletSurface); } else { printf("not needed\n"); } fps=-2; framecount=0; for(;;) { if(process_events()) { break; } /* draw random bottom line in fire array */ myImage = (Uint8*)(paletSurface->pixels) + (paletSurface->pitch * (SCREEN_HEIGHT-1)); for (x = 0; x < SCREEN_WIDTH - 1; x++) { // Stores either 0 or 255 into the paletSurface // Note the probability of maximum heat is slightly lower than the probability of no heat // If you change the default value (8), the effect doesn't look this good if((rand()%16) > 8) *myImage = 255; /* maximum heat */ else *myImage = 0; myImage++; } /* move fire upwards, start at bottom */ myImage = (Uint8*)(paletSurface->pixels) + (paletSurface->pitch * (SCREEN_HEIGHT-1)); for (y = 0; y < FIRE_HEIGHT ; y++) { for (x = 0; x < SCREEN_WIDTH ; x++) { if (x == 0) /* at the left border */ { temp = *myImage; temp += *(myImage + 1); temp += *(myImage - SCREEN_WIDTH); temp /= 3; } else if (x == (SCREEN_WIDTH - 1)) /* at the right border */ { temp = *(myImage + x); temp += *(myImage - SCREEN_WIDTH + x); temp += *(myImage + x - 1); temp /= 3; } else { temp = *(myImage + x); temp += *(myImage + x + 1); temp += *(myImage + x - 1); temp += *(myImage - SCREEN_WIDTH + x); temp >>= 2; } if (temp > 1) temp -= 1; /* decay */ *(myImage - SCREEN_WIDTH + x) = temp; } myImage -= SCREEN_WIDTH; } // Copy the entire surface //SDL_BlitSurface(paletSurface,NULL,screenSurface,NULL); srect.x=0; srect.y=SCREEN_HEIGHT-FIRE_HEIGHT-1; srect.w=SCREEN_WIDTH; srect.h=FIRE_HEIGHT-2; drect.x=0; drect.y=SCREEN_HEIGHT-FIRE_HEIGHT+2; // The original author doesn't display 2 bottom lines drect.w=SCREEN_WIDTH; drect.h=FIRE_HEIGHT-2; SDL_BlitSurface(paletSurface,&srect,screenSurface,&drect); SDL_UpdateWindowSurface(myWindow); SDL_Delay(20); framecount++; gettimeofday(&tv,NULL); newtime=tv.tv_usec; if(oldtime>newtime) { if(fps==-2) { fps=-1; framecount=0; } else { fps=framecount; framecount=0; printf("FPS: %d\n",fps); } } oldtime=newtime; } if(SDL_MUSTLOCK(paletSurface)) { SDL_UnlockSurface(paletSurface); } SDL_FreeSurface(paletSurface); // Destroy window SDL_DestroyWindow(myWindow); // Quit SDL subsystems SDL_Quit(); exit(EXIT_SUCCESS); }