Kirjoittaja: Heikki (2004).
⚠ Huomio! Tämä opas on vanhentunut. Oppaan sisältöön ei voi enää luottaa. Opas on säilytetty vain sen historiallisen arvon vuoksi. ⚠
Tässä vaiheessa hallitset SDL:stä grafiikan piirtämisen perusteet. SDL on kuitenkin muutakin kuin pelkkä grafiikkakirjasto, ja tässä osassa tutustumme erääseen tärkeään osa-alueeseen: syötteiden lukemiseen näppäimistöltä ja hiireltä!
Lähes kaikissa ohjelmissa käyttäjältä luetaan erilaisia syötteitä, joiden perusteella esim. liikutaan valikoissa tai liikutetaan pelihahmoa. Yleisimmät keinot lukea syötteitä ovat näppäimistön ja hiiren lukeminen. Tutustutaan ensin näppäimistöön:
Ennen kuin näppäinten tila voidaan lukea, meidän on luettava tapahtumat:
SDL_PumpEvents();
Tämän jälkeen alhaalla olevat näppäimet haetaan seuraavalla funktiolla
Uint8* nappi; nappi = SDL_GetKeyState(NULL);
Tämän jälkeen voit tarkistaa yksittäisen näppäimen tilan näin:
if ( nappi[SDLK_LEFT] ) // vasen nuolinäppäin pohjassa
SDLK_LEFT
on vasemman nuolinäppäimen tunnus. Katsos täydellinen lista näppäinvakioista.
Näppäimen painumista pohjaan tai nousemista voidaan tarkastella myös tähän tapaan käsittelemällä tapahtumia:
SDL_Event tapahtuma; while( SDL_PollEvent( &tapahtuma ) ){ // niin kauan kun on tapahtumia käsittelemättä switch( tapahtuma.type ){ // tapahtuman tyyppi case SDL_KEYUP: // näppäin noussut // näppäin, jonka tunnus on &event.key nousi case SDL_KEYDOWN: // näppäin, jonka tunnus on &event.key painui pohjaan } }
event.key
on siis tapahtuman kohteena oleva näppäin. Tunnukset löytyvät aiemmin mainitsemastani linkistä.
SDL:ssä on, yllätys yllätys, myös hiiren käsittelyyn yksinkertaiset funktiot.
Kursorin sijainnin saat selville yksinkertaisesti näin:
int x, y; //hiiren koordinaatit SDL_GetMouseState(&x, &y);
Funktiolle SDL_GetMouseState annetaan siis parametreina viittaukset muuttujiin, joihin kursorin koordinaatit tallennetaan.
Jos haluat tietää, onko joku tietty hiiren nappi pohjassa, saat sen selville seuraavan esimerkin tapaan:
int napit, x, y; napit=SDL_GetMouseState(&x, &y); if(napit & SDL_BUTTON(1)) { //hiiren ykkösnappi pohjassa }
Eli käytämme bittioperaattoria & (AND) SDL_BUTTON:in ja SDL_GetMouseState():n paluuarvon välillä. Vertailu on tosi, jos SDL_BUTTON:in parametrina oleva hiiren nappi on pohjassa.
SDL_BUTTON:in parametrit:
Nappi | Tunnus |
---|---|
Vasen painike | 1 |
Keskimmäinen painike (rulla) | 2 |
Oikea painike | 3 |
Sitten loppuun vielä koodivinkki, jossa käytämme kaikkia tähän mennessä oppimiamme asioita:
#include <SDL/SDL.h> // sisällytetään SDL:n otsikkotiedostot void PiirraKuva(SDL_Surface *kuva, SDL_Surface *naytto, int x, int y); // aliohjelma, joka piirtää kuvan int main(int argc, char *argv[]) { /******************************************** * alustetaan SDL:n video-ominaisuudet. ********************************************/ if( SDL_Init(SDL_INIT_VIDEO) < 0 ) // jos paluuarvo on pienempi kuin 0, tapahtui virhe { fprintf(stderr, "SDL:n alustus ei onnistunut: %s\n", SDL_GetError()); //virheestä tiedot tiedostoon SDL_Quit(); return 0; // lopetetaan ohjelma } // vaihdetaan ikkunan nimi (näkyy tehtäväpalkissa) SDL_WM_SetCaption("SDL-ohjelma", NULL); // SDL on nyt alustettu virheettömästi. /********************************************* * muut valmistelut *********************************************/ SDL_Surface * naytto; // näkyvä pinta SDL_Surface * kuva; // pinta laatikolle SDL_Surface * tausta; // pinta taustalle // vaihdetaan resoluutio naytto = SDL_SetVideoMode(1024, 768, 32, SDL_HWSURFACE|SDL_FULLSCREEN|SDL_DOUBLEBUF); // ladataan bittikartat kuva = SDL_LoadBMP("loota.bmp"); tausta = SDL_LoadBMP("tausta.bmp"); int lootax=200; int lootay=200; // laatikon koordinaatit Uint8* nappi; // näppäimet SDL_Event tapahtuma; // tapahtumat int hiiri,x,y; // hiiren tila bool pois=false; /********************************************* * pääsilmukka *********************************************/ while(pois==false) { // poistutaanko while( SDL_PollEvent(&tapahtuma) ) { if ( tapahtuma.type == SDL_QUIT ) { pois = true; } //poistumistapahtuma if ( tapahtuma.type == SDL_KEYDOWN ) { if ( tapahtuma.key.keysym.sym == SDLK_ESCAPE ) { pois = true; } // näinkin voi lukea näppäimiä } } // liikutetaan laatikkoa nappi = SDL_GetKeyState(NULL); if ( nappi[SDLK_UP] ) { lootay -= 1; } if ( nappi[SDLK_DOWN] ) { lootay += 1; } if ( nappi[SDLK_LEFT] ) { lootax -= 1; } if ( nappi[SDLK_RIGHT] ) { lootax += 1; } hiiri = SDL_GetMouseState(&x,&y); // luetaan nappien tila if(hiiri & SDL_BUTTON(1)) // ykkösnappi pohjassa pois = true; PiirraKuva(tausta, naytto, 0, 0); // piirretään tausta PiirraKuva(kuva, naytto, lootax,lootay); // piirretään laatikko // nyt kuva on piirretty, mutta koska käytämme kaksoispuskurointia, kuva ei näy vielä // siksi tarvitsemme SDL_Flip()-funktiota SDL_Flip(naytto); } // Vapautetaan kuvalle varattu muisti SDL_FreeSurface(kuva); SDL_FreeSurface(tausta); SDL_Quit(); // "suljetaan" SDL return 0; } /********************************** * Aliohjelma bittikartan piirtämiseen * Parametreina osoitin kuvan pintaan (lähteeseen), osoitin näyttöpintaan (kohteeseen) sekä koordinaatit, mihin * kohtaan kohdepintaa kuva piirretään **********************************/ void PiirraKuva(SDL_Surface *kuva, SDL_Surface *naytto, int x, int y) { if ( kuva == NULL ) { fprintf(stderr, "Kuvannäyttö ei onnistunu: %s\n", SDL_GetError()); return; } // mihin näytöllä SDL_Rect alue; alue.x = x; alue.y = y; // näytölle SDL_BlitSurface(kuva, NULL, naytto, &alue); // koska toinen parametri on NULL, piirretään koko kuva }
Rivillä 17 havaitset yhden uuden asia, jota emme ole vielä käsitelleet: ikkunan nimen vaihtaminen. Jos tätä riviä ei ole, ikkunan nimenä esim. tehtäväpalkissa näkyy SDL_app.
Rivillä 53 luetaan tapahtumat ja katsotaan onko esciä painettu viime tapahtumien lukemisen jälkeen (eli esc ei välttämättä ole edes pohjassa enään). Tapahtumien käsittelystä löytyy lisätietoja dokumentaatiosta.
Olet nyt edennyt melko pitkälle SDL:n maailmassa. Vielä on kuitenkin paljon asioita käsittelemättä. Opassarjan viimeisessä osassa pureudumme SDL:n lisäkirjastoiden käyttöön.
Viimeisin muokkaus 15.10.2006
Tuolla on muuten virhe. Neljännessä pätkässä tehdään &tapahtuma, mutta kuitenkin haetaan tapahtuman tyyppiä "event.type"
Korjattu.
Lukee
SDL_PollEvent();
, vaikka pitäisi lukea SDL_PollEvent( &tapahtuma );
Korjattu.
"täydellinen lista näppäinvakioista" -linkki on rikki, uudempi toimiva:
http://www.libsdl.org/cgi/docwiki.cgi/SDLKey
Korjattu, ottivat vanhan dokumentaation kokonaan pois ja siirtyvät wikiin.
muutama virhe mutta sain toimimaan ja ihmettelen mitä hyötyä tosta on
Huomasin sellaisen pikku jipon että nuo nappi[SDLK_t] ym jutut voidaan esittää myös näin: nappi[116], eli 116 on merkin "t" ascii arvo.
Tuossa voisi vielä mainita, että mikäli käyttää näppäimien lukemiseen pelkästään tuota SDL_GetKeyState:a, niin pitää kutsua jatkuvasti SDL_PumpEvents()-aliohjelmaa koska muuten mikään inputti ei pääse perille asti... SDL_PollEvent yms. sisältävät kutsun tähän aliohjlemaan, mutta mikäli niitä ei käytä niin syötejono jumittaa.
Lisäsin maininnan.
Tohon koodivinkkiin vois laittaa alkuun kyllä nämä:
#pragma comment(lib, "SDLmain.lib")
#pragma comment(lib, "SDL.lib")
Itselläni heitti erroria sen takia, tajusin kyllä laittaa ne mutta tulevaisuuden varalle ne voisivat olla hyviä myös tuossa. Kiitos hyvästä oppaasta.
#pragma-rivejä ei käytetä opassarjassa ensimmäisen osan esimerkkiä lukuunottamatta, sillä ne toimivat vain Visual C++:n kanssa.
Selvä :)
- Yritin vain auttaa..
Mulla ainakin tota esimekrin lootaa liikutettaessa se edellisessäkin kuvassa ollut boxi jää näkyviin, ja hetken liikuttelun jälkeen ruutu on täynnä niitä boxeja. Miten saisin ne jotenkin pois? Veikkaisin että ruutu pitäisi tyhjentää välissä mutta miten?
eikö tuossa esimerkin lopussa pitäisi olla
SDL_Freesurface(tausta);???
Pitäisi. Korjaanpa.
Ei vittu täähä on ihan mahtavaa! :D
Meikä alkaa peliohjelmoijaksi, ku hoksasin kuinka simppeliä tämä loppujen lopuksi onkin. :D
SDL_WM_SetCaption("SDL-ohjelma", NULL);
Tolla saa vaihdettua nimeä, mutta kuinka sen yläpalkin saa kokonaan pois? (En nimittäin ite saa ainakaa siitä ruksista sammutettua ohjelmaan...)
Huomio! Kommentoi tässä ainoastaan tämän oppaan hyviä ja huonoja puolia. Älä kirjoita muita kysymyksiä tähän. Jos koodisi ei toimi tai tarvitset muuten vain apua ohjelmoinnissa, lähetä viesti keskusteluun.