SDL_FreeSurface() in Schleife benutzen?



  • Hallo,

    Ich möchte gerne eine Text ausgabe mit SDL_ttf machen dafür brauch
    ich aber noch eine Variable die den stand der Lebensenergie eines
    Gegners angibt, jedoch ist das Problem das ich leider nicht weiß
    wie ich das mit den String machen soll, so sieht die Zeile aus:

    SDL_Surface* text_type3 = TTF_RenderText_Shaded(sdlFont, "Hp:", textColor, backgroundColor);
    //Die Variable soll neben Hp: erscheinen.
    //Die Variable besitzt den Wert 100 und wurde über dieser Zeile defeniert
    

    So, jedoch wollte ich auch noch wissen wie es möglich ist mit
    SDL_Freesurface() es so hinzubekommen das wenn diese Funktion in
    einer Schleife ist die bei Knopfdruck von dem Buchstaben "x" ausgelöst wird
    den Gegner vom Bildschirm zu entfernen, jedoch wenn ich das Spiel starte
    und den Buchstaben drücke stürzt das Spiel ab bei der Kollision mit dem Gegner.

    Diese Frage schwirrt mir schon die ganze zeit im Kopf bisjetzt
    hab ich es immer so gelöst wenn ich was vom bildschirm weghaben wollte
    das ich die x Position des Objektes so hoch eingestellt hab das er von dem
    Bildschirm weg war, was defenitiv nicht gerade die eleganteste lösung ist... 😞

    Liebe Grüße Neuling2003! 🙂



  • Dieser Thread wurde von Moderator/in pumuckl aus dem Forum C++ in das Forum Spiele-/Grafikprogrammierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Da du deine Frage ursprünglich im C++-Forum gestellt hast, gehe ich mal davon aus, dass dir auch entsprechende Sprachmittel zur Verfügung stehen.

    Textausgabe

    Das ließe sich über einen String-Stream realisieren. Diese funktionieren ähnlich wie std::cout.

    Ein kleines (kompilierbares) Beispiel:

    #include <iostream>
    #include <sstream>
    
    int main()
        {
            std::stringstream ss;
            int hitpoints = 10;
    
            ss << "Hp: " << hitpoints;
    
            std::string example = ss.str();
    
            std::cout << example << std::endl;
            // Als const char *
            std::cout << example.c_str() << std::endl;
            // Oder in einer Zeile
            std::cout << ss.str().c_str() << std::endl;
    }
    

    Das "Problem", welches du mit der SDL haben wirst, ist dass std::stringstream::str einen std::string zurück gibt [1]. SDL, da es eine C-Bibliothek ist, wird einen 'const char *' erwarten. std::string bietet jedoch eine Methode, welche einen solchen Typ zurück gibt (std::string::c_str) [2].

    SDL_Freesurface

    Diese Funktion sorgt nicht dafür, dass eine Grafik nicht mehr angezeigt wird, sondern sie gibt den von ihr belegten Speicher wieder frei. Wenn du Zeiger auf eine freigegebene SDL_Surface weiter verwendest, kommt es (im besten Fall) zum Crash (im schlimmsten Fall läuft das Programm mit undefiniertem Verhalten einfach weiter).

    SDL_Surfaces sind Resourcen. Diese werden zu Beginn angefordert/geladen etc. um am Ende des Programmes wieder freigegeben zu werden.

    Soll ein Gegner nicht gezeichnet werden, dann zeichne (SDL_Blit) ihn einfach nicht.

    SFML[3] ist auch etwas, was du dir mal ansehen könntest. Es passt besser zu C++.

    Grüße... Heiko

    --
    [1] http://www.cplusplus.com/reference/iostream/stringstream/str/
    [2] http://www.cplusplus.com/reference/string/string/c_str/
    [3] http://sfml-dev.org



  • Hallo ich bin Neuling,

    Ja ich kenne mich mit C++ aus und mir ist auch klar das
    SDL_FreeSurface zur Speicher freigabe ist, ich habe es nur grob formuliert. 😃

    Leider muss ich sagen das ich das mit den Strings nicht verstanden
    hab, ich weiß nicht wie ich das in meinen Code "einbauen" soll.
    Um es nochmal zu verdeutlichen hier die 2 Surfaces für den Text:

    SDL_Surface* text_type1 = TTF_RenderText_Solid(sdlFont,  "Highscore:", textColor);
    	SDL_Surface* text_type2 = TTF_RenderText_Shaded(sdlFont, "Hp:", textColor, backgroundColor);
    

    Das heißt nicht das ich nich weiß was strings sind jedoch konnte ich sie
    noch nie richtig in Programmen mit einem Fenster statt einer Konsole verwenden.

    Und das mit dem SDL_BlitSurface, ich glaube an der Stelle hast
    du mich falsch verstanden weil ich möchte das nachdem der int Wert
    Hp auf 0 landet, der schon gezeichnete Gegner vom Bildschirm entfernt
    wird. Oder geht das auch mit SDL_BlitSurface weil mit meiner Suchmaschine
    finde ich leider nichts dazu..

    Trotzdem danke schonmal für deinen Beitrag! 🙂



  • Das mit den Strings findest du noch selbst raus. Suche mal nach den Zusammenhang und Unterschied zwischen std::string und **const char ***. Auch bei vielen Funktionen aus der C++-Standardbibliothek musst du das beachten.

    Was das ominöse Problem mit deinem SDL_Freesurface angeht, solltest du etwas mehr Code posten. Sollte der Quelltext zu lang werden, verwende am besten einen Dienst wie paste.pocoo.org oder nopaste.org.

    Grüße... Heiko



  • if ( rcChuckles.x < 0 ) {
          rcChuckles.x = 0;
        }
        else if ( rcChuckles.x > SCREEN_WIDTH-SPRITE_SIZE ) {
          rcChuckles.x = SCREEN_WIDTH-SPRITE_SIZE;
        }
        if ( rcChuckles.y < 0 ) {
          rcChuckles.y = 0;
        }
        else if ( rcChuckles.y > SCREEN_HEIGHT-SPRITE_SIZE ) {
          rcChuckles.y = SCREEN_HEIGHT-SPRITE_SIZE;
        }
    
    	//Kollision
    	///////////////
    	if (rcChuckles.x + rcChuckles.w >= rcItem1.x &&
          rcChuckles.x <= rcItem1.x + rcItem1.w &&
          rcChuckles.y + rcChuckles.h >= rcItem1.h &&
          rcChuckles.y <= rcItem1.y + rcItem1.h)
    	{
    		rcSrc.x = 1400;
    		rcItem1.x = rcChuckles.x;
    		rcItem1.y = rcChuckles.y +3;
    	}
    
       if (rcItem1.x + rcItem1.w >= rcRobot.x &&
          rcItem1.x <= rcRobot.x + rcRobot.w &&
          rcItem1.y + rcItem1.h >= rcRobot.h &&
          rcItem1.y <= rcRobot.y + rcRobot.h)
       {
    	   rcRobot.x -= 5;
    	}
    	//Kollision Ende
    	//////////////////
    
    	//Skill 1
    	//////////////////
    	keystate = SDL_GetKeyState(NULL);
    
    	if (keystate[SDLK_x] ) {
    
    		SDL_BlitSurface(skill1, 0, screen, &rcSkill1);
    		SDL_UpdateRect(screen, 0, 0, 0, 0);
    
    		rcSkill1.y = rcChuckles.y;
    
    		rcSkill1.x += 10;
    	}
    	//Kollsion von skill 1:
    	  if (rcRobot.x + rcRobot.w >= rcSkill1.x &&
          rcRobot.x <= rcSkill1.x + rcSkill1.w &&
          rcRobot.y + rcRobot.h >= rcSkill1.h &&
          rcRobot.y <= rcSkill1.y + rcSkill1.h)
    	  {
    		  SDL_BlitSurface(text_type2, 0, 0, &text_pos2);
    		  SDL_Surface* text_type3 = TTF_RenderText_Shaded(sdlFont, "RobotsHp: 80%", textColor, backgroundColor);
    		  SDL_Rect text_pos3 = {190, 0, 0, 0};
    		  SDL_BlitSurface(text_type3, NULL, screen, &text_pos3);
    		  SDL_UpdateRect(screen, 0, 0, 0, 0);
    		  rcRobot.x += 3;
    	  }
    
    	  if (RobotsHp = 0)
    	  {
    		  rcRobot.y = 100;
    	  }
    
    	//Skill1 Ende
    	//////////////////////////
    	/////////////////////////
    
        // Hintergrund Zeichnen
        for (int x = 0; x < SCREEN_WIDTH / SPRITE_SIZE; x++) {
          for (int y = 0; y < SCREEN_HEIGHT / SPRITE_SIZE; y++) {
            rcGround.x = x * SPRITE_SIZE;
            rcGround.y = y * SPRITE_SIZE;
            SDL_BlitSurface(ground, NULL, screen, &rcGround);
          }
        }
        //Spirits zeichnen 
        SDL_BlitSurface(chuckles, &rcSrc, screen, &rcChuckles);
    	SDL_BlitSurface(leiste, 0, screen, &rcLeiste);
    	SDL_BlitSurface(item1, 0, screen, &rcItem1);
    	SDL_BlitSurface(robot, 0, screen, &rcRobot);
    	SDL_BlitSurface(text_type1, NULL, screen, &text_pos1);
        SDL_BlitSurface(text_type2, NULL, screen, &text_pos2);
    
    	//Back und Front Buffer tauschen
    	SDL_Flip(screen);
    
        //Screen Updaten
        SDL_UpdateRect(screen, 0, 0, 0, 0);
      }
    
      // Sauber machen
      SDL_FreeSurface(chuckles);
      SDL_FreeSurface(ground);
      SDL_FreeSurface(leiste);
      SDL_FreeSurface(item1);
      SDL_FreeSurface(skill1);
      SDL_FreeSurface(robot);
      SDL_FreeSurface(text_type1);
      SDL_FreeSurface(text_type2);
      SDL_Quit();
    
      //TTF Font löschen
      TTF_CloseFont(sdlFont);
    
      //SDL_ttf wieder beenden
      TTF_Quit();
    
         //Runter fahren von FMOD Sound
        result = FMOD_Sound_Release(sound1);
        ERRCHECK(result);
    
        result = FMOD_System_Close(system);
        ERRCHECK(result);
        result = FMOD_System_Release(system);
        ERRCHECK(result);
    

    So, das Ziel ist es mit skill 1 oder item 1 den robot zu vernichten
    jeder schlag zieht 20hp von 100hp ab (lebensenergie), wenn man nun öferts
    rauf haut wird logischer weise irgendwann die negative hp Zahl 100 sein,
    also 100-100= 0.
    So jetzt würde ich gerne eine Schleife machen die etwa so aussieht:

    if (hp = 0)
    {
    //So nun bräuchte ich irgend eine möglich keit den Robot vom Bildschirm
    //zu entfernen, und genau das ist mein Problem da ich keine möglichkeit
    //hab deswegen geht es eigentlich nicht um SDL_Surface sondern einfach
    //darum diesen Sprite (robot) vom Bildschirm zu entfernen wenn die
    //bedingung von if also hp = 0 erfüllt würd.
    }
    

    Und genau deswegen dachte ich mir ich benutze SDL_Surface dafür
    aber wie gesagt das Spiel wird gecrasht genau wenn der Robot die 0 hp erreicht.
    Deswegen brauche ich eine andere Variante 🙂



  • Die Antwort hat 'bwbg' dir doch schon geschrieben: zeichne den Robot einfach nicht:

    if(RobotsHp > 0)
        SDL_BlitSurface(..., &rcRobot);
    

    P.S. Gibt dir dein Compiler bei "if (RobotsHp = 0)" eigentlich keine Warnung raus???



  • Fehler von mir ich meinte eigentlich den Operatoren "==",
    und du meintest wohl den

    if(RobotsHp > 0)
        SDL_BlitSurface(..., &rcRobot);
    

    Operatoren: "<" weil sonst hat das teilweise keinen sinn. 😃

    Ok jetzt habe ich zwar das mit den nicht Zeichnen vestanden jedoch
    funktioniert das ganze nicht bei mir, also wenn ich allgemein
    das nicht Zeichnen benutze funktioniert es aber in der Schleife nicht,
    so sieht die Schleife aus,

    int RobotsHp = 100;
    /* ... */
    
    	  if (rcRobot.x + rcRobot.w >= rcSkill1.x &&
          rcRobot.x <= rcSkill1.x + rcSkill1.w &&
          rcRobot.y + rcRobot.h >= rcSkill1.h &&
          rcRobot.y <= rcSkill1.y + rcSkill1.h)
    	  {
    		  rcRobot.x += 3;
    		  RobotsHp -= 100;
    
    		  if( RobotsHp < 1)
    		  {
    			  SDL_BlitSurface(robot, 0, 0, &rcRobot);
    		  }
    
    	  }
    

    Wenn ich jetzt den Skill auf den Roboter abfeuere, ist er leider immer
    noch auf dem Bildschirm zusehen obwohl das eig. so funktionieren sollte, oder?

    Ich weiß ich frag ziemlich viel aber ich bin leider noch ein Anfänger
    was die Spieleprogrammierung betrifft.

    Ich hoffe ihr könnt mir noch einen Tipp geben. 🙂



  • Du solltest dir mal deine Bedingung zum Zeichnen des Roboters noch einmal genau ansehen. Generell solltest du deinen Quelltext aufräumen. Das sieht recht nach "irgendwo gelesen und irgendwie reingewurschtelt" aus.

    Das SDL-Tutorial hat ein paar gute Ansätze, die man durchaus (und gerade zu Beginn) auch umsetzen sollte.

    Grüße... Heiko


Anmelden zum Antworten