Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: SDL: kuvan siirtäminen

Codeprofile [13.07.2007 19:03:56]

#

Seuraavan koodin pitäisi toimia näin: ohjelma tulostaa kuvan kohtaan (1,1). Kun painaa oikeaa nuolinäppäintä, kuva siirtyy yhden pikselin oikealle:

#include <SDL/SDL.h>

void PiirraKuva(SDL_Surface *kuva, SDL_Surface *naytto, int x, int y) {
     SDL_Rect alue;
     alue.x = x;
     alue.y = y;
     SDL_BlitSurface(kuva, NULL, naytto, &alue);
}

void PiirraTausta(SDL_Surface *tausta, SDL_Surface *naytto, int xx, int yy) {
     SDL_Rect rajat;
     rajat.x = xx;
     rajat.y = yy;
     SDL_BlitSurface(tausta, NULL, naytto, &rajat);
}

int main(int argc, char *argv[]) {
    if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
        fprintf(stderr, "SDL:n alustaminen ei onnistunut: %s\n", SDL_GetError());
    }

    SDL_Surface *naytto;
    naytto = SDL_SetVideoMode(1024, 768, 32, SDL_HWSURFACE|SDL_FULLSCREEN|SDL_DOUBLEBUF);

    SDL_Surface *tausta;
    tausta = SDL_LoadBMP("tausta.bmp");
    PiirraTausta(tausta, naytto, 1, 1);
    SDL_Flip(naytto);
    SDL_FreeSurface(tausta);

    SDL_Surface *kuva;
    kuva = SDL_LoadBMP("ukko.bmp");

    bool pois = false;

    while( pois == false ) {
           SDL_Event tapahtuma;

           while( SDL_PollEvent(&tapahtuma) ) {
                  switch( tapahtuma.type ) {
                          case SDL_KEYUP:
                               if ( tapahtuma.key.keysym.sym == SDLK_ESCAPE ) {  }
                          case SDL_KEYDOWN:
                               if ( tapahtuma.key.keysym.sym == SDLK_RIGHT ) {
                                    int xxx = xxx + 1;
                                    PiirraKuva(kuva, naytto, xxx, yyy);
                                    SDL_Flip(naytto);
                               }
                  }
           }
    }

    SDL_FreeSurface(naytto);

    SDL_Quit;
    return 0;
}

Mikä tuossa koodissa on vikana?


EDIT:
Sain tällä toimimaan huonosti:

#include <SDL/SDL.h>

void PiirraTausta(SDL_Surface *tausta, SDL_Surface *naytto, int xx, int yy) {
     SDL_Rect rajat;
     rajat.x = xx;
     rajat.y = yy;
     SDL_BlitSurface(tausta, NULL, naytto, &rajat);
}

void PiirraKuva(SDL_Surface *kuva, SDL_Surface *naytto, int x, int y) {
     SDL_Rect alue;
     alue.x = x;
     alue.y = y;
     SDL_BlitSurface(kuva, NULL, naytto, &alue);
}

int main(int argc, char *argv[]) {
    if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
        fprintf(stderr, "SDL:n alustaminen ei onnistunut: %s\n", SDL_GetError());
    }

    SDL_Surface *naytto;
    naytto = SDL_SetVideoMode(1024, 768, 32, SDL_HWSURFACE|SDL_FULLSCREEN|SDL_DOUBLEBUF);

    SDL_Surface *tausta;
    tausta = SDL_LoadBMP("tausta.bmp");
    PiirraTausta(tausta, naytto, 1, 1);
    SDL_Flip(naytto);

    SDL_Surface *kuva;
    kuva = SDL_LoadBMP("ukko.bmp");

    int ukkox = 1;
    int ukkoy = 1;

    bool pois = false;

    while( pois == false ) {
           SDL_Event tapahtuma;

           while( SDL_PollEvent(&tapahtuma) ) {
                  switch( tapahtuma.type ) {
                          case SDL_KEYUP:
                               if ( tapahtuma.key.keysym.sym == SDLK_RIGHT ) {
                                    int poisx = 0;
                                    int poisy = 0;

                                    PiirraTausta(tausta, naytto, poisx, poisy);
                               }

                               if ( tapahtuma.key.keysym.sym == SDLK_ESCAPE ) {
                                    pois = true;
                               }
                          case SDL_KEYDOWN:
                               if ( tapahtuma.key.keysym.sym == SDLK_RIGHT ) {
                                    ukkox += 1;
                                    ukkoy += 0;
                                    PiirraKuva(kuva, naytto, ukkox, ukkoy);
                                    SDL_Flip(naytto);
                               }
                  }
           }
    }

    SDL_FreeSurface(naytto);

    SDL_Quit;
    return 0;
}

Mitenkäs tuon saisi niin, että kun pitää oikeaa nuolinäppäintä pohjassa, kuva jatkaa siirtymistään eikä liikkuisi vain yhden pykälän edemmäs ja jää paikalleen?

Codeprofile [13.07.2007 20:16:24]

#

Löytyyköhän tuohon mitään kikkaa?

jcd3nton [13.07.2007 20:19:14]

#

Ala liikuta ukkoa keydownissa. Merkkaa ukko liikutettavaksi. Keyupissa taas otat merkin pois. Sitten muualla tarkistat, onko ukko merkattu liikutettavaksi, ja jos on niin liikutat. Vaihtoehtoisesti voit keydownilla ja keyupilla seurata yksittaisen napin tilaa ja taas muualla liikuttaa ukkoa, jos tietyn napin tila on "painettu". Onkohan SDL:ssa keypress?

Edit.
Siis jos tama nyt toimii niinkuin voisi kuvitella, niin keydown ja keyup kertovat kun nappaimen tila muuttuu. Jos painat napin pohjaan, syntyy keydown-eventti, mutta vain kerran (nappihan on painettu pohjaan vain kerran). Voit ottaa tiedon talteen, joten voit pelin tilaa paivittavassa loopissa hyodyntaa tietoa ja liikutella ukkoa, kun tiedetaan etta nappi on pohjassa... Pida pohjassa kuinka pitkaan haluat. Sitten kun paastat ylos niin syntyy keyup-eventti, nappain siis paastettiin nousemaan ylos. Auttoiko ymmartamaan?

Codeprofile [13.07.2007 21:07:12]

#

aaapppuuuaaa. Siis mitä silmukoita laitan ja mihin????????

EDIT: Siis olisiko mahdollista tehä niin että se toimisi mainitsemasi KeyPressedin tavoin?

Olisiko mahdollista tämän kaltainen toteutus:

bool noussut = false;

nappäin on painunut pohjaan:
while( nappäin on painunut pohjaan ) {
        if( näppäin noussut ) {
                noussut = true;
        }
}

jcd3nton [13.07.2007 21:36:32]

#

En tieda onko SDL:ssa keypressia. Veikkaan etta ei ole. Aika nopeestihan tuon varmaan saat tarkistettua. Ja kyseinen silmukka on yleensa peleille ominainen silmukka, jossa pelin tilannetta paivitellaan: syote luetaan, tekoalya kasketaan miettimaan, vihollisten liikkeet paivitetaan, liikkuvien vehkeiden liikeratoja ja sijaintia lasketaan ja paivitellaan, lopulta piirretaan... ko. silmukka sinulla onkin, kannattaisi ehka selkeyden vuoksi ulkoistaa syotteen lukeminen yms. erillisiin metodeihin tai luokkiin. Jarjestys voisi olla esimerkiksi tallainen: 1. Lue syote, 2. Laske uusi sijainti, 3. Piirra.

Pelaajasta voit tehda vaikka oman luokan, jossa on sijainti ja tiedot liikkumisesta. Nappia painettaessa kutsutaan luokan metodia, joka antaa ukolle liikesuunnan ja nopeuden. Pelitilannetta yllapitavassa silmukassa kutsut luokan metodia, joka laskee ukolle uuden sijainnin. Keyupin lauetessa kerrot luokalle, ettei ukkoa enaa tarvitse liikuttaa... Hassun hauskasssa c++-oppaassa oli muistaakseni yksinkertainen esimerkki olioihin liittyen. Jotain junaa kiihdyteltiin. Voisi olla ihan lukemisen arvoinen.

PURKKAVAROITUS. Jos jotain tilapaista viritelmaa olet tekemassa etka halua luokkia sotkea mukaan niin nopeasti saat toiminnallisuutta esim. luomalla muuttujan, jossa on ukon liikesuunta. 0=ei liiketta, 1=ylos, 2=oikealle, jne... Sitten teet silmukan, jossa pelin tilannetta paivitellaan... "if ( suunta == oikealle ) { ukkox++; }". Suosittelen kuitenkin vahvasti luokkien hyodyntamista, hyvin toteutettuna selkeyttavat koodia huomattavasti, helpottaen kasvavan ohjelman hallintaa.

Blaze [13.07.2007 21:43:24]

#

Pelien perusrakennehan siis menee näin:

while(peli_käynnissä) {
  if(nappi_alhaalla) {
    liikuta_ukkoa()
  }
  piirra()
}

Legu [13.07.2007 21:45:06]

#

SDL oppaasta löytyy.

SDL-opas kirjoitti:

Uint8* nappi;
nappi = SDL_GetKeyState(NULL);

if ( nappi[SDLK_LEFT] )
    // vasen nuolinäppäin pohjassa

EDIT: siis tuolla saat sen liikkumaan joka kierroksella sen yhden pikselin verran

Vastaus

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

Tietoa sivustosta