Gamemaking - Collision (Detection)

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von Pi77Bull.

    Gamemaking - Collision (Detection)

    Ich versuche mich gerade an einem kleinen Spiel, dass das Prinzip von Pokemon hat. Also man steuert einen Spieler auf einer Map.

    Mein Problem ist die Levelabgrenzungen bzw. Mapabgrenzungen wo der Spieler nicht durchlaufen kann sondern einfach nur gegen rennt.

    Im großen und ganzen hab ich genau das auch geschafft, aber: Wenn ich gegen die Mauer laufe (in diesem Beispiel nach unten) und während ich die Taste noch halte eine andere Taste (zB nach links) drücke bleibt der Spieler trotzdem an der Wand stehen anstatt nach links zu laufen.

    Weiß jemand von euch wie ich das beheben könnte? ZB mit einer besseren Möglichkeit den Spieler daran zu hindern durch die Mauer zu gehen.

    Hier der Code:

    Quellcode

    1. Public Class Form1
    2. Dim moveRight As Boolean = False
    3. Dim moveDown As Boolean = False
    4. Dim moveLeft As Boolean = False
    5. Dim moveUp As Boolean = False
    6. Dim xNew As Long
    7. Dim yNew As Long
    8. Dim xOld As Long
    9. Dim yOld As Long
    10. Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
    11. Select Case e.KeyValue
    12. Case Keys.D
    13. moveRight = True
    14. Case Keys.S
    15. moveDown = True
    16. Case Keys.A
    17. moveLeft = True
    18. Case Keys.W
    19. moveUp = True
    20. End Select
    21. End Sub
    22. Private Sub Form1_KeyUp(sender As Object, e As KeyEventArgs) Handles MyBase.KeyUp
    23. Select Case e.KeyValue
    24. Case Keys.D
    25. moveRight = False
    26. Case Keys.S
    27. moveDown = False
    28. Case Keys.A
    29. moveLeft = False
    30. Case Keys.W
    31. moveUp = False
    32. End Select
    33. End Sub
    34. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    35. tmrMove.Start()
    36. End Sub
    37. Private Sub tmrMove_Tick(sender As Object, e As EventArgs) Handles tmrMove.Tick
    38. If moveRight = True Then
    39. yOld = player.Left
    40. player.Left = player.Left + 5
    41. xNew = player.Top
    42. yNew = player.Left
    43. End If
    44. If moveDown = True Then
    45. xOld = player.Top
    46. player.Top = player.Top + 5
    47. xNew = player.Top
    48. yNew = player.Left
    49. End If
    50. If moveLeft = True Then
    51. yOld = player.Left
    52. player.Left = player.Left - 5
    53. xNew = player.Top
    54. yNew = player.Left
    55. End If
    56. If moveUp = True Then
    57. xOld = player.Top
    58. player.Top = player.Top - 5
    59. xNew = player.Top
    60. yNew = player.Left
    61. End If
    62. If collision(player, wall) = True Then
    63. player.Top = xOld
    64. player.Left = yOld
    65. End If
    66. 'Label1.Text = "xOld: " & xOld.ToString & " - yOld: " & yOld.ToString
    67. 'Label2.Text = "xNew: " & xNew.ToString & " - yNew: " & yNew.ToString
    68. End Sub
    69. Private Function collision(ByVal Object1 As Object, ByVal Object2 As Object) As Boolean
    70. Dim collided As Boolean = False
    71. If Object1.top + Object1.height >= Object2.top And
    72. Object2.top + Object2.height >= Object1.top And
    73. Object1.left + Object1.width >= Object2.left And
    74. Object2.left + Object2.width >= Object1.left Then
    75. collided = True
    76. End If
    77. Return collided
    78. End Function
    79. End Class

    Pi77Bull schrieb:

    den Spieler daran zu hindern durch die Mauer zu gehen
    So:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Enum MoveDirection
    3. none
    4. moveRight
    5. moveDown
    6. moveLeft
    7. moveUp
    8. End Enum
    9. Private Direction As MoveDirection = MoveDirection.none
    10. Dim Player As New Rectangle(10, 10, 10, 10)
    11. Dim wall As New Rectangle(5, 5, 1, 300)
    12. Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
    13. Direction = MoveDirection.none
    14. Select Case e.KeyValue
    15. Case Keys.D
    16. Direction = MoveDirection.moveRight
    17. Case Keys.S
    18. Direction = MoveDirection.moveDown
    19. Case Keys.A
    20. Direction = MoveDirection.moveLeft
    21. Case Keys.W
    22. Direction = MoveDirection.moveUp
    23. End Select
    24. End Sub
    25. Private Sub Form1_KeyUp(sender As Object, e As KeyEventArgs) Handles MyBase.KeyUp
    26. Direction = MoveDirection.none
    27. End Sub
    28. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    29. tmrMove.Start()
    30. End Sub
    31. Private Sub tmrMove_Tick(sender As Object, e As EventArgs) Handles tmrMove.Tick
    32. Dim playerOld = Player
    33. If Direction = MoveDirection.moveRight Then
    34. Player.Location = New Point(Player.Location.X + 5, Player.Location.Y)
    35. ElseIf Direction = MoveDirection.moveDown Then
    36. Player.Location = New Point(Player.Location.X, Player.Location.Y - 5)
    37. ElseIf Direction = MoveDirection.moveLeft Then
    38. Player.Location = New Point(Player.Location.X - 5, Player.Location.Y)
    39. ElseIf Direction = MoveDirection.moveUp Then
    40. Player.Location = New Point(Player.Location.X, Player.Location.Y + 5)
    41. Else
    42. Return
    43. End If
    44. If collision(Player, wall) Then
    45. Player = playerOld
    46. End If
    47. Me.Invalidate()
    48. End Sub
    49. Private Function collision(ByVal Object1 As Rectangle, ByVal Object2 As Rectangle) As Boolean
    50. Return Object1.IntersectsWith(Object2)
    51. End Function
    52. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
    53. e.Graphics.DrawRectangle(Pens.Black, Me.wall)
    54. e.Graphics.DrawRectangle(Pens.Red, Me.Player)
    55. End Sub
    56. End Class
    Zum Lernen ist das OK, aber zum Spielen eher suboptimal.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Moin,

    so ist das kein guter Anfang, da alles für ein Spiel fehlt. Einfach Timer und KeyDown und evtl. sogar noch Controls(?) ist für ein Spiel total ungeeignet.

    Du brauchst Vektoren, GameLoop, Input, Renderer (GDI+/DirectX), Update-Methode pro Frame, Texturen und dann Polygone, die sich aus den Vertices (Vector2[]) zusammensetzen.
    Damit kannst Du dann auch Kollision managen und das pixelgenau.
    Auch geht das Bewegen viel besser und realistischer mit Vektoren und der GameTime.

    Schau mal hier:
    github.com/ThuCommix/Sharpex2D

    Findest auch hier im VBP-Showroom und so wird das gut und performant gemacht. ;)
    Und bei 2D kann man sich da gut einarbeiten. Aber was meinste, das ist in 3D nicht anders, nur halt auf den Raum übertragen und deshalb macht man das so.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Jo - ein richtiges Spiel kann man mit rumsausenden Controls nicht machen. NIchtmal ownerDrawing ist wirklich für solch geeignet, sondern man braucht tatsächlich eine besondere Spiel-Architektur und eine Drawing-Engine, die einen Bildschirm auch 60 mal pro Sekunde neu aufbaut, und zwar ohne dass die Prozessor-Last über 1% geht (naja, der Wert ist geraten - wieviel Prozessor frisst ein richtiges Spiel im Leerlauf?).

    Was anderes sind primitiv-Spiele bei denen die "Welt" aus Zellen besteht, und wo Figuren einfach von Zelle zu Zelle hopsen.
    Für sowas hab ich mal ein Ansatz veröffentlicht, in dem einfach ein DGV als "Zellen-Lieferant" missbraucht wird:
    FightingSnakes

    Trade schrieb:

    sogar noch Controls(?)

    ErfinderDesRades schrieb:

    mit rumsausenden Controls
    Hab ich in seinem Code nicht gefunden.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    ErfinderDesRades schrieb:

    ein Control
    hab ich in mal als Rectangle interpretiert und so behandelt.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!