PacMan-Clone wird immer langsamer



  • EDIT: Mist! Doppelposting!



  • vielleicht liegt es an

    // Schrift initialisieren
    FTGLPixmapFont font(font_file.c_str());
    

    hab keine ahnung was FTGLPixmapFont für ein typ ist, aber kann es sein dass ihr bei jedem aufruf von printFTGL die schrift neu initialisiert ohne das objekt (font) wieder freizugeben?



  • hi,
    das ist gut möglich, doch wir sind wie gesagt keine Helden in Sachen OpenGL und FTGL. Wir wissen nicht was wir da ändern sollten. Und müsste das Objekt nach dem Beenden der Methode nicht selbst seinen Destruktor aufrufen?
    Wir könnten das Objekt ja auch als Klassenmember deklarieren, doch dann kennen wir die Methode zum Laden unterschiedlicher Schriftarten nicht. In den FTGL-Demos ist von so einer nichts zu sehen und ne ordentlich Doku gibts auch nicht. Wir hoffen ihr könnt uns helfen.

    Tschau Gartenzwerg



  • bei der methode die text zeichnet, schreibt doch einfach mal "return;" gleich am anfang und schaut mal ob der speicherbedarf immer noch so rapide steigt, dann könnte man schonmal entscheiden ob es wirklich am Fontrendering liegt.

    rapso->greets();



  • hi,
    ok hab in die erste Zeile der Funktion ein return; gesetzt und der Speicherfresser ist weg. Ich poste mal hier die Renderfunktion:

    void CGrafik::printFTGL(float x, float y, int size, std::string txt, std::string font_file, int flags)
    {
      font_file="fonts/"+font_file+".ttf";
    
      std::ifstream fontfile(font_file.c_str());
    
      if(fontfile)
      {
        // Schrift initialisieren
        FTGLPixmapFont font(font_file.c_str());
    
        // Schriftgröße angeben
        font.FaceSize(size);
    
        if(flags&ALIGN_CENTER)
        {
          float xl=0, xr=0,
                yl=0, yr=0,
                zl=0, zr=0;
    
          float laenge;
    
          font.BBox(txt.c_str(), xl, yl, zl, xr, yr, zr);
    
          laenge=xr-xl;
    
          x=(640/2)-(laenge/2);      
        }
        else if(flags&ALIGN_RIGHT)
        {
          // bei Rechtsbündig muss der x-Wert der x-Wert des letzten Buchstabens sein
           float xl=0, xr=0,
                 yl=0, yr=0,
                 zl=0, zr=0;
    
          float laenge;
    
          font.BBox(txt.c_str(), xl, yl, zl, xr, yr, zr);
    
          laenge=xr-xl;
    
          x=x-laenge;
        }
    
        // Position setzen    
        glRasterPos2f(x, y);
    
        // Schrift malen
        font.Render(txt.c_str());
      }
      else
      {
      	std::cerr << "Can not found " << font_file << "\n";
      	exit(1);
      }
    
      fontfile.close();
    }
    

    Was ist daran falsch?

    Tschau Gartenzwerg



  • Ich sehe hier auf Anhieb nichts falsches, aber sieh Dir uU mal den Destruktor von FTGLPixmapFont an, vielleicht "leakts" an dem. 😉

    PS: Achte auf const-Correctness und übergib alle Nicht-Primitive per (konstanter) Referenz!



  • hi,
    ok das mit der const-Correctness und den Referenzen werde ich mir zu Herzen nehmen. So nun eine Hintergrundfrage: Der Destruktor von FTGLPixmapFont sieht so aus:

    FTGLPixmapFont::~FTGLPixmapFont()
    {}
    

    völlig leer und nutzlos.

    Aber FTGLPixmapFont erbt public von FTFont und dessen Destruktor ist virtual und sieht so aus:

    FTFont::~FTFont()
    {
        delete glyphList;
    }
    

    Wenn ich das richtig verstanden hab, verursacht eine virtuelle Methode eine abstrakte Klasse und alle erbenden Klassen müssen diese virtuelle Methode ersetzen. Wird der FTFont-Destruktor nun automatisch aufgerufen oder nur der von FTGLPixmap? Die glyphList ist das einzig dynamische an der Klasse. Sie speichert die Zeichen, sie muss am Ende wieder freigegeben werden.

    Tschau Gartenzwerg



  • Gartenzwerg schrieb:

    Wenn ich das richtig verstanden hab, verursacht eine virtuelle Methode eine abstrakte Klasse und alle erbenden Klassen müssen diese virtuelle Methode ersetzen.

    Das hast Du falsch verstanden; eine Klasse ist dann abstrakt wenn sie ein oder mehrere rein virtuelle Methoden hat, diese muss dann auch für die abgeleiteten Klassen implementiert werden.
    Allerdings gilt es hier den Unterschied zwischen virtuellen und rein virtuellen Methoden zu beachten!

    // rein virtuelles foo, Ba kann nicht instanziiert werden (ist abstrakt)
    class Base
    {
        virtual void foo() = 0;
        // ...
    };
    
    // virtuelles foo, Da kann instanziiert werden
    class Derived : public Base
    {
        virtual void foo() {}
        // ...
    };
    

    Wird der FTFont-Destruktor nun automatisch aufgerufen oder nur der von FTGLPixmap?

    ~Derived ruft selbständig ~Base auf. (Nur korrekt wenn ~Base virtuell ist.)

    Die glyphList ist das einzig dynamische an der Klasse. Sie speichert die Zeichen, sie muss am Ende wieder freigegeben werden.

    Das klingt seltsam, ich lade mir mal Deine Sourcen herunter und schau sie mir genauer an!



  • Irgendwie finde ich Deinen Code ein bisschen unüberstichtlich aber wo wird denn zB in FTGlyphContainer charMap freigegeben?



  • hi,
    ok das war einer der Hauptfehler. Das Menü verbraucht jetzt nur konstant Speicher, d.h. der Speicherverbrauch steigt nicht mehr an. Aber mit jedem neuen Level geht der Speicherverbrauch nochmal in die Höhe, d.h. beim Neustart und Einladen des Levels. Was könnte die Ursache dafür sein? Wieso ist mein Code unübersichtlich. Das er nicht super ist, ist mir schon klar. Aber was hätte ich denn anders organisieren sollen?

    Tschau Gartenzwerg



  • Gartenzwerg schrieb:

    ok das war einer der Hauptfehler. Das Menü verbraucht jetzt nur konstant Speicher, d.h. der Speicherverbrauch steigt nicht mehr an.

    *mirselbstaufdieschulterklopf*

    Aber mit jedem neuen Level geht der Speicherverbrauch nochmal in die Höhe, d.h. beim Neustart und Einladen des Levels. Was könnte die Ursache dafür sein?

    Naja, irgendwas was beim Entladen des alten Levels geschieht zB? Ich muss mir die Sourcen genauso anschaun wie Du; checke doch einfach mal was genau Dein Programm da macht und was für den Fehler verantwortlich sein könnte! (Ich muss mich in Deine Sourcen erst einarbeiten, Du dich selbst nicht.)
    Heute habe ich keine Zeit mehr mir die Sache genauer anzusehen, vielleicht komme ich aber im Laufe des Wochenendes noch dazu.

    Wieso ist mein Code unübersichtlich. Das er nicht super ist, ist mir schon klar. Aber was hätte ich denn anders organisieren sollen?

    Gibt jetzt nichts was ich Dir so konkret nennen könnte aber die Kommentare zB sind teilweise echt furchtbar und verunstalten außerdem die Header.



  • hi,
    wie schon gesagt, wir haben nicht so viel Ahnung von OpenGL etc. Wir haben den Code schon mehrmals durchsucht und nichts auffälliges finden können. Manchmal ist es so, dass man die Lösung vor der Nase hat und sie nicht sieht. Doch jemand der objektiv an die Sache herangeht, findet sie sofort. Deshalb wäre es sehr nett, wenn du dir die Mühe machen würdest und dir unseren Code mal genauer ansehen würdest.

    Tschau Gartenzwerg



  • Werde ich machen sobald ich wieder ein bisschen mehr Zeit habe aber sag mir zumindestens welche Methode/ Funktionen aufgerufen werden wenn ein Level beendet ist! (Klar kann ich das auch selbst herausfinden, allerdings wäre das für mich unverhältnismäßig aufwändiger als für Dich!)



  • hi,
    danke für deine Hilfe! Du brauchst den Code nun nicht mehr zu durchsuchen. Ich habe den Fehler jetzt selbst gefunden. War total einfach. Ich hatte vergessen vor dem Neuladen des nächsten Levels die alten Texturen zu löschen. Naja nochmals: "Vielen Dank!"

    Tschau Gartenzwerg



  • Gratuliere! 👍


Anmelden zum Antworten