SuomiGameHUB

Maailma tarvitsee pelejä

C++/SDL2-pelimoottorin valmistaminen kuvien näyttämiseen

Jatketaan tässä oppaassa eteenpäin SDL2-pelimoottorin kehitystä. Seuraavana vuorossa on kuva lataaminen ikkunaan, mutta se vaatii hieman valmisteluja.

Säädetäänpä aluksi ikkunan avautumispaikkaa lisäämällä sen sijainnin määrittelyihin X- ja Y-koordinaatteja. Esimerkiksi lisäämällä 50 pikseliä sekä X- että Y-koordinaatteihin voimme saada ikkunan avautumaan keskeisemmälle paikalle ruudulla.

Lisäksi on huomioitava ohjelman sulkeutumisen jälkeen jäävä debug-konsoli. Kehitysympäristön asetuksista löytyy toiminto, joka sulkee automaattisesti debug-konsolin, kun ohjelman suoritus päättyy. Tämä asetus löytyy yleensä kohdasta Tools -> Options -> Debugging -> General, ja sieltä valitsemalla “Automatically close the console when debugging stops”.

SDL2-kirjasto mahdollistaa kuvatiedostojen lataamisen ja näyttämisen pelissä käyttämällä SDL_Surface-rakennetta. Tämän toiminnallisuuden hyödyntämiseen tarvitsemme ensin ladattavan kuvan. Kuvan voi sijoittaa projektin kansioon, mistä se on helppo ladata ohjelmaan. Kuvan lataamiseen käytetään SDL:n IMG_Load-funktiota, joka vaatii kuvatiedoston polun. On tärkeää varmistaa, että kuvatiedosto on tuettua muotoa, esimerkiksi PNG, ja että se sijaitsee oikeassa hakemistossa.

Jos IMG_Load-funktio antaa virheilmoituksen identifier is undefined, se tarkoittaa, että SDL_image-kirjastoa ei ole vielä linkitetty projektiin. SDL_image on lisäkirjasto, joka tarjoaa laajennetun tuen kuvatiedostojen käsittelyyn SDL:n kanssa. Tämän kirjaston voi ladata SDL:n virallisilta verkkosivuilta ja lisätä projektiin sisällyttämällä tarvittavat header-tiedostot ja linkittämällä kirjaston binääritiedostot.

SDL_image-kirjaston lisäämisen jälkeen on tärkeää päivittää projektin asetuksia, jotta kehitysympäristö tunnistaa uudet kirjastot. Tämä sisältää include- ja library-hakemistojen päivittämisen sekä SDL2_image.lib-lisäriippuvuuden määrittelyn linkkerille. Kun nämä asetukset on määritelty, voimme käyttää SDL_image-kirjaston tarjoamia toimintoja, kuten IMG_Load, kuvien lataamiseen ja käsittelyyn pelissämme.

Seuraavaksi määritellään kuvan polku käyttämällä standardikirjaston std::string-tyyppiä, joka helpottaa merkkijonojen käsittelyä C++:ssa. Tämän jälkeen, kun yritetään ladata kuvaa käyttäen SDL:n IMG_Load-funktiota, törmäämme tilanteeseen, jossa tarvitsemme C-tyylin merkkijonoa (const char*). Tämä onnistuu muuntamalla std::string C-tyylin merkkijonoksi käyttämällä .c_str()-metodia, joka palauttaa osoittimen merkkijonon alkuun.

Seuraavaksi on alustetaan SDL-kirjasto kutsulla SDL_Init, jossa käytetään flagia SDL_INIT_VIDEO videonkäsittelyn aktivoimiseksi. Tämän jälkeen, kun haluamme tukea PNG-kuvia, käytämme IMG_Init-funktiota flagilla IMG_INIT_PNG. Tämä flagi kertoo SDL_image-kirjastolle, että haluamme alustaa tuen PNG-kuvatiedostoille. Jos projekti vaatii tukea myös JPG-kuvien käsittelyyn, voimme yhdistää flagit käyttäen bitwise OR -operaattoria |, esimerkiksi IMG_INIT_PNG | IMG_INIT_JPG.

Muistetaanpa myös hallita muistia vastuullisesti. SDL-kirjasto tarjoaa SDL_FreeSurface-funktion, jolla voidaan vapauttaa kuvan käyttämä muisti sen jälkeen, kun sitä ei enää tarvita. Tämän funktion tulisi olla osa pelin lopetusrutiinia tai kuvan käyttöiän hallintaa, varmistaen, että kaikki dynaamisesti varattu muisti vapautetaan oikeaoppisesti.

Kun lataamme kuvan, sen pikseliformaatti ei välttämättä vastaa peli-ikkunan pikseliformaattia. Tämän ongelman ratkaisemiseksi SDL tarjoaa SDL_ConvertSurface-funktion, joka mahdollistaa kuvan formaatin muuntamisen vastaamaan tiettyä pikseliformaattia. Käytännössä tämä tarkoittaa, että voimme muuntaa ladatun kuvan pikseliformaatin vastaamaan peli-ikkunan screen surface-objektin formaattia, mikä mahdollistaa kuvan optimaalisen renderoinnin ja suorituskyvyn.

Ensin määritämme uuden SDL_Surface-objektin, jolle annamme nimeksi esimerkiksi o_kuva. Tämän jälkeen käytämme SDL_ConvertSurface-funktiota antaen sille ladatun kuvan, kohdeformaatin (joka on haettu peli-ikkunan screenSurface-objektista), ja flagiksi nollan, mikä indikoi, että emme käytä erityisiä flageja muunnoksessa. Näin saavutetaan kaksi tavoitetta: varmistetaan kuvan yhteensopivuus ikkunan kanssa ja optimoidaan suorituskykyä.

#include <SDL.h>
#include <SDL_image.h>
#include <string>

int main(int argc, char* argv[])
{
  SDL_Init(SDL_INIT_VIDEO);
  SDL_Window* window = NULL;
  SDL_Surface* screenSurface = NULL;
  SDL_Surface* kuva = NULL;
  SDL_Surface* o_kuva = NULL;
  window = SDL_CreateWindow("SGH SDL Esimerkki", 50, 50, 1280, 720, SDL_WINDOW_SHOWN);

  int imgFlags = IMG_INIT_PNG;
  IMG_Init(imgFlags);

  screenSurface = SDL_GetWindowSurface(window);
  SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0xFF, 0xFF, 0xFF));
  SDL_UpdateWindowSurface(window);
  std::string kuva_osoite = "kuva.png";
  kuva = IMG_Load(kuva_osoite.c_str());
  o_kuva = SDL_ConvertSurface(kuva, screenSurface->format, 0);

  SDL_Event e;
  bool quit = false;

  while (quit == false)
  {
    while (SDL_PollEvent(&e))
    {
      if (e.type == SDL_QUIT) quit = true;
    }
  }

  SDL_FreeSurface(kuva);
  SDL_FreeSurface(screenSurface);
  SDL_DestroyWindow(window);
  SDL_Quit();

  return 0;
}

Edellinen osa: SDL2 Ikkuna

Keskustelu

Aloita uusi keskustelu