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?
Luultavasti SDLscreen on jo osoitin, eli palauta se ihan yksinkertaisesti komennolla return SDLscreen;
Kiitos. Se olikin vaan yhdestä merkistä kyse =P
Niin ja kiitti kans oppaista. Ne on ollut apuna tähän.
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.
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.. :)
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ä.
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.
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.
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.
Aihe on jo aika vanha, joten et voi enää vastata siihen.