Yksinkertainen sulatusefekti. Perustuu tuliefektin blur filtteriin. Sisällytin tähän kaksi efektin versiota. Toisessa sulatus on jatkuvaa ja toisessa se tapahtuu vain kerran.
tarvitsee SDL -kirjastot.
Linkki valmiiseen exeen molemmista efekteistä: http://koti.mbnet.fi/peku1/melter.zip
#include "SDL.h" #include <stdlib.h> enum { SCREENWIDTH = 640, SCREENHEIGHT = 480, SCREENBPP = 32, SCREENFLAGS = SDL_ANYFORMAT }; SDL_Surface* pkuva; Uint32 buffer[SCREENWIDTH][SCREENHEIGHT]; // puskuri 1 Uint32 buffer2[SCREENWIDTH][SCREENHEIGHT]; // puskuri 2 /* * Pikseli kohdasta x ja y */ Uint32 _fastcall getpixel(SDL_Surface *surface, int x, int y) { int bpp = surface->format->BytesPerPixel; /* Here p is the address to the pixel we want to retrieve */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; switch(bpp) { case 1: return *p; case 2: return *(Uint16 *)p; case 3: if(SDL_BYTEORDER == SDL_BIG_ENDIAN) return p[0] << 16 | p[1] << 8 | p[2]; else return p[0] | p[1] << 8 | p[2] << 16; case 4: return *(Uint32 *)p; default: return 0; /* shouldn't happen, but avoids warnings */ } } void DrawScene(SDL_Surface* surface, SDL_Event* event) { // Lukitse pinta, jotta voimme käsitellä pikseleitä suoraan if ( SDL_MUSTLOCK(surface) ) { if ( SDL_LockSurface(surface) < 0 ) { fprintf(stderr, "Can't lock the screen: %s\n", SDL_GetError()); return; } } // KOMMENTOI TÄMÄ, JOS HALUAT KOKEILLA Melter2:N KÄÄNTÖÄ // haetaan 10 pikselin pituisia viivoja kuvasta 600 kappaletta for (int i=0; i<600; i++) { int xrand, yrand; xrand = rand() % (SCREENWIDTH - 10); yrand = rand() % (SCREENHEIGHT - 1); for (int x=0; x<10; x++) { buffer[xrand + x][yrand] = getpixel(pkuva, xrand + x, yrand); } } Uint32 c1, c2, c3, c4; unsigned int cfr, cfg, cfb; int siirto; // käydään koko ruutu läpi for (int x=1;x<SCREENWIDTH-1;x++) { siirto = (int)rand() % 6; for (int y=1;y<SCREENHEIGHT-siirto;y++) { // ympäröivien pikselien keskiarvo c1 = buffer[x+1][y]; c2 = buffer[x-1][y]; c3 = buffer[x][y+1]; c4 = buffer[x][y-1]; // funktiot, jotka ottavat jokaisen komponentin värin keskiarvon cfr = (((c1 >> 16) & 0xff) + ((c2 >> 16) & 0xff) + ((c3 >> 16) & 0xff) + ((c4 >> 16) & 0xff)) / 4; cfg = (((c1 >> 8) & 0xff) + ((c2 >> 8) & 0xff) + ((c3 >> 8) & 0xff) + ((c4 >> 8) & 0xff)) / 4; cfb = ((c1 & 0xff) + (c2 & 0xff) + (c3 & 0xff) + (c4 & 0xff)) / 4; // kootaan taas yhteen buffer2[x][y+siirto] = cfr << 16 | cfg << 8 | cfb; } } // piirretään ruudulle for (int x=1;x<SCREENWIDTH-1;x++) for (int y=1;y<SCREENHEIGHT-1;y++) { // pointteri oikeaan pikseliin Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 4; // 4 * 8 = 32(tavut->bitit) // pikseli ruudulle *(Uint32 *)p = buffer2[x][y]; // vaihdetaan bufferit buffer[x][y] = buffer2[x][y]; } // poistetaan lukitus if ( SDL_MUSTLOCK(surface) ) { SDL_UnlockSurface(surface); } //päivitä pinta SDL_UpdateRect(surface, 0, 0, 0, 0); } int main(int argc, char* argv[]) { //initialize systems SDL_Init(SDL_INIT_VIDEO); //set our at exit function atexit(SDL_Quit); //create a window SDL_Surface* pSurface = SDL_SetVideoMode ( SCREENWIDTH, SCREENHEIGHT, SCREENBPP, SCREENFLAGS ); pkuva = SDL_LoadBMP("kuva.bmp"); // OTA TÄMÄ POIS KOMMENTEISTA, JOS HALUAT KOKEILLA Melter2:STA /*for (int x=0;x<=SCREENWIDTH-1;x++) for (int y=0;y<=SCREENHEIGHT-1;y++) buffer[x][y] = getpixel(pkuva, x, y);*/ // normi sdl-looppi SDL_Event event; for (;;) { if ( SDL_PollEvent ( &event ) ) { if ( event.type == SDL_QUIT ) break; } DrawScene(pSurface, &event); } // vapautellaan SDL_FreeSurface(pSurface); SDL_FreeSurface(pkuva); return(0); }
Ihan hieno efekti.
// haetaan 10 pikselin pituisia viivoja kuvasta 400 kappaletta for (int i=0; i<400; i++) { for (int x=0; x<10; x++) { int xrand, yrand; xrand = rand() % (SCREENWIDTH - 10) + x; yrand = rand() % (SCREENHEIGHT - 1); buffer[xrand][yrand] = getpixel(pkuva, xrand, yrand); } }
Tuossa on kuitenkin joko kommentissa tai koodissa vikaa. Pisteet ei takuulla osu samalle viivalle, jos kutsut jokaiselle pisteelle uudelleen rand() funkiota :)
Olenpas ollut ajattelematon!
Korjaan tuon heti!
Edit: Sekä koodi, että binaari on nyt päivitetty
Ihan hieno.
Koska (SCREENWIDTH - 1) on nähdäkseni reunimmainen pikseli, pitäisi siinä "// käydään koko ruutu läpi" -kohdassa varmaankin olla (SCREENWIDTH - 2).
for (int x = 1; x <= SCREENWIDTH - 1; x++)
=>
for (int x = 1; x <= SCREENWIDTH - 2; x++)
=> Vielä helpompi näin kokonaisluvuilla mutta täysin samoin toimiva
for (int x = 1; x < SCREENWIDTH - 1; x++)
Lisäksi kriittinen huomautus koodin ulkoasusta: Noihin looppeihin voisi jättää välejä, niinkuin minulla tuossa yllä; OnHyvinVaivalloistaLukeaNoitaPutkeenKirjoitettujaLooppejaKutenEsimerkiksi "for (int x=1;x<=SCREENWIDTH-1;x++)" :D
eniten kyllä huolestuttaa toi kuvan koira, jonka päähän on tungettu laskettelulasit (mitä luultavammin ilman lupaa!) pipokin sillä on.
Hihii, tuo koira on söpö nuo lasit päässä ^^
Hieno efekti. Pitää mun varmaankin vaihtaa vb c++:ssaan jos sillä tollasta saa aikaan.
Wanha kuva :D Hieno efekti.
Se vinee Dll-tiedoston puuttmisesta... (MSVCR70)
http://www.dll-files.com täältä saat :)
Tuo on kyllä ihan perus dll-tiedostoja, jotka kannattaa hankkia. Yleensä ne laitetaan mukaan pakettiin isommissa ohjelmissa, mutta jätin tuon pois tilan säästämiseksi.
Aihe on jo aika vanha, joten et voi enää vastata siihen.