Hein Pragt Heinpragt.com
© Hein Pragt ( FacebookLinkedin  )

  Taalfoutje melden! 

Waardeer deze site:
 
 

Broncode van vuur effect in C
© 2010 Hein Pragt

vuur Een heel leuk grafisch effect dat u vaak tegenkomt in demo's is gegenereerd vuur. Ik zal in het kort proberen uit te leggen hoe we vuur kunnen maken. Eerst hebben we een kleurenpalet nodig dat van donkerblauw naar donkerrood overloopt en dan van rood naar geel en daarna van geel naar wit. Dit zijn de kleuren waar het vuur uit gaat bestaan. We hebben 255 kleuren en 0 is het meest donker en 255 is het meest licht. We maken een scherm buffer en die vullen we eerst met alleen maar 0. We zetten onder in de laatste regel om de beurt 255 of 0 met een random functie. Daarna gaan we het scherm omhoog scrollen waarbij we van een punt het gemiddelde kleurwaarde nemen met de omliggende punten. Dit zetten we als kleurwaarde in het nieuw pixel en dit blijven we herhalen. De pixels op hogere lijnen zullen dus steeds meer gedempt gaan worden en aangezien ons kleurenpalet mooi de kleuren van vuur bevat zal het een redelijk realistisch beeld van vuur opleveren. Aangezien we met een loop de informatie punt voor punt op het scherm kopiëren blinkt deze routine niet uit in snelheid en is wel een redelijk zware machine nodig om een goed resultaat te zien.

Omdat het om vrij universele code gaat heb ik de Windows Win32 interface zo minimaal mogelijk gemaakt, dit is trouwens altijd mijn voorkeur om programma’s zo portable mogelijk te maken en niet te afhankelijk te zijn van het besturingssysteem.


// ------------------------------------
// Win32 Demo  Fire
// (c) 2010 Hein Pragt
// Standard GDI is realy too slow!
// ------------------------------------

#include <windows.h>
#include <windowsx.h>
#include <stdlib.h>

// Interface to windows
void PlotPixel(int x, int y, DWORD c);

// -------------------------------------------------------------
// This is our demo code
// -------------------------------------------------------------

#define SCREEN_WIDTH 240
#define SCREEN_HEIGHT 180

static COLORREF colors[256];
static unsigned char fire[SCREEN_WIDTH][SCREEN_HEIGHT];

int   sWidth, sHeight; 
DWORD nStartTime; 

void Init(int WinWidth, int WinHeight);
void GameLoop(void);
void ProcFire(void);



// ---------------------------------------
// Call this before at init of the app
// ---------------------------------------

void Init(int WinWidth, int WinHeight) 
{ 
int i;

  sWidth = WinWidth;
  sHeight = WinHeight; 

  /* 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] = RGB(0,0,i << 1);

    /* blue to red, 32 values*/
    colors[i + 32] = RGB(i << 3,0,64 - (i << 1));

    /*red to yellow, 32 values*/
    colors[i + 64] = RGB(255,i << 3,0);

    /* yellow to white, 162 */
    colors[i + 96] = RGB(255,255,i << 2);
    colors[i + 128] = RGB(255,255,64 + (i << 2));
    colors[i + 160] = RGB(255,255,128 + (i << 2));
    colors[i + 192] = RGB(255,255,192 + i);
    colors[i + 224] = RGB(255,255,224 + i);
  } 
  nStartTime = GetTickCount(); // Init timer
  memset(fire,0,sHeight * sWidth);
} 

// ---------------------------------------
// Call this to keep the engine running
// ---------------------------------------

void GameLoop()
{
  if ((GetTickCount() - nStartTime) < 10) {
    Sleep(1);
    return; // Wait for next frame
  }
  nStartTime = GetTickCount(); 
  ProcFire();
}

// ---------------------------------------
// Call this to keep the engine running
// ---------------------------------------

void ProcFire()
{
int x,y,v;
unsigned char *src;

  for (y=sHeight - 140; y<sHeight; y++) {
    for (x=1; x<sWidth-1; x++) {
      fire[x][y-1] = (fire[x][y] + fire[x][y-1]-1 + fire[x][y+1]) / 3;
    }
  }
  v = 255;
  for (x=1; x<sWidth-1; x++) { 
    int random = rand() % 14;
    if (random > 10) 
    if (v == 0) v = 255; else v = 0;	 
    fire[x][sHeight-1] = v; 
  }
  // Copy to screen
  src = &fire[0];
  for (x=0; x<sWidth; x++) {
    for (y=0; y<sHeight; y++) {
      PlotPixel(x,y, colors[*src++]);
    }
  }
}




// ---------------------------------------------
// The minimal Window interface code
// ---------------------------------------------

#define WIN_CLASS_NAME "MyGraphClass" 

HDC hMainDC; 
HINSTANCE hInstance; 
HWND hWnd; 

int WinWidth = SCREEN_WIDTH;
int WinHeight = SCREEN_HEIGHT; 

LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); 


int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) 
{ 
WNDCLASSEX winclass;
HWND hwnd;
MSG msg;

  winclass.cbSize = sizeof(WNDCLASSEX); 
  winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; 
  winclass.lpfnWndProc = WindowProc; 
  winclass.cbClsExtra = 0; 
  winclass.cbWndExtra = 0; 
  winclass.hInstance = hinstance;  
  winclass.hIcon = LoadIcon(NULL, IDI_WINLOGO); 
  winclass.hCursor = LoadCursor(NULL, IDC_ARROW); 
  winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 
  winclass.lpszMenuName = NULL; // no menu 
  winclass.lpszClassName = (LPCWSTR) WIN_CLASS_NAME; 
  winclass.hIconSm = LoadIcon(NULL, IDI_WINLOGO); 

  if (!RegisterClassEx(&winclass)) 
    return(0); 

  if (!(hwnd = CreateWindowEx(NULL,  
    WIN_CLASS_NAME, // class identifier 
    TEXT("Demo"), // window title 
    WS_OVERLAPPEDWINDOW | WS_VISIBLE, // parameters 
    CW_USEDEFAULT, CW_USEDEFAULT, // initial position 
    WinWidth, WinHeight, // Window size 
    NULL, // handle to parent
    NULL, // handle to menu 
    hinstance, // app handle 
    NULL)))
    return(0); 

  // Copy to globals 
  hWnd = hwnd; 
  hInstance = hinstance; 
  hMainDC = GetDC(hWnd); 

  Init(WinWidth, WinHeight); 

  while(TRUE) { 
    if (PeekMessage(&msg,0,0,0,PM_REMOVE)) { 
      if (msg.message == WM_QUIT) // exit loop on quit 
        break; 
      TranslateMessage(&msg); 
      DispatchMessage(&msg); 
    } 
    GameLoop(); // keep animation running
  } 
  ReleaseDC(hWnd, hMainDC); 
  return(msg.wParam); 
} 

// ---------------------------------------------
// The minimal Window message handler
// ---------------------------------------------

LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg,WPARAM wparam, LPARAM lparam) 
{ 
  switch(msg) { 
  case WM_DESTROY: 
    PostQuitMessage(0); 
    return(0); 
    break; 
  case WM_CLOSE: 
    break; 
  } 
  return(DefWindowProc(hwnd, msg, wparam, lparam)); 
} 

// ---------------------------------------------
// The plot pixel function
// ---------------------------------------------

void PlotPixel(int x, int y, DWORD c)
{
  SetPixel(hMainDC, x, y, c);
}




Last update: 09-04-2010




Disclaimer.

Hoewel de heer Hein Pragt de informatie beschikbaar op deze pagina met grote zorg samenstelt, sluit de heer Pragt alle aansprakelijkheid uit met betrekking tot de informatie die, in welke vorm dan ook, via zijn site wordt aangeboden. Het opnemen van een afbeelding of verwijzing is uitsluitend bedoeld als een mogelijke bron van informatie voor de bezoeker en mag op generlei wijze als instemming, goedkeuring of afkeuring worden uitgelegd, noch kunnen daaraan rechten worden ontleend.
Op de artikelen van de heer Pragt op deze Internet Site rust auteursrecht. Overname van informatie (tekst en afbeeldingen) is uitsluitend toegestaan na voorafgaande schriftelijke toestemming van de rechthebbende. Voor vragen over copyright en het gebruik van de informatie op deze site kunt u contact opnemen met: (email: copyright@heinpragt.com)

Webdesign: © Hein Pragt
Fotografie: © Hein Pragt
Auteur: © Hein Pragt (Veenendaal - Utrecht - Nederland)

Privacy beleid

Wij maken gebruik van externe advertentiebedrijven om advertenties weer te geven wanneer u onze website bezoekt. Deze bedrijven gebruiken mogelijk informatie (niet uw naam, adres, e-mailadres of telefoonnummer) over uw bezoek aan deze of aan andere websites om advertenties weer te geven over goederen en services waarin u wellicht geïnteresseerd bent. Als u hierover meer informatie wenst of als u wilt voorkomen dat deze bedrijven deze informatie gebruiken, klikt u op deze link.