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

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

11

12.12.2012, 16:06

das Interface sollte ein eigenständies Interface sein und der StateManager, der sich um die Verwaltung der States (also auch um den aktiven State) kümmert, sollte eine eigenständige Kasse sein
die Klasse, die du bei dir "Game" genannt hast, würde ich eher "GameState" nennen und die Klasse "Intro" "IntroState"

der Fehler mit der Exit() Methode ist sehr offensichtlich durch unüberlegtes Copy&Paste entstanden

vlt. wäre es wirklich ganz gut, wenn du dir nochmal ein Buch zu Gemüte führst, allerdings scheint es bei dir weniger dramatisch zu sein, als bei manch anderen...
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

12

12.12.2012, 16:18

Ein Interface ist im Prinzip eine Klasse nur mit Methodenrümpfen. Du siehst, welche Funktionen die Klasse nach außen anbietet, aber nicht was genau passiert. Du weißt zum Beispiel, dass ein Spielzustand gerendert werden kann, es ist aber egal wie das passiert. Selbes gilt für Update. Für Exit könntest du dir eine Referenz auf Game1 speichern. Auf dieser kannst du dann Exit aufrufen. Einem Zustand ein State hinten anzuhängen ist gar nicht doof. Zumindest bei XNA hab ich das auch immer so gelöst. Ein GameStateManager ist so eine Sache. Ich habe am Anfang auch immer eine extra Klasse verwendet. Hinter habe ich den Code dann meist in Game1 gesteckt. Einfach der Übersicht halber. Bei XNA gab es glaube ich auch irgendwie GameComponents. Diese definieren schon, dass bestimmte Methoden vorhanden sein müssen. Das lohnt sich auch mal anzusehen.
„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.“

Yannic

unregistriert

13

12.12.2012, 19:47

Wert zu erwähnen ist auch noch, dass bei einem Interface alle Methoden implementiert werden müssen.

14

12.12.2012, 23:09

Ich habe jetzt ein paar Änderungen vorgenommen. Wenn ich das Programm ausführe, bekomme ich aber folgende Fehlermeldungen:
'menuinterface.Hauptspiel' does not implement interface member 'menuinterface.IState.Load()'
'menuinterface.Hauptspiel' does not implement interface member 'menuinterface.IState.Render()'
'menuinterface.Intro' does not implement interface member 'menuinterface.IState.Load()'
'menuinterface.Intro' does not implement interface member 'menuinterface.IState.Render()'
'menuinterface.Menu' does not implement interface member 'menuinterface.IState.Load()'
'menuinterface.Menu' does not implement interface member 'menuinterface.IState.Render()'
Was mache ich falsch? Ist der Aufbau des Spiels gut so oder muss man das mit dem Interface anders machen?
Kann man irgendwo ein Sample von einem kleinen Interface runterladen?

Game1-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
public class Game1 : Microsoft.Xna.Framework.Game     { 
        GraphicsDeviceManager graphics; 
        SpriteBatch spriteBatch; 
        private IState currentState; 
      
        public Game1() 
        { 
            graphics = new GraphicsDeviceManager(this); 
            Content.RootDirectory = "Content"; 
        } 
        
        protected override void Initialize() 
        { 
            currentState = new Intro(); 
            base.Initialize(); 
        } 

        protected override void LoadContent() 
        {        
            spriteBatch = new SpriteBatch(GraphicsDevice); 
        } 
      
        protected override void Update(GameTime gameTime) 
        { 
            currentState.Update();          
            base.Update(gameTime); 
        } 

        protected override void Draw(GameTime gameTime) 
        { 
            GraphicsDevice.Clear(Color.CornflowerBlue); 
            spriteBatch.Begin(); 
            currentState.Render(); 
            spriteBatch.End(); 
            
            base.Draw(gameTime); 
        } 
    } 


Interface:

C#-Quelltext

1
2
3
4
5
public interface IState         { 
            void Load(); 
            void Update(); 
            void Render(); 
        } 


Intro-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
public class Intro : IState     { 
        private IState currentState; 
        Texture2D Titelbildschirm; 

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

        public void Update() 
        { 
            KeyboardState kbState = Keyboard.GetState(); 
            if (kbState.IsKeyDown(Keys.Space)) 
              currentState = new Menu();          
        } 

        public void Render(SpriteBatch batch) 
        { 
            batch.Begin(); 
            batch.Draw(Titelbildschirm, new Rectangle(0, 0, 1280, 720), Color.White); 
            batch.End(); 
        } 
    } 


Menü-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
public class Menu:IState   { 
    private IState currentState; 
    private Game1 exit; 
    Texture2D Auswahlbildschirm; 

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

    public void Update() 
    { 
        KeyboardState kbState = Keyboard.GetState(); 
        if (kbState.IsKeyDown(Keys.Enter)) 
            currentState = new Hauptspiel(); 
        if (kbState.IsKeyDown(Keys.Escape)) 
            exit.Exit(); 
    } 

    public void Render(SpriteBatch batch) 
    { 
        batch.Begin(); 
        batch.Draw(Auswahlbildschirm, new Rectangle(0, 0, 1280, 720), Color.White); 
        batch.End(); 
    } 
} 


Hauptspiel-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
public class Hauptspiel : IState     { 
        private IState currentState; 
        private Game1 exit; 
        Texture2D Spielbildschirm; 

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

        public void Update() 
        { 
            KeyboardState kbState = Keyboard.GetState(); 
            if (kbState.IsKeyDown(Keys.Escape)) 
                exit.Exit(); 
        } 

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

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

15

12.12.2012, 23:41

die Fehlermeldung sagt alles

nur nochmal als Erinnerung:
2 Methoden unterscheiden sich in C# (und einigen anderen Sprachen) durch den Namen und die Parameterliste (um genauer zu sein durch die Liste der Typen der Parameter)
schau nochmal ganz genau hin... ;)
(und sollte der Hinweis nicht helfen: schau dir alternativ die Methode Update() an, welche keinen Fehler aufwirft)
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

16

13.12.2012, 12:36

Den Fehler hat Sacaldur schon gut beschrieben. Ansonsten sind mir aber noch mehrere Sachen aufgefallen. Die Klassen Hauptspiel, Intro und Menu speichert bei dir einen IState namens currentState. Noch wird dieser nicht benutzt. Kann ja gut sein, dass du dein Spiel, etc selbst in einen solchen Zustandsautomaten einteilen willst, lass das aber erst mal. Dann kommt hinzu, dass dein Hauptspiel und Menu eine Referenz auf Game1 hält. Dieser wird aber nie etwas zugewiesen. Außerdem nennst du die Referenz exit. Vermutlich, da du die Klasse zum beenden benutzen möchtest. Trotzdem würde ich es anders benennen.
Ich glaube jedoch sehr stark, dass du dir einige Grundlagen noch mal ansehen solltest. Vererbung und Interfaces sind eigentlich nicht so schwer zu verstehen, man muss sie jedoch einmal verstanden haben um sie benutzen zu können.
Wenn du in Visual Studio bei C# von einer Klasse ableiten möchtest, dann gibt es da eine Hilfe. Nehmen wir zum Beispiel mal die Klasse Intro. Du schreibst "Intro:IState" und klickst dann auf Intro. Dann kannst du dort anklicken, dass du das Interface implementieren möchtest. Nun schreibt er die alle benötigten Methodenrümpfe in deine Klasse. Das erspart Tipparbeit, bzw Kopierarbeit.
http://openbook.galileocomputing.de/csharp/ Hier kannst du dir ja noch mal die Themen durchlesen, welche dir nicht ganz klar sind. Ich würde vorschlagen, noch mal über Vererbung und Interfaces(Schnittstellen) zu sehen.
„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.“

17

13.12.2012, 13:40

Ich bin mir vor allem bei den Tasten nicht sicher. Also ich weiß nicht ob ich in der Game1 oder der Intro Klasse abfragen soll, ob die Escape-Taste gedrückt wurde um das Spiel durch Exit() zu beenden. Genau so bei den anderen Tasten. Ich weiß nicht in welcher Klasse ich prüfen soll ob der Spieler das Spiel starten will, ins Menü wechseln will, etc.
Wo soll ich das am besten prüfen? In einer Klasse(Game1) oder lieber in der jeweiligen Klasse, so wie ich es bis jetzt gemacht habe?
Ich möchte das ganze nicht zu unübersichtlich aufbauen.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

18

13.12.2012, 14:02

Den ganzen Zustandskram baust du dir ja an sich auf, um es dir übersichtlicher zu schaffen. Alles was für einen Zustand gilt sollte auch in dem Zustand gelöst werden. Alles was global gelten soll solltest du eine Ebene darüber ansetzen. In deinem Fall wäre die Ebene darüber dann Game1. Um mal auf dein Beispiel mit exit einzugehen. Normalerweise möchte man nicht, dass sich ein Programm in jeder Situation durch Escape beendet. Wenn man ein Intro hat, möchte man dieses oft durch Escape überspringen. Im Menü könnte Escape dann Beenden des Spiels bedeuten, oder aber dass der Beenden Button markiert wird und durch Enter drücken das Spiel beendet wird. Im Spiel selbst möchte man mit Escape oft ein Ingame Menü aufrufen. Möglicherweise aber auch das Hauptmenü.
Hier siehst du also, dass jeder Zustand eine andere Anforderung an das drücken der Escape Taste hat. Also solltest du das in den jeweiligen Zuständen implementieren. Wenn du jedoch möchtest, dass Escape in jedem Zustand die Anwendung schließt, dann solltest du das auch nur ein mal implementieren. In deinem Fall in Game1. Deswegen sag ich ja, halte es möglichst einfach. Ich hatte ein paar Posts vorher ja mal ein Beispiel geschrieben welches du mal implementieren solltest. Versuch dich mal daran. Dabei handelt es sich um einen Anwendungsfall wie man ihn eigentlich recht oft zu sehen bekommt. Zumindest ist das bei meinen Anwendungen so. Ist jedoch recht einfach und sollte dir die Funktion von allem zeigen.
„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.“

19

13.12.2012, 14:15

Den Statemanager aus diesem Beispiel braucht man ja nur wenn man das ganze in einer dafür vorgesehenen Klasse lösen möchte. Wenn ich die if-Abfragen in die jeweilige Klasse(Intro, Menu, etc.) einbaue, dann brauche ich diesen Statemanager doch nicht, oder?
https://www.spieleprogrammierer.de/wiki/…stand-Automaten

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

20

13.12.2012, 14:27

Habe keinen genauen Überblick über diese Wikiseite. Hatte damals als das angelegt wurde jedoch recht viel daran auszusetzen. Der Stack hat da meiner Meinung nach erst mal nichts zu suchen, da er eine Erweiterung darstellt und viele andere Sachen waren mir nicht allgemein genug.
Einen StateManager würde man sich normalerweise zur Verwaltung schreiben. Ich habe das oft so gemacht, dass der StateManager das selbe Interface implementiert wie ein State. Dann rufst du in Game1 auf dem StateManager die jeweiligen Funktionen auf. Für Game1 sieht es so aus, als wenn es ein einfacher Zustand wäre und die ganze Logik zum austauschen der Zustände etc verschleiert der StateManager. Dieser Manager wäre zum Beispiel auch ein Punkt an welchem du Globalen Code ausführen könntest. Du könntest dir einen Zustand schreiben der alles globale macht (also alles was überall gelten soll) und diesen zusätzlich zum aktuellen Zustand ausführen. Das sind aber alles Dinge die Erweiterungen darstellen.
Hilfreich wäre es, wenn du mal genauer auf unsere Beiträge eingehen würdest. Ich weiß zum Beispiel nicht, ob du deine Probleme mit dem Code lösen konntest. Ich weiß nicht ob du dir die jeweiligen Grundlagen noch mal angeguckt hast. Ich weiß allgemein nicht was du kannst und was dir wohl Probleme bereitet und kann dies nur vermuten. So kann ich dir sehr schwierig weiter helfen. Ich weiß nicht in wie weit du mal ein Beispiel mit dem Zustandsautomaten umsetzen konntest. Dein nicht funktionierender Code war ein sehr simples Beispiel, welches nicht lief, wobei deine Fragen an sich schon ein zweiter Schritt sind. Wenn du möchtest, dass wir dir vernünftig helfen können, dann geh bitte etwas mehr auf die Antworten ein.
„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