Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

31

18.05.2017, 15:46

Vieles wurde ja schon gesagt. Anstatt dein CText per Zeiger zu halten und jedes mal mit new zu erstellen kannst du einfach ein CText Objekt benutzen. Es gibt ja keinen Grund warum du da ein Objekt auf dem Heap benutzt. Weiterhin benutzt du C-Strings was nicht besonders schon ist. Damit ist dein Char Array gemeint. In C++ gibt es die Klasse std::string. Das sind zwei Punkte die schnell umgesetzt sind. Vor allem der erste Punkt ist wichtig. Stell dir vor beim erstellen deines CText Objektes geht etwas schief. Kurz danach rufst du die Render Funktion darauf auf. Dann würde es krachen. Die Zeilen 53 bis 57 könntest du dir dann einsparen. Bevor du einen Zeiger mit delete freigibst musst du übrigens nicht prüfen ob dieser valide ist. Du kannst das selbst mal testen. An sich solltest du dir diese Raw Pointer aber allgemein abgewöhnen. Wurde ja schon gesagt. Ich weiß du wolltest nicht hören dass du "modernes" C++ benutzen sollst, den Punkt wollte ich trotzdem noch anmerken.
Ansonsten wäre es nett wenn du noch mal kurz sagen könntest was dann nun genau das Problem ist. Dein Speicher läuft immer noch voll? Na genau deshalb benutzt man ja Smartpointer. Weil diese ganzen Fehlerquellen dann nicht mehr vorhanden sind. Ich kann ich dem Code den du da gepostet hast aktuell nicht sehen was da nicht gelöscht wird. Bist du dir sicher dass aktuell hier das Problem ist? Sicher dass du nicht in einer der anderen Methoden Objekte erstellst ohne sie zu löschen? Oder geht es aktuell um ein anderes Problem? Beschreibe das vielleicht noch mal und gegebenenfalls müssten wir dann mehr Code sehen.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

32

18.05.2017, 15:53

Vieles wurde ja schon gesagt. Anstatt dein CText per Zeiger zu halten und jedes mal mit new zu erstellen kannst du einfach ein CText Objekt benutzen. Es gibt ja keinen Grund warum du da ein Objekt auf dem Heap benutzt. Weiterhin benutzt du C-Strings was nicht besonders schon ist. Damit ist dein Char Array gemeint. In C++ gibt es die Klasse std::string. Das sind zwei Punkte die schnell umgesetzt sind. Vor allem der erste Punkt ist wichtig. Stell dir vor beim erstellen deines CText Objektes geht etwas schief. Kurz danach rufst du die Render Funktion darauf auf. Dann würde es krachen. Die Zeilen 53 bis 57 könntest du dir dann einsparen. Bevor du einen Zeiger mit delete freigibst musst du übrigens nicht prüfen ob dieser valide ist. Du kannst das selbst mal testen. An sich solltest du dir diese Raw Pointer aber allgemein abgewöhnen. Wurde ja schon gesagt. Ich weiß du wolltest nicht hören dass du "modernes" C++ benutzen sollst, den Punkt wollte ich trotzdem noch anmerken.
Ansonsten wäre es nett wenn du noch mal kurz sagen könntest was dann nun genau das Problem ist. Dein Speicher läuft immer noch voll? Na genau deshalb benutzt man ja Smartpointer. Weil diese ganzen Fehlerquellen dann nicht mehr vorhanden sind. Ich kann ich dem Code den du da gepostet hast aktuell nicht sehen was da nicht gelöscht wird. Bist du dir sicher dass aktuell hier das Problem ist? Sicher dass du nicht in einer der anderen Methoden Objekte erstellst ohne sie zu löschen? Oder geht es aktuell um ein anderes Problem? Beschreibe das vielleicht noch mal und gegebenenfalls müssten wir dann mehr Code sehen.


Schon mal vielen Dank für diese Antwort!

Das Problem liegt darin, dass der Arbeitsspeicher jedes Frame immer voller wird, und zwar sehr rasant.

33

18.05.2017, 15:54

Und ich denke, dass es nicht an einem anderen Objekt liegt, da ohne diesen Text alles super geklappt hat.

Und du hast wirklich Recht, Heap macht hier keinen Sinn :) .
Ich experimentiere noch ein wenig herum.

34

18.05.2017, 16:29

Aber etwa so ändert sich auch nichts:

Game.hpp (gekürzt):

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Game.hpp
//

#ifndef GAME_HPP
#define GAME_HPP

#include "Player.hpp"
#include "Banana.hpp"
#include "Text.hpp"
#include <list>


class CGame
{
     public:
         CGame ();         
         
         void Init ();    
         void Run  ();     
         void Quit ();    
         void Menu ();

     private:
         void ProcessEvents  (); 
         

         bool m_bGameRun;            // Läuft das Spiel noch?
         bool m_bMenu;               // Läuft das Hauptmenü noch?
         int      m_Score;           // Der Score für ein Spiel
         CText    m_tScore;          // Text - Score

};

#endif



Game.cpp (gekürzt):

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// Run
//
// Aufgabe: Der eigentliche "Herzschlag" des Spiels
//
void CGame::Run()
{
    
    char TextBuffer_Score[15];

    // Die "Herzschlag"-Schleife
    while (m_bGameRun == true)
    {

        // Hauptmenü aufrufen, falls noch aktiv
        if (m_bMenu == true)
        {
            Menu ();
        } // Menu

        
        // Framework updaten und Buffer löschen
        g_pFramework->Update ();
        g_pFramework->Clear  ();

        // Events überprüfen
        ProcessEvents ();

        // Hintergrundbild rendern
        m_pSpriteGame->Render ();

        // Spieler updaten und rendern
        m_pPlayer->Update ();
        m_pPlayer->Render ();

        // Neue Bananas hinzufügen
        SpawnBananas ();

        // Kollisionen überprüfen
        CheckCollisions ();

        // Bananas rendern
        RenderBananas ();

        sprintf_s(TextBuffer_Score, "Score: %i", m_Score);
        m_tScore.Draw (g_pFramework->GetRenderer(), "Schriftarten/comic.ttf", 50, TextBuffer_Score, { 0, 0, 0, 0 });
        // Gesammelte Bananas anzeigen
        

        // Erreichten Score anzeigen
        m_tScore.display (1320, 15, g_pFramework->GetRenderer());
        m_tScore.~CText();

        // Falls 'H' gedrückt wird, zum Hauptmenü
        // zurückkehren und Spielerstand zurücksetzen
        if (g_pFramework->KeyDown(SDL_SCANCODE_H))
            m_bMenu = true;


        // Spiel darstellen
        g_pFramework->Render ();

    }

} // Run



Text.cpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// Text.cpp
//

#include "Text.hpp"

// Konstruktor
//
CText::CText ()
{
}

void CText::Draw(SDL_Renderer *renderer,
            const string &font_path,
            int font_size,
            const string &message_text,
            const SDL_Color &color)
{
    m_text_texture = loadFont(renderer, font_path, font_size, message_text, color);
    SDL_QueryTexture(m_text_texture, nullptr, nullptr, &m_text_rect.w, &m_text_rect.h);
}


// Destruktor
//
CText::~CText ()
{
    TTF_CloseFont (m_pFont);
    SDL_DestroyTexture(m_text_texture);
    m_pFont = NULL;
}


void CText::display(int x, int y, SDL_Renderer *renderer)
{
    m_text_rect.x = x;
    m_text_rect.y = y;
    SDL_RenderCopy(renderer, m_text_texture, nullptr, &m_text_rect);
}


SDL_Texture *CText::loadFont(SDL_Renderer *renderer,
                             const string &font_path,
                             int font_size,
                             const string &message_text,
                             const SDL_Color &color)
{
    TTF_Font *m_pFont = TTF_OpenFont(font_path.c_str(), font_size);

    if (!m_pFont)
    {
        cout << "failed to load font!" << endl;
    }
    auto m_text_surface = TTF_RenderText_Solid (m_pFont, message_text.c_str(), color);
    if (!m_text_surface)
    {
        cout << "failed to load surface!" << endl;
    }
    if (!message_text.c_str())
    {
        cout << "failed to load message!" << endl;
    }
    auto text_texture = SDL_CreateTextureFromSurface(renderer, m_text_surface);
    if (!text_texture)
    {
        cout << "failed to load texture!" << endl;
    }
    SDL_FreeSurface (m_text_surface);
    return text_texture;
    SDL_DestroyTexture(text_texture);
}



Würde mich sehr über hilfreiche Antworten freuen!

Wenn ich aus Game.cpp in der Run-Funktion die Draw - und Display-Sache entferne, läuft alles gut.
Nach meinen Forschungen läuft etwas in Draw schief, da ohne Display auch alles gut ist.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

35

18.05.2017, 16:31

In CText::Draw lädst du jedes Mal die Schrift neu.
In CText::loadFont hast du nach dem return noch eine Anweisung stehen, die natürlich nie ausgeführt wird.

36

18.05.2017, 16:32

Das hat auch nichts mit dem TextBuffer zu tun, weil bei einfachen, unveränderbaren Strings genau dasselbe passiert.
In Draw wird also etwas zu oft erstellt, was natürlich den RAM rasant überfüllt (Wenn ich so in den Taskmanager gucke)).

37

18.05.2017, 16:37

In CText::Draw lädst du jedes Mal die Schrift neu.
In CText::loadFont hast du nach dem return noch eine Anweisung stehen, die natürlich nie ausgeführt wird.


Aber ich dachte ja, dass ich mit CloseFont die Schrift lösche oder nicht?

Wie sähe dann das Endergebnis aus?

( Und außerdem danke, Admin :) ).

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

38

18.05.2017, 16:47

Sorry, aber dein Code ist total chaotisch. Du musst da dringend etwas mehr Struktur reinbringen. Es kommt mir so vor, als würdest du einfach irgendwo was reinschreiben ohne dir Gedanken darüber zu machen, was das eigentlich bedeutet. Überleg dir, wie oft und wann OpenFont aufgerufen wird und wie oft und wann CloseFont aufgerufen wird. Tipp: OpenFont nur im Konstruktor, CloseFont nur im Destruktor, jeweils nur ein einziges Mal.

39

18.05.2017, 17:00

Tipp: OpenFont nur im Konstruktor, CloseFont nur im Destruktor.

Genau das habe ich am Anfang auch schon vorgeschlagen (vielleicht habe ich mich auch undeutlich ausgedrückt, aber das wollte ich eigentlich damit sagen)
Albert Einstein sagte: "2 Stunden mit einem netten Mädchen fühlen sich an wie 20 Minuten, 20 Minuten auf einem heißen Ofen fühlen sich an wie 2 Stunden. - Das ist Relativität"

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

40

18.05.2017, 17:20

Warum rufst du den Destruktor explizit auf? Wenn du in jedem Durchlauf der Schleife ein neues Textobjekt benötigst dann nimm es aus deiner Klasse raus und steck es in deine Schleife. Dann wird es nach jedem Durchlauf automatisch wieder zerstört. Der Umgang mit Konstruktor und Destruktor ist eine wichtige Sache. Vielleicht guckst du dir das noch mal an.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Werbeanzeige