MyAdventure Kapitel 1 XNA

Tutorials zu verschiedenen Softwarenutzungen

Moderator: Moderatoren

Benutzeravatar
Jaegerfeld
Tribunus Angusticlavius
Tribunus Angusticlavius
Beiträge: 3571
Registriert: 10. November 2010 21:15
Wohnort: AudiCity
:
Pfeiler der Community Gewinner Userwahl

MyAdventure Kapitel 1 XNA

Beitragvon Jaegerfeld » 29. Januar 2011 12:02

MyAdventure Kapitel 1
XNA


Nachdem wir uns in der ersten Tutorialreihe die Basics angeeignet haben, wollen wir jetzt in die Vollen gehen.

Auf dem Programm steht ein klassisches Point & Click Adventure im Stile von Monkey Island 1 und ähnlichem.

Natürlich nicht ganz so technisch ausgereift, und für die Story müsst ihr schon selber sorgen. Aber die Engine dazu entsteht in den nächsten paar dutzend Kapiteln. Ich versuche den Stoff so einfach wie möglich zu halten, auch wenn dies manchmal bedeutet auf wesentliche Features moderner Programmiersprachen zu verzichten. Der Code, den ich hier präsentiere ist auch nie endgültig, es wird ständig vorkommen, dass alter Code überarbeitet wird und neue Funktionen hinzu wachsen.

Ab jetzt werde ich regelmäßig die gesamte Projektdatei zum Download anbieten, denn mit ein bischen Code posten ist es jetzt nicht mehr getan.

Das Spiel an sich wird aus zwei wesentlichen Komponenten bestehen, dem Adventure an sich und einem leistungsfähigen Editor, mit dessen Hilfe wir das Spiel erstellen. Beide werden parallel entwickelt und fußen auf völlig unterschiedlichen Techniken, auch wenn sie sich Code teilen. Der Editor wird mit Hilfe von WindowsForms entstehen, also eine stark an Windows selbst angelehnte Benutzerführung erhalten. Das Spiel nutzt das XNA - Framework.

Was uns gleich zur ersten Frage bringt:

Was ist XNA?

XNA ist ein Framework, also ein Programmiergerüst das uns wesentliche Aufgaben abnimmt. Seit seiner Veröffentlichung durch Microsoft im Dezember 2006 ist es ständig gewachsen und befindet sich momentan in der Version 4.0. XNA basiert auf C# (deshalb haben wir damit geübt) und erweitert das .NET Framework um viel Klassen, die sich vor allem um Probleme der Spieleentwicklung kümmern. So kann sich der Entwickler um die wesentlichen Dinge, wie eine tolle Spiellogik kümmern. Er muss sich keine großen Gedanken darüber machen, wie eigentlich ein 3D Modell zur Grafikkarte kommt, oder wie ein MP3 Titel abgespielt wird. Er nutzt einafch die dafür vorgesehenen Klassen. Da alles auf C# basiert ist das Endprodukt managed Code, d.h. der Entwickler muss sich auch nicht um Speicherverwaltung etc, kümmern. Das erledigt das Framework für ihn.

EIn weiterer Pluspunkt ist die Vertreibsstrategie Seitens Microsoft. XNA ist ein Tool für mehrere Plattformen, es läuft sowohl auf PC als auch auf XBOX360. In letzter Zeit sind noch Zune und Windows Phone 7 hinzu gekommen.

Wir können unser Spiel also relativ einfach auf die XBOX übertragen.

Natürlich hat XNA auch einige Nachteile:
  • Es verlangt zwingend eine Grafikkarte mit Shader 1.1 (2.0 ist besser).

    Das soll uns 2010 aber nicht weiter stören. Wer noch so einen uralt PC sein eigen nennt wird wohl auch nicht am PC spielen.

  • Da es managed Code ist, kann ein C# Spiel nie so performant werden wie eines in C++.

    Wie wollen aber kein Crysis 2,5 erstellen, sondern ein nettes kleines Adventure. "Edna bricht aus" ist in JAVA geschrieben, das(JAVA, nicht "Edna bricht aus" welches ein tolles Adventure ist) schlagen wir locker.
Sowas ist aber ohne weiteres möglich :



oder das hier:



In Vorbereitung dieses Tutorials habe ich mir mal ein paar englische Fachbücher angesehen.

EIn kleines Spielchen ist schon in wenigen Minuten möglich:





Bevor wir aber mit unserem Projekt beginnen wollen wir uns erst mal das Grundgerüst genauer ansehen.

Startet Visual Studio und legt ein neues Projekt an.

Diesmal ein XNA Spiel.



Bild



Haben wir das getan, öffnet sich ein neues Projekt in dem schon eine Menge für uns angelegt und ausgefüllt wurde.

Betrachten wir uns mal den Projektmappenexplorer:


Bild


Es fällt sofort auf, dass wir eigentlich zwei Projekte haben, MyAdventure2(so habe ich es genannt) und MyAdventure2Content.

Kurz gesagt ist das eine virtuelle Trennung, in Content landet genau dieser: Alles was im Spiel angezeigt, abgespielt oder als Video abgespielt werden soll.

XNA verfügt im Hintergrund über einen eigene Contentverwaltung, die dafür sorgt das das geünschte Bild etc. genau zum richtigen Zeitpunkt im Speicher verfügbar ist.

Das hat nur einen Nachteil: Diese Sachen sind im Nachhinein (zur Laufzeit) nur schwer veränder-/austauschbar. Das soll uns im ersten Kapitel aber noch nicht stören.



Im eigentlichen Projektordner gibt es eine Menge Dateien und Ordner.

In Properties können wir Sachen definieren, die sich ein Spiel merken soll, also z.B. die Grafikeinstellungen oder den Spielernamen.

In Verweise stehen Verweise zu benutzten Bibliotheken. Es ist uns jederzeit möglich sogenannte .dll einzubinden. Das sind von anderen geschriebene Funktionalitäten, die wir hier wiederverwenden wollen. Und natürlich all die Klassen, die wir aus dem Fundus des XNA und .NET Frameworks nutzen wollen. VS hat da schon mal was für euch eingetragen. Da wir ein XNA Spielprojekt erstellt haben war es logisch, dass wir auch die XNA Bibliotheken nutzen wollen.



In Content References wird auf MyAdventure2Content verwiesen, wie gesagt ist die Trennung eher der Ordnung dienlich.



Game.ico ist unser Spieleicon. Wer will kann dort ein eigenes verwenden(machen wir später auch).

Game1.cs ist das Herz unseres Spieles, hier läuft unser gesamter Code zusammen. Wir beschäftigen uns gleich eingehnder mit diese Klasse.

GameThumbnail.png ist quasi das Icon wenn wir dieses Spiel auf der XBOX360 veröffentlichen. das wollen wir zu diesem Zeitpunkzt aber nicht, deshalb ist es unwesentlich.

Die Png Dateien grass .png und roman.png habt ihr noch gar nicht. Das kommt gleich :-).

Bevor wir uns nun aber der Game1.cs zuwenden klickt einfach mal oben auf den grünen Pfeil oder startet das Programm mit F5.

Bild

Nicht wirklich ein tolles Game, aber immerhin tut sich schon was.

Das was ihr hier seht ist die Arbeit, die VS beim Projekterstellen für euch übernommen hat.

Das ist ein Riesenvorteil im Vergleich zum herkömmlichen Spieleprogrammieren im professionellen Umfeld.

Dort ist es ein weiter Weg bis ein solches Fenster gerendert wird.

Wenn alles geklappt hat können wir uns nun die Game1.cs ansehen.



Neben den üblichen Sachen in einer frisch erzeugten Klasse (namespace, erste using Einbindungen etc.), hat VS auch gleich mal 5 Methoden als Rümpfe eingefügt.

Wir wollen die mal der Reihe nach kurz durchgehen und erläutern für was die zuständig sind.



protected override void Initialize()

Dort kommt alles rein, das erledigt werden soll, wenn das Spiel initialisiert, sprich gestartet wird.

Wir fügen dort gleich ergänzen das gleich mal:


Code: Alles auswählen

Window.Title = "MyAdventure Kapitel 1";
 graphics.PreferredBackBufferHeight = 600;
 graphics.PreferredBackBufferWidth = 800;
 this.IsMouseVisible = true;


Window.Title verändert den Titel des Fensters (wer hätte es gedacht)

graphics.PrefferedBackBufferHeigth und graphics.PreferredBackBufferWidth definieren die Auflösung unseres Spiels, 800x600 reicht erst mal.

this.IsMouseVisible = true macht den Mauszeiger sichtbar.



Probiert mal mit F5 das Ergebnis aus.

protected override void LoadContent()

Dort sagen wir XNA welcher Content beim Spielstart geladen werden soll.



protected override void UnloadContent()

macht genau das Gegenteil, es entlädt Content, räumt also nach getaner Arbeit den Speicher wieder brav auf.



protected override void Update(GameTime gameTime)

Ist eine der wichtigsten Methoden überhaupt. Sie wird jede Sekunde 60 mal gestartet. Unser Spiel läuft also mit 60 Frames die Sekunde.

Warum nicht mehr? Euer Monitor kann aller Vorraussicht nach gar nicht mehr darstellen, 80 FPS(oder noch mehr wenn man manchem ShooterKiddie zuhört) finden also eigentlich gar nicht statt.

Es ist also sinnlos öfter rendern zu wollen. Wir sollten lieber schauen das die 60 FPS immer gewährleistet sind.



In die Updatemethode kommt nun alles, was in einem "Tick" oder "Frame" gemacht werden soll. Ihr könnt euch das so vorstellen: Euer Spiel blinzelt in der Sekunde 60 mal, die Welt veerändert sich also für den Betrachter sprunghaft, nicht kontinuierlich. Wir werden hier also später Prüfen wo der mauszeiger gerade ist, ob geklickt wurde oder ob jemand eine Taste gedrückt hat usw. und dann darauf reagieren.



protected override void Draw(GameTime gameTime)

Draw ist die andere große Methode, auch sie wird jede Sekunde 60 mal ausdgelöst und zwar immer NACH der Update().

Hier zeichnen (rendern) wir dann auf dem Bildschirm. Momentan streht da noch nicht viel, nur



GraphicsDevice.Clear(Color.CornflowerBlue);

Damit wird unser Bildschirm (eigentlich der BackBuffer der Grafikkarte aber das ist momentan unwesentlich) geleert, oder vielmehr mit der Farbe Cornflowerblue (tolles Ding) überschrieben.

damit verhindern wir z.B. unschöne Schliereneffekte.


base.Draw (gameTime);

Damit sagen wir anderen Komponenten des Spiels (kommt VIEL später in diesem Tutorial), dass sie jetzt dran sind.

Nun wollen wir aber auch mal etwas sehen und Bewegung haben!

Ich habe euch die von mir verwendeten Datein plus das gesamte Projekt als zip hochgeladen.

Projektdateien

Alle Grafiken die wir in unserem Spiel benutzen werden sind Sprites, d.h reine 2D Objekte.

Um Bilder(Texturen im XNA Kontext genannt) ins Spiel zu laden müssen wir erst einmal Variablen dafür bereitstellen.

Dies machen wir in der Game1.cs Klasse gleich ganz oben,


Code: Alles auswählen

Texture2D boden, held;



zusätzlich wollen wir auch gleich Variablen für den Keyboardstatus (also: welche Taste ist gerade gedrückt) und eine in der wir eien 2D Position speichern können. Wozu sehen wir gleich.


Code: Alles auswählen

KeyboardState keyState, oldState;
 Vector2 position;


Um Bilder im Spiel verfügbar zu haben müssen wir diese erst einmal als Content bekannt machen.

Das geht sehr einfach, klickt mit der rechten Maustaste auf MyAdventureContent2 -> Hinzufügen -> Vorhandenes Element und wählt anschließend die beiden Bilder aus der Kapitel1.zip



Im Anschluss müssen wir die Texturen in der LoadContent() Methode laden.


Code: Alles auswählen

protected override void LoadContent()
 {
 // Create a new SpriteBatch, which can be used to draw textures.
 spriteBatch = new SpriteBatch(GraphicsDevice);

 boden = Content.Load<Texture2D>("grass");
 held = Content.Load<Texture2D>("roman");
 // TODO: use this.Content to load your game content here
 }



Das Schema ist einfach: Content.Load lädt Content, <Texture2D> bedeutet, dass es sich um einen 2DTextur handelt. ("grass") ist der Dateiname.

Damit unser Held beweglich wird geben wir ihm eine Positionsvariable. Sie wird in der initialize() methode vorbelegt.


Code: Alles auswählen

protected override void Initialize()
 {
 // TODO: Add your initialization logic here
 Window.Title = "MyAdventure Kapitel 1";
 graphics.PreferredBackBufferHeight = 600;
 graphics.PreferredBackBufferWidth = 800;
 this.IsMouseVisible = true;
 position = new Vector2(10, 10);
 base.Initialize();
 }



Um das ganze zu zeichnen müssen wir nun nur noch die Draw() Methode verändern:


Code: Alles auswählen

protected override void Draw(GameTime gameTime)
 {
 GraphicsDevice.Clear(Color.CornflowerBlue);
 spriteBatch.Begin();
 spriteBatch.Draw(boden, new Rectangle(0, 0, 800, 600), Color.White);
 spriteBatch.Draw(held, new Rectangle((int)position.X, (int)position.Y, 25, 30), Color.White);
 spriteBatch.End();

 // TODO: Add your drawing code here

 base.Draw(gameTime);
 }



Da XNA eigentlich in 3D rechnet müssen wir etwas zaubern um in reinem 2D zu arbeiten.

Das übernimmt der spriteBatch für uns.

In der Draw Methode sagen wir nun das wir anfangen wollen Sprites zu zeichnen (spriteBatch.Begin()), und abschließend wieder zu beenden (spriteBatch.End()).

Dazwischen zeichnen wir alle Sprites:

spriteBatch.Draw(boden, new Rectangle(0, 0, 800, 600), Color.White); ist wie folgt aufgebaut:

Zeichne einen Sprite, und zwar mit der Textur boden, im Bereich ( von links oben 0 Pixel nach rechts und 0 Pixel nach unten, 800 Pixel breit und 600 Pixel hoch) Weiß ist transparent).

Das muss euch noch nicht weiter schocken, die Einstellungen hier werden aber noch wichtig sobald wir Animationen einbauen.

Beim held setzen wir statt einer starren Position die oben definierte Variable position ein.

Wenn wir das Ganze nun starten sieht das schon mal toll aus:

Bild

Leider bewegt sich noch nichts, das wollen wir jetzt ändern.

held hat ja eine Position bekommen, die wollen wir nun über die aus vielen Spielen bekannte wsad steuerung verändern.

Dazu fragen wir in der Update() Methode den Status der Tastatur ab und beeinflussen so position.

Ich habe dafür eine neue Methode checkTastatur() gebastelt, die wir in der Update() aufrufen:


Code: Alles auswählen

public void checkTastatur() {
 keyState = Keyboard.GetState();

 if (keyState.IsKeyDown(Keys.A))
 { position.X -= 5; }
 if (keyState.IsKeyDown(Keys.D))
 { position.X += 5; }
 if (keyState.IsKeyDown(Keys.W))
 { position.Y -= 5; }
 if (keyState.IsKeyDown(Keys.S))
 { position.Y += 5; }


 oldState = keyState;

 }



Code: Alles auswählen

protected override void Update(GameTime gameTime)
 {
 // Allows the game to exit
 if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
 this.Exit();

 checkTastatur();
 // TODO: Add your update logic here

 base.Update(gameTime);
 }



Wenn wir das jetzt mit F5 ausprobieren können wir unseren Helden mit der Tastatur bewegen.

Noch sehr einfach, aber das solls für dieses Kapitel gewesen sein.

Im nächsten bringen wir etwas Struktur in unser Spiel indem wir uns mit Vererbung beschäftgen.

Viel Spaß!
„Ich schätze mal, das kann jeder Online-Community passieren. Irgendwann stellen die höflichen und vernünftigen Leute fest, dass sie sich in dieser Gruppe nicht mehr aufhalten wollen. Also verschwinden die. Und diejenigen die übrig bleiben, erfahren nur noch die Leute die genau so wie sie drauf sind.“

=== David Gaider, Bioware ===

Flying-Horse
Tiro
Tiro
Beiträge: 1
Registriert: 12. April 2011 18:02

Re: MyAdventure Kapitel 1 XNA

Beitragvon Flying-Horse » 12. April 2011 18:13

Hallo wollte mal fragen wann das 2 kommt

Benutzeravatar
Jaegerfeld
Tribunus Angusticlavius
Tribunus Angusticlavius
Beiträge: 3571
Registriert: 10. November 2010 21:15
Wohnort: AudiCity
:
Pfeiler der Community Gewinner Userwahl

Re: MyAdventure Kapitel 1 XNA

Beitragvon Jaegerfeld » 12. April 2011 20:29

Ich bin grade leider vollauf mit Darkest Hour und einem zweiten Softwareprojekt (sowie Software ganz anderer Natur :strategie_zone_160:) ausgelastet.
Sobald ich wieder Luft habe gehts weiter, versprochen.
„Ich schätze mal, das kann jeder Online-Community passieren. Irgendwann stellen die höflichen und vernünftigen Leute fest, dass sie sich in dieser Gruppe nicht mehr aufhalten wollen. Also verschwinden die. Und diejenigen die übrig bleiben, erfahren nur noch die Leute die genau so wie sie drauf sind.“

=== David Gaider, Bioware ===

Benutzeravatar
Buchhalter007
Optio
Optio
Beiträge: 631
Registriert: 16. Januar 2011 16:32
:
Teilnahme an einem Contest

Re: MyAdventure Kapitel 1 XNA

Beitragvon Buchhalter007 » 25. September 2011 13:35

Ich stelle mich irgendwie blöd :
Um Bilder im Spiel verfügbar zu haben müssen wir diese erst einmal als Content bekannt machen. Das geht sehr einfach, klickt mit der rechten Maustaste auf MyAdventureContent2 -> Hinzufügen -> Vorhandenes Element und wählt anschließend die beiden Bilder aus der Kapitel1.zip

Aber wo ist denn MyAdventureContent2?
Bild

Benutzeravatar
Jaegerfeld
Tribunus Angusticlavius
Tribunus Angusticlavius
Beiträge: 3571
Registriert: 10. November 2010 21:15
Wohnort: AudiCity
:
Pfeiler der Community Gewinner Userwahl

Re: MyAdventure Kapitel 1 XNA

Beitragvon Jaegerfeld » 25. September 2011 16:10

Im Projektmappenexplorer. Das zweite Projekt.
VS legt das automatisch an (ist ein Template).
Wenn du dort was hinzufügst ist es als Content ansprechbar.
Bei XNA 3 war das noch etwas anders, welches nutzt du denn?
„Ich schätze mal, das kann jeder Online-Community passieren. Irgendwann stellen die höflichen und vernünftigen Leute fest, dass sie sich in dieser Gruppe nicht mehr aufhalten wollen. Also verschwinden die. Und diejenigen die übrig bleiben, erfahren nur noch die Leute die genau so wie sie drauf sind.“

=== David Gaider, Bioware ===

Benutzeravatar
Buchhalter007
Optio
Optio
Beiträge: 631
Registriert: 16. Januar 2011 16:32
:
Teilnahme an einem Contest

Re: MyAdventure Kapitel 1 XNA

Beitragvon Buchhalter007 » 26. September 2011 13:34

Ich nuze VS C# Express oder was meinzt du?
Bild

Benutzeravatar
Jaegerfeld
Tribunus Angusticlavius
Tribunus Angusticlavius
Beiträge: 3571
Registriert: 10. November 2010 21:15
Wohnort: AudiCity
:
Pfeiler der Community Gewinner Userwahl

Re: MyAdventure Kapitel 1 XNA

Beitragvon Jaegerfeld » 26. September 2011 21:28

Bei XNA 4 sollte das so aussehen:

Bild
„Ich schätze mal, das kann jeder Online-Community passieren. Irgendwann stellen die höflichen und vernünftigen Leute fest, dass sie sich in dieser Gruppe nicht mehr aufhalten wollen. Also verschwinden die. Und diejenigen die übrig bleiben, erfahren nur noch die Leute die genau so wie sie drauf sind.“

=== David Gaider, Bioware ===

gorgomir
Tiro
Tiro
Beiträge: 1
Registriert: 25. Januar 2013 22:44
Wohnort: Hamm NRW
Kontaktdaten:

Re: MyAdventure Kapitel 1 XNA

Beitragvon gorgomir » 25. Januar 2013 23:10

Ich grabe diesen Thread nun mal aus und bitte um Fortsetzung.

Mfg, Gorgomir.

Benutzeravatar
Jaegerfeld
Tribunus Angusticlavius
Tribunus Angusticlavius
Beiträge: 3571
Registriert: 10. November 2010 21:15
Wohnort: AudiCity
:
Pfeiler der Community Gewinner Userwahl

Re: MyAdventure Kapitel 1 XNA

Beitragvon Jaegerfeld » 25. Januar 2013 23:36

Von meiner Seite wird es auf absehbare Zeit hier keinerlei Tutorials mehr geben.

Wer Unterstützung bei etwas benötigt kann sich gerne per PN bei mir melden.
„Ich schätze mal, das kann jeder Online-Community passieren. Irgendwann stellen die höflichen und vernünftigen Leute fest, dass sie sich in dieser Gruppe nicht mehr aufhalten wollen. Also verschwinden die. Und diejenigen die übrig bleiben, erfahren nur noch die Leute die genau so wie sie drauf sind.“

=== David Gaider, Bioware ===