Snake - Ein Versuch ;)

    • VB.NET

    Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von VaporiZed.

      Snake - Ein Versuch ;)

      Hi,

      gibt ja öfters mal die Anfrage wie man "Snake" programmiert, deswegen habe ich mal ne einfache "Snake" Klasse gebastelt. Ist nicht so super sauber, aber immerhin (kommt auch ohne Panels etc aus!). Evtl als Grundgerüst geeignet für eigene Versuche.

      Spoiler anzeigen

      VB.NET-Quellcode

      1. Public Enum FeldStatus
      2. Frei
      3. Schlange
      4. Hindernis
      5. Futter
      6. End Enum
      7. Public Class Feld
      8. Public Rect As Rectangle
      9. Public Index_X As Integer
      10. Public Index_Y As Integer
      11. Public Status As FeldStatus
      12. End Class
      13. Public Enum Richtung
      14. Rauf
      15. Runter
      16. Links
      17. Rechts
      18. End Enum
      19. Public Class Bewegung
      20. Private _richtung As Richtung = SnakeSample.Richtung.Rauf
      21. Private _dx As Integer = 0
      22. Private _dy As Integer = -1
      23. Public Property Richtung() As Richtung
      24. Get
      25. Return _richtung
      26. End Get
      27. Set(ByVal value As Richtung)
      28. _richtung = value
      29. Select Case _richtung
      30. Case SnakeSample.Richtung.Rauf
      31. _dx = 0
      32. _dy = -1
      33. Case SnakeSample.Richtung.Runter
      34. _dx = 0
      35. _dy = 1
      36. Case SnakeSample.Richtung.Links
      37. _dx = -1
      38. _dy = 0
      39. Case SnakeSample.Richtung.Rechts
      40. _dx = 1
      41. _dy = 0
      42. End Select
      43. End Set
      44. End Property
      45. Public ReadOnly Property DeltaX() As Integer
      46. Get
      47. Return _dx
      48. End Get
      49. End Property
      50. Public ReadOnly Property DeltaY() As Integer
      51. Get
      52. Return _dy
      53. End Get
      54. End Property
      55. End Class
      56. Public Class Schlange
      57. Public Bewegungsrichtung As New Bewegung
      58. Public Koerper As New List(Of Feld)
      59. Public Sub Friss(ByVal sp(,) As Feld, ByVal Futterfeld As Feld)
      60. Koerper.Insert(0, Futterfeld)
      61. sp(Futterfeld.Index_X, Futterfeld.Index_Y).Status = FeldStatus.Schlange
      62. End Sub
      63. Public Sub SchwanzVor(ByVal sp(,) As Feld)
      64. If Koerper.Count > 1 Then
      65. Dim f As Feld = Koerper(Koerper.Count - 1)
      66. sp(f.Index_X, f.Index_Y).Status = FeldStatus.Frei
      67. Koerper.RemoveAt(Koerper.Count - 1)
      68. End If
      69. End Sub
      70. Public ReadOnly Property Kopf() As Point
      71. Get
      72. Return New Point(Koerper(0).Index_X, Koerper(0).Index_Y)
      73. End Get
      74. End Property
      75. Public ReadOnly Property Schwanz() As Point
      76. Get
      77. Return New Point(Koerper(Koerper.Count - 1).Index_X, Koerper(Koerper.Count - 1).Index_Y)
      78. End Get
      79. End Property
      80. End Class
      81. Public Class SnakeGame
      82. Private picture As PictureBox
      83. Private spielfeld(,) As Feld
      84. Private die_schlange As New Schlange
      85. Private WithEvents tm As New Timers.Timer
      86. Public Sub New(ByVal pbox As PictureBox, ByVal width As Integer, ByVal height As Integer)
      87. picture = pbox
      88. ' Spielfeld bauen
      89. Dim w As Integer = pbox.Width \ width
      90. Dim h As Integer = pbox.Height \ height
      91. Dim f As Feld
      92. ReDim spielfeld(width - 1, height - 1)
      93. For x = 0 To width - 1
      94. For y = 0 To height - 1
      95. f = New Feld With {.Index_X = x, .Index_Y = y, .Status = FeldStatus.Frei}
      96. f.Rect = New Rectangle(x * w, y * h, w - 1, h - 1)
      97. spielfeld(x, y) = f
      98. Next
      99. Next
      100. ' Rand setzen
      101. For x = 0 To width - 1
      102. spielfeld(x, 0).Status = FeldStatus.Hindernis
      103. spielfeld(x, height - 1).Status = FeldStatus.Hindernis
      104. Next
      105. For y = 0 To height - 1
      106. spielfeld(0, y).Status = FeldStatus.Hindernis
      107. spielfeld(width - 1, y).Status = FeldStatus.Hindernis
      108. Next
      109. ' Schlange setzen:
      110. die_schlange.Bewegungsrichtung.Richtung = Richtung.Rauf
      111. die_schlange.Friss(spielfeld, spielfeld(width \ 2, height \ 2))
      112. spielfeld(width \ 2, height \ 2).Status = FeldStatus.Schlange
      113. ' Futter platzieren
      114. SetzeFutter()
      115. ' Timer setzen
      116. tm.Enabled = False
      117. tm.Interval = 500
      118. tm.AutoReset = True
      119. End Sub
      120. Public Sub Start()
      121. tm.Enabled = True
      122. End Sub
      123. Private ran As New Random
      124. Private Sub SetzeFutter()
      125. Dim rx, ry As Integer
      126. Do
      127. rx = ran.Next(1, spielfeld.GetUpperBound(0) - 1)
      128. ry = ran.Next(1, spielfeld.GetUpperBound(1) - 1)
      129. If spielfeld(rx, ry).Status <> FeldStatus.Frei Then Continue Do
      130. ' Schlangenkopf muss mehr als drei Felder weg sein!
      131. If Math.Abs(rx - die_schlange.Kopf.X) < 4 Then Continue Do
      132. If Math.Abs(ry - die_schlange.Kopf.Y) < 4 Then Continue Do
      133. ' feld ok
      134. Exit Do
      135. Loop
      136. spielfeld(rx, ry).Status = FeldStatus.Futter
      137. End Sub
      138. Private Sub ThreadSafeDraw()
      139. Dim d As dlgZeichneSpielfeld = AddressOf ZeichneSpielfeld
      140. picture.Invoke(d)
      141. End Sub
      142. Private Delegate Sub dlgZeichneSpielfeld()
      143. Public Sub ZeichneSpielfeld()
      144. Dim b As New Bitmap(picture.ClientRectangle.Width, picture.ClientRectangle.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb)
      145. picture.Image = b
      146. Dim g As Graphics = Graphics.FromImage(picture.Image)
      147. Dim f As Feld
      148. Dim br As System.Drawing.Brush = Nothing
      149. For x = 0 To spielfeld.GetUpperBound(0)
      150. For y = 0 To spielfeld.GetUpperBound(1)
      151. f = spielfeld(x, y)
      152. Select Case f.Status
      153. Case FeldStatus.Frei
      154. br = New System.Drawing.SolidBrush(Color.White)
      155. Case FeldStatus.Schlange
      156. br = New System.Drawing.SolidBrush(Color.Black)
      157. Case FeldStatus.Hindernis
      158. br = New System.Drawing.SolidBrush(Color.Red)
      159. Case FeldStatus.Futter
      160. br = New System.Drawing.SolidBrush(Color.Green)
      161. End Select
      162. g.FillRectangle(br, f.Rect)
      163. Next
      164. Next
      165. End Sub
      166. Public Sub OnKey(ByVal keycode As Keys)
      167. Select Case keycode
      168. Case Keys.A
      169. die_schlange.Bewegungsrichtung.Richtung = Richtung.Links
      170. Case Keys.Y
      171. die_schlange.Bewegungsrichtung.Richtung = Richtung.Runter
      172. Case Keys.S
      173. die_schlange.Bewegungsrichtung.Richtung = Richtung.Rechts
      174. Case Keys.W
      175. die_schlange.Bewegungsrichtung.Richtung = Richtung.Rauf
      176. End Select
      177. End Sub
      178. Private Sub tm_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles tm.Elapsed
      179. ' Prüfe neue Position des Schlangenkopfes
      180. Dim nx, ny As Integer
      181. With die_schlange
      182. nx = .Kopf.X + .Bewegungsrichtung.DeltaX
      183. ny = .Kopf.Y + .Bewegungsrichtung.DeltaY
      184. End With
      185. Dim f As Feld = spielfeld(nx, ny)
      186. Select Case f.Status
      187. Case FeldStatus.Frei
      188. ' nix besonders
      189. die_schlange.Friss(spielfeld, f)
      190. die_schlange.SchwanzVor(spielfeld)
      191. Case FeldStatus.Futter
      192. die_schlange.Friss(spielfeld, f)
      193. tm.Interval -= 25
      194. SetzeFutter()
      195. Case FeldStatus.Hindernis
      196. ' game over
      197. GameEnde()
      198. Case FeldStatus.Schlange
      199. If f.Index_X = die_schlange.Schwanz.X AndAlso f.Index_Y = die_schlange.Schwanz.Y Then
      200. ' Ist ok
      201. die_schlange.SchwanzVor(spielfeld)
      202. die_schlange.Friss(spielfeld, f)
      203. Else
      204. ' game over
      205. GameEnde()
      206. End If
      207. End Select
      208. ThreadSafeDraw()
      209. End Sub
      210. Private Sub GameEnde()
      211. tm.Enabled = False
      212. MessageBox.Show("Game Over")
      213. Application.Exit()
      214. End Sub
      215. End Class


      Die anwendung ist im Prinzip super simpel. Komplett leere Form und dann:

      Spoiler anzeigen

      VB.NET-Quellcode

      1. Public Class Form1
      2. Private sg As SnakeGame
      3. Private sh As Boolean = False
      4. Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
      5. sg.OnKey(e.KeyCode)
      6. End Sub
      7. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      8. Me.KeyPreview = True
      9. Dim p As New PictureBox
      10. Me.Controls.Add(p)
      11. p.Dock = DockStyle.Fill
      12. sg = New SnakeGame(p, 20, 20)
      13. End Sub
      14. Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
      15. sg.ZeichneSpielfeld()
      16. If Not sh Then
      17. sh = True
      18. sg.Start()
      19. End If
      20. End Sub
      21. End Class
      Das Spiel ist einfach nur klasse!
      Nur ein Fehler war bei mir: (Fehler mit > < markiert)

      VB.NET-Quellcode

      1. Public Class Bewegung
      2. Private _richtung As Richtung = >SnakeSample.<Richtung.Rauf
      3. Private _dx As Integer = 0
      4. Private _dy As Integer = -1
      5. Public Property Richtung() As Richtung
      6. Get
      7. Return _richtung
      8. End Get
      9. Set(ByVal value As Richtung)
      10. _richtung = value
      11. Select Case _richtung
      12. Case >SnakeSample.<Richtung.Rauf
      13. _dx = 0
      14. _dy = -1
      15. Case >SnakeSample.<Richtung.Runter
      16. _dx = 0
      17. _dy = 1
      18. Case >SnakeSample.<Richtung.Links
      19. _dx = -1
      20. _dy = 0
      21. Case >SnakeSample.<Richtung.Rechts
      22. _dx = 1
      23. _dy = 0
      24. End Select
      25. End Set
      26. End Property
      27. Public ReadOnly Property DeltaX() As Integer
      28. Get
      29. Return _dx
      30. End Get
      31. End Property
      32. Public ReadOnly Property DeltaY() As Integer
      33. Get
      34. Return _dy
      35. End Get
      36. End Property
      37. End Class

      Da kam :
      Der Name "SnakeSample" wurde nicht deklariert
      Als Lösung habe ich die "SnakeSample." weg gemacht, dann ging's.

      Trotzdem gutes Spiel

      :thumbsup:
      meine XNA-Version ist ähnlich aufgebaut
      ist aber dennoch schmaler an Code aber mehr an eine Projekt gebunden und lässt sich nich so einfach integrieren ^^

      Mangafreak1995 schrieb:

      ist aber dennoch schmaler an Code

      Ich hab nicht versucht, möglichst KLEIN zu schreiben, sondern möglichst OO/portabel ;)
      Anyway: Primär hatte ich eigentlich die User als Zielgruppe, die 351 Pictureboxen über den Bildschirm jagen ... Dass man mit XNA, DirectX etc anders arbeitet ist klar und wer das nutzt, ist ja auch schon mindestens einen Schritt weiter.
      Das ist sehr unwahrscheinlich, da picoflop schon länger nicht mehr ein Forummitglied ist. Erstelle notfalls (und zwar, wenn Du konkrete Fragen hast) einen neuen Thread im Unterforum Multimedia- und Spieleprogrammierung.
      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

      Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.