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

Gelöschter Benutzer

unregistriert

1

02.12.2013, 20:39

SDL_ttf Text "laden" Problem

Sehr geehrtes Forum,
ich (mal wieder :) ) habe leider ein Problem mit der SDL_ttf. Ich verwende VisualStudio 2013. Ich möchte gerne einen Textauschnitt laden, welcher mit m_pFont->zeichneText("Hallo"); übergeben wird (in der "Game.cpp", Hauptschleife des Spiels). Da ich mich mit der SDL_ttf noch nicht so auskenne, habe ich aus diesem Beitrag klick-mich die Header und .cpp Datei kopiert. Sie sieht bei mir so aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef FONT_HPP
#define FONT_HPP

#include <SDL_ttf.h>

class CFont
{
public:
    void init();
    void setFont( TTF_Font *font);
    void zeichneText(char cText[]);
    ~CFont();

private:
    TTF_Font *m_font;           // Font-Datei
    SDL_Surface *m_surface;     // Auf dieses Surface wird dann geschrieben...
};
#endif

die "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
#include "Font.hpp"
#include <iostream>
#include <SDL_ttf.h>
#include "Framework.hpp"

using namespace std;

//Init mit Parametern
void CFont::init()
{
    //Initialisierung: SDL_ttf
    if(TTF_Init() == -1 )
    {
        cout << "SDL_ttf konnte nicht initialisiert werden!" << endl;
        cout << "Fehlermeldung:"<< SDL_GetError();
    }
    // Schriftart "FreeSans.ttf" laden.
    TTF_Font* m_font = TTF_OpenFont("Data\\FreeSans.ttf", 30);
    if(!m_font)
    {
       cout << "Konnte Schriftart nicht laden!" << endl;
       cout << "Fehlermeldung: " << TTF_GetError() << std::endl;
    }
    cout << "HALLO" << endl;
}//Init


//Destruktor
CFont::~CFont()
{
    if(m_surface != NULL)
    {
        delete(m_surface);
        m_surface = NULL;
    }
}//Desktruktor


//zeichneText: Text auf das Surface schreiben
void CFont::zeichneText(char cText[])
{
    SDL_Color textColor = {0, 0, 0};
    SDL_Surface *NewText;
    NewText = TTF_RenderText_Solid (m_font, cText, textColor);
    SDL_BlitSurface (NewText, NULL, g_pFramework->GetScreen (), NULL);
    SDL_FreeSurface(NewText);

}//zeichneText

Natürlich habe ich die Dateien entsprechend meines Falles gekürzt. Wenn ich nun den Debugger starte, kompiliert zwar das Programm, jedoch kommt bei "NewText = TTF_RenderText_Solid (m_font, cText, textColor);" immer ein Fenster, in welchem steht: "Unbehandelte Ausnahme bei 0x01135979 in RPG.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00000000". Leider weis ich nicht was ich falsch mache :dash: wenn ihr zusatzinfos braucht, einfach schreiben, ich werde versuchen alles so gut wie Möglich zu schildern,
mfG,
alex41018

patrick246

Treue Seele

Beiträge: 328

Wohnort: nahe Heilbronn/BW

Beruf: TG Profil Informatik-Schüler

  • Private Nachricht senden

2

02.12.2013, 20:48

Prüfe mal mit dem Debugger, ob einer der Parameter (speziell m_font) zufällig null ist.

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

3

02.12.2013, 21:58

Du solltest dich direkt an Konstruktoren und Destruktoren anstelle deiner init Methode gewöhnen. ;)
Und dein m_font member ist null, da du ihn verdeckst:

C-/C++-Quelltext

1
TTF_Font* m_font = TTF_OpenFont("Data\\FreeSans.ttf", 30);
Stichwort variable shadowing.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Gelöschter Benutzer

unregistriert

4

03.12.2013, 10:31

Wenn ich das richtig verstanden habe, speicher ich m_font dann in einer lokalen Variablen, d. h. sie ist nur in dieser Funktion ("init") verfügbar. Wenn ich dies aber so schreibe:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//Init
void CFont::init()
{
    //Initialisierung: SDL_ttf
    if(TTF_Init() == -1 )
    {
        cout << "SDL_ttf konnte nicht initialisiert werden!" << endl;
        cout << "Fehlermeldung:"<< SDL_GetError();
    }
    // Schriftart "FreeSans.ttf" laden.
    m_font = TTF_OpenFont("Data\\FreeSans.ttf", 30);
    if(!m_font)
    {
       cout << "Konnte Schriftart nicht laden!" << endl;
       cout << "Fehlermeldung: " << TTF_GetError() << endl;
    }
}//Init
kommt immer noch derselbe Fehler :dash:

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

5

03.12.2013, 10:38

Hast du denn deine init Methode (und ich rate dir hier immer noch zu einem Konstruktor) vorher aufgerufen und einmal geprüft, ob m_font beim zeichnen != NULL (bzw != nullptr) ist?
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Gelöschter Benutzer

unregistriert

6

03.12.2013, 10:51

Danke für die schnelle Antwort :) also init wird ganz sicher aufgerufen, weil ich ganz am Anfang von Init einen "cout"-Befehl mache (ich poste gleich den Code). ich kopiere einfach nochmal den ganzen code hierrein:
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
#include "Font.hpp"
#include <iostream>
#include <SDL_ttf.h>
#include "Framework.hpp"
#include <Windows.h>

using namespace std;

//Init
void CFont::init()
{
    cout << "init wurde aufgerufen!" << endl;
    //Initialisierung: SDL_ttf
    if(TTF_Init() == -1 )
    {
        cout << "SDL_ttf konnte nicht initialisiert werden!" << endl;
        cout << "Fehlermeldung:"<< SDL_GetError();
    }
    // Schriftart "FreeSans.ttf" laden.
    m_font = TTF_OpenFont("Data\\FreeSans.ttf", 30); //!!!!!!!!!Hier kommt jetzt der Fehler!!!!!!!!!
    if(m_font == NULL)
    {
       cout << "Konnte Schriftart nicht laden!" << endl;
       cout << "Fehlermeldung: " << TTF_GetError() << endl;
       Sleep(200000); //zum testen ob m_font == NULL
    }
}//Init


//Destruktor
CFont::~CFont()
{
    if(m_surface != NULL)
    {
        delete(m_surface);
        m_surface = NULL;
    }
}//Desktruktor


//zeichneText: Text auf das Surface schreiben
void CFont::zeichneText(char cText[])
{
    SDL_Color textColor = {0, 0, 0};
    SDL_Surface *NewText;
    NewText = TTF_RenderText_Solid (m_font, cText, textColor);
    SDL_BlitSurface (NewText, NULL, g_pFramework->GetScreen (), NULL);
    SDL_FreeSurface(NewText);

}//zeichneText

die zugehörige Header-Datei:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef FONT_HPP
#define FONT_HPP

#include <SDL_ttf.h>

class CFont
{
public:
    void init();
    void setFont( TTF_Font *font);
    void zeichneText(char cText[]);
    ~CFont();

private:
    TTF_Font *m_font;           // Font-Datei
    SDL_Surface *m_surface;     // Auf dieses Surface wird dann geschrieben...
};
#endif

Den Tipp mit dem Konstruktor werde ich auf jeden Fall beherzigen, doch dass greife ich erst an, wenn dieses Grundgerüst läuft :)

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

7

03.12.2013, 11:13

Hm, mich würde die Verwendung mal interessieren. Aber ansonsten: ich hatte mal denselben Fehler weil ich mit einer veralteten SDL_TTF.dll gearbeitet habe. Nachdem ich mir die neue geladen hatte lief alles wunderbar. Könntest du ja mal ausprobieren. ;)

edit:
delete(m_surface); ist eine ganz fatale Idee. Verwende SDL_FreeSurface. Auch wenn mir nicht ganz klar ist, wofür du diese Surface überhaupt benötigst.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

8

03.12.2013, 11:36

"NULL" ist außerdem ein "Gegurke", welches aus "Windows.h" kommt. Eigentlich nennt sich das in C++ nun "nullptr". Wozu genau Du "Windows.h" brauchst würde ich auch gern wissen. Schaff das ab.
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]

Gelöschter Benutzer

unregistriert

9

03.12.2013, 14:03

So, ich bin die ganzen Punkte mal durchgegangen. Hier mal als erstes der Code, den ich überarbeitet habe, natürlich werde ich mich dazu noch äußern:
die "Font.hpp"

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef FONT_HPP
#define FONT_HPP

#include <SDL_ttf.h>

class CFont
{
public:
    CFont();
    void init();
    void zeichneText(char cText[]);
    ~CFont();

private:
    TTF_Font *m_font;    // Font-Datei
};
#endif

Als nächstes die "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
#include <iostream>
#include <SDL_ttf.h>
#include "Font.hpp"
#include "Framework.hpp"

using namespace std;

//Konstruktor
CFont::CFont()
{
    m_font = TTF_OpenFont("Data\\FreeSans.ttf", 30);
    if(m_font == nullptr)
    {
       cout << "Konnte Schriftart nicht laden!" << endl;
       cout << "Fehlermeldung: " << TTF_GetError() << endl;
    }
    //Initialisierung: SDL_ttf
    if(TTF_Init() == -1 )
    {
        cout << "SDL_ttf konnte nicht initialisiert werden!" << endl;
        cout << "Fehlermeldung:"<< SDL_GetError();
    }
}

//Destruktor
CFont::~CFont()
{
}//Desktruktor

//zeichneText: Text auf das Surface schreiben
void CFont::zeichneText(char cText[])
{
    SDL_Color textColor = {0, 0, 0};
    SDL_Surface *NewText;
    NewText = TTF_RenderText_Solid (m_font, cText, textColor);
    SDL_BlitSurface (NewText, NULL, g_pFramework->GetScreen (), NULL);
    SDL_FreeSurface(NewText);
}//zeichneText

Nun, was zum drumrumerzählen :D wie aus meinem ersten beitrag hervor geht, habe ich als Anreiz für diese hpp und cpp diese Codevorlage (Klick mich :-) ) genommen, da ich noch nie mit SDL_ttf gearbeitet habe. Auf die SDL_ttf kam ich durch das Tutorial, welches sich oben im Bereich Tutorials befindet (das SDL-TUT). Die Schriftart downloadete ich von dem Tutorial, sie heißt FreeSans (was man dem Quellcode davor noch NIE entnehmen konnte :crazy: ). Das "nullptr" das gleiche ist wie "NULL" wusste ich nicht, ehrlich gesagt, ich habe noch nie was von "nullptr" gehört. Hat aber schon Verwendung gefunden. "Windows.h" brauchte ich für "Sleep", damit ich genau feststellen kann, wo alles zusammenbricht, eigentlich zeigt es mir der Debugger, aber ich wollte mich mal langsam herantasten (warum habe ich nicht cin.get(); genommen?). Die SDL_ttf habe ich auch schon ausgetauscht, nur das das Projekt überhaupt nicht mehr startet, bzw. es kommt die .exe, aber dann dieses tolle "Fehler"-Fenster. Die Surface habe ich jetzt ganz rausgeschmissen, ich wusste selber nicht für was ich die brauche, sie war halt im Code drin von der oben aufgeführten Seite (die KlickMich). Verwendung soll das ganze in meinem ersten kleinen Projekt finden, in dem man ab und zu Blöcke bekommt, die Anzahl der Blöcke soll angezeigt werden. Dazu wird die Funktion einmal in der Hauptschleife des Spieles aufgerufen (sieht so aus: "m_pFont->zeichneText("Hallo");"), natürlich gibt es in der "'Game.cpp" die #include <SDL_ttf.h>. Mehr fällt mir gerade nicht ein, was ich noch schreiben könnte, halt doch, genau: von hier habe ich die "SDL_ttf" her: KlickMich2 dort einfach unter Binary/Windows/SDL_ttf-devel-2.0.11-VC.zip. Vielen Dank für euer Engagement,
alex41018

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

10

03.12.2013, 15:19

Und was steht im Fehlerfenster drin? Immer noch Access Violation?
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Werbeanzeige