Da MonoGame die tolle Eigenschaft besitzt, verschiedene Plattformen zu unterstützen, bietet es sich an, Projekte direkt als Multiprojekt anzulegen. In diesem Artikel möchte ich euch zeigen, wie ihr ein Windows-Desktop- und Android-Projekt zusammenbringt und euren Programmieraufwand um ein vielfaches reduziert.

Freigegebenes Projekt anlegen

Als erstes müsst ihr in Visual Studio ein neues Projekt erstellen. Wählt als Projektvorlage „Freigegebenes Projekt“ aus. Als Projektnamen könnt ihr [Projektname].Shared wählen.

sharedProject

Diesem Projekt könnt ihr im Projektmappen-Explorer zahlreiche Projekte hinzufügen. Klickt dazu mit der rechten Maustaste auf eure Projektmappe und wählt unter „Hinzufügen“ -> „Neues Projekt“ aus. 

Windows-Projekt anlegen

Ich werde bei mir als erstes ein MonoGame-Windows-Projekt anlegen. Ich nenne das Projekt „MeinSpiel.Windows“.

Bei jedem neu hinzugefügten Projekt müsst ihr die Dateien, die plattformunabhängig sind, in euer Shared-Projekt verschieben oder löschen, wenn das Shared-Projekt z.B. schon eine Game-Klasse besitzt. Die Game1-Klasse wäre so unabhängige Klasse, weshalb ihr sie direkt in euer Shared-Projekt verschieben könnt. Wenn ihr diese Klasse verschoben habt, öffnet sie, und entfernt beim „namespace“-Schlüssel das Windows.


namespace MeinSpiel

{ }

Das hat den Zweck, aus Projekten, die nicht im „MeinSpiel.Windows“-Namespace liegen, einfach auf die Typen zugreifen zu können. Wenn ihr den Namespace in „MeinSpiel.Shared“ ändert, müsst ihr in euren Projekten dementsprechend immer eine Using-Direktive hinzufügen.


using MeinSpiel.Shared;

Ich empfehle einfachheitshalber aber, den Namespace von der Game-Klasse einfach in „MeinSpiel“ zu ändern, damit ihr das nicht tun müsst.

Um aus dem Windows-Projekt die Shared-Game1-Klasse initialisieren zu können, muss im Windows-Projekt ein Verweis hinzugefügt werden. Rechte Maustaste auf „Verweise“ und dann „Verweis hinzufügen“. Wählt links im aufgetauchten Fenster „Freigegebene Projekte“. Dort sollte euer Shared Projekt erscheinen. Markiert es und klickt auf den OK-Button.

verweis_shared

Sobald ihr das getan habt, könnt ihr auf alle Klasse des Shared-Projekts zugreifen. Da die Game1-Klasse gleichheißt, müsst ihr auch keine Änderung in der Program-Klasse vornehmen.

Solltet ihr die Klasse umbenennen wollen, z.B. in „SharedGame“, müsst ihr in „Program.cs“ einfach die Instanz-Erstellung wie folgt umändern.


public static class Program
{
///

/// The main entry point for the application.
/// 

[STAThread]
static void Main()
{
using (var game = new SharedGame())
game.Run();
}
}

Shared-Content

Der Content unseres Spiels soll ebenfalls in allen Projekten gleich sein. Diesen können wir allerdings nicht in das Shared-Projekt verschieben. Für den Content müssen wir ein separates MonoGame-Projekt hinzufügen. Den Grund seht ihr gleich.

Ich habe mich für ein Windows-MonoGame-Projekt entschieden, jedoch ist das irrelevant welches ihr auswählt. Entfernt in diesem Projekt alle Dateien bis auf die „Content.mgcb“-Datei. Bei mir sieht das Projekt nun wie in der Abbildung aus.

content_projektmappe

Damit ist dieses Projekt auch fertig konfiguriert. Ihr könnt wie gewohnt eure Assets in dieser Content-Datei hinzufügen.

Damit ihr den Content auch in eurem Spiel laden könnt, müsst ihr diese Datei als Link eurem Projekt hinzufügen. Klappt dazu beim „Hinzufügen“-Button einfach das Menü auf und wählt „Als Link hinzufügen“.

link_content

Wenn ihr das richtig gemacht habt, sollte eure Content-Datei ein blaues Symbol im Windows Projekt haben.

windowsprojektmappe

Fügt dieser Datei eure Game-Assets hinzu. Wenn ihr versucht diese zu laden, erhaltet ihr einen Fehler. Das liegt daran, dass wir den Buildvorgang noch nicht auf „MonoGameContentReference“ gesetzt haben. Hier liegt auch der Grund, warum wir den Content nicht im Shared-Projekt unterbringen, da dieser Buildvorgang dort nicht zur Auswahl steht.

buildvorgang_content

Ist der Buildvorgang eingestellt, könnt ihr euer Spiel kompilieren. Erinnert euch daran, den Buildvorgang bei jedem neuem Projekt richtig zu setzen.

Ich habe dem Content eine SpriteFont hinzugefügt und in meiner Shared-Game1-Klasse ganz normal geladen.


SpriteFont font;

protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);

font = Content.Load("Font");
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);

spriteBatch.Begin();
spriteBatch.DrawString(font, "Hello World", Vector2.One, Color.White);
spriteBatch.End();

base.Draw(gameTime);

meinspiel_windows

Klappt wunderbar.

Android-Projekt anlegen

Zur besseren Demonstration will ich ein weiteres Projekt hinzufügen. Ich entscheide mich dabei für ein Android-Projekt. Der Name des Projekts ist bei mir „MeinSpiel.Android“.

Ich lösche im Android-Projekt genau zwei Dateien: Die Game1-Klasse und die Content-Datei. Die Game1-Klasse lösche ich deshalb, weil wir im Shared-Projekt bereits eine haben, die wir verwenden wollen. Die Content-Datei aus unserem MeinSpiel.Content-Projekt füge ich wieder als Link hinzu.

Um unsere Game1-Klasse einzubinden, müssen wir wieder einen Verweis zu unserem Shared-Projekt hinzufügen. Also Rechtsklick auf Verweise im Android-Projekt, dann „Verweis hinzufügen“ und unter den freigegebenen Projekten „MeinSpiel.Shared“ markieren und mit dem OK-Button bestätigen.

Falls die Game1-Klasse umbenannt wurde, geht einfach in die Datei namens „Activity1.cs“ und ändert den folgenden Code.


public class Activity1 : Microsoft.Xna.Framework.AndroidGameActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
var g = new SharedGame();
SetContentView((View)g.Services.GetService(typeof(View)));
g.Run();
}
}

Wenn ihr versucht, das Android-Spiel zu starten, bekommt ihr eine Fehlermeldung, dass eine Manifest-Datei fehle. Um eine hinzuzufügen geht ihr in die Projekt-Eigenschaften (Rechtsklick auf das Android-Projekt, dann ganz unten „Eigenschaften“)

Wählt links im Menü „Android-Manifest“. Nun seht ihr einen blauen Link wie im Screenshot. Wenn ihr draufklickt, wird ganz automatisch eine Manifest-Datei angelegt, die keine weiteren Veränderungen erfordert.

android_manifest

Eine kleine Änderung müsst ihr noch in der Activity-Klasse vornehmen. Oben in den Activity-Einstellungen steht beim Launchmode folgendes:


LaunchMode = Android.Content.PM.LaunchMode.SingleInstance

Ändert diese Zeile in


LaunchMode = LaunchMode.SingleInstance

Jetzt solltet ihr das Spiel starten können.

meinspiel_android

Ihr seht den gleichen „Hello World“-Text wie im Windows-Spiel. Und wir haben es nur einmal programmiert. Ehrfahrungsgemäß ändert man in den plattformspezifischen Projekten nach der Einrichtung nichts mehr, sondern hält sich nur noch im Shared-Projekt auf. 

Bei Fragen und Problemen unterstütze ich im Kommentarbereich gerne.