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

1

13.03.2014, 12:20

Dynamische Variablen in TTF-SDL

Hallo,

Aktuell arbeite ich an meinem ersten Projekt, einem einfachen Tic Tac Toe Spiel.
Folgende Situation bereitet mir jedoch Schwierigkeiten:

Jedes Mal wenn ein Spieler gewonnen hat, soll er einen Punkt erhalten. Dabei soll der Punktestand beider Spieler
auf dem Screen ersichtlich sein. Ich habe dabei mit der TTF SDL-Library zwei SDL_Textures kreiert welche auch auf dem Screen dargestellt werden.
Nun sollen jedoch die beiden Punktestand-Variablen (punktX sowie punkteO) jeweils neu geladen werden.
Wie mache ich dies?

Aktuell sieht es etwa so aus:
Ich lade einen String, dann generiere ich eine Klasse für den CText (dort geschieht alles mit TTF SDL-Library) und
lade dann das Bild.


C-/C++-Quelltext

1
2
3
4
5
    std::stringstream b;
    ppunkteO = &punkteO;
    b << "Player 2: " << punkteO;
    Spieler2 = new CText;
    Spieler2->LoadText (b.str().c_str(), { 0, 0, 0 }, ".../Tic Tac Toe/Tic Tac Toe/AvenirNext.ttc", 20, "Player 2");



Ausgegeben wird es dann an einer anderen Stelle:


C-/C++-Quelltext

1
    Spieler2->RenderText(40, 120, 110, 24, "Player 2")



Der Spielstand bleibt immer bei 0, whs. weil das Bild nur einmal geladen wird und die Renderfunktion ja keinen Einfluss auf den Text hat?
Ich blicke nicht mehr durch und hoffe jmd. kann mir helfen.

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

2

13.03.2014, 13:03

Du musst sie einmal erstellen und danach updaten. Dazu renderst du die von SDL_TTF_Render* zurück gegebene SDL_Surface einfach auf deine SDL_Texture.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Fawkes

Frischling

Beiträge: 58

Beruf: Realschüler :)

  • Private Nachricht senden

3

13.03.2014, 17:22

Erstell doch einfach einen Integer dessen Wert du dann einfach einem String zu weißt. Diesen String lässt du dann einfach bei jedem render Durchlauf rendern.

Pseudotext:

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
int pointsX, pointsY = 0;

    SDL_String sPointsX, sPointsX;

    sPointsX = "Player 1: " + pointsX;
    sPointsY = "Player 2: " + pointsY;



    int main(){

        ....


            while( running ){

                sPointsX = "Player 1: " + pointsX;
                sPointsY = "Player 2: " + pointsY;

                SDL_Render( sPointsX );
                SDL_Render( sPointsY );

            }


        ....
    }


Anmerkung: Da ich kein SDL verwende bin ich mir nicht sicher ob die Methoden die ich oben hingeschrieben habe richtig sind oder nicht.

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

4

13.03.2014, 19:42

Hab' noch nie was von SDL_String gehört oder dessen Eigenschaften, sich einfach so rendern zu lassen. O.o
Das Problem an SDL_TTF ist eben, dass jedesmal neuer Speicher angefordert wird, obgleich man schon eine SDL_Surface hat, die man vermeidlich wiederverwenden könnte. Da allerdings in der Regel jeder gerenderte Text unterschiedlich groß sein wird (die Grafik für den Punktestand 10 würde standardmäßig eine kleinere Grafik benötigen, als die für den Punktestand 1000) ist das irgendwie auch gerechtfertigt. Deswegen muss, sofern die bisherigen Pixel nicht manuell geändert werden [1], jedesmal eine erneute SDL_Texture aus der durch SDL_TTF generierten SDL_Surface erzeugt werden. Aber um zumindest ein wenig neu Erzeugung zu sparen, sollte man schon prüfen, ob sich der Punktestand verändert hat.

[1]:
Eine Änderung der Pixeldaten sollte auch nur dann geschehen, wenn beide SLD_Surfaces gleich groß sind. Also z.B. für die Punktestände 0 .. 9, 10 .. 99, 100 .. 999 etc.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Fawkes

Frischling

Beiträge: 58

Beruf: Realschüler :)

  • Private Nachricht senden

5

13.03.2014, 20:06

Ja wie gesagt, ich habe sdl noch nie benutzt. Ich dachte eher an sowas wie einen String der durch die library selber Grafisch dargestellt wird. Wie bei sfml.

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

6

13.03.2014, 20:21

Nein, sowas existiert nicht in der SDL.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

7

14.03.2014, 10:51

Danke für die Antworten. Ich bin mir leider immer noch nicht sicher wie es zu bewerkstelligen ist.
Hier meine Funktionen. Der Text (hier string textureText) wird ja bei der Erstellung der Surface schon verwendet.
Dies würde doch heissen, dass ich auch die Surface ständig updaten müsste?

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
bool CText::LoadText(string textureText, SDL_Color textColor, string fontFile, int fontSize, string id)
{
    
    // Font wird geladen
    fFont = TTF_OpenFont( fontFile.c_str(), fontSize );
    if( fFont == NULL )
    {
        cout << "Font konnte nicht geladen werden: " << SDL_GetError () << endl;
        return false;
    }
    else
    {
    
    // Der Text wird auf eine Surface gerendert
    SDL_Surface* textSurface = TTF_RenderText_Blended(fFont, textureText.c_str(), textColor );
    if( textSurface == NULL )
    {
        cout << "Text Surface konnte nicht gerendert werden: " << SDL_GetError () << endl;
        return 0;
    }
    else
    {
        // Von Surface zu einer Texture
        textTexture = SDL_CreateTextureFromSurface(r_pRenderer, textSurface);
        if( textTexture == NULL )
        {
            cout << "Text Template konnte nicht gerendert werden: " << SDL_GetError () << endl;
            return 0;
        }
        else
        {
            // Bild Dimension eintragen
            fWidth = textSurface->w;
            fHeight = textSurface->h;
        }
        
        // Alte Surface löschen
        SDL_FreeSurface( textSurface );
    }
    }
    // Erfolg!
    textImage[id] = textTexture;
    return true;
}



C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//
// RENDER TEXT
//
void CText::RenderText(int x, int y, int width, int height, string id)
{
    SDL_Rect srcRect;
    SDL_Rect destRect;
    srcRect.x = 0;
    srcRect.y = 0;
    srcRect.w = destRect.w = width;
    srcRect.h = destRect.h = height;
    destRect.x = x;
    destRect.y = y;
    SDL_RenderCopy(r_pRenderer, textImage[id], &srcRect, &destRect);
} // RENDER

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

8

14.03.2014, 12:25

Du musst sie ständig updaten bzw. die Texture neu erstellen, sofern der Punktestand mit dem vorherigen nicht übereinstimmt, ja.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

9

14.03.2014, 12:30

Alles klar. Braucht dies nicht massiv viel Speicher? Ich müsste doch die alten Texturen dann irgendwie wieder löschen?

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

10

14.03.2014, 12:31

Du musst sie ständig updaten bzw. die Texture neu erstellen, sofern der Punktestand mit dem vorherigen nicht übereinstimmt, ja.

Aber dann wäre es doch einfacher, das Updaten genau dann durchzuführen, wenn die Punktezahl aktualisiert wurde.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Werbeanzeige