Xna Tutorial Nr 2 (Kollision, 2D Kamera, Animation, Maps Aus Txt Datei Laden)

    • VB.NET

    Es gibt 18 Antworten in diesem Thema. Der letzte Beitrag () ist von Chriis.

      Xna Tutorial Nr 2 (Kollision, 2D Kamera, Animation, Maps Aus Txt Datei Laden)

      Hi,
      Da es zwischendurch immer wieder anfragen zu Xna Tutorials gab
      habe ich mich heute beschlossen wieder ein Tutorial zu machen.
      1. Kollision 2 Verschiedene Möglichkeiten (mit etwas umschreiben könnte man die zweite
      auch mit Polygons Kreisen u.a. machen)
      2. 2D Kamera (Durch die Map Scrollen)
      3. Animieren von Sprites durch Tilesets
      4. Maps Aus Txt Dateien Laden

      Also fangen mit mal mit erstens an: Die Kollision:
      Spoiler anzeigen
      Dieser Code stammt vom User vcjunk (vcjunk.de) und ist sehr schnell:

      VB.NET-Quellcode

      1. Public Function Kollisionskontrolle(ByVal Rect1 As Microsoft.Xna.Framework.Rectangle, ByVal Rect2 As Microsoft.Xna.Framework.Rectangle) As Boolean
      2. Dim sx, sy As Boolean
      3. sx = Rect1.Left <= (Rect2.Left + Rect2.Width) And (Rect1.Left + Rect1.Width) >= Rect2.Left
      4. sy = (Rect1.Top + Rect1.Height) >= Rect2.Top And Rect1.Top <= (Rect2.Top + Rect1.Height)
      5. Kollisionskontrolle = sx And sy
      6. End Function

      Code nummer 2 (Pixel Kollision) wenn man ihn etwas umbaut klappt er auch mit Polygons usw. (von mir):

      VB.NET-Quellcode

      1. Private Shared Function GetMax(ByVal Value1 As Integer, ByVal Value2 As Integer) As Integer
      2. If Value1 > Value2 Then
      3. Return Value1
      4. Else
      5. Return Value2
      6. End If
      7. End Function
      8. Public Shared Function CheckForKollision2(ByVal rect1 As Microsoft.Xna.Framework.Rectangle, ByVal rect2 As Microsoft.Xna.Framework.Rectangle) As Boolean
      9. ' Genauer Prüfen
      10. ' rect2 = Object dass sich bewegt
      11. Dim bmp As New Bitmap(GetMax(rect1.X + rect1.Width, rect2.X + rect2.Width) + 1, GetMax(rect1.Y + rect1.Height, rect2.Y + rect2.Height) + 1)
      12. Using g As Graphics = Graphics.FromImage(bmp)
      13. Dim r1 As New Rectangle(rect1.X, rect1.Y, rect1.Width, rect1.Height)
      14. Dim r2 As New Rectangle(rect2.X, rect2.Y, rect2.Width, rect2.Height)
      15. g.FillRectangle(Brushes.Black, r1)
      16. g.FillRectangle(Brushes.Red, r2)
      17. Dim hclr As Color = bmp.GetPixel(r2.X + 1, r2.Y + 1)
      18. For x = r1.X To r1.X + r1.Width
      19. For y = r1.Y To r1.Y + r1.Height
      20. If bmp.GetPixel(x, y) = hclr Then
      21. MsgBox(x.ToString & " ," & y.ToString)
      22. Return True
      23. Exit Function
      24. End If
      25. Next
      26. Next
      27. End Using
      28. Return False
      29. End Function


      Was die Codes machen sollte völlig klar sein denke ich mal :)

      Bitte in Extra Klasse Lagern ! Deshalb Shared

      Kommen wir zum zweiten Punkt: 2D Kamera:
      Spoiler anzeigen
      Das ist die Klasse wir nennen sie Kamera.

      VB.NET-Quellcode

      1. Imports Microsoft.Xna.Framework
      2. Imports Microsoft.Xna.Framework.Graphics
      3. Imports Microsoft.Xna.Framework.Input
      4. Public Class Kamera
      5. ''' <summary>
      6. ''' Position der Kamera.
      7. ''' </summary>
      8. ''' Darf man nach Unten mit der Kamera?
      9. Dim Downe As Boolean
      10. ' Darf man nach oben mit der Kamera?
      11. Dim Upe As Boolean
      12. ' Darf man nach Links mit der Kamera?
      13. Dim Lefte As Boolean
      14. ' Darf man nach rechts mit der Kamera?
      15. Dim Righte As Boolean
      16. ' Aktuelle Kamera Position
      17. Public Property Position() As Vector2
      18. Get
      19. ' m_position enthält die Kamera Position && Wiedergeben
      20. Return m_position
      21. End Get
      22. Set(ByVal value As Vector2)
      23. ' Value = wert der Zugewiesen werden soll
      24. m_position = value
      25. End Set
      26. End Property
      27. ' enthält die aktuelle Position (private) kann nicht von aussen
      28. ' ohne die Property geändert werden
      29. Private m_position As Vector2
      30. Public Sub Update(ByVal gameTime As GameTime)
      31. ' gametime = Zeit des SPiels
      32. Dim elapsed As Single = CSng(gameTime.ElapsedGameTime.TotalSeconds)
      33. ' Stand der Tastatur in Variable speichern
      34. Dim kbState As KeyboardState = Keyboard.GetState()
      35. ' Kamera bewegen
      36. ' Darf man nach oben mit der Kamera?
      37. If Upe Then
      38. ' Prüfen ob Oben Taste gedrückt ist:
      39. If kbState.IsKeyDown(Keys.Up) Then
      40. ' Nach oben bewegen bewegen
      41. m_position.Y += 200.0F * elapsed
      42. End If
      43. End If
      44. ' Darf man nach unten mit der Kamera?
      45. If Downe Then
      46. ' Prüfen ob Unten Taste gedrückt ist:
      47. If kbState.IsKeyDown(Keys.Down) Then
      48. ' Nach unten bewegen
      49. m_position.Y -= 200.0F * elapsed
      50. End If
      51. End If
      52. ' Darf man nach Links mit der Kamera?
      53. If Lefte Then
      54. ' Prüfen ob Linke Taste gedrückt ist:
      55. If kbState.IsKeyDown(Keys.Left) Then
      56. ' Nach Links bewegen
      57. m_position.X -= 200.0F * elapsed
      58. End If
      59. End If
      60. ' Darf man nach Rechts mit der Kamera?
      61. If Righte Then
      62. ' Prüfen ob Nach Rechts gedrückt ist?
      63. If kbState.IsKeyDown(Keys.Right) Then
      64. ' Nach Rechts bewegen mit der Kamera
      65. m_position.X += 200.0F * elapsed
      66. End If
      67. End If
      68. End Sub
      69. Public Function GetMatrix() As Matrix
      70. ' Matrix zurückgeben
      71. Return Matrix.CreateTranslation(New Vector3(m_position, 0))
      72. End Function
      73. Public Sub New(ByVal DownEnabled As Boolean, ByVal UpEnabled As Boolean, ByVal Leftenabled As Boolean, ByVal RightEnabled As Boolean)
      74. ' werte in den Booleans zuweisen
      75. ' wo man mit der Kamera hin darf!
      76. Downe = DownEnabled
      77. Upe = UpEnabled
      78. Lefte = Leftenabled
      79. Righte = RightEnabled
      80. End Sub
      81. End Class

      So erläutern wir kurz.
      In der Sub new wird den Booleans downe, Upe, lefte und Righte
      zugewiesen ob man nach unten, oben, links und rechts bewegen kann.
      GetMatrix gibt die Matrix zurück die wir später für die Spritebatch benutzen.
      Position erhält die Position der Kamera.
      So verwenden wir die Klasse:
      Wir deklarieren unter Public Class Game1 die Kamera
      Dim Kamera as new Kamera(True, True, True, True)
      In Update kommt folgender for Mybase.Update(gametime) rein:
      camera.Update(gameTime)
      Und in der Draw Sub Anstatt:
      spritebatch.begin() einfach:

      VB.NET-Quellcode

      1. spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Deferred, SaveStateMode.None, camera.GetMatrix())

      Und Fertig.

      Animieren von Sprites via Tileset
      Spoiler anzeigen
      Gehen wir zum nächsten Abschnitt: Animieren von Sprites mit einem Tileset:
      Wir haben ein Tileset wir wollen die Höhe angeben und die Breite
      jedes einzelnen Tiles dann haben wir eine einzige Texture die alles enthält
      und schneiden es sozusagen heraus.
      Dies ist eigentlich nichtmal so schwer...
      Die Klasse:

      VB.NET-Quellcode

      1. Imports Microsoft.Xna.Framework
      2. Imports Microsoft.Xna.Framework.Graphics
      3. Imports Microsoft.Xna.Framework.Input
      4. Imports Microsoft.Xna.Framework.Content
      5. Imports Microsoft.Xna.Framework.Game
      6. Public Class AnimatedSprite
      7. Public Texture As Texture2D
      8. Private totalElapsed As Double
      9. Private rows As Integer
      10. Private columns As Integer
      11. Private width As Integer
      12. Private height As Integer
      13. Private animationspeed As Double
      14. Private currentRow As Integer
      15. Private currentColumn As Integer
      16. Public Sub LoadGraphics(ByVal texture As Texture2D, ByVal rows As Integer, ByVal columns As Integer, ByVal animationspeed As Double)
      17. Me.Texture = texture
      18. Me.rows = rows
      19. Me.columns = columns
      20. Me.width = width
      21. Me.height = height
      22. Me.animationspeed = 1 / animationspeed
      23. totalElapsed = 0
      24. currentRow = 0
      25. currentColumn = 0
      26. End Sub
      27. Public Sub Update(ByVal elapsed As Double)
      28. totalElapsed += elapsed
      29. If totalElapsed > animationspeed Then
      30. totalElapsed -= animationspeed
      31. currentColumn += 1
      32. If currentColumn >= columns Then
      33. currentRow += 1
      34. currentColumn = 0
      35. If currentRow > rows Then
      36. currentRow = 0
      37. End If
      38. End If
      39. End If
      40. End Sub
      41. Public Sub Draw(ByRef spritebatch As SpriteBatch, ByVal Position As Vector2, ByVal Color As Color)
      42. spritebatch.Draw(Texture, New Rectangle(CInt(Position.X), CInt(Position.Y), width, height), New Rectangle(currentColumn * width, currentRow * height, width, height), Color)
      43. End Sub
      44. End Class


      Erstmal werden die werte wieviele Spalten und Reihen sowie
      der Double Animationspeed (wie schnell läuft die animation)
      in den Variablen gespeichert.
      Bei Update wird immer eins hoch getickt.
      In der Draw Methode wird nur die Aktuelle Texture gemalt.
      Aufruf:

      VB.NET-Quellcode

      1. Dim wasweißich As New AnimatedSprite
      2. wasweißich.LoadGraphics(Texture2D.Fromfile(graphics.Graphicsdevice, "Pfad"), 5, 5, 1.5)
      3. ' = 5 Reihen 5 Spalten und Animationspeed 1.5


      Und das letzte und auch einfachste: Maps Aus Txt Dateien Laden:
      Spoiler anzeigen

      Wir legen erstmal eine Structure An:

      VB.NET-Quellcode

      1. Public Structure Tile
      2. Dim Texture As Texture2D
      3. Dim Kollision As Boolean
      4. Dim Position As Vector2
      5. End Structure

      Jetzt legt ihr nur noch eine Liste mit den Namen Tiles an (Of Tile)
      So damit ist der Anfang schon getan jetzt nur noch in der Loadcontent:

      VB.NET-Quellcode

      1. Dim Pfad As String = "Pfad"
      2. Dim Content As String = IO.File.ReadAllText(Pfad)
      3. For Each lines As String In Content.Split(vbCrLf.ToCharArray)
      4. Dim count As Integer = 0
      5. Dim tile As New Tile
      6. For Each Propertys As String In lines.Split(Convert.ToChar("|"))
      7. count += 1
      8. If count = 1 Then
      9. tile.Texture = Texture2D.FromFile(graphics.GraphicsDevice, Propertys)
      10. ElseIf count = 2 Then
      11. tile.Kollision = Convert.ToBoolean(Propertys)
      12. ElseIf count = 3 Then
      13. Dim Vector As New Vector2(0, 0)
      14. Dim cnt As Integer = 0
      15. For Each vxy As Integer In Propertys.Split(Convert.ToChar(","))
      16. cnt += 1
      17. If cnt = 1 Then
      18. Vector.X = vxy
      19. ElseIf cnt = 2 Then
      20. Vector.Y = vxy
      21. End If
      22. Next
      23. tile.Position = Vector
      24. End If
      25. Tiles.Add(tile)
      26. Next
      27. Next

      Soweit so gut...
      Jetzt müssen wir es nur noch malen also noch spritebatch.Begin folgt folgender Code:

      VB.NET-Quellcode

      1. For each Tile As Tile in Me.Tiles
      2. spritebatch.draw(Tile.Texture, Tile.Position, Color.white)
      3. next

      Somit ist auch der letzte Abschnitt fertig...

      Das wars jetzt erstmal falls ihr noch fragen anregungen, Fehler etc. habt
      dann schreibt mir einfach.
      Übrigens für jemand der C# kann ist xnamag.de eine Super Seite.
      Daher kommen auch die Tutorials 2 und 3 (Aus C# übersetzt) und abgeändert.
      Edit: Fehler geändert!
      Mfg
      Loadsoft

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Load-soft.ch.vu“ ()

      progglord schrieb:

      Also mit der Kollissionskontrolle geht viel einfacher:

      VB.NET-Quellcode

      1. Rect1.Bounds.IntersectsWith(Rect2)
      gibt nat. Boolean zurück. Somit kann man das ganze Zahlenprüfen auch lassen.
      Also einmal muss man sagen das das was du meinst vom Typ system.drawing.Rectangle ist und das andere ist Microsoft.xna.framework.Rectangle und anderseits ist deine abfrage ungenau.
      Übrigens, dass was du da hast ist ein Control da nur ein Control ein Rectangle mit dem namen Bounds enthält es heißt also rect1.IntersectsWith.

      Topic:
      Übrigens:
      Die Zweite Kollision bitte in einer Extra klasse Lagern!
      @Chriss
      Du willst also ne Ki machen..
      Du legst ne KI klasse an in einen extra thread gehst mit einer Do schleife durch und schläfst das Intervall mit threading.thread.sleep außerdem kannst du auch einfach dim timer as new system.windows.forms.Timer schreiben
      Mfg
      Loadsoft

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Load-soft.ch.vu“ ()

      Entweder zu zeichnest ne Textur auf dem Vector2 von Input.Mouse oder du initialisierst dein XNA-Game mit der Showcursor-property auf true.
      Schau dir mal das an: msdn.microsoft.com/en-us/libra…=XNAGameStudio.31%29.aspx

      Zu den Rectangle-Kollisionen:
      Ich finde Rectangles dafür nicht so toll. Ich benutze BoundingSpheres (Kreis/Kugel) und BoundginBoxes (Quadrat/Quader)
      Von meinem iPhone gesendet

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

      nikeee13 schrieb:

      Entweder zu zeichnest ne Textur auf dem Vector2 von Input.Mouse oder du initialisierst dein XNA-Game mit der Showcursor-property auf true.
      Schau dir mal das an: msdn.microsoft.com/en-us/libra…=XNAGameStudio.31%29.aspx

      Zu den Rectangle-Kollisionen:
      Ich finde Rectangles dafür nicht so toll. Ich benutze BoundingSpheres (Kreis/Kugel) und BoundginBoxes (Quadrat/Quader)
      Hi,
      Joa, aber bei einer Tile Engine reicht Rectangle Kollision finde ich - zumindest für die Anfänger. Man kann auch die Pixelgenaue Kollision oben so umwandeln, dass es mit einem Kreis funktioniert.
      Mfg
      Mike
      die Rectangle Kollision kommt im 2D Bereich auf dasselbe raus, wie BoundingBox und dabei könnte man diese aber noch relativ stark optimieren(mit AndAlso) jenachdem wie du die BoundingBoxes anwendest ist es gleich gut oder auch entsprechend schlechter...BoundingSphere ist bei der Kollision von Texturen völliger Quatsch, da die Texturen ja auch als Rechtecke gespeichert werden...nur nach der Rechteckskollision sollte eine PerPixelCollision durchgeführt werden, wird hier so wie es aussieht auch gemacht, jedoch mit Bitmap.GetPixel->Sehr unperformant...
      1. ist LockBits besser->für DirectX
      2. XNA Texturen bieten für das auslesen der Farben bereits schöne sachen an...
      3. Optimieren lässt es sich noch(bei Textur to Textur Kollision) indem man die Differenz rechtecke nimmt und nur von diesen Bereichen die PerPixelCollision durchführt...
      Ich wollte auch mal ne total überflüssige Signatur:
      ---Leer---
      Mal eine Super Dimme Frage,

      habe Win XP, Einen defekten PDF Reader und kann daher dein vorheriges xna tut nicht lesen

      aber wo bitte bekomme ich die xna libary weil habe mir mal aus dem anderen tutu das beispiel project gekladen bekomme da 23 Fehler und 4Warnings oder so

      Wäre euch sehr dankbar wenn mir jemand einen Link zum Downloade der libary gibt.
      Hi, ich hab mal eine Frage zur Kamera.

      Ich habe alles schön wie es hier im Thema steht abgetippt (nicht kopiert damit ich es in dem Kopf bekomme) und komme nicht mehr weiter.
      Bin jetzt grade bei der Kamera, doch leider versteh ich diese nicht so ganz.

      Benötigt die Kamera nicht eine anfangs Position? m_position = mäpmöp

      Und wenn nach unten gedrückt wird bewegt sich die Kamera 200? * die verstrichene Zeit während des Tastendrucks?

      Bei mir spinnt die kamera einfach nur rum..
      Ich drücke nach unten 3 Sekunden tut sich nichts (nur die "Figur" bewegt sich.
      Nach den 3 Sekunden beginnt die Kamera sich nach unten zu bewegen.
      Jetzt gibt es 2 möglichkeiten die auftreten:

      1. Die Kamera leuft unendlich weiter nach unten (auch ohne druck der Tasten)
      2. Die Kamera lässt sich mit "nach oben" auf einen richtungswechsel ein und bewegt sich nun unendlich nach oben.

      Gruß Eistee
      Hallo erstmal!
      Ich wollte mal fragen ob es möglich ist, jetzt abzufragen ob etwas nur an einer bestimmten fläche mit einem Objekt Kollidiert.
      Hier zum beispiel sollte es nur oben auf der grünen halbkugel reagieren. Wenn es irgendwo auf der seite ist, soll nichts geschehen.
      Wäre das möglich?
      Bitte kein code höchstens ansätze ja ;)
      Wäre dankbar wenn ihr mir die Frage beantworten könntet!
      Hey
      Ich würde mich freuen wenn du nich weitere Tutorials machen wirst, vielleicht ein in dem du ein kleines 2D-Spiel erstellst. Also alles mit Kollision und so weiter einmal genauer erklärst.
      Gruß Götterspeise

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Göterspeise“ ()

      könnteste du vielleicht im nächsten Tut zeigen, wie man text zeichnet?
      Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.

      BeryJu.org BeryJu.org/Blog