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

T0X

Frischling

  • »T0X« ist der Autor dieses Themas
  • Private Nachricht senden

1

21.04.2011, 02:24

Probleme beim Punktezähler

Hallo erstmal :)
Ich bin gerade dabei (wie im Buch vorgeschlagen), das Spiel aus dem letzen Kapitel zu erweitern. Ich bin schon relativ weit gekommen (Verschiedene Sounds, Hintergrundmusik, Explosions-Animationen für die Asteroiden), doch nun bin ich dabei einen Punktezähler zu machen und habe große Probleme.
Ich benutze dazu SDL_TTF.
Ich habe mir also eine neue Text-Klasse erstellt, die unter anderem eben die Punktzahl ausgeben soll. Diese sieht zur Zeit so aus:

Text.hpp:

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
#ifndef TEXT_HPP
#define TEXT_HPP

#include "CFramework.hpp"
#include <sstream>
#include <SDL_ttf.h>

using namespace std;

class CText
{
public:

    CText();
    ~CText();

    void Open (const int Size);

    void Write (const char *Text,
                int x_Pos, int y_Pos,
                int R, int G, int B);

    void Write (const int Number,
                int x_Pos, int y_Pos,
                int R, int G, int B);

private:

    TTF_Font *m_pFont;           // Zeiger auf Font
    SDL_Surface *m_pScreen; // Zeiger auf den Screen des Frameworks

};
#endif


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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include "Text.hpp"

// Konstruktor
//
// Aufgabe: Allgemeine Daten initialisieren
//
CText::CText ()
{

    // Zeiger auf Null setzen
    m_pScreen = NULL;
    m_pScreen = g_pFramework->GetScreen ();

}

// Open
//
// Schriftart öffnen und Zeiger auf die Schriftart zurückgeben
//
void CText::Open (const int Size)
{
    if (TTF_Init() == -1)
    {
        cout << "Konnte SDL_ttf nicht starten: " << endl << TTF_GetError () << endl;
    }
    m_pFont = TTF_OpenFont ("SF Comic Script.ttf", Size);

} // Open

// Write
// 
// Text auf Bildschrim ausgeben
//
void CText::Write (const char *Text, int x_Pos, int y_Pos, int R, int G, int B)
{
    // Farbe des Textes initialisieren
    SDL_Color m_TextColor = {R, G, B, 0};

    // Text rendern
    SDL_Surface *m_pTextOut;
    SDL_Rect m_Text_Pos;
    m_Text_Pos.x = x_Pos;
    m_Text_Pos.y = y_Pos;

    m_pTextOut = TTF_RenderText_Blended (m_pFont, Text, m_TextColor);
    SDL_BlitSurface (m_pTextOut, NULL, m_pScreen, &m_Text_Pos);

    if (m_pTextOut != NULL)
    {
    SDL_FreeSurface (m_pTextOut);
    }
    
}

// Write
//
// Aufgabe: Zahl auf Bildschrim ausgeben
//
void CText::Write (const int Number, int x_Pos, int y_Pos, int R, int G, int B)
{
    //
    // Zahl in char umwandeln
    stringstream Text;
    Text.clear ();
    Text.str ("");
    Text << Number;
    
    // Farbe des Textes initialisieren
    SDL_Color m_TextColor = {R, G, B, 0};

    // Text rendern
    SDL_Surface* m_pTextOut;
    SDL_Rect m_Text_Pos;
    m_Text_Pos.x = x_Pos;
    m_Text_Pos.y = y_Pos;

    m_pTextOut = TTF_RenderText_Solid (m_pFont, Text.str().c_str(), m_TextColor);
    SDL_BlitSurface (m_pTextOut, NULL, m_pScreen, &m_Text_Pos);

    if (m_pTextOut != NULL)
    {
    SDL_FreeSurface (m_pTextOut);
    }
    
}

// Destruktor
//
// Aufgabe: SDL_TTF schließen
//
CText::~CText ()
{
    TTF_CloseFont (m_pFont);
    TTF_Quit ();
}


Ich rufe die Funktionen so auf:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
CText *m_pScore;
m_pScore = NULL;
m_Score = new CText;

m_pScore->Open (32);
m_pScore->Write (5, 600, -60, 255, 255, 255);

if (m_pScore != NULL)
    {
        delete (m_pScore);
        m_pScore = NULL;
    }


Dann stürzt das Programm allerdings ab und es erscheint diese Fehlermeldung:

Quellcode

1
Unhandled exception at 0x6f4c27f4 in Asteroid1.exe: 0xC0000005: Access violation reading location 0x00000000.


Was ich im Debug-Modus bereits herausgefunden habe, ist, dass die Fehlermeldung in dieser Linie auftritt:

C-/C++-Quelltext

1
m_pTextOut = TTF_RenderText_Solid (m_pFont, Text.str().c_str(), m_TextColor);


Ansonsten habe ich nach 5-stündigen Suchen im Internet und in meinem Code immer noch keine Ahnung, wie ich das Problem lösen kann :(
Ich hoffe ihr könnt mir helfen.
Vielen Dank im Voraus
T0X

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

2

21.04.2011, 09:18

Hm, zunächst mal "SF Comic Script.ttf" erscheint mir recht komisch. Ich würde nie eine Datei mit Leerzeichen verwenden.
Mir war so, als müsste man eine Surface mittels "SDL_CreateRGBSurface" erstellen, bevor man etwas darauf malen kann, also in dem Fall

C-/C++-Quelltext

1
m_pTextOut = TTF_RenderText_Solid (m_pFont, Text.str().c_str(), m_TextColor);

vorher

C-/C++-Quelltext

1
SDL_Surface * m_pTextOut = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32,rmask, gmask, bmask, amask);
, aber sicher bin ich nicht, probiers mal aus.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Theinnersea

Frischling

Beiträge: 15

Wohnort: Böblingen

Beruf: Zahntechniker

  • Private Nachricht senden

3

21.04.2011, 11:08

Hi TOX,
probier es mal so
-->

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
void CText::Write (const int Number, int x_Pos, int y_Pos, int R, int G, int B)
{
    
 // Zahl in char umwandeln mit ostringstream
      
       string font_message; 
       ostringstream stream; 
    stream<<Number;  
    font_message = stream.str(); 
    stream.clear(); 
   
 // Farbe des Textes initialisieren
    SDL_Color m_TextColor = {R, G, B, 0};

    // Text rendern
    SDL_Surface* m_pTextOut = NULL; // hier den Zeiger auf NULL
    SDL_Rect m_Text_Pos;
    m_Text_Pos.x = x_Pos;
    m_Text_Pos.y = y_Pos;

    m_pTextOut = TTF_RenderText_Solid (m_pFont, font_message.c_str(), m_TextColor);
     
     if(!m_pTextOut)
    printf("Render Font failed: %s\n",TTF_GetError());
        
    

    if(SDL_BlitSurface (m_pTextOut, NULL, m_pScreen, &m_Text_Pos) == -1)
      printf("Blitting Font failed: %s\n",TTF_GetError());

    if (m_pTextOut != NULL)
    {
    SDL_FreeSurface (m_pTextOut);
     m_pTextOut = NULL;
    }


Und hier --> m_pScore->Write (5, 600, -60, 255, 255, 255); gibst du der y_pos ne negative Zahl was bedeutet das du dein Text nachher nicht siehst da er oberhalb der Screen liegt. Also 60 anstatt -60.
Hoffe es hilft.

Grüßle

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

21.04.2011, 11:18

Also ich würde ja eber tippen, dass "Text" hier "null" ist:

C-/C++-Quelltext

1
m_pTextOut = TTF_RenderText_Solid (m_pFont, Text.str().c_str(), m_TextColor);

Zumindest würde das zu der Fehlermeldung passen.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Theinnersea

Frischling

Beiträge: 15

Wohnort: Böblingen

Beruf: Zahntechniker

  • Private Nachricht senden

5

21.04.2011, 12:23

Könnte aber auch an m_pFont liegen das der Font nicht geladen wurde. Würde ich mal prüfen.

C-/C++-Quelltext

1
2
3
4
5
6
7
if (TTF_Init() == -1)
    {
        cout << "Konnte SDL_ttf nicht starten: " << endl << TTF_GetError () << endl;
    }
    m_pFont = TTF_OpenFont ("SF Comic Script.ttf", Size);
    if(!m_pFont)
       cout<<"Konnte Font nicht laden"<<endl;

Und m_pFont im Konstruktor davor auf NULL setzten.

Grüßle

T0X

Frischling

  • »T0X« ist der Autor dieses Themas
  • Private Nachricht senden

6

21.04.2011, 13:54

Danke erstmal für die schnellen vielen Antworten :)

Zitat von »Architekt«

Hm, zunächst mal "SF Comic Script.ttf" erscheint mir recht komisch. Ich würde nie eine Datei mit Leerzeichen verwenden.

Ich habe die Schriftart jetzt in arial.ttf geändert. Es funktioniert allerdings immer noch nicht.
Nachdem ich eure Fehlerüberprüfungen eingefügt habe, weiß ich aber nun das der Fehler sich nicht beim Rendern des Textes, sondern beim öffnen der Font befindet.
Das Problem liegt also bei:

C-/C++-Quelltext

1
m_pFont = TTF_OpenFont ("arial.ttf", Size);

Ich denke, dass irgendwas mit der Schriftart arial.ttf nicht stimmt. Genau diese Schriftart befindet sich aber in meinem C:\Windows\Fonts Verzeichnis.
Ich habe auch versucht, m_pFont im Konstruktor auf NULL zu setzen, was allerdings ebenfalls nichts brachte.

MCP

Alter Hase

Beiträge: 513

Wohnort: Paderborn

Beruf: Software-Entwickler

  • Private Nachricht senden

7

21.04.2011, 14:03

Hab von SDL nicht viel Ahnung, aber muss die Schriftart nicht im Verzeichnis liegen? Oder musst Du nicht den kompletten Pfad angeben?

T0X

Frischling

  • »T0X« ist der Autor dieses Themas
  • Private Nachricht senden

8

21.04.2011, 14:15

Ah jetzt funktioniert es. Vielen Dank :)
Ich habe zwar bereits ausprobiert, die Schriftart ins Verzeichnis zu legen, da habe ich es aber noch mit SF Comic Script.ttf versucht, mit der wohl irgendetwas nicht stimme. Jetzt mit arial.ttf funktioniert es.
Naja, ein sehr dummer Fehler von mir aber was solls :D
Trotzdem vielen Dank für die nette und schnelle Hilfe :)

TigerClaw25

unregistriert

9

07.04.2013, 17:40

Ich bekomme beim beenden folgende Meldung:

Eine Ausnahme (erste Chance) bei 0x67c093a2 in SDL_Game.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0xfeeeff2a.
Unbehandelte Ausnahme bei 0x67c093a2 in SDL_Game.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0xfeeeff2a.
Das Programm "[5084] SDL_Game.exe: Systemeigen" wurde mit Code -1073741819 (0xc0000005) beendet.

Anscheind wird der Fehler beim Freigeben in der Game::Quit erzeugt. UNd zwar beim freigeben von m_pFontLive und m_pFontNumb

Font.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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include "Font.h"

// Konstruktor
//
CFont::CFont()
{
    // Zeiger auf Screen holen
    m_pScreen = NULL;
    m_pScreen = g_pFramework->GetScreen ();
} // Konstruktor

// Destruktor
//
CFont::~CFont ()
{
    TTF_CloseFont (m_pFont);
    TTF_Quit ();
} // Destruktor

// LoadFont()
//
void CFont::LoadFont(const std::string sFilename, int size)
{

    if(!m_pFont)
    {
        std::cerr << "Konnte Schriftart nicht laden! Fehler: " << TTF_GetError() << std::endl;
    }

    m_pFont = TTF_OpenFont(sFilename.c_str (), size);

} // LoadFont()


// WriteFont()
//
void CFont::WriteFont (const char *Text, int x_Pos, int y_Pos, int R, int G, int B)
{
    // Farbe des Textes
    m_TextColor.r = R;
    m_TextColor.g = G;
    m_TextColor.b = B;

    m_pTextout = TTF_RenderText_Blended(m_pFont, Text, m_TextColor);
    // Position vom Text
    m_TextRect.x = x_Pos;
    m_TextRect.y = y_Pos;
    m_pScreen = g_pFramework->GetScreen();
    SDL_BlitSurface(m_pTextout, 0, m_pScreen, &m_TextRect);

    if (m_pTextout != NULL)
    {
        SDL_FreeSurface (m_pTextout);
    }

} // WriteFont()

// WriteNumber()
//
void CFont::WriteNumber (int Number, int x_Pos, int y_Pos, int R, int G, int B)
{

    // Zahl in char umwandeln
    stringstream Text;
    Text.clear ();
    Text.str ("");
    Text << Number;

    // Farbe des Textes
    m_TextColor.r = R;
    m_TextColor.g = G;
    m_TextColor.b = B;

    m_pTextout = TTF_RenderText_Blended(m_pFont, Text.str().c_str(), m_TextColor);
    // Position vom Text
    m_TextRect.x = x_Pos;
    m_TextRect.y = y_Pos;
    m_pScreen = g_pFramework->GetScreen();
    SDL_BlitSurface(m_pTextout, 0, m_pScreen, &m_TextRect);

    if (m_pTextout != NULL)
    {
        SDL_FreeSurface (m_pTextout);
    }

} // WriteNumber()


Gam

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include "Game.hpp"

// Konstruktor
//
// Aufgabe: Allgemeine Initialisierungen
//
CGame::CGame ()
{
    m_pPlayer = NULL;
    m_pSpriteBackground = NULL;
    m_pSpriteAsteroid = NULL;
} // Konstruktor

// Init
//
// Aufgabe: Spieler, Hintergrund und Asteroid initialisieren
//
void CGame::Init ()
{
    // Neuen Spieler initialisieren
    m_pPlayer = new CPlayer;
    m_pPlayer->Init ();
    m_pPlayer->Reset ();

    // Hintergrundbild (Sprite) laden
    m_pSpriteBackground = new CSprite;
    m_pSpriteBackground->Load ("Data/Background.bmp");

    // Sprite für Asteroiden laden
    m_pSpriteAsteroid = new CSprite;
    m_pSpriteAsteroid->Load ("Data/Asteroid.bmp", 20, 64, 64);
    m_pSpriteAsteroid->SetColorKey (255, 0, 255);

    // Sound laden
    m_pMusic = NULL; 
    m_pMusic = new CSound (44100, AUDIO_S16SYS, 2, 4096);
    m_pMusic->LoadMusic("Data/test.wav",100);
    m_pMusic->PlayMusic();

    // Sound für Asteroiden-Explosion laden
    m_pSoundAsteroid = NULL;
    m_pSoundAsteroid = new CSound (44100, AUDIO_S16SYS, 2, 4096);
    m_pSoundAsteroid->LoadSound("Data/Asteroid_Explosion.wav", 100);

    // Font Lebensenergie
    m_pFontLive = NULL;
    m_pFontLive = new CFont();
    m_pFontLive->LoadFont("Data/sfd/FreeMono.ttf", 15);

    // Font Lebensenergie - Anzahl
    m_pFontNumb = NULL;
    m_pFontNumb = new CFont();
    m_pFontNumb->LoadFont("Data/sfd/FreeMono.ttf", 15);

    // Timer für Asteroiden zurücksetzen
    m_fAsteroidTimer = 0.0f;

    // Spiel läuft
    m_bGameRun = true;
} // Init

// Quit
//
// Aufgabe: Instanzen freigeben
//
void CGame::Quit ()
{
    // Spieler freigeben
    if (m_pPlayer != NULL)
    {
        m_pPlayer->Quit ();
        delete (m_pPlayer);
        m_pPlayer = NULL ;
    }

    // Hintergrundsprite freigeben
    if (m_pSpriteBackground != NULL)
    {
        delete (m_pSpriteBackground);
        m_pSpriteBackground = NULL;
    }

    // Asteroidensprite freigeben
    if (m_pSpriteAsteroid != NULL)
    {
        delete (m_pSpriteBackground);
        m_pSpriteBackground = NULL;
    }

    // Hintergrundmusik freigeben
    if (m_pMusic != NULL)
    {
        delete (m_pMusic);
        m_pMusic = NULL;
    }

    // Sound für Asteroiden-Explosion freigeben
    if (m_pSoundAsteroid != NULL)
    {
        delete (m_pSoundAsteroid);
        m_pSoundAsteroid = NULL;
    }

    // Lebensenergie freigeben
    if (m_pFontLive != NULL)
    {
        delete (m_pFontLive);
        m_pFontLive = NULL;
    }

    // Lebenspunkte freigeben
    if (m_pFontNumb != NULL)
    {
        delete (m_pFontNumb);
        m_pFontNumb = NULL;
    }


} // Quit

// Run
//
// Aufgabe: Hauptschleife des Spiels
//
void CGame::Run ()
{
    // Hauptschleife des Spiels durchlaufen
    //
    while (m_bGameRun == true)
    {
        // Events bearbeiten
        ProcessEvents ();

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

        // Hintergrundbild rendern
        m_pSpriteBackground->Render ();

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

        // Neue Asteroiden hinzufügen
        SpawnAsteroids ();

        // Lebensenergie (Name)
        m_pFontLive->WriteFont("Lebensenergie:", 10, 550, 255, 20, 50);

        // Lebensenergie (Anzahl)
        m_pFontNumb->WriteNumber(10, 200, 550, 255, 20, 50);

        // Kollisionen prüfen
        CheckCollisions ();

        // Asteroiden rendern
        RenderAsteroids ();

        // Buffer flippen
        g_pFramework->Flip ();

    }

} // Run
e.cpp

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »TigerClaw25« (08.04.2013, 10:50)


10

07.04.2013, 22:23

TTF_Quit () gehört nicht in den Destruktor von CFont. Dadurch wird einmal TTF_CloseFont() nach TTF_Quit aufgerufen.

Werbeanzeige