Verweise und Referenzen, oder: Wie greife ich auf die Game-Klasse zu?

In den letzten Wochen und Monaten musste ich in den Foren und Communities, in denen ich mich so rumtreibe immer wieder eine ganz bestimmte Frage lesen und beantworten. Auch in der Liste mit Suchanfragen, die auf meinen Blog geführt haben, sind immer wieder Hinweise auf diese Frage zu finden. Eine Frage, die immer wieder von den Einsteigern in die Spieleentwicklung mit XNA gestellt wird und anscheinend eine recht große Hürde darstellt.

Wie kann ich in einer anderen Klasse auf die Game-Klasse zugreifen?

Dies ist eine sehr gute Frage, führt aber immer wieder zu erhitzten Gemütern, da diese Frage halt sehr häufig gestellt wird und eigentlich absolutes Grundlagenwissen darstellt. Zum Glück ist die Frage nicht sonderlich schwer zu beantworten und daher werde ich das jetzt in diesem kleinen Beitrag auch machen.

In C# gibt es keine Zeiger bzw. Pointer, so wie dies z.B. in C/C++ der Fall ist. Dies ist einer der Gründe, warum C# und ähnliche Programmiersprachen einfacher sind, als andere, die ausgiebigen Gebrauch von Zeigern machen. Zeiger sind ein durchaus schwieriges Thema, daß für viele Einsteiger eine sehr, sehr große Hürde darstellt. Trotzdem sind Zeiger ein sehr wichtiges Konzept in jeder Art von Computer, allerdings kann man diese vor dem Entwickler weitestgehend verbergen, so daß dieser sich nicht damit rumschlagen muss und so einen einfacheren Einstieg findet.

Exakt dies wurde mit C# unter anderem gemacht.

Aber wie funktioniert das denn nun genau? Ganz einfach. Klassen werden instanziert, wodurch aus einer Klasse eine Instanz oder ein Objekt wird (wobei sich das oder darauf bezieht, dass man das was entsteht Instanz oder Objekt nennt. Beides ist also gleichwertig). Dabei ist die Klasse das Stück Sourcecode, was ihr schreibt und was irgendwo im ausführbaren Programm liegt. Diese Klasse wird aber nicht vom Computer abgearbeitet, sondern muss zuvor instanziiert werden. Dies erfolgt sehr einfach mit dem new Operator von C#.

Game1 game = new Game1();

Dies ist eine Zeile, die im Standard XNA-Template für ein neues Spiel in der Datei Program.cs versteckt ist. Dies ist der Haupteinstiegspunkt für dein Spiel und bedeutet folgendes:

  • Erzeuge eine Referenz-Variable vom Typ Game1 mit dem Namen game
  • Weise der zuvor erzeugten Referenz-Variable eine neue Instanz von Game1 zu

Hinter der Referenz-Variablen verbirgt sich nun der aus C/C++ bekannte Zeiger. Die Variable game aus dem obigen Beispiel enthalt nicht die konkrete Instanz von Game1 sondern lediglich eine Referenz darauf. Für den C#-Entwickler ist dies jedoch erstmal relativ egal, da dies vollkommen transparent von der Programmiersprache behandelt wird. Der Einsteiger muss sich nur folgendes verdeutlichen:

Game1 game = new Game1();
Game1 game2 = game;

In der zweiten Zeile erzeugen wird eine weitere Referenz-Variable vom Typ Game1 mit Namen game2. Wir weisen ihr dann game zu. Dies bedeutet nun nicht, daß wir zwei Instanzen von Game1 haben, sondern wir haben lediglich die Referenz auf die einzige existierende Instanz von Game1 in die Variable game2 kopiert. Es ist nun egal, ob wir game oder game2 verwenden, wir benutzen in beiden Fällen die gleiche Instanz, da wir die gleiche Referenz verwenden.

Um also nun aus einer selbsterstellten Klasse auf die Game-Variable zuzugreifen, müssen wir ihr einfach eine Referenz auf die Game-Instanz übergeben und schon können wir darauf zugreifen. Dies kann z.B. wie folgt geschehen:

public class MyOwnNewClass
{
  private Game game;

  public MyOwnNewClass(Game gameReference)
  {
    this.game = gameReference;
  }

  public void MyMethod()
  {
    GraphicsDevice graphics = this.game.GraphicsDevice;
  }
}

Dies ist schon ein wenig mehr Code, aber alles was wir nun benötigen. Wir erzeugen einen eigenen Konstruktor ab Zeile 5 der eine Referenz auf die Game-Klasse als Parameter erwartet. Dieser Konstruktor wird aufgerufen, wenn wir eine Instanz unserer eigenen Klasse erzeugen, wie ich gleich zeigen werde. Diese Referenz speichern wir dann in Zeile 7 in eine Member-Variable. Dies erfolgt mittels der this Referenz. this ist dabei immer eine Referenz auf die Instanz der Klasse, in der die Code-Zeile ausgeführt wird.

Ab Zeile 10 habe ich dann eine Beispiel-Methode dargestellt, die nun die Game-Referenz verwendet. So können wir z.B. auf das einzige, in der Game-Klasse existierende GraphicsDevice zugreifen. Dabei greifen wir über eine Referenz in der Referenz-Variablen game auf die konkrete Instanz von Game zu und haben damit Zugriff auf die öffentlichen Member, Properties und Methoden dieser Klasse.

Hier noch ein kurzes Beispiel, wie eine Instanz der eigenen Klasse erzeugt wird, welches in diesem Fall in der Game-Klasse gemacht wird.

MyOwnNewClass myClass = new MyOwnNewClass(this);

this ist dabei wieder eine Referenz auf die aufrufende Klasse, in diesem Fall die Game-Klasse. Würde dies in einer anderen Klasse aufgerufen werden, dann funktioniert dies nicht, weil als Parameter des Konstruktors von MyOwnNewClass eine Referenz vom Typ Game erwartet wird.

Als weiterführendes Thema möchte ich hier noch erwähnen, daß es nicht nur Referenztypen (Reference-Type) gibt, sondern auch noch Werttypen (Value-Types). Dies sind z.B. int, float usw. Diese möchte ich hier nicht genauer beschreiben, denn das würde dieses kleine Thema doch sehr aufblähen. Wenn genug Nachfrage da ist, werde ich dies in einem weiteren Artikel genauer erklären. Schreibt dafür einfach in die Kommentare…

About these ads

Veröffentlicht am 22.04.2011 in C#, Grundlagen, Grundlagen, XNA, XNA 3.1, XNA 4.0 und mit , , , , , getaggt. Setze ein Lesezeichen auf den Permalink. 7 Kommentare.

  1. Hi Glatzemann,

    dachte eigentlich zuerst, dass das ein Artikel für mich wäre, aber soweit bin ich doch schon, das ich weis was call-by-value und call-by-reference ist. Ich hatte gehofft du zeigst ein paar Tipps und Tricks wie man es sauber übergibt und vielleicht ein paar Design Patterns die man verwenden kann für bestimmte Dinge. Denn meistens bin ich mir nicht sicher wie ich etwas sauber aufbauen soll. Hättest du da vielleicht einen kurzen Tipp oder einen guten Link?
    Aber der Artikel ist sicher nicht schlecht für einen Anfänger.

    • Danke sehr… Schade, dass dir der Artikel nicht weitergeholfen hat, aber natürlich auch schön, dass du ihn garnicht erst benötigt hast :-)

      Ich persönlich finde es immer schwer, einfach nur theoretisch zu erläutern, wie und warum man etwas auf eine bestimmte Art und Weise strukturiert und aufbaut. Praktische Beispiele sind viel plastischer und in meinen Augen ist der Lerneffekt dabei auch viel größer. Wenn du ein konkretes Beispiel hättest, dann inspiriert mich das vielleicht.

      • Bis jetzt konnte ich alles programmieren was ich wollte, aber ich hätte gerne mal gehört/gesehen wie man etwas richtig strukturiert/aufbaut oder wie es jemand macht der damit jahrelang arbeitet und sich darüber Gedanken gemacht hat. Konkretes Beispiel fällt mir jetzt nicht ein, aber falls doch, melde ich mich hier nochmal.

      • Ja, mach das… Ist immer schwer einfach so ein Beispiel aus der Luft zu greifen… Hier habe ich mal ansatzweise sowas beschrieben…

  2. Max.Bodycount

    Ich bitte darum, dieses Thema weiter auszuführen, ausgesprochen hilfreich.

    • In welche Richtung sollte ich das Thema denn weiter ausführen? Was wünschst du dir? Ich schaue natürlich gerne bei Themenvorschlägen, ob ich diese erfüllen kann.

  1. Pingback: Terrain 101: Das erste Dreieck « "Mit ohne Haare"

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ photo

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

Folgen

Erhalte jeden neuen Beitrag in deinen Posteingang.

Schließe dich 140 Followern an

%d Bloggern gefällt das: