Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: SDL_Surfacen palautus funktiosta

Sivun loppuun

temu92 [04.08.2006 21:06:04]

#

Eli ongelmana on SDL_Surfacen palautus funktiosta. Olen yrittänyt tehdä luokkaa SDL:n käyttöön helpommin.

Tässä funktio

SDL_Surface *ReturnScreen(){
    return &SDLscreen;
}

Tämän koodin tarkoituksena palauttaa se screeni jota SetVideoMode käyttää. Miten tämän saisi pelittämään?

Heikki [04.08.2006 21:11:42]

#

Luultavasti SDLscreen on jo osoitin, eli palauta se ihan yksinkertaisesti komennolla return SDLscreen;

temu92 [04.08.2006 21:17:37]

#

Kiitos. Se olikin vaan yhdestä merkistä kyse =P
Niin ja kiitti kans oppaista. Ne on ollut apuna tähän.

temu92 [04.08.2006 23:07:41]

#

Mitenkä saisin piirtokomennon piirtämään suoraan ilman tätä äskeistä funktiota kuvan tuohon SDLscreen pintaan.

Koska oon tehny erilliset luokat screenille ja kuville.

Kuvan piirto Image-luokassa.

void Draw(SDL_Surface *SDLscreen, int x, int y){
    SDL_Rect area;
    area.x=x;
    area.y=y;
    SDL_BlitSurface(this->SDLimage, NULL, SDLscreen, &area);
}

Tuo ReturnScreen() palauttaa sen näytön Screen-luokasta jota käytän sitten tossa funktiossa.

Mazzimo [05.08.2006 18:32:14]

#

Jos haluat jättää parametrit pois Draw-funktiosta, ota kuvaa ladattaessa screen-olion (tai sen sisältämän pinnan) osoite ylös Image-olioon. Sitten vain blittaat Image-olion sisältämän pinnan sen screen-osoittimen osoittamaan pintaan:

void Load(char* fileName, ScreenObject* so)
{
    // lataa kuva pintaan yms..
    this->pScreen = so;
}

void Draw()
{
    SDL_BlitSurface(this->SDLimage, NULL, this->pScreen->SDLscreen, &(this->myArea));
}

Jos haluat koko funktiosta eroon, sinun täytyy lisätä Image-olion pintaa ladatessa olion muistiosoite vaikka Screen-luokassa sijaitsevaan linkitettyyn listaan.

Aina ennen SDL_Flip()-komentoa käyt linkitetyn listan läpi ja piirrät siinä olevat kuvat näytölle (sinulla täytyy olla Draw-metodi, jolla voit blitata Image-olioiden pinnat näyttöön).


_____________________________

EDIT: Tälläistä systeemiä itse käytän:

void System::Update()
{
	UpdateObjects();	// piirretään objektit (tämä on System-luokan privaatti metodi)
	SDL_Flip( screenSurface );

	// päivitetään nääpäinsyötteet, hiiri yms..

}

// tässä updateObjects():

void System::UpdateObjects()
{
	Object* pCurrent = pSysCore->objList.First();  // haetaan listan eka objekti

	while(pCurrent)    // käydään läpi niin kauan, kunnes objektit loppuvat
	{
		pCurrent->Draw(*(pSysCore->pDrawBuffer));  // piirretään
		pCurrent = pSysCore->objList.Next();       // haetaan seuraava
	}
}

// Object-luokan Draw()-metodi:

void Object::Draw(SDL_Surface* srfc)
{
	if(isLoaded)
		SDL_BlitSurface( surface, NULL, srfc, &myPosition );
}

Tuo pSysCore-osoitin voi hämätä. System-luokka on sama, kuin sinun Screen-luokkasi. pSysCore on osoitin Core-luokan olioon, jossa on kaikki tarvittava tieto pelistä (objektit yms..) Miksi haen piirrettävä pinnan muualta, enkä käytä suoraan System-luokan pintaa (joka on näyttö)? Vastaukseksi tähän voin sanoa, että tuolla tavalla voin muuttaa TODELLA helposti piirron vaikka toiseen kuvaan. Oletuksena tietysti on, että piirto-osoitin osoittaa näyttöpintaan.

Toivottavasti sait jotain selvää sekavista sätöstyksistäni.. :)

temu92 [06.08.2006 15:03:32]

#

Aloittelija kun vielä olen en edes tiedä mikä linkitetty lista on. Jos joku vaikka auttaisi. Tuon ekan jutun tajusin ja sainkin koodiin.

Ja Alla on tämän hetkinen kirjastoni

#include <SDL\SDL.h>
#include <SDL\SDL_Rotozoom.h>

class Screen { // Yleisluokka ikkunalle
    private:
    // Leveys ja korkeus
    int width;
    int height;
    // Syvyys ja Fullscreen
    int depth;
    int fullscreen;

    // Luodaan pinta screenille
    SDL_Surface * SDLscreen;

    public:
    Screen(int width, int height, int depth, int fullscreen);

    SDL_Surface *ReturnScreen(){
        return SDLscreen;
    }

    inline void SetCaption(char *caption){
        SDL_WM_SetCaption(caption, NULL);
    }

    inline void Draw(void){
        SDL_Flip(SDLscreen);
    }

    // Odotus
    inline void Wait(int waittime){
        SDL_Delay(waittime);
    }

    // Endit
    inline void End(){
        SDL_FreeSurface(SDLscreen);
        SDL_Quit();
    }
};

// Parametrillinen muodostin. Alustaa SDL:n
Screen::Screen(int screenwidth, int screenheight, int depth, int fullscreen){
    if(SDL_Init(SDL_INIT_VIDEO) < 0){
        fprintf(stderr,"SDL:n alustus epäonnistui: %s\n", SDL_GetError());
    }

    SDLscreen = SDL_SetVideoMode(screenwidth, screenheight, depth, SDL_HWSURFACE|SDL_DOUBLEBUF);
}

class Image { // Luokka kuville
    private: // Privaattia
    SDL_Surface * SDLimage;
    SDL_Surface * pScreen;

    int angle;
    public: // Vapaat funktiot ja muuttujat

    void LoadImage(char *filename, SDL_Surface* so){
        SDLimage = SDL_LoadBMP(filename);
        this->pScreen=so;
    }

    // Piirretään kuva
    inline void Draw(int x, int y){
        SDL_Rect area;
        area.x=x;
        area.y=y;
        SDL_BlitSurface(this->SDLimage, NULL, this->pScreen, &area);
    }

    inline void RotateImage(double newangle){
        //int currentangle, temp, rangle;
        /*currentangle = this->angle;
        if (currentangle < newangle){
            rangle=newangle-currentangle;
        } else {
            rangle=currentangle-newangle;
        }
        this->angle=newangle;*/
        rotozoomSurface(SDLimage, newangle, 2, 1);
    }

    inline void MaskImage(int r, int g, int b){
        SDL_SetColorKey(this->SDLimage, SDL_SRCCOLORKEY, SDL_MapRGB(this->SDLimage->format,r,g,b));
    }

    inline void DropImage(){
        SDL_FreeSurface(SDLimage);
    }
};

Jos joku vaikka yrittäisi parannella tätä.

Jaska [06.08.2006 15:28:40]

#

Linkitetty lista on tietorakenne, jossa on solmuja ja linkkejä solmusta toisiin. Linkitettyjä listoja voi käyttää monissa ohjelmissa, vaikkapa suuren tarkkuuden liukulukujen toteuttamiseen. Jos sinulla on vaikkapa luku pii laskettu 500 desimaalin tarkkuudella ja haluat likiarvon 50 desimaalin tarkkuudella, voit lisätä listan perään solmun, johon tallennat nuo puuttuvat 50 desimaalia.

Kannattaa lukea jokin hyvä tietorakennekirja, vaikkapa Cormenin, Leisersonin, Rivestin ja Steinin Introduction to algorithms, sillä linkitetyt listat ovat ohjelmoijan peruskamaa, joita tulet tarvitsemaan vielä monia kertoja, mikäli ohjelmoijaksi haikailet.

Metabolix [06.08.2006 16:22:15]

#

Näyttöpintaa ei kuulu vapauttaa, se on poikkeustapaus. Sen sijaan rotozoomSurface ei toimi noin. Se luo (palauttaa) uuden pinnan, ja sekä vanha että uusi pitää vapauttaa joskus. Eli esimerkiksi näin:

class Kuva {
private:
  SDLscreen *alkuperainen, *kaannetty;

public:
  Kuva() {
    alkuperainen = kaannetty = NULL;
  }

  ~Kuva() {
    if (kaannetty) {
      SDL_FreeSurface(kaannetty);
    }
    if (alkuperainen) {
      SDL_FreeSurface(alkuperainen);
    }
  }

  void Kaanna(double kulma) {
    if (!alkuperainen) {
      perror("Ei ole kuvaa!\n");
      return;
    }
    if (kaannetty) {
      SDL_FreeSurface(kaannetty);
    }
    kaannetty = rotozoomSurface(alkuperainen, kulma, 1, 1);
  }
};

Jaskan esimerkki linkitetystä listasta oli harvinaisen kummallinen, minäkään en oikein ymmärtänyt sen ideaa. Mielestäni parempi analogia on vaikkapa joukko vuorikiipeilijöitä. Jokaisesta lähtee köysi ylempänä olevaan ja alempana olevaan, paitsi tietenkin ylimmästä, joka kuljettaa köyden päätä mukanaan, ja alimmasta, jonka perässä köyden pää ehkäpä roikkuu vapaasti.

Mazzimo [06.08.2006 22:37:54]

#

Jos haluat vähentää vielä pääloopissa olevan koodin määrää, voit määritellä sekä Screen-, että Image-luokalle tuhoajafunktiot. Niitä kutsutaan automaattisesti, kun olio tuhotaan (saavuttaa scopensa lopun, dynaamisesti luoduilla delete-komentoa käyttämällä). Esimerkiksi Image-luokan tuhoaja voisi olla:

~Image()
{
    SDL_FreeSurface(SDLimage);
}

Tällöin se korvaisi automaattisesti ImageDrop-metodin. Vastaavasti Screen-luokalle kannattaa tehdä sama, mutta se lopettaa SDL:n. Tällöin on kuitenkin tärkeää, että luot Screen-olion ennen Image-olioiden luontia pääkoodissasi.


Sivun alkuun

Vastaus

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

Tietoa sivustosta