Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: C++: Sulatusefekti

Sivun loppuun

peki [21.08.2004 10:41:06]

#

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);
}

FooBat [21.08.2004 21:15:42]

#

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 :)

peki [21.08.2004 21:48:44]

#

Olenpas ollut ajattelematon!
Korjaan tuon heti!
Edit: Sekä koodi, että binaari on nyt päivitetty

Metabolix [21.08.2004 23:22:08]

#

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ä; OnHy­vin­Vaival­lois­ta­Lukea­Noita­Putkeen­Kirjoi­tet­tu­ja­Loop­pe­ja­Kuten­Esimer­kiksi "for (int x=1;x<=SCREENWIDTH-1;x++)" :D

ruuvari [22.08.2004 00:35:13]

#

eniten kyllä huolestuttaa toi kuvan koira, jonka päähän on tungettu laskettelulasit (mitä luultavammin ilman lupaa!) pipokin sillä on.

Blaze [22.08.2004 01:31:51]

#

Hihii, tuo koira on söpö nuo lasit päässä ^^

tuomas [22.08.2004 10:30:15]

#

Hieno efekti. Pitää mun varmaankin vaihtaa vb c++:ssaan jos sillä tollasta saa aikaan.

sooda [22.08.2004 10:31:50]

#

Wanha kuva :D Hieno efekti.

FrozenFire [17.12.2004 06:38:31]

#

Se vinee Dll-tiedoston puuttmisesta... (MSVCR70)

peki [10.01.2005 20:06:09]

#

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.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta