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

31

17.12.2012, 15:02

Ich habe den Code in Game1 ein wenig erweitert, jedoch funktioniert das mit dem Ingamemenü noch nicht. Wenn ich während des Spiels die Escape-Taste drücke kommt zwar der Quit-Bildschirm, jedoch sieht man dabei das Hauptspiel nicht im Hintergrund.
Das ganze kann auch nicht funktionieren, da nicht mal die Breakpoints in den Zeilen "lastState.Update(gameTime);" und "lastState.Render(spriteBatch);" ausgelöst werden. Ich verstehe aber nicht warum die Breakpoints nicht ausgelöst werden. In der Update-Methode habe ich doch diese Zeile geschrieben: "lastState = currentState;"
Also müsste lastState doch den alten Zustand(MaingameState) und currentState den neuen Zustand(QuitgameState) haben, oder?
Ich habe die if-Abfragen eingebaut da das lastState ja nicht immer geupdatet und gezeichnet werden muss. Das Pausieren habe ich noch nicht eingebaut, ich wollte zuerst mal sehen ob ich es irgendwie hinbekomme dass sich das Ingamemenü über dem Hauptspiel befindet wenn man Escape drückt.

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
public class Game1 : Microsoft.Xna.Framework.Game     { 
        GraphicsDeviceManager graphics; 
        SpriteBatch spriteBatch; 
        IState lastState, currentState; 

        public enum GameStates 
        { 
            IntroState = 0, 
            MenuState = 1, 
            MaingameState = 2, 
            QuitgameState = 3 
        } 

        public void ChangeGameState(GameStates newState) 
        { 
            switch (newState) 
            { 
                case GameStates.IntroState: 
                    currentState = new Intro(this); 
                    break; 
                case GameStates.MenuState: 
                    currentState = new Menu(this); 
                    break; 
                case GameStates.MaingameState: 
                    currentState = new Maingame(this); 
                    break; 
                case GameStates.QuitgameState: 
                    currentState = new Quit(this); 
                    break; 
            } 
            currentState.Load(Content); 
        } 

        public GameStates CurrentState 
        { 
            get { return currentGameState; } 
            set { currentGameState = value; } 
        } 

        private GameStates currentGameState = GameStates.IntroState; 
        private GameStates lastGameState; 
      
        public Game1() 
        { 
            graphics = new GraphicsDeviceManager(this); 
            Content.RootDirectory = "Content"; 
        } 
        
        protected override void Initialize() 
        { 
            ChangeGameState(GameStates.IntroState); 
            base.Initialize(); 
        } 

        protected override void LoadContent() 
        {        
            spriteBatch = new SpriteBatch(GraphicsDevice); 
            currentState.Load(Content); 
        } 

      
        protected override void Update(GameTime gameTime) 
        { 
            currentState.Update(gameTime);            
     if ((lastGameState == GameStates.MaingameState) && (currentGameState == GameStates.QuitgameState)) 
            { 
                lastState.Update(gameTime); 
            } 
            lastState = currentState; 
            base.Update(gameTime); 
        } 

        protected override void Draw(GameTime gameTime) 
        { 
            GraphicsDevice.Clear(Color.CornflowerBlue); 
            spriteBatch.Begin(); 
            if ((lastGameState == GameStates.MaingameState) && (currentGameState == GameStates.QuitgameState)) 
            { 
              lastState.Render(spriteBatch); 
            } 
            currentState.Render(spriteBatch); 
            spriteBatch.End(); 
            
            base.Draw(gameTime); 
        } 
    } 

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

32

17.12.2012, 16:01

Du machst da einiges falsch. Warum wird in jedem Frame in Update lastState auf currentState gesetzt? Das sollte in ChangeGameState passieren. Außerdem fragst du deine Enumvariablen currentGameState und lastGameState ab, ohne diese in ChangeGameState neu zu setzen. Du tauschst zwar die Zustandsinstanz aus, aber diese Variablen nicht. Den Debugger hast du ja löblicherweise schon benutzt. Bei sowas musst du dir einfach mal die Werte angucken. Wenn du merkst, dass der Körper einer if-Abfrage nicht ausgeführt wird, dann musst du dir die Bedingung ansehen und die Werte der jeweiligen Variablen angucken. Dann kommst du meist schnell selbst drauf.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

33

17.12.2012, 17:52

Ich habe jetzt noch ein paar Änderungen vorgenommen. Vor allem am Switch-Block. Die Breakpoints werden zwar noch nicht ausgelöst, jedoch weiss ich nicht was ich noch am Switch-Block ändern soll. Ich weiß vor allem nicht wie ich die Variable lastState benutzen soll. Ich gehe ja mal davon aus dass nicht dauernd lastState und currentState geupdatet und gezeichnet werden sollen. Es macht ja z.B. keinen Sinn das normale Menü(lastGameState) und das Hauptspiel(currentGameState) zu zeichnen. In dem Fall bräuchte ja nur das Hauptspiel(currentGameState) gezeichnet zu werden.
Wie geht man vor? Muss wirklich immer beides geupdatet und gezeichnet werden?

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
public class Game1 : Microsoft.Xna.Framework.Game     { 
        GraphicsDeviceManager graphics; 
        SpriteBatch spriteBatch; 
        IState lastState, currentState; 

        public enum GameStates 
        { 
            IntroState = 0, 
            MenuState = 1, 
            MaingameState = 2, 
            QuitgameState = 3 
        } 

        public void ChangeGameState(GameStates newState) 
        { 
            switch (newState) 
            { 
                case GameStates.IntroState: 
                    currentState = new Intro(this); 
                    currentGameState = GameStates.IntroState; 
                    break; 
                case GameStates.MenuState: 
                    currentState = new Menu(this); 
                    currentGameState = GameStates.MenuState; 
                    break; 
                case GameStates.MaingameState: 
                      currentState = new Maingame(this); 
                      currentGameState = GameStates.MaingameState; 
                    break; 
                case GameStates.QuitgameState: 
                    currentState = new Quit(this); 
                    currentGameState = GameStates.QuitgameState; 
                    break; 
            } 
            lastGameState = currentGameState; 
            currentState.Load(Content); 
        } 

        public GameStates CurrentState 
        { 
            get { return currentGameState; } 
            set { currentGameState = value; } 
        } 

        public GameStates LastState 
        { 
            get { return lastGameState; } 
            set { lastGameState = value; } 
        } 

        private GameStates currentGameState = GameStates.IntroState; 
        private GameStates lastGameState = GameStates.IntroState; 
      
        public Game1() 
        { 
            graphics = new GraphicsDeviceManager(this); 
            Content.RootDirectory = "Content"; 
        } 
        
        protected override void Initialize() 
        { 
            ChangeGameState(GameStates.IntroState); 
            base.Initialize(); 
        } 

        protected override void LoadContent() 
        {        
            spriteBatch = new SpriteBatch(GraphicsDevice); 
            currentState.Load(Content); 
        } 
      
        protected override void Update(GameTime gameTime) 
        { 
            currentState.Update(gameTime); 
            if ((lastGameState == GameStates.MaingameState) && (currentGameState == GameStates.QuitgameState)) 
            { 
                lastState.Update(gameTime); 
            } 
            base.Update(gameTime); 
        } 

        protected override void Draw(GameTime gameTime) 
        { 
            GraphicsDevice.Clear(Color.CornflowerBlue); 
            spriteBatch.Begin(); 
            if ((lastGameState == GameStates.MaingameState) && (currentGameState == GameStates.QuitgameState)) 
            { 
              lastState.Render(spriteBatch); 
            } 
            currentState.Render(spriteBatch); 
            spriteBatch.End(); 
            
            base.Draw(gameTime); 
        } 
    } 

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

34

17.12.2012, 18:08

Wenn du erst den currentGameState neu setzt und danach den lastGameState auf currentGameState setzt, dann haben beide wieder den selben Wert.

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
int a;
int b;
a = 1; // Hier setzt du den Wert
b = a; // b und a sind nun gleich

// du willst aber:
int c;
int d;
d = c; // d bekommt nun den alten Wert
c = 1; // erst jetzt wird c neu gesetzt

Außerdem machst du das ganze nur für lastGameState und currentGameState, nicht aber für lastState und currentState. lastState hat also immer den Wert null. Hast du ein Buch gefunden?;)
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

35

18.12.2012, 00:06

Ich habe den Switch-Block wie folgt geändert:

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
public void ChangeGameState(GameStates newState)         { 
            lastGameState = currentGameState; 
            lastState = currentState; 
            switch (newState) 
            { 
                case GameStates.IntroState: 
                    currentState = new Intro(this); 
                    currentGameState = GameStates.IntroState; 
                    break; 
                case GameStates.MenuState: 
                    currentState = new Menu(this); 
                    currentGameState = GameStates.MenuState; 
                    break; 
                case GameStates.MaingameState: 
                      currentState = new Maingame(this); 
                      currentGameState = GameStates.MaingameState; 
                    break; 
                case GameStates.QuitgameState: 
                    currentState = new Quit(this); 
                    currentGameState = GameStates.QuitgameState; 
                    break; 
            } 
            currentState.Load(Content); 
        } 


Außerdem habe ich noch folgende Zeile public gemacht um von der Quit-Klasse darauf zugreifen zu können.

C#-Quelltext

1
public IState lastState, currentState;


Die Quit-Klasse ist bis jetzt das Ingamemenü. Drückt man Escape im Hauptspiel kommt das Ingamemenü. Wenn man in diesem Menü Y drückt kommt man wieder zum Hauptmenü zurück. Das funktioniert auch. Wenn man N drückt sollte man wieder in den alten Spielstand(Hauptspiel) zurückkehren. Das funktioniert aber nicht. Ich habe einen Breakpoint in die if-Abfrage gesetzt und musste feststellen dass CurrentState und LastState auf QuitgameState stehen. Eigentlich müsste LastState doch auf MaingameState stehen und dadurch CurrentState auch diesen Zustand annehmen. Aus irgendeinem Grund ist dies aber nicht der Fall.
Ich verstehe aber nicht warum das so ist ?(

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
public class Quit : IState     { 
        Texture2D Quitscreen; 
        private Game1 game1; 

        public Quit(Game1 game) 
        { 
            game1 = game; 
        } 

        public void Load(ContentManager content) 
        { 
            Quitscreen = content.Load<Texture2D>("quit"); 
        } 

        public void Update(GameTime gametime) 
        { 
            KeyboardState kbState = Keyboard.GetState(); 
            if (kbState.IsKeyDown(Keys.Y)) 
                game1.ChangeGameState(Game1.GameStates.MenuState); 
            if (kbState.IsKeyDown(Keys.N)) 
                { 
                  game1.CurrentState = game1.LastState; 
                  game1.currentState = game1.lastState; 
                } 
        } 

        public void Render(SpriteBatch batch) 
        { 
            batch.Draw(Quitscreen, new Rectangle(200, 200, 200, 200), Color.White); 
        } 
    } 

Bei dem Buch bin ich mir noch nicht sicher. Ich werde mich aber bald entscheiden.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

36

18.12.2012, 00:24

Das State wechseln solltest du nicht in Quit machen sondern weiterhin in Game1. Oder du schreibst dir eine Klasse zum verwalten der GameStates.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

37

18.12.2012, 12:04

Wenn ich es so mache(diese Zeile in der Quit-Klasse schreibe) dann wird das pausierte Hauptspiel doch zurückgesetzt, wenn ich vom Ingamemenü ins Hauptspiel zurück will, oder?

C#-Quelltext

1
2
3
if (kbState.IsKeyDown(Keys.N))                 { 
                  game1.ChangeGameState(Game1.GameStates.MaingameState); 
                } 

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

38

18.12.2012, 14:43

Genau das. Wenn du den Zustand ändern möchtest solltest du das immer über die Methode machen. Versuche allgemein möglichst immer nur einen Weg zu gehen und nicht zu viele verschiedene gleichzeitig. Es ist schöner und ja auch einfacher, wenn du einfach fix die Methode benutzt und nicht auf den Zustandsobjekten selbst rumspielst. Weiterhin hat es den Vorteil, dass du die ChangeGameState Methode jederzeit ändern kannst, falls du das mal musst. Wenn du jetzt zig Ausnahmestellen hast, in denen du den Zustand irgendwie anders setzt, so musst du diese Stellen alle beachten und auch anpassen. Du ersparst dir also viel viel arbeit, mit so einer Methode die das für dich regelt. Wie gesagt, Bücher helfen ungemein. Du lernst ja nicht nur wie es theoretisch funktioniert, sondern auch solche Tricks. Natürlich muss das Buch dann vernünftig sein. Deswegen habe ich ja so oft darauf hingewiesen. Du hast ja nichts davon, wenn du dir alles nur halb aneignest. Wenn man etwas falsch oder schlecht lernt ist es hinterher doppelte Arbeit es richtig zu lernen.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

39

18.12.2012, 15:57

Ich weiß dass es besser ist wenn man immer die ChangeGameState Methode benutzt. Ich hatte es versucht anders zu machen da ich es nicht hinbekomme habe dass das Spiel nach dem Pausieren wieder normal weiter läuft. Bei mir wird das Spiel/Level immer auf den Anfang zurückgesetzt wenn ich beim Pausieren(Ingamemenü) die N Taste drücke. Ich möchte aber nicht dass das Spiel/Level wieder von vorne beginnt.
Hier mal meine Maingame und Quit-Klasse:

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
public class Maingame : IState     { 
        Texture2D Spielbildschirm, axe; 
        Vector2 position = new Vector2(100,100); 

        private Game1 game1; 

        public Maingame(Game1 game) 
        { 
            game1 = game; 
        } 

        private bool paused = false; 
        private bool pauseKeyDown = false; 

        private void BeginPause(bool UserInitiated) 
        { 
            paused = true; 
        } 

        private void EndPause() 
        { 
            paused = false; 
        } 

        private void checkPauseKey(KeyboardState keyboardState) 
        { 
            bool pauseKeyDownThisFrame = (keyboardState.IsKeyDown(Keys.Escape)); 
            // If key was not down before, but is down now, we toggle the 
            // pause setting 
            if (!pauseKeyDown && pauseKeyDownThisFrame) 
            { 
                if (!paused) 
                    BeginPause(true); 
                else 
                    EndPause(); 
            } 
            pauseKeyDown = pauseKeyDownThisFrame; 
        } 

        public void Load(ContentManager content) 
        { 
            Spielbildschirm = content.Load<Texture2D>("hauszombie"); 
            axe = content.Load<Texture2D>("axxx"); 
        } 

        public void Update(GameTime gametime) 
        { 
            KeyboardState keyboardState = Keyboard.GetState(); 
            // Check to see if the user has paused or unpaused 
           checkPauseKey(keyboardState);    
           // If the user hasn't paused, Update normally 
           if (!paused) 
           { 
              float delta = (float)gametime.ElapsedGameTime.TotalSeconds; 
              position.X += 5 * delta; 
              position.Y += 3 * delta; 
            } 
            else 
              game1.ChangeGameState(Game1.GameStates.QuitgameState);        
        } 

        public void Render(SpriteBatch batch) 
        { 
            batch.Draw(Spielbildschirm, new Rectangle(0, 0, 1280, 720), Color.White); 
            batch.Draw(axe, position, Color.White); 
        } 
    } 


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
public class Quit : IState     { 
        Texture2D Quitscreen; 
        private Game1 game1; 

        public Quit(Game1 game) 
        { 
            game1 = game; 
        } 

        public void Load(ContentManager content) 
        { 
            Quitscreen = content.Load<Texture2D>("quit"); 
        } 

        public void Update(GameTime gametime) 
        { 
            KeyboardState kbState = Keyboard.GetState(); 
            if (kbState.IsKeyDown(Keys.Y)) 
                game1.ChangeGameState(Game1.GameStates.MenuState); 
            if (kbState.IsKeyDown(Keys.N)) 
                game1.ChangeGameState(Game1.GameStates.MaingameState); 
        } 

        public void Render(SpriteBatch batch) 
        { 
            batch.Draw(Quitscreen, new Rectangle(200, 200, 200, 200), Color.White); 
        } 
    } 


Reicht es die ChangeGameState Methode irgendwie zu erweitern damit das Spiel/Level nach dem Pausieren wieder normal weiter läuft?

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

40

18.12.2012, 16:18

Ist natürlich quatsch was ich geschrieben habe. Wenn du ChangeGameState aufrufst, dann wird der Zustand natürlich neu gesetzt. Schreib dir doch eine neue Methode, welche den Zustand zurücksetzen kann. Diese Methode würdest du dann aufrufen um zurück auf den LastState zu stellen.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Werbeanzeige