Getting started | Sharpex2D 1.2.3

    • C#
    • .NET (FX) 4.0

    Es gibt 25 Antworten in diesem Thema. Der letzte Beitrag () ist von Radinator.

      Getting started | Sharpex2D 1.2.3

      Vorwort

      Herzlich willkommen zum 'getting started' von Sharpex2D. In diesem Tutorial werde ich euch die grundlegenden Elemente zeigen, um euch mit dieser Engine vertraut zu machen. Bevor wir beginnen müssen wir uns über folgende Aspekte Gedanken machen:

      • Auf welchem Zielsystem soll die Applikation laufen
      • Welche externen Komponenten werden benötigt


      Der erste Punkt hängt sehr mit dem zweiten zusammen, da zum Beispiel nicht jedes RenderDevice auf jedem System läuft. Die niedrigste Windows Version, die von Sharpex2D unterstützt wird, ist XP. Dies hat den Grund da Windows XP die älteste Plattform ist, auf der sich das .NET Framework installieren lässt. Es empfiehlt sich, immer die älteste Version zu unterstützen, solange der Portierungsaufwand nicht zu groß wird.

      1. GDI (Windows XP)
      2. DirectX 9 (Windows XP)
      3. DirectX 10 (Windows Vista)
      4. DirectX 11 (Windows 7, Service Pack 1)

      Da alle Schnittstellen über das RenderDevice angesteuert werden ist die Handhabung mit jeder Schnittstelle gleich. Jedoch empfehle ich, falls viele Geometrien gezeichnet werden, auf das DirectX9 RenderDevice zu verzichten. Falls nur Texturen oder Schriftzüge gezeichnet werden, gibt es keinerlei Einschränkungen.
      Falls man sich dennoch unsicher ist, kann man die Auswahl auch den DeviceSelector überlassen. Dieser wählt automatisch ein geeignetes RenderDevice entsprechend der Plattform aus. Hierbei kann man auswählen, ob das RenderDevice mit den niedrigsten Voraussetzung oder der höchsten Voraussetzung ausgewählt werden soll. Zusätzlich gibt es ein integriertes Softwarefallback, falls kein RenderDevice unterstützt wird. Doch dazu später mehr.


      Einstieg

      1. Ein neues WindowsForms Projekt erstellen
      2. Verweise hinzufügen (Sharpex2D, sowie die verschiedenen Renderer, die neuesten Versionen findet ihr hier: sharpex2d.de/?p=components oder direkt unter nuget.org)

      Als nächstes könnt ihr Form1 löschen, diese benötigen wir nicht explizit. Als nächstes navigieren wir in die Program.cs - Da wir die Form1 gelöscht haben, benötigen wir auch die Zeile:

      C#-Quellcode

      1. Application.Run(new Form1());


      Stattdessen initialisieren wir nun Sharpex2D, dies erfolgt über die statische Klasse SGL. Von dieser Klasse rufen wir nun die parameterlose Methode Initialize auf.

      C#-Quellcode

      1. SGL.Initialize();


      Diese Methode erstellt automatisch ein neues Fenster für uns, und sucht die Game-Klasse über Reflection. Diese Klasse haben wir natürlich noch nicht erstellt, doch das werden wir nun im nächsten Schritt nachholen. Wir erstellen eine neue Klasse und nennen diese "MainGame" anschließend implementieren wir in diese Klasse die abstrakte Klasse "Game" welche sich in Sharpex2D.Framework.Game befindet.

      C#-Quellcode

      1. using System;
      2. using Sharpex2D;
      3. using Sharpex2D.GameService;
      4. namespace MyGame
      5. {
      6. public class MainGame : Game
      7. {
      8. public override void OnUpdate(GameTime gameTime)
      9. {
      10. }
      11. public override void OnRendering(Sharpex2D.Rendering.RenderDevice renderer, GameTime gameTime)
      12. {
      13. }
      14. public override EngineConfiguration OnInitialize(LaunchParameters launchParameters)
      15. {
      16. }
      17. public override void OnLoadContent()
      18. {
      19. }
      20. }
      21. }


      Uns fällt als erstes auf das die abstrakte Methode OnInitialize eine Klasse mit den Namen "EngineConfiguration" zurück gibt. Dies ist die Stelle, an der wir über die Audio sowie Grafik Schnittstelle entscheiden. Da wir faul und unentschlossen sind, lassen wir die Grafikschnittstelle automatisch auswählen.

      C#-Quellcode

      1. RenderDevice resultDevice = DeviceSelector.Select(
      2. new RenderDevice[]
      3. {
      4. new Sharpex2D.Rendering.DirectX9.DirectXRenderDevice(),
      5. new Sharpex2D.Rendering.DirectX10.DirectXRenderDevice(),
      6. new Sharpex2D.Rendering.DirectX11.DirectXRenderDevice()
      7. }, DeviceSelector.SelectorMode.Lowest);


      Dank SelectorMode.Lowest wird uns dasjenige RenderDevice zurückgeliefert, welches die niedrigsten Anforderungen besitzt und auf den aktuellen System verfügbar ist.

      [list=1]SelectorMode.Lowest - Liefert das RenderDevice zurück, welches die niedrigsten Anforderungen besitzt und auf der aktuellen Plattform lauffähig ist.
      SelectorMode.Highest - Liefert das RenderDevice zurück, welches die höchsten Anforderungen besitzt und auf der aktuellen Plattform lauffähig ist.
      SelectorMode.Generic - Liefert das erst lauffähige RenderDevice zurück.[/list]

      Desweiteren kann man einen zusätzlichen boolschen Wert übergeben, der angibt ob ein Softwarefallback verwendet werden soll, falls kein RenderDevice verfügbar ist.

      Da wir nun über das RenderDevice entschieden haben, müssen wir uns um einen ISoundInitializer kümmern. Da wir Sound erstmal nicht brauchen, fahren wir mit null genau richtig. Unsere fertige Methode sieht also nun so aus:

      C#-Quellcode

      1. public override EngineConfiguration OnInitialize(LaunchParameters launchParameters)
      2. {
      3. RenderDevice resultDevice = DeviceSelector.Select(
      4. new RenderDevice[]
      5. {
      6. new Sharpex2D.Framework.Rendering.DirectX9.DirectXRenderDevice(),
      7. new Sharpex2D.Framework.Rendering.DirectX10.DirectXRenderDevice(),
      8. new Sharpex2D.Framework.Rendering.DirectX11.DirectXRenderDevice()
      9. }, DeviceSelector.SelectorMode.Lowest);
      10. return new EngineConfiguration(resultDevice, null);
      11. }


      Als nächstes entfernen wir das Exception throwing aus der OnContentLoad Methode und fügen in der OnRendering Methode folgenden Code ein.

      C#-Quellcode

      1. renderer.Begin();
      2. //draw code here
      3. render.End();


      Nun können wir unsere Applikation das erste mal Ausführen. Wir sollten nun ein Fenster mit blauer Farbe gefüllt sehen.





      Wie wir sehen können ist unsere Form noch namenlos, das sollten wir schnell ändern, also gehen wir zurück in die Program.cs und fügen nach der Initialize Methode von SGL folgenden Code ein.

      C#-Quellcode

      1. SGL.Components.Get<RenderTarget>().Window.Title = "MyGame";


      Wir greifen auf die interne Komponentenauflistung von SGL zu, und holen uns das RenderTarget. Über RenderTarget.Window haben wir nun Zugriff auf unsere Oberfläche. Nach dieser kleinen Spielerei sollten wir Anfangen eine Textur zu laden und diese anschließend zu zeichnen.

      Eine Texture sowie jeder andere Content wird über den ContentManager geladen, welcher in der Game-Klasse als Eigenschaft vorliegt. Der ContentManager möchte von uns den Typ der Resource, sowie den Pfad innerhalb des automatisch generierten Content Ordners. Eine Texture besitzt immer den Typ Texture2D, also sollten wir unsere Texturen auch mit diesen Typ laden.

      C#-Quellcode

      1. public override void OnLoadContent()
      2. {
      3. Texture2D texture2D = Content.Load<Texture2D>("pig.png");
      4. }


      Texture2D hat automatisch das richtige Format um von jeden RenderDevice gezeichnet zu werden. Um nun tatsächlich etwas zu sehen, legen wir eine private Variable mit den Type Texture2D innerhalb der Game-Klasse an und laden diese mithilfe des ContentManagers. Anschließend, fügen wir in die OnRendering Methode folgenden Code ein.

      C#-Quellcode

      1. public override void OnRendering(Sharpex2D.Rendering.RenderDevice renderer, GameTime gameTime)
      2. {
      3. renderer.Begin();
      4. renderer.DrawTexture(_texture2D, new Vector2(0, 0), Color.White);
      5. renderer.End();
      6. }


      Durch den DrawTexture Aufruf, weisen wir das RenderDevice an, unsere Textur auf den entsprechenden Koordinaten zu zeichnen. Die angegebene Farbe fügt zusätzliches Texture Tinting ein. (Color.White = Kein Tinting)

      Unsere gesamte Game-Klasse sollte nun ähnlich wie hier aussehen.

      C#-Quellcode

      1. using System;
      2. using Sharpex2D;
      3. using Sharpex2D.GameService;
      4. using Sharpex2D.Math;
      5. using Sharpex2D.Audio;
      6. using Sharpex2D.Rendering;
      7. namespace MyGame
      8. {
      9. public class MainGame : Game
      10. {
      11. public override void OnUpdate(GameTime gameTime)
      12. {
      13. }
      14. public override void OnRendering(Sharpex2D.Rendering.RenderDevice renderer, GameTime gameTime)
      15. {
      16. renderer.Begin();
      17. renderer.DrawTexture(_texture2D, new Vector2(0, 0), Color.White);
      18. renderer.End();
      19. }
      20. private Texture2D _texture2D;
      21. public override EngineConfiguration OnInitialize(LaunchParameters launchParameters)
      22. {
      23. RenderDevice resultDevice = DeviceSelector.Select(
      24. new RenderDevice[]
      25. {
      26. new Sharpex2D.Rendering.DirectX9.DirectXRenderDevice(),
      27. new Sharpex2D.Rendering.DirectX10.DirectXRenderDevice(),
      28. new Sharpex2D.Rendering.DirectX11.DirectXRenderDevice()
      29. }, DeviceSelector.SelectorMode.Lowest);
      30. return new EngineConfiguration(resultDevice, null);
      31. }
      32. public override void OnLoadContent()
      33. {
      34. _texture2D = Content.Load<Texture2D>("pig.png");
      35. }
      36. }
      37. }


      Führen wir nun unsere Applikation aus, sollten wir die entsprechende Textur sehen, vorausgesetzt diese befindet sich auch im Content Ordner.





      Um unser Schweinchen ein bisschen mehr zu Kapseln sollten wir eine neue Klasse für es anlegen - Diese Klasse nennen wir PiggyPlayer. PiggyPlayer muss 4 verschiedene Merkmale aufweisen.

      [list=1]Eigenschaft, die die Position angibt
      Eigenschaft, die eine Texture2D angibtMethode um PiggyPlayer zu zeichnenMethode um PiggyPlayer zu updaten[/list]

      Um nun unsere Klasse zu modellieren, helfen uns zwei Interfaces IUpdateable und IDrawable. Implementieren wir diese in unsere Klasse, werden wir gezwungen die Methode Update und Render zu implementieren. Dies kann VisualStudio ggbfs. automatisch tun. Desweiteren legen wir eine Öffentliche Eigenschaft vom Typ Vector2 mit den Namen Position an, sowie eine Eigenschaft vom Typ Texture2D und den Namen Texture. Anschließend initialisieren wir im Konstruktor von PiggyPlayer die Position, damit es später nicht zu Fehlern kommt.

      Nun fügen wir in die Render Methode von PiggyPlayer die DrawTexture Operation ein, dies sollte nun so aussehen.

      C#-Quellcode

      1. using Sharpex2D;
      2. using Sharpex2D.Math;
      3. using Sharpex2D.Rendering;
      4. namespace MyGame
      5. {
      6. public class PiggyPlayer : IUpdateable, IDrawable
      7. {
      8. public PiggyPlayer()
      9. {
      10. Position = new Vector2(0, 0);
      11. }
      12. public Vector2 Position { set; get; }
      13. public Texture2D Texture { set; get; }
      14. public void Update(GameTime gameTime)
      15. {
      16. }
      17. public void Render(RenderDevice renderer, GameTime gameTime)
      18. {
      19. renderer.DrawTexture(Texture, Position, Color.White);
      20. }
      21. }
      22. }


      In unserer Game-Klasse erstellen wir nun ein neues PiggyPlayer Objekt und weisen die geladene Texture2D der Eigenschaft von PiggyPlayer zu. Die OnRendering Methode ändern wir nun so ab, das die Render Methode von PiggyPlayer aufgerufen wird. Das Ergebnis sollte nun so aussehen.

      C#-Quellcode

      1. using Sharpex2D;
      2. using Sharpex2D.GameService;
      3. using Sharpex2D.Audio;
      4. using Sharpex2D.Rendering;
      5. namespace MyGame
      6. {
      7. public class MainGame : Game
      8. {
      9. public override void OnUpdate(GameTime gameTime)
      10. {
      11. }
      12. public override void OnRendering(Sharpex2D.Rendering.RenderDevice renderer, GameTime gameTime)
      13. {
      14. renderer.Begin();
      15. _piggyPlayer.Render(renderer, gameTime);
      16. renderer.End();
      17. }
      18. private PiggyPlayer _piggyPlayer;
      19. public override EngineConfiguration OnInitialize(LaunchParameters launchParameters)
      20. {
      21. RenderDevice resultDevice = DeviceSelector.Select(
      22. new RenderDevice[]
      23. {
      24. new Sharpex2D.Rendering.DirectX9.DirectXRenderDevice(),
      25. new Sharpex2D.Rendering.DirectX10.DirectXRenderDevice(),
      26. new Sharpex2D.Rendering.DirectX11.DirectXRenderDevice()
      27. }, DeviceSelector.SelectorMode.Lowest);
      28. return new EngineConfiguration(resultDevice, null);
      29. }
      30. public override void OnLoadContent()
      31. {
      32. _piggyPlayer = new PiggyPlayer();
      33. _piggyPlayer.Texture = Content.Load<Texture2D>("pig.png");
      34. }
      35. }
      36. }



      Im folgenden wollen wir unserer PiggyPlayer Klasse noch einen Namen, sowie Bewegung spendieren, zu erst sollten wir mit den Namen anfangen. Um einen Schriftzug zu rendern benötigt wir ein Font Objekt welches sich leicht über new Font(Typeface) initialisieren lässt. Das Typeface beschreibt dabei, welche Eigenschaften die Font zu besitzen hat. Mit diesem Wissen können wir nun beherzt die DrawString Methode im PiggyPlayer Objekt aufrufen und einen beliebigen Text rendern.

      C#-Quellcode

      1. using Sharpex2D;
      2. using Sharpex2D.Math;
      3. using Sharpex2D.Rendering;
      4. namespace MyGame
      5. {
      6. public class PiggyPlayer : IUpdateable, IDrawable
      7. {
      8. public PiggyPlayer()
      9. {
      10. Position = new Vector2(0, 0);
      11. _font = new Font(new Typeface {FamilyName = "Segoe UI", Size = 11});
      12. }
      13. public Vector2 Position { set; get; }
      14. public Texture2D Texture { set; get; }
      15. private Font _font;
      16. public void Update(GameTime gameTime)
      17. {
      18. }
      19. public void Render(RenderDevice renderer, GameTime gameTime)
      20. {
      21. renderer.DrawTexture(Texture, Position, Color.White);
      22. renderer.DrawString("PiggyPlayer", _font, Position, Color.White);
      23. }
      24. }
      25. }


      Eventuell bedarf es nun noch einer besseren Positionierung, aber uns soll es erst mal um das Prinzip gehen. Um nun unsere Figur zu bewegen, brauchen wir eine Instanz zum InputManager aus der Game-Klasse. Hier wird uns mal wieder SGL.Components aushelfen, mit der wir uns einfach eine Instanz erstellen können. Der InputManager besitzt eine Eigenschaft mit den Namen Keyboard, über diese können wir dann Tasten abfragen. Die Abfrage läuft in der Update Methode von PiggyPlayer ab. Damit diese überhaupt ausgeführt wird, muss in der Game-Klasse das PiggyPlayer Objekt geupdatet werden.

      C#-Quellcode

      1. public override void OnUpdate(GameTime gameTime)
      2. {
      3. _piggyPlayer.Update(gameTime);
      4. }


      Die PiggyPlayer Klasse könnte nun wie folgt aussehen.

      C#-Quellcode

      1. using Sharpex2D;
      2. using Sharpex2D.Input;
      3. using Sharpex2D.Math;
      4. using Sharpex2D.Rendering;
      5. namespace MyGame
      6. {
      7. public class PiggyPlayer : IUpdateable, IDrawable
      8. {
      9. public PiggyPlayer()
      10. {
      11. Position = new Vector2(0, 0);
      12. _font = new Font(new Typeface {FamilyName = "Segoe UI", Size = 11});
      13. _input = SGL.Components.Get<InputManager>();
      14. }
      15. public Vector2 Position { set; get; }
      16. public Texture2D Texture { set; get; }
      17. private Font _font;
      18. private InputManager _input;
      19. public void Update(GameTime gameTime)
      20. {
      21. var state = _input.Keyboard.GetState();
      22. if (state.IsKeyDown(Keys.Down))
      23. {
      24. Position = new Vector2(Position.X, Position.Y+16);
      25. }
      26. if (state.IsKeyDown(Keys.Up))
      27. {
      28. Position = new Vector2(Position.X, Position.Y-16);
      29. }
      30. if (state.IsKeyDown(Keys.Left))
      31. {
      32. Position = new Vector2(Position.X - 16, Position.Y);
      33. }
      34. if (state.IsKeyPressed(Keys.Right))
      35. {
      36. Position = new Vector2(Position.X + 16, Position.Y);
      37. }
      38. }
      39. public void Render(RenderDevice renderer, GameTime gameTime)
      40. {
      41. renderer.DrawTexture(Texture, Position, Color.White);
      42. renderer.DrawString("PiggyPlayer", _font, Position, Color.White);
      43. }
      44. }
      45. }




      Dies sollte es auch erstmal für das 'getting started' gewesen sein, wenn ihr noch Fragen dazu habt, stellt sie Ruhig. Natürlich behandelt dieser kleine Abschnitt noch nicht wie man Szenen verwendet, UIElemente erstellt o.a. Denn das würde den Thread glaube ich sprengen. Wenn dennoch Interesse vorliegt, werde ich den Thread gerne erweitern.
      Dateien
      • MyGame.zip

        (1,78 MB, 282 mal heruntergeladen, zuletzt: )
      • Sharpex2D.dll

        (233,98 kB, 244 mal heruntergeladen, zuletzt: )

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ThuCommix“ ()

      Das ist sehr passend, dass du dieses Tutorial gestartet hast, ich hoffe von diesen kommen noch mehr.

      Wirst du auch noch ggf. auf 3D eingehen?

      PS: Ich wollte das Projekt debuggen, allerdings bekam ich folgenden Fehler (siehe Anhang).


      Beiträge zusammengefügt
      -Artentus

      Bilder
      • Unbenannt.png

        8,89 kB, 534×260, 329 mal angesehen
      Polling is trolling!

      Achtung: Ich habe die komische Angewohnheit, simple Dinge zu verkomplizieren..

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Artentus“ ()

      Hallo!
      Sehr nette Engine, allerdings habe ich ein Problem mit dem SceneManager:

      C#-Quellcode

      1. public override void OnLoadContent()
      2. {
      3. sceneManager.Construct();
      4. sceneManager.AddScene(SceneManager.Get<Titlescreen>());
      5. }


      Er throwt mir immer eine Exception, von wegen die Klasse Titlescreen sei nicht bereit... Die Methoden der Scene-Klasse hab ich alle schon overrided:

      C#-Quellcode

      1. public abstract class Titlescreen : Scene
      2. {
      3. public override void Initialize()
      4. {
      5. }
      6. public override void Update(GameTime gameTime)
      7. {
      8. }
      9. public override void LoadContent(Sharpex2D.Framework.Content.ContentManager content)
      10. {
      11. }
      12. public override void Render(Sharpex2D.Framework.Rendering.Devices.RenderDevice renderer, GameTime gameTime)
      13. {
      14. }
      15. }


      Wo liegt der Fehler?

      Danke :)

      Beispiel Spiel

      Hallo Leute, ich habe heute etwas mehr visuelles für euch. Anbei ist ein Beispiel für ein komplettes kleines Spiel in Sharpex2D 0.6.200. Im Beispiel könnt ihr euch ansehen wie man verschiedene Renderer händeln kann, und außerdem wie man verschiedene Sachen benutzt. Also einfach mal rein schauen wer interesse hat.
      Bilder
      • 0.png

        23,89 kB, 287×266, 291 mal angesehen
      • 1.png

        47,23 kB, 656×518, 5.018 mal angesehen
      • 2.png

        51,32 kB, 656×518, 284 mal angesehen
      • 3.png

        33,18 kB, 656×518, 314 mal angesehen
      Dateien

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ThuCommix“ ()

      Bei mir funktioniert das Tutorial nicht. Der Namespace Sharpex2D.GameServices wird bei mir nicht gefunden, daher funktioniert SGL.Initialize() nicht. Ich habe in mein Projekt alles was auf dieser Website (sharpex2d.de/?p=components) ist via NuGet geholt, trotzdem wird der Namespace nicht gefunden.
      Versuche es mal mit Sharpex2D.GameService

      Am besten du schaust dir das Sample unter Codeplex an. Hier der Link: sharpex2d.codeplex.com/SourceC…rd/FlyingBird/MainGame.cs

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Artentus“ ()

      ThuCommix schrieb:

      Wenn dennoch Interesse vorliegt, werde ich den Thread gerne erweitern.

      Also Ich habe Interesse daran und fände es cool, wenn du mal deine GameEngine noch ein bisschen besser erklären könntest. Ich -komplett neu in der Spieleentwicklung- habe kein Plan, wie Ich jetzt fortfahren müsste. Vielleicht würde Ich es nach 3 Stunden mal hinbekommen noch ein SoundDevice zu initialisieren, danach ist aber echt schluss :D

      LG
      Hallo,

      bin gerade auch am versuchen mich an Sharpex ranzuwagen. Bin halt dem Getting started gefolgt und klappt auch alles, nur macht mich etwas ein wenig stutzig. Wenn ich meine Textur zeichne flackert diese ein wenig.. Egal ob ich den GDI Renderer nutze oder eine Component z.B. Dx11 von deiner site lade...