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

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

11

08.05.2007, 22:36

Heut wirds mir zu spät (muss morgen Deutsch LK Prüfung schreiben :shock: ) aber morgen kann ich noch paar Hinweise zu dem Menuproblem geben (hab da schon ne schöne Lösung für Console auf der Platte rumliegen, die eigentlich gut auf SDL portierbar sein müsste ;)

12

09.05.2007, 09:56

als informatiker deutsch LK oO

was bist du denn für einer :D

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

13

09.05.2007, 16:08

Zitat von »"Schnitter"«

Könnte mir mal bitte jemand erläutern, wie ich das machen soll, dass man auch direkt in "mittlere" Navigationspunkte navigieren kann? Die While-schleife läuft ja so schnell durch, dass die Aktion bei jedem Tastendruck mehrmals durchgeführt wird.
Ich hab schon versucht, das ganze mit dem Timer zu lösen, ist aber alles nicht besonders was geworden... :(


Soo... jetzt wie versprochen dazu was...
Das Problem ist ja, dass du einfach seltener auf Tastendrücke reagieren musst. Du brauchst also eine Möglichkeit, nur auf Tastendrücke zu reagieren, wenn du vorher einige Zeit nicht reagiert hast.
Und weil ich zu faul war mir was neues auszudenken hab ich lediglich ein System was ich immer nutze leicht abgeändert damit es auf dein Game passt:

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// *.hpp -------------------------------------------------------------------------


#include <memory>


#define g_Keys Input::_Keycontrol::Instance()

namespace Input
{
    class _Keycontrol
    {
    private:
        _Keycontrol(): _TimeDiff(0.0f)
        {
            memset(_Keys, 0, sizeof (_Keys));
            memset(_Oldkeys, 0, sizeof (_Oldkeys));
            memset(_TimeElapsed, 0, sizeof (_TimeElapsed));
        }

        _Keycontrol(const _Keycontrol& _copy)
        {}
        ~_Keycontrol()
        {}
        const _Keycontrol& operator = (const _Keycontrol& _copy)
        {return _copy;}

        bool _isActive() const
        {return (true);} // Wenn du testen willst, ob das Game im Vordergrund ist muss das hier hin


    public:
        static _Keycontrol& Instance()
        {
            static _Keycontrol _instance;
            return _instance;
        }

        void Update(float TimeDiff);
        bool KeyPressed(int vKey) const;
        bool KeyReleased(int vKey) const;
        bool KeyDown(int vKey) const;
        bool KeyDownDelayed(int vKey);

    private:
        bool _Oldkeys[SDLK_LAST];
        bool _Keys[SDLK_LAST];
        float _TimeElapsed[SDLK_LAST];
        float _TimeDiff;
    };
};

// *.cpp -------------------------------------------------------------------------


#include "*.hpp"

namespace Input
{
    void _Keycontrol::Update(float TimeDiff)
    {
        _TimeDiff=TimeDiff;
        memcpy_s( _Oldkeys, sizeof(_Oldkeys), _Keys, sizeof(_Keys));

        for (int i=0; i<SDLK_LAST; ++i)
        {
            _Keys[i] = g_pFramework->keyDown (i);

            if (_Keys[i] && !_Oldkeys[i])
                _TimeElapsed[i]=0.1f;
            else if (_Keys[i])
                _TimeElapsed[i] += _TimeDiff;
        }
    }

    bool _Keycontrol::KeyPressed(int vKey) const
    {
        if (!_isActive())
            return false;
        return (_Keys[vKey] && !(_Oldkeys[vKey]));
    }

    bool _Keycontrol::KeyReleased(int vKey) const
    {
        if (!_isActive())
            return false;
        return (!(_Keys[vKey]) && _Oldkeys[vKey]);
    }

    bool _Keycontrol::KeyDown(int vKey) const
    {
        if (!_isActive())
            return false;
        return (_Keys[vKey]);
    }

    bool _Keycontrol::KeyDownDelayed(int vKey)
    {
        if (!_isActive())
            return false;
        if (_Keys[vKey] && (_TimeElapsed[vKey] >=0.1f))
        {
            _TimeElapsed[vKey]=0.0f;
            return true;
        }
        return false;
    }

};


Jetzt muss das ganze nur noch mit dem Menu zusammenarbeiten:

C-/C++-Quelltext

1
2
3
4
5
6
7
void CMenu::show( bool ingame )
{
    // ...

    while(m_isShowing)
    {
        g_pFramework->update();
        g_Keys.Update(g_pTimer->getElapsed()); // <- das is wichtig, könnte man auch direkt bei CFramework::update() mit integrieren...


Nachdem jetzt technisch alles klar ist muss man nur noch die Tastenauswertung vom Menu anpassen:

C-/C++-Quelltext

1
2
3
4
5
6
void CMenu::processEvents()
{
    //Nach oben

    if(g_Keys.KeyDownDelayed(SDLK_UP)) // <- dieses Schema bei allen Sachen, die verzögert & mehrfach reagieren sollen

    // ...

    if(g_Keys.KeyReleased(SDLK_RETURN)) // <- dieses (wahlweise auch mit KeyPressed(...) wenn es um nen einmaligen Tastendruck geht


Und da ich das alles (mehr oder weniger^^) getestet hab kann ich dir jetzt schon sagen, dass nachdem dann das Menu halbwegs passt noch ne Menge Arbeit bei den Aktionen die hinter der Menuwahl stehen zu bewältigen ist ;)

Schnitter

Treue Seele

  • »Schnitter« ist der Autor dieses Themas

Beiträge: 141

Wohnort: Remshalden

Beruf: Schüler

  • Private Nachricht senden

14

10.05.2007, 17:35

Ok, ich habs jetzt selbst gelöst. Nach dem man mich angeregt hat, mich mal wieder sehen zu lassen, poste ich für andere mal die Lösung:

Ich habe einfach eine Variable m_last vom Typ float deklariert, die die letzte Navigation zu einem Menüpunkt repräsentiert.

Bis jetzt habe ich das nur im Ingame-Menü eingebaut, da ich im outgame-Menü nur 2 Menüpunkte habe, und das somit total pberflüssig wäre ;)

Naja, hier mal die Menu.cpp. Die relevanten Stellen sind bei der Tastaturabfrage über das Framework.

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


CMenu::CMenu()
{
    //Standard-Werte setzen

    if(m_isInGame) //Wenn das Menü ingame gestartet wurde

    {
        m_menuPoints[0] = "Fortsetzen";
        m_menuPoints[1] = "Neu starten";
        m_menuPoints[2] = "Beenden";
    }
    else
    {
        m_menuPoints[0] = "Spiel starten";
        m_menuPoints[1] = "Beenden";
    }
    //Farben initialisieren

    m_color.r = 0;
    m_color.g = 255;
    m_color.b = 0;

    m_hoverColor.r = 255;
    m_hoverColor.g = 0;
    m_hoverColor.b = 255;

    m_selectedPoint = 0;
}

void CMenu::show( bool ingame )
{
    m_isInGame  = ingame;

        //Standard-Werte setzen

    if(m_isInGame) //Wenn das Menü ingame gestartet wurde

    {
        m_menuPoints[0] = "Fortsetzen";
        m_menuPoints[1] = "Neu starten";
        m_menuPoints[2] = "Beenden";
    }
    else
    {
        m_menuPoints[0] = "Spiel starten";
        m_menuPoints[1] = "Beenden";
    }
    m_isShowing = true;
    //While-schleife

    while(m_isShowing)
    {
        g_pFramework->update();
        g_pFramework->clear();

        if(m_isInGame)
        {
            for( int i = 0; i < 3; i++)
            {
                if( i == m_selectedPoint)
                    g_pFont->write(g_pFramework->getScreen(), m_menuPoints[i], m_hoverColor, g_pFramework->getScreen()->w/2, 50+(i*25));
                else
                    g_pFont->write(g_pFramework->getScreen(), m_menuPoints[i], m_color, g_pFramework->getScreen()->w/2, 50+(i*25));
            }
        }
        else
        {
            for( int i = 0; i < 2; i++)
            {
                if( i == m_selectedPoint)
                    g_pFont->write(g_pFramework->getScreen(), m_menuPoints[i], m_hoverColor, g_pFramework->getScreen()->w/2, 50+(i*25));
                else
                    g_pFont->write(g_pFramework->getScreen(), m_menuPoints[i], m_color, g_pFramework->getScreen()->w/2, 50+(i*25));
            }
        }
        
        processEvents();
        g_pTimer->update();
        g_pFramework->flip();
    }
}//show


void CMenu::hide()
{
    m_isShowing = false;
}


void CMenu::processEvents()
{
    //Nach oben

    if(g_pFramework->keyDown(SDLK_UP))
    {
        if( (SDL_GetTicks() / 1000.0f) > m_last+0.1 )
        {
            if(m_selectedPoint != 0)
                m_selectedPoint--;
            else
                m_selectedPoint = 0;
            m_last = SDL_GetTicks() / 1000.0f;
        }
    }
    //Nach unten

    if(g_pFramework->keyDown(SDLK_DOWN))
    {
        //Hier muss zwischen Ingame und nicht-Ingame unterschieden werden, da sich die Länge des Arrays unterscheidet!

        if((SDL_GetTicks() / 1000.0f) > m_last+0.1) //  <----

        {
            if(m_isInGame)
            {
                if(m_selectedPoint != 2)
                    m_selectedPoint++;
                else
                    m_selectedPoint = 2;
                m_last = SDL_GetTicks() / 1000.0f;  //   <----

            }
            else
            {
                if(m_selectedPoint != 1)
                    m_selectedPoint++;
                else
                    m_selectedPoint = 1;
            }
        }
    }
    if(g_pFramework->keyDown(SDLK_RETURN) || g_pFramework->keyDown(SDLK_KP_ENTER))
    { 

        if(m_isInGame)
        {
            switch(m_selectedPoint)
            {
            case(0): //Fortsetzen

                {

                }break;
            case (1): //Neu starten

                {
                    m_game.reset();
                    m_isShowing = false;
                }break;
            case(2): //beenden

                {
                    m_isShowing = false;
                    m_game.quit();

                }break;
            }
            
        }
        else
        {
            //Abfragen, welcher Menüpunkt selektiert wurde

            switch(m_selectedPoint)
            {
            case(0): //Spiel starten

                {
                    m_game.init();
                    m_game.run();
                    m_game.quit();
                }break; 
            case (1): //beenden

                {
                    m_isShowing = false;
                }break;
            }
        }
    }
}//processEvents

Werbeanzeige