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

09.11.2010, 22:20

SDL Highscore Problem

8| Hallo zusammen!

Ich bin seit ein paar Tagen mit dem Buch "C++ für Spieleprogrammierer" durch und habe das Spiel, das am Ende kommt, bereits um Explosionen, ein Menü (wenn auch nur in der Konsole) und um eine Text/Punktanzeige erweitert.
Jetzt will ich noch, dass die Punkte, die man erreicht hat, wenn man "Escape" drückt bzw. das Spiel verlässt, in 3 Dateien gespeichert werden (1 für Punkte, 1 für Namen und 1 für die Anzahl der Asteroiden, die man zerstört hat).
Für die Anzahl der Asteroiden und die Punkte habe ich 2 Variablen, die jeweils um den entsprechenden Wert erhöht werden, wenn ein Schuss mit einem Asteroiden kollidiert.
Für das Schreiben, lesen und prüfen des HG habe ich mir eine Klasse geschrieben. Der Name wird nach beenden des Spiels in der Konsole abgefragt.

Das Problem ist jetzt folgendes:
Sobald das Spiel beendet wird, verabschiedet es sich mit "Spiel_SDL.exe funktioniert nicht mehr...".
An der ReadHighscore () und OutHighscore () Funktion meiner Klasse kann es meiner Meinung nach nicht liegen, da ich diese bereits im Menü testen kann ((2)Highscore anzeigen).
Der Fehler muss also irgendwo in der WriteHighscore () liegen, allerdings finde ich den Fehler nicht.

Außerdem habe ich die letzte Version die funktionierte (also ohne das ganze Highscore zeug) mal an 2 Freunde geschickt, um zu testen, jedoch fehlte bei beiden die MSVCR71.dll, msvcp100.dll sowie ein paar weitere mit ähnlichen Namen. Dem einen konnte ich die dlls meines PCs schicken, womit es dann klappte. Beim anderen half das jedoch auch nichts, dort wurde der Einsprungpunkt in der MSVCR71.dll nicht gefunden. Hat jemand ne Ahnung was es damit auf sich hat?
Compiliert wurde das ganze mit VS C++ 2010 Express.

Hier ist der Code:

Hier ein Auszug aus der Main.cpp, wie ich den Highscore im Menü auslese.

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
int main (int argc, char *argv[])
{   
    int Auswahl;
    // Instanz des Highscores anlegen
    CHighscore HG;


    do
    {

        cout << endl;
        cout << "-----------------" << endl;
        cout << "(1) Spiel starten" << endl;
        cout << "(2) Highscore anzeigen" << endl; 
        cout << "(3) Steuerung anzeigen" << endl;  
        cout << "(4) Beenden" << endl; 
        cout << endl; 

        cin >> Auswahl;

        switch (Auswahl)
        { 
            //......

            case (2):
            {
                HG.OutHighscore (); 

                cout << endl;  
        
            } break; 



Hier der Auszug aus der CGame.cpp, wie ich das ganze am Ende aufrufe:

  1. C-/C++-Quelltext

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    while (m_bGameRun == true)
         {
               // Events bearbeiten 
               ProcessEvents (); 
               
               // .......
               
               // Buffer flippen 
               g_pFramework->Flip (); 
         }
        // Highscore prüfen 
        m_pHighscore->NewHighscore (m_Punkte, m_AsteroidCounter); 
    
    }




    Hier die CHighscore.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
    34
    35
    
    #ifndef HIGHSCORE_HPP
    #define HIGHSCORE_HPP
    
    #include "CText.hpp"
    #include <fstream> 
    #include <iostream>
    
    class CHighscore
    {
    public: 
        CHighscore (); 
    
        void ReadHighscore ();  // m_Punkte sind die Punkte aus der CGame Klasse
        void OutHighscore ();  // m_AsteroidCounter ist der Zähler für die Asteroiden aus der CGame Klasse
        void NewHighscore (int m_Punkte, int m_AsteroidCounter); 
        void WriteHighscore (int m_Punkte, int m_AsteroidCounter); 
    
    private: 
        ofstream m_HGName; // Name des Highscore Besitzers stream
        ofstream m_HGPunkteDat; // Punkte des Highscores stream
        ofstream m_HGAst; // Zähler der asteroiden stream
        ifstream m_HG_Ast; 
        ifstream m_HG_Name;
        ifstream m_HG_PunkteDat; 
        
        string m_DatName; // Name der Name datei 
        string m_DatPkt; // Name der Pkt datei
        string m_DatAst; // Name der Ast. Zähler datei
        string m_PlayerName; // SpielerName
    
        int m_HGPunkte; // zum speichern der HG-Punkte 
        int m_HGAsteroidCounter; // zum speichern der zerstörten HG-Asteroiden
    }; 
    
    #endif 



    und hier die CHighscore.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
    
    #include "CHighscore.hpp"
    
    
    // Konstruktor 
    // Aufgabe: Werte initialisieren 
    CHighscore::CHighscore ()
    {
        m_DatName = "Name.hsg"; 
        m_DatPkt = "Pkt.hsg"; 
        m_DatAst = "Ast.hsg"; 
        m_HGPunkte = 0; 
        m_HGAsteroidCounter = 0; 
    }
    
    
    // Read Highscore 
    // Aufgabe: Highscore Lesen und ggf. überschreibung einleiten, wenn neuen HG größer
    void CHighscore::ReadHighscore ()
    {
    
        // Punkte lesen, zwischenspeichern und datei wieder schließen 
        m_HG_PunkteDat.open(m_DatPkt.c_str(), ios_base::in); 
        m_HG_PunkteDat >> m_HGPunkte; 
        m_HG_PunkteDat.close (); 
        
        // Name Lesen, zwischenspeichern und datei wieder schließen 
        m_HG_Name.open(m_DatName.c_str(), ios_base::in); 
        m_HG_Name >> m_PlayerName; 
        m_HG_Name.close(); 
    
        // Asteroiden Zähler lesen, zwischenspeichern und datei wieder schließen
        m_HG_Ast.open(m_DatAst.c_str(), ios_base::in); 
        m_HG_Ast >> m_HGAsteroidCounter; 
        m_HG_Ast.close(); 
    
    } 
    
    // Out Highscore 
    // Aufgabe: Highscore auf der Konsole ausgeben
    void CHighscore::OutHighscore ()
    {
        // Highscore lesen 
        ReadHighscore (); 
    
        // Punkte sowie Namen des aktuellen Highscores ausgeben
        cout << endl;  
        cout << "-Highscore-" << endl; 
        cout << "-----------" << endl;
        cout << "Name: " << m_PlayerName << endl; 
        cout << "Punkte: " << m_HGPunkte << endl; 
        cout << "Zerstoerte Asteroiden: " << m_HGAsteroidCounter << endl; 
        cout << endl; 
    }
    
    // NewHighscore 
    // Aufgabe: Prüfen ob neuer Highscore 
    void CHighscore::NewHighscore (int m_Punkte, int m_AsteroidCounter) 
    {
        ReadHighscore (); // Highscore lesen
    
        if (m_Punkte > m_HGPunkte)
        {     
            cout << "Neuer Highscore!" << endl; 
            cout << "Namen eingeben:"; 
            cin.get(); // cin leeren
            getline (cin, m_PlayerName); 
            OutHighscore (); 
            cin.get(); // um das Fenster offen zu halten
        } 
    }
    
    // Write Highscore 
    // Aufgabe: Highscore writen, wenn höher als der aktuelle
    void CHighscore::WriteHighscore (int m_Punkte, int m_AsteroidCounter)
    {
        // Punkte schreiben und schließen 
        m_HGPunkteDat.open(m_DatPkt.c_str(), ios_base::out); 
        m_HGPunkteDat << m_Punkte; 
        m_HGPunkteDat.close (); 
        
        // Name schreiben und schließen 
        m_HGName.open(m_DatName.c_str(), ios_base::out); 
        m_HGName << m_PlayerName; 
        m_HGName.close(); 
    
        // Asteroiden schreiben und schließen
        m_HGAst.open(m_DatAst.c_str(), ios_base::out); 
        m_HGAst << m_AsteroidCounter; 
        m_HGAst.close(); 
    }




Danke an alle die mir helfen :)

idontknow

unregistriert

2

09.11.2010, 22:33

Die beiden muessen natürlich die vc++ Runtime installieren!!

3

09.11.2010, 22:38

Hi Chaia*,

also um den Post von idontknow noch zu ergänzen, falls du nicht genau weißt was gemeint ist: Microsoft Visual C++ 2010 Redistributable Package
Das musst du letzten Endes fast immer mit deinen Spielen mitliefern bzw. darauf verweisen, weil sonst wohl kaum eins deiner Programme auf einem Nicht-Entwickler-PC laufen wird.

Zu deinem Problem: Benutz doch mal den Debugger. Du könntest z.B. damit anfangen, dass du einen Haltepunkt setzt und dir anschaust ob das Programm bis dorthin durchläuft etc. So kannst du die Fehlerquelle besser lokalisieren.

Gruß
SaRu_

4

09.11.2010, 23:02

Okay danke, dann werd ich es ihnen mal sagen :)

Das mit dem Debuggen ist so ne Sache...
Im Konsolenfenster ist das kein Problem, aber sobald ich irgendwie in den Fenstermodus der SDL gelange ploppt das Fenster nur kurz auf und die Anwendung ist beendet. Haltepunkte sind natürlich erstellt.

Dabei bekomme ich dann folgende Meldung:

Quellcode

1
2
Der Thread 'Win32-Thread' (0xcc4) hat mit Code 1 (0x1) geendet.
Das Programm "[4708] Spiel_SDL.exe: Systemeigen" wurde mit Code 1 (0x1) beendet.


und es werden sehr viele dlls geladen, wobei bei so ziemlich allen das PDB File nicht gefunden bzw. geöffet werden konnte. (was auch immer das ist ?( )

lg

5

09.11.2010, 23:48

wobei bei so ziemlich allen das PDB File nicht gefunden bzw. geöffet werden konnte.

Das kannst du guten Gewissens ignorieren. ;) Falls du dich da weiter erkundingen möchtest, dann könntest du danach googlen. Müsstest einen Symbolserver eintragen, von dem die Dateien beim Erstellen geladen werden. Aber das verlängert die Buildtime und hat für dich so erstmal keinen Nutzen.

Du solltest vielleicht bevor du das Programm mit return 1 beendest noch eine Fehlermeldung ausgeben, dann kannst du zurückverfolgen, wo der Fehler liegt.

Gruß
SaRu_

6

10.11.2010, 06:57

naja also wie gesagt, wenn ich das Spiel mit dem debugger bzw. aus VS C++ raus starten will ploppt es nur kurz auf.
Ich meine dort noch in der Konsole gesehen zu haben, dass meine Sprites nicht geladen werden konnten, aber warum weiß ich nicht.
VS C++ ist im Admin Modus gestartet und der Data Ordner liegt der exe auch bei. Wenn ich es außerhalb ausführe klappt alles.

MCP

Alter Hase

Beiträge: 513

Wohnort: Paderborn

Beruf: Software-Entwickler

  • Private Nachricht senden

7

10.11.2010, 09:30

naja also wie gesagt, wenn ich das Spiel mit dem debugger bzw. aus VS C++ raus starten will ploppt es nur kurz auf.
Ich meine dort noch in der Konsole gesehen zu haben, dass meine Sprites nicht geladen werden konnten, aber warum weiß ich nicht.
VS C++ ist im Admin Modus gestartet und der Data Ordner liegt der exe auch bei. Wenn ich es außerhalb ausführe klappt alles.

Die Dateien müssen in dem Projektordner liegen, damit sie gefunden werden, oder Du änderst den Projektpfad auf das Debug- und Release Verzeichnis, je nach Konfiguration.

TGGC

1x Rätselkönig

Beiträge: 1 799

Beruf: Software Entwickler

  • Private Nachricht senden

8

10.11.2010, 09:32

Was hat das Ganze mit SDL zu tun?

9

10.11.2010, 14:38

Das "Spiel" aus dem Buch (welches ja hier von mir erweitert wurde) nutzt die SDL für Grafik und Eingaben.
Aber du hast Recht, mein Problem hat wahrscheinlich nichts damit zu tun.
Hab mir jetzt mit dem Debugger die Stelle angesehen, an der die Funktion aufgerufen wird und habe herausgefunden, dass die 3 ofstreams fehlerhaft sind und sich die Namen der 3 Dateien in die sie geschrieben werden geändert haben. Die Datei für den Namen hieß plötzlich Pkt.hsg und die für die Punkte hieß Ast.hsg. Die Datei für die Asteroiden hatte gar keinen Namen. Und ich denke da war der Fehler, da man ja keine Dateien erstellen kann, die keinen Namen haben. Daraufhin habe ich eine Init Funktion geschrieben, die das macht, was ich eigentlich im Konstruktor hatte.
Jetzt funktioniert alles soweit.

Danke an alle die mir geholfen haben :)


Edit:

Ich hätte da noch eine Frage, zu meinen Explosionen:

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
// RenderExlosion
// Aufgabe: Alle Explosionen rendern und updaten
void CGame::RenderExplosion ()
{
 
  list<CExplosion>::iterator It = m_ExplosionList.begin (); 

  

  while (It != m_ExplosionList.end ())
  {
    It->Init(m_pSpriteExplosion ,m_fXPos, m_fYPos);
    It->g_fExplosionTimer = It->g_fExplosionTimer + 0.02f; 
    
    It->Render ();
    It->Update ();


    if (It->g_fExplosionTimer > 0.1f)
        It->SetAlive(false); 

    if (It->IsAlive ())
       It++; 
            
    else 
        It = m_ExplosionList.erase (It);
           

  }

}


Im Moment ist es so, dass, wenn ich einen Asteroiden treffe, eine Explosion an diesem Punkt gerendert wird und er erst verschwindet, wenn ich den nächsten abschieße. Ich hätte aber gerne, dass mehrere Gleichzeitig dargestellt werden können und nach einer gewissen Zeit verschwinden bzw. wenn die Variable g_fExplosionTime 0.1 erreicht hat. Ich dazu hätte gerne, dass die Variable g_fExplosionTime jede Runde um 0.02 erhöht wird.
Ich hatte mir das eigentlich so vorgestellt:
Jeder Eintrag in der Liste besitzt eine eigene g_fExplosionTime Variable, die dann eben jede Runde erhöht wird. Dann wird, wenn Wert 0.1 erreicht ist, der Eintrag gelöscht.

Aber anscheinend ist es nicht so. Habe mir die Variable mal per cout angeschaut, sie bleibt immer bei 0.02 - bei jedem Eintrag und jeder Runde. Außerdem werden nicht die einzelnen Einträge gleichzeitig gerendert sondern, wie oben beschrieben immer nur einer, bis ich den nächsten abschieße.

Wenn eine Kollision erkannt wird, habe ich einen neuen Eintrag in der Liste erstellt. (per push back)
Die Variablen m_fXPos und m_fYPos speichern immer die Koordinaten des eben abgeschossenen Asteroiden.

Kann mir jemand verraten, wie ich das anständig hinbekomme, bzw. so wie ich es mir vorstelle?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Chaia*« (10.11.2010, 22:29)


Werbeanzeige