Laden...

[GameProgramming/C#] UserControl als eigene Instanz bei jedem GameState?

Erstellt von ingram333 vor 18 Jahren Letzter Beitrag vor 18 Jahren 2.083 Views
I
ingram333 Themenstarter:in
72 Beiträge seit 2005
vor 18 Jahren
[GameProgramming/C#] UserControl als eigene Instanz bei jedem GameState?

Hallo Leute!

Ich sitze gerade an der Umsetzung eines kleinen
Computerspiels, für das ich bereits einen
Codeabschnitt für die einzelnen "States" habe
(z.B. 1. State = TITLESCREEN, 2. State = Menü,
3. State = PlayingGame, etc.).

Ich möchte nun das für jeden einzelnen State, ein
eigenes UserControl erstellt und instanziert wird, das
sich beim Aufruf des jeweiligen States über das MainForm
legt (also jeder State hat seine ganze Logik und GUI in
einem eigenem UserControl).

Problem:
Ich bin mir mit UserControls noch etwas unsicher, ich denke
ich habe irgendwas wichtiges übersehen, derzeit füge ich
die Controls zwar ein, kann sie aber nicht sehen (sie erscheinen
einfach nicht). Wäre super wenn mir wer in meinem Code
zeigen könnte wo der Fehler liegt.

Mein Versuch die UserControls einzubauen findet ihr unten
bei "ExampleStates.cs".

Es soll wie gesagt so sein, das bei einem Statewechsel, ein neues
UserControl sich komplett über das bestehende MainForm legt,
ein voriges sollte ggf. entfernt oder überlagert werden.

MainForm.cs:


using System; 
using System.Windows.Forms; 
using System.Drawing; 

namespace ArchitectureI { 

   public class stringholder { 

      public string output; 

      public void change( string newString ) { 
         output = newString; 
      } 
   } 

   public class Arch : Form { 

      GameStateManager gamestateManager; 
      stringholder pretendDevice; 

      protected override void OnPaint( PaintEventArgs pea ) { 
         pea.Graphics.DrawString( pretendDevice.output, this.Font, Brushes.Black, 0, 0 ); 
      } 

      protected override void OnKeyPress( KeyPressEventArgs e ) { 
         if( (int)e.KeyChar == (int)Keys.Enter ) { 
            //MessageBox.Show("You pressed Enter"); 
            gamestateManager.switchState( new PlayingGameState( pretendDevice ) ); 
            Invalidate(); 
         } 
      } 


      public Arch() { 
         pretendDevice = new stringholder(); 
         pretendDevice.change( "No State" ); 
         gamestateManager = new GameStateManager( new TitleScreen( pretendDevice ) ); 
      } 

      static void Main() { 
         Arch arch = new Arch(); 
         arch.Show(); 

         while( arch.Created ) { 
            gamestateManager.process(); 
            Application.DoEvents(); 
         } 
      } 
   } 
} 
	

GameState.cs


using System; 
using System.Windows.Forms; 
using System.Drawing; 

namespace ArchitectureI { 

   public interface GameState { 
      void render(); 
   } 

} 

GameStateManager:


using System; 

namespace ArchitectureI { 

   public class GameStateManager { 

      private GameState state; 
       
      public void process() { 
         if( state != null ) 
            state.render(); 
      } 

      public GameStateManager( GameState intialState ) { 
         state = intialState; 
      } 

      public GameState switchState( GameState newState ) { 
         GameState oldState = state;   //store current state 
         state = newState;   //replace current state 
         return ( oldState );   //return old value 
      } 
   } 
} 

ExampleStates.cs:


using System; 
using System.Windows.Forms; 
using System.Drawing; 

namespace ArchitectureI 

{ 

public class TitleScreenControl : System.Windows.Forms.UserControl 
{ 
  /// <summary> 
  /// Required designer variable. 
  /// </summary> 
  private System.ComponentModel.Container components = null; 
  
  public TitleScreenControl() 
  { 
     InitializeComponent(); 
  } 
  
  private void InitializeComponent() { 
         this.Name = "TESTUSERCONTROL"; 
         this.Size = new System.Drawing.Size(800, 600); 
         this.BackColor =  Color.AliceBlue; 
this.Visible = true; 

         //this.BackgroundImage = Image.FromFile("titlescreen.bmp"); 
      } 
} 



 public class TitleScreen : GameState 
 { 
  stringholder s; 
  bool boxShowed = false; 

  public TitleScreen(stringholder output) 
  { 
     // Logic 
   s = output; 
    
  } 

  public void render() 
  { 
     // Mein Versuch das UserControl einzubauen... 
     TitleScreenControl actualTitle = new TitleScreenControl(); 
     actualTitle.Visible = true; 
     actualTitle.BackColor = Color.AliceBlue; 
     actualTitle.Show(); 
     actualTitle.Invalidate(); 
      
   s.change("In TitleScreenState!"); 
   if(!boxShowed){ 
      MessageBox.Show("In TITLE!"); 
      boxShowed=true; 
  } 

 } 
 } 

public class PlayingGameState : GameState 
{ 

...  snip ... 

}

Danke für eure Zeit!

P
939 Beiträge seit 2003
vor 18 Jahren

Es fehlt der Code, der das TitleScreenControl zum Arch-Form hinzufügt.



// Control des letzten States entfernen.
archForm.Controls.Clear();

// Control für den TitleScreen-State hinzufügen.
TitleScreenControl titleScreen = new TitleScreenControl();
archForm.Controls.Add(titleScreen);

Gruss
Pulpapex

I
ingram333 Themenstarter:in
72 Beiträge seit 2005
vor 18 Jahren

Danke!
Das hab ich wohl nicht gemacht, mit dem Controls.Add.

Allerdings, wo kann ich diesen Code sinnvoll unterbringen?
Wenn ich versuche ihn in meiner ExampleState.cs zu implementieren,
(was glaube ich am sinnvollsten wäre) habe ich leider keinen
Zugriff auf das MainForm 'arch' aus MainForm.cs.
In MainForm.cs selbst wäre es knifflig, da es ja nur je nach
State ausgeführt werden soll.

Frage daher:
Wie bekomme ich Zugriff auf mein MainForm von allen
Klasses/Methoden aus? So, dass ich deinen Code in meiner
ExampleState.cs einbauen kann und er jedesmal ausgeführt
wird wenn man in den State wechselt.

Vielen Dank für eure Zeit!

P
939 Beiträge seit 2003
vor 18 Jahren

Na der GameStateManager schaltet die States um. Also ist es wahrscheinlich auch seine Aufgabe, die State-Controls in der MainForm auszutauschen. Dafür benötigt er eine GameStateManager.MainForm-Eigenschaft, in der die Arch-Form von aussen gesetzt werden kann.

Gruss
Pulpapex

I
ingram333 Themenstarter:in
72 Beiträge seit 2005
vor 18 Jahren

hmm klingt vernünftig, aber ehrlich gesagt kein Plan wie genau
das gehen soll, kannst du mir ein/zwei Zeilen Code dazu posten?
Bin noch recht unerfahren... 🙁

Vielen, vielen Dank aber für deine Hilfe, denke das
ist bis jetzt der schlauste Ansatz den man mir empfohlen hat!

4.506 Beiträge seit 2004
vor 18 Jahren

Hallo ingram333!

Naja, ist zwar kein vollständiger Code, aber genauso hilfreich.

Was Pulpapex meinte wäre, dass Du eine Methode oder Property in Deiner MainForm hinzufügst, mit der Du das ändern kannst.

Etwa so:



public class Arch : Form {

public static Arch myArchHandle;

public Arch ()
{
   myFormHandle = this;
}

public void ChangeStatus(GameState newState)
{
   // ersetze altes GameState mit neuem GameState
}

}

Dann kannst Du in Deinem Manager folgendes tun:



Arch.myArchHandle.ChangeStatus(newState);


Dieser Code ist nur als Ergänzung zu sehen, das heißt einfach dazuaddieren, der Rest, kann ja so bleiben.

Hoffe das war jetzt das was Du gemeint hast?

Ciao
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

I
ingram333 Themenstarter:in
72 Beiträge seit 2005
vor 18 Jahren

glaube das ist schon ungefähr das, aber so 100% hab ichs noch
nicht gecheckt.

Also, ich muss irgendwie meinem GameStateManager die
"public static Arch myArchHandle;" übergeben um dort
dann das UserControl zum state hinzuzufügen?

Derzeit erstelle ich das UserControl ja im State selbst, soll
ich das dann im GameStateManager statt dessen machen?

🤔

4.506 Beiträge seit 2004
vor 18 Jahren

Huch!

Ja, sorry, bin ehrlich ich hab Deinen Sourcecode nicht genau genug durchgelesen.

Dann solltest Du diese "static"-Variable in Deinem Manager implementieren und in dessen Konstruktor setzen, damit Du von der Main-Form dann auf eine zusätzliche Methode im Manager zugreifen kannst.

Also sozusagen grad rumgedreht 😉

Aber das Prinzip ist das selbe.

Ciao
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

I
ingram333 Themenstarter:in
72 Beiträge seit 2005
vor 18 Jahren

jo, jetzt hab ichs, danke euch!!!