Kirjautuminen

Haku

Tehtävät

Opasarkisto: SDL 1.2: Osa 3 - Syötteet

  1. Osa 1 - Perusteet
  2. Osa 2 - Grafiikka
  3. Osa 3 - Syötteet
  4. Osa 4 - Lisäkirjastot

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:

Näppäimistön käsittely

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ä.

Hiiren käsittely

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:

NappiTunnus
Vasen painike1
Keskimmäinen painike (rulla)2
Oikea painike3

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
}

Kopioi esimerkkiohjelma

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.

Loppusanat

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


Kommentit

Gwaur [18.02.2005 19:25:49]

#

Tuolla on muuten virhe. Neljännessä pätkässä tehdään &tapahtuma, mutta kuitenkin haetaan tapahtuman tyyppiä "event.type"

Heikki [03.03.2005 00:31:26]

#

Korjattu.

aWW [13.04.2005 18:39:15]

#

Lukee

SDL_PollEvent();

, vaikka pitäisi lukea SDL_PollEvent( &tapahtuma );

Heikki [15.04.2005 22:47:30]

#

Korjattu.

T.M. [31.07.2005 00:42:27]

#

"täydellinen lista näppäinvakioista" -linkki on rikki, uudempi toimiva:
http://www.libsdl.org/cgi/docwiki.cgi/SDLKey

Heikki [02.08.2005 15:17:32]

#

Korjattu, ottivat vanhan dokumentaation kokonaan pois ja siirtyvät wikiin.

C++Amatööri [16.08.2005 15:22:46]

#

muutama virhe mutta sain toimimaan ja ihmettelen mitä hyötyä tosta on

T.M. [28.10.2005 20:42:07]

#

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.

sqwiik [22.06.2006 16:39:43]

#

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.

Heikki [24.07.2006 07:13:41]

#

Lisäsin maininnan.

Tontsa-san [31.07.2006 21:46:14]

#

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.

Heikki [31.07.2006 23:17:18]

#

#pragma-rivejä ei käytetä opassarjassa ensimmäisen osan esimerkkiä lukuunottamatta, sillä ne toimivat vain Visual C++:n kanssa.

Tontsa-san [01.08.2006 15:51:22]

#

Selvä :)
- Yritin vain auttaa..

Akseli F [04.08.2006 11:20:43]

#

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?

Betaversio [05.08.2006 19:51:46]

#

eikö tuossa esimerkin lopussa pitäisi olla
SDL_Freesurface(tausta);???

Heikki [15.10.2006 11:44:50]

#

Pitäisi. Korjaanpa.

ankzilla [24.09.2009 16:38:26]

#

Ei vittu täähä on ihan mahtavaa! :D
Meikä alkaa peliohjelmoijaksi, ku hoksasin kuinka simppeliä tämä loppujen lopuksi onkin. :D

Wusakko [23.02.2010 14:52:45]

#

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

Kirjoita kommentti

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.

Muista lukea kirjoitusohjeet.
Tietoa sivustosta