Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++ SDL ongelma

Sivun loppuun

mika132 [12.10.2009 12:06:59]

#

Vanhaan topicikiin ei vastattu ja se painui hieman alas, joten päätin kysäistä uudestaan. Olen testannut jo kaksi päivää tätä miten sen saisi korjattua, mutta ei niin ei.

Kun kuulin, että goto on huono koodaus vaihtoehto muutin sitä, mutta tuhoisin seurauksin. :O

Pistin "valinta" muuttujan. Eli tarkistetaan jos valinta muuttuja on jotain tiettyä niin mennään pisteeseen jotain.

Ongelma:
Painan oikeaan kohtaa ykkösnapilla. Mitään ei tapahdu. Painan kolmoshiiren nappia ihan missä vain (sulkee pelin) niin katsoppas kuva välähtää taustalla joka piti tulla jo aikaisemmin. Pistin SDL_delayn(5000); ja kyllä haluaman ikuva tulee siihen. Okei yritys kaksi: En painanut lainkaan taloa, mutta painoin suoraan kolmosta. Peli sammui ilman viivettä. Ja kolmas yritys painoin kuvaa ykköshiirellä ja sitten painoin kolmosta niin kuva tuli taas viideksi sekuntiksi. Miksei se tule aikaisemmin?

if valinta jälkeinen tapahtuma on alapuolella ja niiden alla nuo nappula sörsselit. =)

if (valinta==1)
    {
    SDL_FreeSurface(kuva);
    SDL_FreeSurface(talo_1);
    SDL_FreeSurface(talo_2);

    SDL_Surface *Tausta;

    Tausta=SDL_LoadBMP("grafiikat/tausta.bmp");
    PiirraKuvaTausta(Tausta, naytto);

    TTF_Init();
    SDL_Surface *teksti;
    SDL_Surface *teksti2;
    TTF_Font *font = NULL;
    SDL_Color textcolor = {255, 0, 0};
    font = TTF_OpenFont("courbd.ttf", 20);

    int c=50;
    char mjono[10];
    sprintf(mjono, "%i", c);
    teksti = TTF_RenderText_Blended(font, mjono, textcolor);
    teksti2 = TTF_RenderText_Blended(font, "Rahaa: ", textcolor);


    SDL_Rect alue_tekstille;
    alue_tekstille.x = 200;
    alue_tekstille.y = 200;

    SDL_Rect alue_tekstille2;
    alue_tekstille2.x = 120;
    alue_tekstille2.y = 200;

    SDL_BlitSurface(teksti, NULL, naytto, &alue_tekstille);
    SDL_BlitSurface(teksti2, NULL, naytto, &alue_tekstille2);

    SDL_Flip(naytto);
    SDL_Delay(5000);

}
void TarkastaOnkoPisteSuorakulmiossa(int hiiren_x, int hiiren_y, int taloKuvanX, int taloKuvanY, int taloKuvanLeveys, int taloKuvanKorkeus)
{
    int talon_viimeinen_X = taloKuvanX + taloKuvanLeveys;
    int talon_viimeinen_y = taloKuvanY + taloKuvanKorkeus;
    if ((hiiren_x >= taloKuvanX) && (hiiren_x <= talon_viimeinen_X))
    {
        if ((hiiren_y >= taloKuvanY) && (hiiren_y <= talon_viimeinen_y))
        {
        valinta = 1;

        }
    }
}

hiiri=SDL_GetMouseState(&hiiren_x,&hiiren_y);
if (SDL_GetMouseState(&hiiren_x, &hiiren_y) & SDL_BUTTON(1))
{
    TarkastaOnkoPisteSuorakulmiossa(hiiren_x, hiiren_y, taloKuvanX, taloKuvanY, taloKuvanLeveys, taloKuvanKorkeus);
}

    if(hiiri & SDL_BUTTON(3))
        pois=true;
        //koodia muutama rivi ja sitten
SDL_Flip(naytto);

vehkis91 [12.10.2009 15:11:14]

#

Voisitko laittaa sitä koodia vähän enemmän näkyville?

Kuvat pitäisi ladata ohjelman alussa ja vapauttaa lopussa, ellei ole jotain hyvää syytä vapautella kuvia kesken kaiken.

TTF_Init(); kannattaisi myös kutsua tuota funktiota ohjelman alussa.

Ja luulen, että flippaat tuossa taustakuvan sen sun kuvas päälle, joten siksi et ehdi nähdä sitä kuvaasi, ku vain sen 5sec.

Sori ku tuli taas vaihteeks vähän epäselvää tekstiä, mutt toivottavasti ymmärsit jotain.

Edit: eli piirtojärestyksen pitäisi olla:

1.piirrä tausta
2.piirrä muut kamat
3.ja sitten lopuksi flipataan.

en nää sun pääsilmukkaasi mutt luulen ett on jotenki näin

1.jos painettu nappia, niin piirrä kuva
  flipataan tässä väliss.
2.jos painettu toista nappia, niin lopeta
3.piirrä tausta
4.flippaa näytölle.

eli jos on jotenkin noin, niin vaihda se taustan piirto tonne ensimmäiseksi, sitten poista se flippaus tolta funtiosta, koska sitä ei tarvitse tehdä kuin pääsilmukan lopussa.

JEE taas epäselvää tekstiä.

mika132 [14.10.2009 01:30:25]

#

Juu ymmärsin jotenkin. Mites tälläinen:

string team_name = "Hehe";
char name[10];
sprintf(name, "%s", team_name);

Eli mitä laitan tuohon sprintf keskelle? %s tulee vain (null) teksti ja %i tulee nolla koitin myös %c mutta tuli pelkkää tyhjää. Mikä on oikea?

hunajavohveli [14.10.2009 08:13:47]

#

En C++:aa erityisemmin osaa, mutta sprintf on C-kirjaston funktio eikä siten ymmärrä string-olioita. Muotoilujono "%s" vaatii osoittimen char-taulukkoon, ja string-oliolta sellaisen saa googlen mukaan c_str()-metodilla. Eli:

string team_name = "Hehe";
char name[10];
sprintf(name, "%s", team_name.c_str());

Torgo [14.10.2009 12:59:07]

#

Juu noin se pitäisi toimia kuten hunajavohveli sanoi, mutta tarvitseeko sen olla välttämättä char[] -tyyppiä? Jos ei niin tälläinen hoitaisi homman vähän simppelimmin:

string team_name = "Hehe";
string name (team_name);

mika132 [14.10.2009 13:45:12]

#

Kiitos. =)

teksti = TTF_RenderText_Blended(font, "Huomenna tulee \n uusi lehmä", textcolor);

Miksi tuo tyypillinen \n rivinvaihto ei toimi tuossa? :O

Sisuaski [14.10.2009 13:49:25]

#

Koska SDL_ttf ei tue rivinvaihtoja tekstissä.

vehkis91 [14.10.2009 13:51:43]

#

Eli sun pitää tehdä näin:

rivi1 = TTF_RenderText_Blended(font, "Huomenna tulee", textcolor);
rivi2 = TTF_RenderText_Blended(font, "uusi lehmä", textcolor);

Sitten vaan sopivasti tuon rivi2 koordinaatit, ettet piirrä niitä päällekkäin.

mika132 [14.10.2009 14:02:19]

#

Ajattelin vain, että olisiko nopeampaa tapaa, kun tuota tahtia koodi menee aivan mössöksi. : <

lisäksi nappuloiden kanssa onkelmia.

SDL_PollEvent(&tapahtuma);
while(SDL_PollEvent(&tapahtuma))
{
	if (tapahtuma.key.keysym.sym == SDLK_1)
	{
		rahaa++;
		SDL_BlitSurface(teksti6, NULL, naytto, &alue_tekstille6);
		SDL_Flip(naytto);
	}
}

Tuo koodi ei tee mitään.

vehkis91 [14.10.2009 14:09:54]

#

Teet vaikka jonkun oman funktion, mikä osaa rivitää tekstin tms.

Edit: lukaseppas tuo: https://www.ohjelmointiputka.net/oppaat/opas.php?tunnus=sdl3

Niin selviää, ett miten niitä nappeja käsitellään.


laitetaan nyt pieni esimerkki

Tässä tapauksessa kun painaa ruksia ikkunan kulmasta tai painaa esc nappia, niin pääsilmukka loppuu. Tosta sun pitäis jo osata muokata toimiva versio.

Tämä siis suoraan yhdestä projektistani, joten toimivuus on varma.

//ennen pääsilmukkaa
Uint8* button;

//Pääsilmukass

  while( SDL_PollEvent( &event ) )
  {
      //Jos painetaan ruksia
      if( event.type == SDL_QUIT )
      {
          running = false;
     }
     if (this->button[SDLK_ESCAPE]) //Lopetus
     {
         running = false;
     }
  }

mika132 [14.10.2009 21:34:01]

#

Juu nyt toimii. Evotin vähän. :DD

Yksi ongelma kuitenkin. Niinkuin näette ylempää iffissä on koodi:

rahaa++;

se ei kuitenkaan lisää rahaa yhtään, joten mistä johtuu päivitys moka tms? :O

vehkis91 [14.10.2009 21:43:23]

#

Näytäppäs vähän sitä koodias.

mika132 [15.10.2009 00:45:24]

#

Ennen kuin esittelen sitä niin putsaan sitä hieman (nimittäin pari ominaisuutta ja toista sataa riviä koodia. : <

Mikä olisi SDL:ssä hyvä tapa vaihtaa ns. Huonetta? :O

vehkis91 [15.10.2009 02:59:50]

#

Ai niinkuin pelissä? 1. huoneesta 2. huoneeseen?

Varmaan teet jonkin kohdan 1. huoneeseen, mikä kertoo enginelle, että pitää ladata 2. huone.
Kun 2.huone on ladattu engine siirtää pelaajan 1.huoneesta 2.huoneen aloituskoordinaatteihin.

mika132 [15.10.2009 14:48:36]

#

Niin mutta tarkoitan, että miten? case, if goto?

vehkis91 [15.10.2009 15:13:27]

#

No vaikka.

//pääsilmukass
//Tämä siis kentän maali
if(pelaajaX == maaliX && pelaajaY == maaliY)
 //tee jotain

mika132 [15.10.2009 15:18:35]

#

ok. Taisin saadakkin tuollaisen luotua on vain pieni ongelma. =)

En tiedä tarkkaan miten C++ suorittaa koodia. Vetääkö se sen kerran loppuun ja antaa olla. Eli tällöin mikä funktio jättää tietyn kohdan päälle mitä C++ suorittaa koko ajan. Katsos tällä hetkellä on kaksi eri huonetta. Kun painaa taloa 1 pitäisi päästä toiseen huoneeseen, mutta ei pääse ja luulen, että vika on siinä, että pää funktio:

int main(int argc, char *argv[])

ei ala uudestaan jonka takia peli ei osaa ottaa huonetta kaksi näkyviin. Eli miten aloitan koko funktion uudestaan tai jätän tuo huone välin päälle jollain silmukalla?

vehkis91 [15.10.2009 15:31:33]

#

Siis kaikkien pelien pohjana on jonkinlainen pääsilmukka, jota sitten rullataan eestakas. Pääsilmukassa tapahtuu kaikki pelin mekaniikka. esim. pelaajan liikutus, kaikkien objektien piirto ja ...

mika132 [15.10.2009 15:57:12]

#

Eli tuo minun int main on pääsilmukka koska se oli valmiina siinä aloittaessani uuden projektin. No miksi sitten tuo ei toimi. (nyt tulee monta riviä koodia, mutta tärkeää on vain ne ominaisuudet siellä.)

Koodi

vehkis91 [15.10.2009 16:08:39]

#

Ei vaan sen on main funktio. Sun pääsilmukka on tämä:

while(pois==false)
{
    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;
    }
}

Ei millään pahalla, mutta koodisi on sen näköistä, että kannattais tutustua vaikka putkan c++ oppaaseen...

Torgo [15.10.2009 16:15:19]

#

Lyhyesti vastattuna: int main ei ole pääsilmukka, eikä silmukka ylipäätänsäkään. Pääsilmukkasi on while(pois==false), minkä sisällä ei tehdä mitään muuta kuin tutkitaan ESCin painallusta.

Pidemmästi vastattuna:
Opettele debuggerin käyttöä ja steppaamaan koodiasi. Voit tehdä samaa ihan paperillakin(/ruudullakin) käymällä koodin suoritusta mielessäsi läpi rivi riviltä. Nyt kun ohjelmaa menee läpi rivi riviltä, niin paljastuu tälläinen rakenne:

1. Alusta SDL
2. Piirrä huone 0
3. Looppaa tyhjää pääsilmukkaa tekemättä mitään kunnes painetaan ESC
4. Lue hiiren tila ja tarkasta paikka
5. Poistu ohjelmasta välittömästi tarkastusten jälkeen

Matalammalla tasolla en alkanut koodia tutkimaan, mutta jo ylemmällä tasolla näkee selvästi missä pahimmat loogiset virheet.

Tapoja tehdä huonesiirtymä on yhtä paljon kun ohjelmoijiakin. En osaa sanoa onko varinaisesti universaalia parasta tapaa olemassakaan, mutta esim. tilakoneisiin perustuva ratkaisu on toimiva. Peli voi olla esim. PELAA tilassa tasolla 1 ja sopivan ehdon täytyttyä se siirtyy tilaan SEURAAVA_TASO, jolloin ladataan seuraava taso ja tila päivitetään PELAA tilaan tasolla 2. Tiloja on helppo lisätä jälkikäteenkin (kuten PAUSE, MENU, DEBUG yms.) ja niiden muokkaus yhteisen tilakäsittelijän kautta on aika helppoa.

EDIT. Taas Vehkis ehti ensin :p

mika132 [15.10.2009 16:48:18]

#

JES! :D

Kiitos! Sain tuon huone systeemin toimimaan. Tiesin koko ajan vian, mutta en tajunnut sitä kunnolla ja sitten tajusin ja kysyin asiasta täällä. Eli vika miksi huone ei vaihtunut oli Pääloopin väärä paikka. :P


Sivun alkuun

Vastaus

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

Tietoa sivustosta