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

30.03.2012, 16:32

Mein erstes Spiel lässt sich nicht richtig beenden

Hallo erstmal,
ich bin dabei mein erstes selbsterstelltes 3D-Spiel zu programmieren. Bin auch schon fast fertig aber hab noch folgendes Problem: wenn ich im Menü das Spiel beenden will habe ich auf meinem Bildschirm noch das Bild meines Spiels und kann effektiv nichts mehr machen. Taskmanager lässt sich zwar aufrufen, ist aber hinter dem Bild und ich kann nicht auf ihn zugreifen. Habe jetzt lange darüber gerätselt aber keine Lösung gefunden.

Ich hoffe ihr könnt mir helfen.

Hier ist der Quellcode von meinem Menü(ich verwende die Tribase):

Quellcode

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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/*
**  MARBEL
**  ==========
**
**  MainMenu.cpp
**  ------------
**  Das Hauptmenü
*/

#include "Marbel.h"


// __________________________________________________________________
// Vertizes für das Hintergrundbild
struct SBackgroundVertex
{
    tbVector3           vPosition;
    float               fRHW;
    D3DCOLOR            Color;
    tbVector2           vTex0;
    static const DWORD  dwFVF;
};

const DWORD SBackgroundVertex::dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1;

// __________________________________________________________________
// Initialisiert den Spielzustand
tbResult CMainMenu::Init()
{
    // Laden...
    if(Load()) TB_ERROR("Fehler beim Laden des Spielzustands!", TB_ERROR);

    // Menücursor auf 0 setzen
    m_iCursor = 0;

    return TB_OK;
}

// __________________________________________________________________
// Fährt den Spielzustand herunter
tbResult CMainMenu::Exit()
{
    // Entladen...
    Unload();

    return TB_OK;
}

// __________________________________________________________________
// Lädt den Spielzustand
tbResult CMainMenu::Load()
{
    // Hintergrundbild laden
    m_pBackground = tbTextureManager::Instance().GetTexture("Data\\MainMenu.png");
    if(m_pBackground == NULL) TB_ERROR("Fehler beim Laden von Data\\MainMenu.png!", TB_ERROR);

    return TB_OK;
}

// __________________________________________________________________
// Entlädt den Spielzustand
tbResult CMainMenu::Unload()
{
    // Hintergrundbild löschen
    tbTextureManager::Instance().ReleaseTexture(m_pBackground);

    return TB_OK;
}

// __________________________________________________________________
// Bewegt den Spielzustand
tbResult CMainMenu::Move(float fTime)
{
    if(!m_bShowingHelp)
    {
        // Wenn die Taste nach unten/oben gedrückt wurde, muss der Cursor
        // des Hauptmenüs bewegt werden.
        if(g_pbButtons[TB_KEY_UP])
        {
            m_iCursor--;
            tbDelay(100);
        }
        if(g_pbButtons[TB_KEY_DOWN])
        {
            m_iCursor++;
            tbDelay(100);
        }

        // Cursor in die Grenzen weisen
        if(m_iCursor < 0) m_iCursor = 2;
        if(m_iCursor > 2) m_iCursor = 0;
    }

    // Wenn die Enter-, Leer- oder Return-Taste gedrückt wurde,
    // dann möchte der Benutzer einen Eintrag auswählen oder
    // den Hilfetext wieder ausblenden.
    if(g_pbButtons[TB_KEY_RETURN] ||
       g_pbButtons[TB_KEY_NUMPADENTER] ||
       g_pbButtons[TB_KEY_SPACE])
    {

        if(!m_bShowingHelp)
        {
            // Nun kommt es darauf an, was gerade ausgewählt ist!
            switch(m_iCursor)
            {
            case 0: // Spiel starten
                // Spielzustand auf GS_GAME setzen
                g_pMarbel->SetGameState(GS_GAME);
                break;

            case 1: // Hilfe anzeigen
                m_bShowingHelp = TRUE;
                tbDelay(1000);
                break;

            case 2: // Spiel beenden
                PostQuitMessage(0);
                break;
            }
        }
        else
        {
            // Die Hilfe wieder deaktivieren
            m_bShowingHelp = FALSE;
            tbDelay(1000);
        }
    }

    return TB_OK;
}

// __________________________________________________________________
// Rendert den Spielzustand
tbResult CMainMenu::Render(float fTime)
{
    SBackgroundVertex   aVertex[4];
    char*               apcMenuEntry[3] = {"Spiel starten",
                                           "Hilfe anzeigen",
                                           "Spiel beenden"};
    tbVector2           vPosition;
    tbColor             Color;


    // Puffer leeren und Szene beginnen
    tbDirect3D& D3D = tbDirect3D::Instance();
    D3D->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, tbColor(0.0f, 0.0f, 0.0f), 1.0f, 0);
    D3D->BeginScene();

    // ------------------------------------------------------------------

    // Vertexformat und Hintergrundbildtextur setzen, Z-Buffer aus
    D3D.SetFVF(SBackgroundVertex::dwFVF);
    D3D.SetTexture(0, m_pBackground);
    D3D.SetRS(D3DRS_ZENABLE, D3DZB_FALSE);

    // Die vier Vertizes des Bilds erstellen (Rechteck)
    // Links unten
    aVertex[0].vPosition = tbVector3(0.0f, D3D.GetScreenSize().y, 0.5f);
    aVertex[0].fRHW = 1.0f;
    aVertex[0].Color = tbColor(1.0f, 0.8f, 0.8f);
    aVertex[0].vTex0 = tbVector2(0.0f, 1.0f);

    // Links oben
    aVertex[1].vPosition = tbVector3(0.0f, 0.0f, 0.0f);
    aVertex[1].fRHW = 1.0f;
    aVertex[1].Color = tbColor(0.8f, 1.0f, 0.8f);
    aVertex[1].vTex0 = tbVector2(0.0f, 0.0f);

    // Rechts unten
    aVertex[2].vPosition = tbVector3(D3D.GetScreenSize().x, D3D.GetScreenSize().y, 0.5f);
    aVertex[2].fRHW = 1.0f;
    aVertex[2].Color = tbColor(0.8f, 0.8f, 1.0f);
    aVertex[2].vTex0 = tbVector2(1.0f, 1.0f);

    // Rechts oben
    aVertex[3].vPosition = tbVector3(D3D.GetScreenSize().x, 0.0f, 0.5f);
    aVertex[3].fRHW = 1.0f;
    aVertex[3].Color = tbColor(1.0f, 1.0f, 0.8f);
    aVertex[3].vTex0 = tbVector2(1.0f, 0.0f);

    // Als Dreiecksfolge zeichnen
    D3D->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, aVertex, sizeof(SBackgroundVertex));

    // ------------------------------------------------------------------

    if(!m_bShowingHelp)
    {
        g_pMarbel->m_pFont1->Begin();

        // Die Menüeinträge zeichnen
        for(int iEntry = 0; iEntry < 3; iEntry++)
        {
            // Die Position für den Text dieses Eintrags berechnen
            vPosition.x = 0.5f;
            vPosition.y = 0.4f + (float)(iEntry) * 0.125f;

            // Wenn der Cursor auf diesem Eintrag liegt, dann schwingt
            // er sinusförmig hin und her.
            if(m_iCursor == iEntry) vPosition.x += 0.05f * sinf(g_pMarbel->m_fTime);

            // Die Farbe berechnen.
            // Normalerweise ist ein Eintrag dunkelblau.
            // Wenn der Cursor aber darauf liegt, dann ist er heller.
            if(m_iCursor != iEntry) Color = tbColor(0.3f, 0.3f, 0.9f, 0.75f);
            else Color = tbColor(0.5f, 0.5f, 1.0f, 1.0f);

            // Den Text zeichnen
            g_pMarbel->m_pFont1->DrawText(vPosition, apcMenuEntry[iEntry],
                                              TB_FF_ALIGN_HCENTER | TB_FF_ALIGN_HCENTER | TB_FF_RELATIVE | TB_FF_RELATIVESCALING,
                                              -1, Color, Color + tbColor(-0.3f, 0.4f, 0.0f), tbVector2(1.5f, 1.5f));
        }

        g_pMarbel->m_pFont1->End();
    }
    else
    {
        // Hilfe anzeigen
        g_pMarbel->m_pFont2->Begin();
        g_pMarbel->m_pFont2->DrawText(tbVector2(0.5f, 0.55f), "Bewegen Sie die Kugel durch das Brett.", TB_FF_ALIGN_HCENTER | TB_FF_ALIGN_VCENTER | TB_FF_RELATIVE | TB_FF_RELATIVESCALING);
        g_pMarbel->m_pFont2->DrawText(tbVector2(0.5f, 0.6f), "Sie steuern das Brett mit der Maus!", TB_FF_ALIGN_HCENTER | TB_FF_ALIGN_VCENTER | TB_FF_RELATIVE | TB_FF_RELATIVESCALING);
        g_pMarbel->m_pFont2->DrawText(tbVector2(0.5f, 0.65f), "Je schneller Sie sind, desto mehr Punkte gibt's.", TB_FF_ALIGN_HCENTER | TB_FF_ALIGN_VCENTER | TB_FF_RELATIVE | TB_FF_RELATIVESCALING);
        g_pMarbel->m_pFont2->DrawText(tbVector2(0.5f, 0.7f), "Mit [Q] Musik ein- und ausschalten.", TB_FF_ALIGN_HCENTER | TB_FF_ALIGN_VCENTER | TB_FF_RELATIVE | TB_FF_RELATIVESCALING);
        g_pMarbel->m_pFont2->DrawText(tbVector2(0.5f, 0.75f), "Mit [P] pausieren.", TB_FF_ALIGN_HCENTER | TB_FF_ALIGN_VCENTER | TB_FF_RELATIVE | TB_FF_RELATIVESCALING);
        g_pMarbel->m_pFont2->DrawText(tbVector2(0.5f, 0.8f), "Viel Spass!", TB_FF_ALIGN_HCENTER | TB_FF_ALIGN_VCENTER | TB_FF_RELATIVE | TB_FF_RELATIVESCALING);
        g_pMarbel->m_pFont2->End();
    }

    // ------------------------------------------------------------------

    // Szene beenden
    D3D->EndScene();

    return TB_OK;
}

ich habe jetzt den ganzen Code geschickt, weil ich nicht weiß wo der Fehler liegt.

Ich bedanke mich schonmal bei jeder Hilfe :thumbsup:

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »setset1994« (30.03.2012, 16:49)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

30.03.2012, 16:59

Debugger benutzen. Wirklich, das Ding hilft mehr als hier im Forum eine Menü-Klasse zu posten und alle raten zu lassen wie der Rest vom Spiel wohl funktioniert.
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]

3

30.03.2012, 17:52

Das Problem ist nur ich mach das ganze schon mit einem Debugger und wenn das Problem auftritt seh ich nur noch meinen Hintergrund vom Menü, die Maus und nichts weiter. Mir ist aber aufgefallen, dass dies nur im Vollbildmodus passiert.

Hier auch noch meine Hauptklasse(gekürzt):

Quellcode

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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
#include "Marbel.h"


// __________________________________________________________________
// Globale Variablen
CMarbel*        g_pMarbel = NULL;
float*          g_pfButtons = NULL;
BOOL*           g_pbButtons = NULL;

// __________________________________________________________________
// Windows-Hauptfunktion
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   char* pcCommandLine,
                   int iShowCommand)
{
    tbResult r;

    // Spiel initialisieren
    g_pMarbel = new CMarbel;
    r = g_pMarbel->Init();
    if(r == TB_CANCELED)
    {
        // Der Konfigurationsdialog wurde abgebrochen!
        // Das Programm "leise" verlassen.
        TB_SAFE_DELETE(g_pMarbel);
        return 0;
    }
    else if(r)
    {
        g_pMarbel->Exit();
        TB_SAFE_DELETE(g_pMarbel);
        MessageBox(NULL, "Fehler beim Initialisieren des Spiels!",
                   "Fehler", MB_OK | MB_ICONEXCLAMATION);
        return 1;
    }

    // Spiel laufen lassen
    if(g_pMarbel->Run())
    {
        g_pMarbel->Exit();
        TB_SAFE_DELETE(g_pMarbel);
        MessageBox(NULL, "Fehler im Spiel!",
                   "Fehler", MB_OK | MB_ICONEXCLAMATION);
        return 1;
    }

    // Spiel verlassen
    g_pMarbel->Exit();
    TB_SAFE_DELETE(g_pMarbel);

    return 0;
}

// __________________________________________________________________
// Initialisiert das Spiel komplett
tbResult CMarbel::Init()
{
    tbResult r;

    // Alles zurücksetzen
    ZeroMemory(this, sizeof(CMarbel));

    // Die TriBase-Engine initialisieren und den Konfigurationsdialog aufrufen
    if(tbInit()) return TB_ERROR;
    r = tbDoConfigDialog(&m_Config);
    if(r == TB_CANCELED) return TB_CANCELED;
    else if(r) TB_ERROR("Engine konnte nicht initialisiert werden!", r);

    // Laden...
    if(Load()) TB_ERROR("Fehler beim Laden des Spiels!", TB_ERROR);

    // Klassen für alle Spielzustände erstellen
    m_pIntro = new CIntro;
    m_pMainMenu = new CMainMenu;
    m_pGame = new CGame;

    // Wir beginnen beim Intro!
    SetGameState(GS_INTRO);

    return TB_OK;
}

// __________________________________________________________________
// Fährt das Spiel herunter
tbResult CMarbel::Exit()
{
    // Kein Spielstatus (aktuellen Spielstatus entladen)
    SetGameState(GS_NONE);

    // Entladen...
    Unload();

    // Die Klassen für die Spielzustände löschen
    TB_SAFE_DELETE(m_pIntro);
    TB_SAFE_DELETE(m_pMainMenu);
    TB_SAFE_DELETE(m_pGame);


    // Die Engine herunterfahren
    tbExit();

    return TB_OK;
}

// __________________________________________________________________
// Lädt das Spiel
tbResult CMarbel::Load()
{
    char acFilename[256];

    // Direct3D initialisieren
    if(tbDirect3D::Instance().Init(&m_Config, "Marbel",
                                   NULL, LoadIcon(GetModuleHandle(NULL),
                                   MAKEINTRESOURCE(IDI_ICON1))))
    {
        // Fehler!
        TB_ERROR("Fehler beim Initialisieren von Direct3D!", TB_ERROR);
    }

    // Statusblock für Direct3D erstellen
    tbDirect3D::Instance()->CreateStateBlock(D3DSBT_ALL, &m_pStateBlock);

    // Texturmanager erstellen
    if(tbTextureManager::Instance().Init())
    {
        // Fehler!
        TB_ERROR("Texturmanager konnte nicht initialisiert werden!", TB_ERROR);
    }

    // DirectInput initialisieren
    if(tbDirectInput::Instance().Init())
    {
        // Fehler!
        TB_ERROR("DirectInput konnte nicht initialisiert werden!", TB_ERROR);
    }

    // Speicher für die analogen Knöpfe reservieren
    g_pfButtons = new float[tbDirectInput::Instance().GetNumButtons()];
    g_pbButtons = new BOOL[tbDirectInput::Instance().GetNumButtons()];

    // Und nun noch DirectSound...
    if(tbDirectSound::Instance().Init(&m_Config, NULL, DSSCL_PRIORITY, FALSE))
    {
        // Fehler!
        TB_ERROR("DirectSound konnte nicht initialisiert werden!", TB_ERROR);
    }

    // ------------------------------------------------------------------

    // Schriftarten laden und mehr
    ...
    
    return TB_OK;
}

// __________________________________________________________________
// Entlädt das Spiel
tbResult CMarbel::Unload()
{
    // Schriftarten und mehr löschen
    TB_SAFE_DELETE(...);
    
    // DirectX-Klassen löschen
    TB_SAFE_RELEASE(m_pStateBlock);
    TB_SAFE_DELETE_ARRAY(g_pfButtons);
    TB_SAFE_DELETE_ARRAY(g_pbButtons);
    tbDirect3D::Instance().Exit();
    tbDirectInput::Instance().Exit();
    tbDirectSound::Instance().Exit();
    tbTextureManager::Instance().Exit();

    return TB_OK;
}

// __________________________________________________________________
// Move- und Render-Funktion (Kapselung)
tbResult Move(float fTime) {return g_pMarbel->Move(fTime);}
tbResult Render(float fTime) {return g_pMarbel->Render(fTime);}

// __________________________________________________________________
// Lässt das Spiel laufen
tbResult CMarbel::Run()


// __________________________________________________________________
// Setzt einen neuen Spielzustand
tbResult CMarbel::SetGameState(EGameState NewGameState)
{
    //Fehler beim Bildpuffer
    if(tbDirect3D::Instance().GetPresentResult())
    {
        //Aktuellen Spielzustand entladen
        switch(m_GameState)
        {
        case GS_INTRO:      m_pIntro->Unload();     break;
        case GS_MAIN_MENU:  m_pMainMenu->Unload();  break;
        case GS_GAME:       m_pGame->Unload();      break;
        }

        //Das ganze Spiel entladen und wieder neu Laden
        Unload();
        Load();

        //Aktuellen Spielzustand neu laden
        switch(m_GameState)
        {
        case GS_INTRO:      m_pIntro->Load();       break;
        case GS_MAIN_MENU:  m_pMainMenu->Load();    break;
        case GS_GAME:       m_pGame->Load();        break;
        }
    }

    tbResult r = TB_OK;

    // Alten Spielzustand entladen
    switch(m_GameState)
    {
    case GS_INTRO:      m_pIntro->Exit();           break;
    case GS_MAIN_MENU:  m_pMainMenu->Exit();        break;
    case GS_GAME:       m_pGame->Exit();            break;
    }

    // ------------------------------------------------------------------

    // Zeit zurücksetzen
    m_fTime = 0.0f;

    // Direct3D-Status zurücksetzen
    m_pStateBlock->Apply();
    tbDirect3D::Instance().Capture();

    // ------------------------------------------------------------------

    // Neuen Spielzustand laden
    m_GameState = NewGameState;
    switch(m_GameState)
    {
    case GS_INTRO:      r = m_pIntro->Init();       break;
    case GS_MAIN_MENU:  r = m_pMainMenu->Init();    break;
    case GS_GAME:       r = m_pGame->Init();        break;
    }

    // Eventuelle Fehler abfangen
    if(r) TB_ERROR("Fehler beim Laden des Spielzustands!", TB_ERROR);

    return TB_OK;
}

// __________________________________________________________________
// Bewegt das Spiel
tbResult CMarbel::Move(float fTime)

// __________________________________________________________________
// Rendert das Spiel
tbResult CMarbel::Render(float fTime)

// __________________________________________________________________

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »setset1994« (30.03.2012, 18:16)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

31.03.2012, 14:24

Warum jetzt die "Run" Methode fehlt und was darin passiert müssen wir nicht wissen, oder?
Sorry, aber Du musst doch wirklich nur Deine Abbruch-Bedingung in der Run-Methode testen und schauen ob Du die überhaupt setzt.
Das Forum hier ist eigentlich nicht dafür gedacht, dass wir in Deinem gesamten Quellcode herum suchen und Deine Fehler finden, die Du selbst mit Debugger nicht entdecken konntest, sonst eher für generelle Hilfe und Fragen.
Ich weiß, dass das einem Neuling jetzt schlecht aufstoßen mag, aber Du musst Deine Bugs schon auch ein Stück weit selber suchen oder zumindest deutlicher einschränken und dann den relevanten Code schicken. Den relevanten Code aber wegzulassen und darauf zu hoffen, dass wir Deine Bugs dann erraten, das finde ich nicht in Ordnung.
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]

FSA

Community-Fossil

  • Private Nachricht senden

5

01.04.2012, 00:25

Ich würde sagen, dass du den Debugger nicht vollständig nutzt! Drücke F10 oder F11, dann kannst du alles Debuggen. (Einzelschritte) Aber Rätselraten :nono:

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

Werbeanzeige