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

29.05.2011, 16:07

Erweiterung Menü [Finde den Fehler nicht]

Hallo liebe Community,
ich bin noch ein ziemlicher Anfänger, und dachte mir, dass ich das mal ändern möchte. Also kaufte ich mir dieses Buch um selbiges zu tun. Nun hatte ich mich mal hingesetzt und versucht ein Menü einzubauen, wo man erst auf Buttons klicken muss, damit das entsprechende Fenster dann geöffnet wird. Das funktionierte auch soweit sehr gut, allerdings habe ich irgendwas gemacht, dass das Programm sich direkt nach Start wieder beendet, und ich finde den Fehler nicht. Vielleicht habe ich sogar Unmengen an unnötigem Zeug drin, ich hoffe ihr könnt mir da helfen...
Hier ist der Prototyp:

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
#include "Menu.hpp"
#include "Game.hpp"

CMenu::CMenu()
{
    m_pSpriteBackground = NULL;
}

void CMenu::Init()
{
    m_pSpriteBackground = new CSprite;
    m_pSpriteBackground->Load("Data/background.bmp");

    m_pSpriteMenuItemStart = new CSprite;
    m_pSpriteMenuItemStart->Load("Data/start.bmp");
    m_pSpriteMenuItemStart->SetPos(400, 300);

    m_bMenuRun = true;
}

void CMenu::Run()
{
    while (m_bMenuRun == true)
    {
        ProcessEvents();

        g_pFramework->Update();
        g_pFramework->Clear();

        m_pSpriteBackground->Render(); 
        m_pSpriteMenuItemStart->Render();

        g_pFramework->Flip();
    }
}

void CMenu::Quit()
{
    if(m_pSpriteBackground)
    {
        delete (m_pSpriteBackground);
    m_pSpriteBackground = NULL;
    }
}

void CMenu::ProcessEvents()
{

    SDL_Event Event;

    if(SDL_PollEvent(&Event))
    {
        switch (Event.type)
        {

            //Mausbewegung
        case (SDL_MOUSEMOTION):
            {
                if( Event.button.button == SDL_BUTTON_LEFT)
                {
                //Get the mouse offsets
                float x = Event.button.x;
                float y = Event.button.y;
            
                SDL_Rect MenuItem;
                MenuItem = m_pSpriteMenuItemStart->GetRect();
                //If the mouse is over the button
                if( ( x > MenuItem.x ) && ( x < MenuItem.x + MenuItem.w ) && ( y > MenuItem.y ) && ( y < MenuItem.y + MenuItem.h ) )
                {
                    SetMenuRun(false);
                    g_pFramework->Clear();
                }
                }

            }break;
            }
    }
}



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
#include "Game.hpp"

CGame::CGame()
{
    m_pSpriteGameBG = NULL;
}

void CGame::Init()
{
    m_pSpriteGameBG = new CSprite;
    m_pSpriteGameBG->Load("Data/game.bmp");

    m_bGameRun = true;
}


void CGame::Quit()
{
    if(m_pSpriteGameBG != NULL)
    {
        delete (m_pSpriteGameBG);
        m_pSpriteGameBG = NULL;
    }
}

void CGame::Run()
{
    while (m_bGameRun == true)
    {
        ProcessEvents();

        g_pFramework->Update();
        g_pFramework->Clear();

        m_pSpriteGameBG->Render();

        g_pFramework->Flip();
    }
}

void CGame::ProcessEvents()
{
    SDL_Event Event;

    if(SDL_PollEvent(&Event))
    {
        switch (Event.type)
        {
        case (SDL_QUIT):
            {
                m_bGameRun = false;
            }break;
        case (SDL_KEYDOWN):
            {
                switch (Event.key.keysym.sym)
                {
                case (SDLK_ESCAPE):
                    {

                    }break;
                }
            }break;
        }
    }
}




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
#include "Framework.hpp"
#include "Game.hpp"
#include "Menu.hpp"


int main (int argc, char* argv[])
{
    if (g_pFramework->Init(800, 600, 16, true) == false)
        return(0);

    CMenu Menu;

    if(Menu.MenuRun() == true)
    {
    Menu.Init();

    Menu.Run();

    Menu.Quit();


    }

    if(Menu.MenuRun() == false || Game.GetGameRun() == true)
    {
    
    CGame Game;

    Game.Init();

    Game.Run();

    Game.Quit();

    g_pFramework->Quit();

    g_pFramework->Del();

    return (0);
    }
    return(0);
}

2

29.05.2011, 17:46

Hallo gothmog13,

erst einmal ein Herzliches Willkommen in der Community. :)

Du erzeugst in deiner main-Funktion ein neues Objekt von der Klasse CMenu. Dabei wird nur der Konstruktor der Klasse aufgerufen. Dieser tut allerdings nichts weiter als sicherheitshalber den Pointer für das Hintergrundsprite auf NULL zu setzen. die Variable m_bMenuRun wird an dieser Stelle nicht gesetzt. Dann rufst du allerdings in der if-Bedingung die Methode MenuRun() auf, die - so vermute ich mal - den Wert der oben genannten Variable zurückgibt. Du solltest also dafür sorgen, dass die Variable den richtigen Wert erhält, bevor du sie aufrufst. So etwas macht man deshalb nach Möglichkeit im Konstruktor. Das Konzept mit den Init()-Funktionen stößt (zu Recht) häufig auf Kritik, denn dafür ist eigentlich der Konstruktor gedacht. Den kann man ja auch nicht vergessen aufzurufen. ;)

Also entweder rufst du die Init()-Methode deines Menüs auf, bevor du in der if-Bedingung auf das Objekt zugreifst oder aber du verschiebst das, was die init()-Methode macht einfach in den Konstruktor und sparst dir das init().

Gruß
SaRu_

PS: Du hast mit Microsoft VC++ die Möglichkeit beim Debuggen dein Projekt "Schritt für Schritt" zu durchlaufen oder aber einen Punkt zu markieren, an dem das Programm stoppt, wenn es ihn erreicht. Damit kannst du leicht herausfinden, bis zu welcher Stelle dein Programm läuft und so könntest du beim nächsten Mal einen solchen Fehler eingrenzen.

3

29.05.2011, 19:08

Danke für deine ausführliche Antwort. Ich hatte allerdings zuvor auch deine Idee, diesen boolean Wert im Konstruktor zu setzen, bereits ausprobiert. Allerdings auch ohne Erfolg, ich habe das ganze nun umgeschrieben, und so funktioniert es auch =) Es lag an der If-Abfrage.
Aber trotz der Tatsache das es nun funktioniert, bekomme ich nach dem Beenden des Programms eine Fehlermeldung,

Quellcode

1
Unbehandelte Ausnahme bei 0x76699e4d in SDL.exe: 0xC0000005: Zugriffsverletzung beim Schreiben an Position 0xfddddfb2.


Habe ich da Speicher nicht wieder freigegeben, oder was fehlt da?

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

4

30.05.2011, 15:41

Kannst du nochmal den aktuellen Code posten?
Ich sehe dort nur zwei Fehler, die aber nichts mit der Zugriffsverletzung zutun haben können.
Diese Zeile:

C-/C++-Quelltext

1
if(Menu.MenuRun() == false || Game.GetGameRun() == true)

dürfte garnicht kompiliert werden, weil Game an dieser stelle garnicht deklariert ist.

Das zweite return in der mainfunktion ist überflüssig bzw. zu viel und die Zeilen

C-/C++-Quelltext

1
2
g_pFramework->Quit();
g_pFramework->Del();

sollten in jedem Fall aufgerufen werden.
Also return löschen und die Zeilen direct vor das letzte return der mainfunktion verschieben.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »NachoMan« (30.05.2011, 15:51)


5

30.05.2011, 15:44

Ja das Game ist an der Stelle bekannt, ich habe es aber bei dem Post hier versehentlich weggelöscht, und bei 2. hast du Recht, die müssen rein =)
Auf die Weise funktioniert es auch, aber meine Variante funktioniert auch, danke dir. Weist du vielleicht eine Lösung zu dem anderem Problem, was ich gepostet habe?

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

6

30.05.2011, 15:51

Weist du vielleicht eine Lösung zu dem anderem Problem, was ich gepostet habe?

Kannst du nochmal den aktuellen Code posten?

Ich kann leider nicht hellsehen ;(
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

7

30.05.2011, 16:02

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
void CFramework::Clear ()
{
    
    SDL_FillRect (m_pScreen, NULL, SDL_MapRGB (m_pScreen->format, 0, 0, 0));

} 

void CFramework::Flip ()
{
    // Surface umschalten
    SDL_Flip (m_pScreen);

} 



Bei den 2 Funktionen bringt er mir den Fehler.

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

8

30.05.2011, 16:32

Wie sieht die mainfunktion jetzt aus?
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

9

30.05.2011, 16:35

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "Framework.hpp"
#include "Game.hpp"
#include "Menu.hpp"


int main (int argc, char* argv[])
{
if (g_pFramework->Init(800, 600, 16, true) == false)
return(0);

CMenu Menu;

Menu.Init();
Menu.Run();
Menu.Quit();
g_pFramework->Quit();
g_pFramework->Del();


}


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
#include "Menu.hpp"
#include "Game.hpp"

CMenu::CMenu()
{
    m_pSpriteBackground = NULL;
    m_pSpriteMenuItemStart = NULL;
}

void CMenu::Init()
{


    m_pSpriteBackground = new CSprite;
    m_pSpriteBackground->Load("Data/background.bmp");

    m_pSpriteMenuItemStart = new CSprite;
    m_pSpriteMenuItemStart->Load("Data/start.bmp");
    m_pSpriteMenuItemStart->SetPos(300, 120);

    m_bMenuRun = true;
}

void CMenu::Run()
{
    while (m_bMenuRun == true)
    {
        ProcessEvents();

        SDL_ShowCursor(1);

        g_pFramework->Update();
        g_pFramework->Clear();
        m_pSpriteBackground->Render();
        m_pSpriteMenuItemStart->Render();

        g_pFramework->Flip();


    }
}

void CMenu::Quit()
{
    if(m_pSpriteBackground)
    {
        delete (m_pSpriteBackground);
    m_pSpriteBackground = NULL;
    }

    if(m_pSpriteMenuItemStart)
    {
        delete (m_pSpriteMenuItemStart);
    m_pSpriteMenuItemStart = NULL;
    }


}


void CMenu::ProcessEvents()
{

    SDL_Event Event;
    CGame Game;

    if(SDL_PollEvent(&Event))
    {
        switch (Event.type)
        {

        case (SDL_KEYDOWN):
            {
                switch (Event.key.keysym.sym)
                {
                case (SDLK_ESCAPE):
                    {
                        SDL_Quit();
                    }break;
                }
            }break;


            //Mausbewegung
        case (SDL_MOUSEMOTION):
            {
                m_bMouseIsActive = true;
                
            }break;
            }

        if(m_bMouseIsActive == true)
        {
        if( Event.button.button == SDL_BUTTON_LEFT)
                {
                //Get the mouse offsets
                float x = Event.button.x;
                float y = Event.button.y;
            
                SDL_Rect MenuItem;
                MenuItem = m_pSpriteMenuItemStart->GetRect();
                //If the mouse is over the button
                if( ( x > MenuItem.x ) && ( x < MenuItem.x + MenuItem.w ) && ( y > MenuItem.y ) && ( y < MenuItem.y + MenuItem.h ) )
                {
                    Game.SetGameRun(true);
                    Quit();

                    CGame Game;

                    Game.Init();
                    Game.Run();
                    Game.Quit();

                    g_pFramework->Clear();
                }
                }
        }
    }
    
}

Werbeanzeige