/*************************************************************************** * Copyright (C) 2005 by Michal Turek - Woq * * WOQ (zavinac) seznam.cz * * * * Program pomoci primeho pristupu do pameti pixelu surface * * generuje ohen * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ // Algoritmu na ohen je spousta. Zde je pouzito obycejne prumerovani pixelu // smerem od spodu nahoru. Clanek o generovani jednoho z tech lepsich typu // lze najit na http://radek.jinak.cz/tutors/ohen/ohen.html #include <stdio.h> #include <stdlib.h> #include <time.h>// Kvuli srand() #include <SDL.h> /* * Symbolicke konstanty */ #define SDL_SUBSYSTEMS SDL_INIT_VIDEO // NEMEL by byt pouzit hardwarovy surface, protoze by pixely neustale // putovaly ke graficke karte a zpet!!! #define WIN_FLAGS SDL_SWSURFACE|SDL_RESIZABLE #define WIN_WIDTH 320 #define WIN_HEIGHT 120 // S jinou barevnou hloubkou nez 32 bpp tento program nepracuje!!! #define WIN_BPP 32 #define WIN_TITLE "Ohen" // Paleta ohne obsahuje 256 barev #define NUM_COL 256 /* * Globalni promenne */ SDL_Surface *g_screen; // Surface okna SDL_Cursor *g_cursor = NULL; // Kurzor Uint32 g_last_time; // Pro casovac // Paleta ohne (BGR format); hodnoty vygenerovany z obrazku fire_pallete.bmp // pomoci zakomentovaneho kodu v Init(). Obrazek palety lze vytvorit napr. // v grafickem editoru barevnym prechodem od cerne pres cervenou ke // zlute barve. Rucni vytvareni neni zrovna nejlepsi napad ;) Uint8 g_fpal[NUM_COL][3] = { { 0, 0, 0 },{ 0, 0, 3 },{ 0, 0, 5 },{ 0, 0, 8 }, { 1, 1, 11 },{ 1, 1, 15 },{ 1, 1, 18 },{ 2, 1, 22 }, { 2, 2, 27 },{ 2, 2, 31 },{ 3, 2, 35 },{ 3, 3, 40 }, { 4, 3, 45 },{ 3, 4, 50 },{ 4, 4, 55 },{ 4, 5, 59 }, { 4, 5, 65 },{ 5, 5, 70 },{ 5, 5, 75 },{ 6, 6, 80 }, { 6, 6, 85 },{ 6, 6, 90 },{ 7, 7, 95 },{ 7, 7, 100 }, { 8, 8, 105 },{ 8, 8, 110 },{ 8, 8, 115 },{ 8, 9, 119 }, { 9, 9, 124 },{ 9, 9, 128 },{ 10, 10, 133 },{ 10, 10, 138 }, { 10, 10, 143 },{ 11, 11, 148 },{ 11, 11, 153 },{ 11, 11, 158 }, { 11, 12, 163 },{ 12, 12, 168 },{ 13, 13, 173 },{ 13, 13, 178 }, { 13, 13, 184 },{ 13, 13, 188 },{ 14, 14, 193 },{ 14, 14, 198 }, { 17, 19, 238 },{ 17, 20, 238 },{ 17, 21, 238 },{ 16, 23, 239 }, { 16, 25, 239 },{ 17, 27, 239 },{ 16, 29, 239 },{ 16, 31, 239 }, { 16, 33, 239 },{ 16, 35, 240 },{ 15, 37, 239 },{ 15, 40, 240 }, { 15, 42, 240 },{ 15, 45, 240 },{ 15, 47, 240 },{ 14, 50, 241 }, { 15, 53, 241 },{ 14, 55, 241 },{ 14, 58, 241 },{ 14, 61, 242 }, { 13, 64, 242 },{ 13, 67, 242 },{ 13, 70, 242 },{ 13, 72, 242 }, { 12, 75, 243 },{ 12, 78, 243 },{ 12, 81, 243 },{ 12, 84, 243 }, { 12, 87, 244 },{ 11, 90, 244 },{ 11, 94, 244 },{ 11, 96, 244 }, { 11, 99, 244 },{ 10, 102, 245 },{ 10, 105, 245 },{ 10, 108, 245 }, { 10, 110, 245 },{ 9, 113, 246 },{ 9, 116, 246 },{ 9, 119, 246 }, { 9, 122, 246 },{ 9, 124, 247 },{ 8, 127, 246 },{ 8, 129, 247 }, { 8, 132, 247 },{ 8, 135, 247 },{ 8, 137, 247 },{ 7, 140, 248 }, { 7, 143, 248 },{ 7, 146, 248 },{ 7, 149, 249 },{ 6, 152, 249 }, { 6, 155, 249 },{ 6, 158, 249 },{ 6, 161, 249 },{ 6, 164, 250 }, { 5, 167, 250 },{ 5, 170, 250 },{ 5, 173, 250 },{ 5, 176, 250 }, { 4, 178, 251 },{ 4, 181, 251 },{ 4, 185, 251 },{ 4, 187, 251 }, { 4, 190, 251 },{ 3, 193, 252 },{ 3, 196, 252 },{ 3, 198, 252 }, { 3, 201, 253 },{ 3, 204, 252 },{ 2, 206, 253 },{ 2, 209, 253 }, { 2, 211, 253 },{ 2, 214, 253 },{ 1, 216, 254 },{ 1, 218, 254 }, { 1, 220, 254 },{ 1, 223, 254 },{ 1, 224, 254 },{ 1, 226, 255 }, { 1, 228, 254 },{ 0, 229, 254 },{ 0, 231, 255 },{ 0, 233, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 }, { 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 },{ 0, 234, 255 } }; /* * Funkcni prototypy */ bool Init(); // Inicializace void Destroy(); // Deinicializace void Draw(); // Vykresleni bool ProcessEvent(); // Osetruje udalosti int main(int argc, char *argv[]); // Vstup do programu // Zamyka/odemyka surface pro primy pristup k pixelum bool Lock(SDL_Surface *surface); void Unlock(SDL_Surface *surface); /* * Zamyka/odemyka surface */ bool Lock(SDL_Surface *surface) { if(SDL_MUSTLOCK(surface)) { if(SDL_LockSurface(surface) < 0) { return false; } } return true; } void Unlock(SDL_Surface *surface) { if(SDL_MUSTLOCK(surface)) { SDL_UnlockSurface(surface); } } /* * Inicializacni funkce */ bool Init() { // Inicializace generatoru nahodnych cisel srand((unsigned int)time((time_t*)NULL)); // Inicializace SDL if(SDL_Init(SDL_SUBSYSTEMS) == -1) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); return false; } // Vytvori okno s definovanymi vlastnostmi g_screen = SDL_SetVideoMode(WIN_WIDTH, WIN_HEIGHT, WIN_BPP, WIN_FLAGS); if(g_screen == NULL) { fprintf(stderr, "Unable to set %dx%d video: %s\n", WIN_WIDTH, WIN_HEIGHT, SDL_GetError()); return false; } SDL_WM_SetCaption(WIN_TITLE, NULL); // Kurzor mysi /* hvezdicka - cerna, krizek - bila, pomlcka - pruhledna ---**--- -*----*- -------- *--xx--* *--xx--* -------- -*----*- ---**--- */ Uint8 data[] = { 0x18, 0x42, 0x00, 0x81, 0x81, 0x00, 0x42, 0x18 }; Uint8 mask[] = { 0x18, 0x42, 0x00, 0x99, 0x99, 0x00, 0x42, 0x18 }; g_cursor = SDL_CreateCursor(data, mask, 8, 8, 3, 3); SDL_SetCursor(g_cursor); // Generovani "textovych hodnot" palety ohne z obrazku // Zadne chyby nejsou testovany - pouzije se jen jednou... /* SDL_Surface *tmp; tmp = SDL_LoadBMP("fire_pallete.bmp"); FILE* fw; fw = fopen("pal.txt", "w"); Uint8 *col; for(int i = 0; i < NUM_COL; i++) { fprintf(fw, "{ "); col = (Uint8 *)tmp->pixels + (i*tmp->format->BytesPerPixel);// B fprintf(fw, "%3d, ", *col); col = (Uint8 *)tmp->pixels + (i*tmp->format->BytesPerPixel + 1);// G fprintf(fw, "%3d, ", *col); col = (Uint8 *)tmp->pixels + (i*tmp->format->BytesPerPixel + 2);// R fprintf(fw, "%3d ", *col); fprintf(fw, "},"); if(i % 4 == 3) fprintf(fw, "\n"); } fclose(fw); */ return true; } /* * Deinicializacni funkce */ void Destroy() { if(g_cursor != NULL) SDL_FreeCursor(g_cursor); SDL_Quit(); } /* * Vykresleni sceny */ void Draw() { Uint8 *p_pix; // Ukazatel na prave modifikovane pixely int rnd; // Uklada nahodne vygenerovane cislo register int x, line, col; // Cykly int mouse_x, mouse_y; // Pozice mysi if(!Lock(g_screen)) return; // Pokud je stiskle leve mysitko, zacerni ctyri pixely na pozici kurzoru if(SDL_GetMouseState(&mouse_x, &mouse_y) & SDL_BUTTON(1)) { p_pix = (Uint8 *)g_screen->pixels + mouse_y*g_screen->pitch + mouse_x*4; // Test okraju if(mouse_x < g_screen->w - 2 && mouse_y < g_screen->h - 2) { *p_pix = 255; *(p_pix + g_screen->pitch) = 255; p_pix++; *p_pix = 255; *(p_pix + g_screen->pitch) = 255; p_pix++; *p_pix = 255; *(p_pix + g_screen->pitch) = 255; p_pix+=2; *p_pix = 255; *(p_pix + g_screen->pitch) = 255; p_pix++; *p_pix = 255; *(p_pix + g_screen->pitch) = 255; p_pix++; *p_pix = 255; *(p_pix + g_screen->pitch) = 255; } } // Generovani paliva na poslednim radku p_pix = (Uint8 *)g_screen->pixels + (g_screen->h - 1)*g_screen->pitch; for(x = 0; x < g_screen->w; x++) { rnd = rand() % NUM_COL; for(col = 0; col < 3; col++, p_pix++) *p_pix = g_fpal[rnd][col]; p_pix++; } // Horeni (prumerovani pixelu od spoda nahoru) for(line = g_screen->h - 2; line > 0; line--) { // Adresace radku p_pix = (Uint8 *)g_screen->pixels + line*g_screen->pitch; // Okraje se nemusi testovat, protoze pozice bude vzdy ve validni // pameti (posledni radek palivo) for(x = 0; x < g_screen->w; x++) { for(col = 0; col < 3; col++, p_pix++) { *p_pix = (Uint8)((*(p_pix) // Aktualni + *(p_pix + g_screen->pitch) // Spodni + *(p_pix + g_screen->pitch - 4)// Levy + *(p_pix + g_screen->pitch + 4)// pravy ) / 4.07f);// Ne 4, aby nehorel tak vysoko } p_pix++; } } Unlock(g_screen); SDL_Flip(g_screen);// Zobrazeni } /* * Osetreni udalosti * V tomto pripade ceka se na klavesu ESC, ktera ukonci program a reaguje * na zmenu velikosti okna */ bool ProcessEvent() { SDL_Event event; while(SDL_PollEvent(&event)) { switch(event.type) { // Klavesnice case SDL_KEYDOWN: switch(event.key.keysym.sym) { case SDLK_ESCAPE: return false; break; default: break; } break; // Zmena velikosti okna case SDL_VIDEORESIZE: g_screen = SDL_SetVideoMode(event.resize.w, event.resize.h, WIN_BPP, WIN_FLAGS); if(g_screen == NULL) { fprintf(stderr, "Unable to resize window: %s\n", SDL_GetError()); return false; } break; // Pozadavek na ukonceni case SDL_QUIT: return false; break; default: break; } } return true; } /* * Vstup do programu */ int main(int argc, char *argv[]) { printf(WIN_TITLE); printf("\nPress ESC key to quit.\n"); // Inicializace if(!Init()) { Destroy(); return 1; } g_last_time = SDL_GetTicks(); // Hlavni smycka programu bool done = false; while(!done) { done = !ProcessEvent(); Draw(); // Rychlostni optimalizace (hodne provizorni :( Uint32 time = SDL_GetTicks(); if(time-g_last_time < 20) { SDL_Delay(40-(time-g_last_time)); } g_last_time = time; } // Deinicializace a konec Destroy(); return 0; }