在 Mono Winforms 编程教程的这一部分中,我们将创建贪食蛇游戏克隆。
贪食蛇游戏
贪食蛇是较旧的经典视频游戏。 它最初是在 70 年代后期创建的。 后来它被带到 PC 上。 在这个游戏中,玩家控制蠕虫。 目的是尽可能多地吃苹果。 蠕虫每次吃一个苹果,它的身体就会长大。 它必须避开墙壁和自己的身体。
开发
蠕虫每个关节的大小为 10 像素。 蠕虫由光标键控制。 最初,蠕虫具有三个关节。 通过按下光标键之一开始游戏。 如果游戏结束,我们将在棋盘中间显示Game Over消息。
board.vb
Imports SystemImports System.CollectionsImports System.ComponentModelImports System.DrawingImports System.DataImports System.Windows.FormsNameSpace BoardSpacepublic class BoardInherits UserControlConst WIDTH As Integer = 300Const HEIGHT As Integer = 300Const DOT_SIZE As Integer = 10Const ALL_DOTS As Integer = 900Const RAND_POS As Integer = 27Const DELAY As Integer = 140Dim x(ALL_DOTS) As IntegerDim y(ALL_DOTS) As IntegerDim dots As IntegerDim apple_x As IntegerDim apple_y As IntegerDim left As Boolean = FalseDim right As Boolean = TrueDim up As Boolean = FalseDim down As Boolean = FalseDim inGame As Boolean = TruePrivate Dim timer As TimerPrivate Dim dot As BitmapPrivate Dim apple As BitmapPrivate Dim head As BitmapPrivate Dim components As IContainerPublic Dim BORDER_WIDTH As IntegerPublic Dim TITLEBAR_HEIGHT As IntegerPublic Sub Newcomponents = New ContainerMe.BackColor = Color.BlackMe.DoubleBuffered = TrueMe.ClientSize = New Size(WIDTH, HEIGHT)Trydot = New Bitmap("dot.png")apple = New Bitmap("apple.png")head = New Bitmap("head.png")Catch e As ExceptionConsole.WriteLine(e.Message)Environment.Exit(1)End TryMe.InitGameEnd SubPrivate Sub InitGamedots = 3For z As Integer = 0 To dots-1x(z) = 50 - z*10y(z) = 50NextMe.LocateAppleAddHandler Me.KeyUp, AddressOf Me.OnKeyUptimer = New Timer(Me.components)timer.Enabled = Truetimer.Interval = DELAYAddHandler timer.Tick, AddressOf Me.OnTickAddHandler Me.Paint, AddressOf Me.OnPaintEnd SubPrivate Sub OnPaint(ByVal sender As Object, _ByVal e As PaintEventArgs)Dim g As Graphics = e.GraphicsIf inGameMe.DrawObjects(g)ElseMe.GameOver(g)End IfEnd SubPrivate Sub DrawObjects(ByVal g As Graphics)g.DrawImage(apple, apple_x, apple_y)For z As Integer = 0 To dots-1If z = 0g.DrawImage(head, x(z), y(z))Elseg.DrawImage(dot, x(z), y(z))End IfNextEnd SubPrivate Sub GameOver(ByVal g As Graphics)Dim msg As String = "Game Over"Dim rectF As RectangleF = RectangleF.op_Implicit(Me.ClientRectangle)Dim format As New StringFormatformat.Alignment = StringAlignment.Centerformat.LineAlignment = StringAlignment.Centerg.DrawString(msg, Font, Brushes.White, rectF , format)timer.StopEnd SubPrivate Sub CheckAppleIf x(0) = apple_x And y(0) = apple_ydots += 1Me.LocateAppleEnd IfEnd SubPrivate Sub MoveFor z As Integer = dots To 1 Step -1x(z) = x(z - 1)y(z) = y(z - 1)NextIf leftx(0) -= DOT_SIZEEnd IfIf rightx(0) += DOT_SIZEEnd IfIf upy(0) -= DOT_SIZEEnd IfIf downy(0) += DOT_SIZEEnd IfEnd SubPrivate Sub CheckCollisionFor z As Integer = dots To 1 Step -1If z > 4 And x(0) = x(z) And y(0) = y(z)inGame = FalseEnd IfNextIf y(0) >= HEIGHT - DOT_SIZE - TITLEBAR_HEIGHTinGame = FalseEnd IfIf y(0) < 0inGame = FalseEnd IfIf x(0) >= WIDTH - DOT_SIZE - BORDER_WIDTH:inGame = FalseEnd IfIf x(0) < 0inGame = FalseEnd IfEnd SubPrivate Sub LocateAppleDim rand As New RandomDim r As Integer = rand.Next(RAND_POS)apple_x = r * DOT_SIZEr = rand.Next(RAND_POS)apple_y = r * DOT_SIZEEnd SubPrivate Sub OnTick(ByVal sender As Object, ByVal e As EventArgs)If inGameMe.CheckAppleMe.CheckCollisionMe.MoveEnd IfMe.RefreshEnd SubPrivate Sub OnKeyUp(ByVal sender As Object, ByVal e As KeyEventArgs)Dim key As Integer = e.KeyCodeIf key = Keys.Left And Not rightleft = Trueup = Falsedown = FalseEnd IfIf key = Keys.Right And Not leftright = Trueup = Falsedown = FalseEnd IfIf key = Keys.Up And Not downup = Trueright = Falseleft = FalseEnd ifIf key = Keys.Down And Not updown = Trueright = Falseleft = FalseEnd IfEnd SubEnd ClassEnd Namespace
首先,我们将定义游戏中使用的常量。
WIDTH和HEIGHT常数确定电路板的大小。 DOT_SIZE是苹果的大小和蠕虫的点。 ALL_DOTS常数定义了板上可能的最大点数。 (900 = 300 * 300 / 10 * 10)RAND_POS常数用于计算苹果的随机位置。 DELAY常数确定游戏的速度。
Dim x(ALL_DOTS) As IntegerDim y(ALL_DOTS) As Integer
这两个数组存储蠕虫的所有关节的 x,y 坐标。
在Move方法中,我们有游戏的关键算法。 要了解它,请查看蠕虫如何移动。 您控制蠕虫的头部。 您可以使用光标键更改其方向。 其余关节在链上向上移动一个位置。 第二关节移动到第一个关节的位置,第三关节移动到第二个关节的位置,依此类推。
For z As Integer = dots To 1 Step -1x(z) = x(z - 1)y(z) = y(z - 1)Next
该代码将关节向上移动。
If leftx(0) -= DOT_SIZEEnd If
将头向左移动。
在CheckCollision方法中,我们确定蠕虫是否已经击中自己或撞墙之一。
For z As Integer = dots To 1 Step -1If z > 4 And x(0) = x(z) And y(0) = y(z)inGame = FalseEnd IfNext
如果蠕虫用头撞到关节之一,就结束游戏。
If y(0) >= HEIGHT - DOT_SIZE - TITLEBAR_HEIGHTinGame = FalseEnd If
如果蠕虫到达了棋盘的底部,我们就结束了游戏。
下图有助于了解蠕虫对象与板子底部的碰撞。

图:碰撞
locateApple方法在表格上随机定位一个苹果。
Dim rand As New RandomDim r As Integer = rand.Next(RAND_POS)
我们得到一个从 0 到RAND_POS-1的随机数。
apple_x = r * DOT_SIZE...apple_y = r * DOT_SIZE
这些行设置了apple对象的 x,y 坐标。
在OnKeyUp方法中,我们确定了键击玩家击键的时间。
If key = Keys.Left And Not rightleft = Trueup = Falsedown = FalseEnd If
如果我们按左光标键,则将left变量设置为True。 在Move方法中使用此变量来更改蠕虫对象的坐标。 还要注意,当蠕虫向右移动时,我们不能立即向左转。
nibbles.vb
' ZetCode Mono Visual Basic Winforms tutorial'' In this program, we create' a Nibbles game clone'' author jan bodnar' last modified May 2009' website www.zetcode.comImports SystemImports System.DrawingImports System.Windows.FormsPublic Class WinVBAppInherits FormPublic Sub NewMe.Text = "Nibbles"Me.FormBorderStyle = FormBorderStyle.FixedSingleDim borderWidth As Integer = (Me.Width - Me.ClientSize.Width) / 2Dim titleBarHeight As Integer = Me.Height - Me.ClientSize.Height - borderWidthDim board As New BoardSpace.Boardboard.BORDER_WIDTH = borderWidthboard.TITLEBAR_HEIGHT = titleBarHeightMe.Controls.Add(board)Me.CenterToScreenEnd SubPublic Shared Sub MainApplication.Run(New WinVBApp)End SubEnd Class
这是主要的类。

图:贪食蛇
这是使用 Mono Winforms 库和 Visual Basic 语言编写的贪食蛇游戏。
