VB.NET吃豆人项目:如何实现幽灵无抽搐的随机移动?
解决VB.NET吃豆人幽灵随机移动的抽搐问题
嘿,我来帮你搞定这个幽灵移动的麻烦!你遇到的抽搐现象,根源在于每次Timer Tick都在随机切换方向,而且碰撞检测的逻辑完全没跟上节奏——一会儿换方向,一会儿同时尝试多个方向移动,幽灵自然会像抽风一样乱晃。
先给你分析下你两段代码的问题:
- 第一段代码:每次Tick里两次随机设置
direction,甚至碰撞检测时又随机一次,等于幽灵每帧都在乱换方向,根本不会保持一个方向走。 - 第二段代码:逻辑混乱到极致——既按
direction移动,又同时检测四个方向并尝试移动,等于幽灵同时在四个方向上“挣扎”,不抽搐才怪。
核心解决方案思路
我们要实现的是:幽灵保持当前方向移动,直到碰到墙体;撞墙时,从所有可行的移动方向(移动后不会撞墙的方向)里随机选一个新方向,然后继续保持这个方向移动,循环往复。
完整实现代码
先整理全局变量和枚举,然后写碰撞检测函数,最后实现Timer的Tick逻辑:
' 全局变量:保持当前方向、随机实例、幽灵控件引用 Dim currentDirection As Movementdirection Dim rnd As New Random() ' 假设你的幽灵是名为red的PictureBox Private red As PictureBox = Me.red ' 替换成你实际的控件引用 ' 移动方向枚举 Public Enum Movementdirection Up = 1 Down = 2 Left = 3 Right = 4 End Enum ' 核心:检测某个方向移动后是否会撞墙 Private Function CanMoveInDirection(dir As Movementdirection) As Boolean ' 计算移动后的位置(这里移动步长是2,和你之前的一致) Dim newLocation As Point = red.Location Select Case dir Case Movementdirection.Up newLocation.Y -= 2 Case Movementdirection.Down newLocation.Y += 2 Case Movementdirection.Left newLocation.X -= 2 Case Movementdirection.Right newLocation.X += 2 End Select ' 检测移动后的位置是否和任何墙体碰撞 For Each wall As PictureBox In WallList If New Rectangle(newLocation, red.Size).IntersectsWith(wall.Bounds) Then Return False ' 撞墙了,不能走这个方向 End If Next Return True ' 可以走这个方向 End Function ' Timer Tick事件:实现幽灵移动逻辑 Private Sub redtimer_Tick(sender As Object, e As EventArgs) Handles redtimer.Tick ' 首先尝试按当前方向移动,如果能走就直接移动 If CanMoveInDirection(currentDirection) Then Select Case currentDirection Case Movementdirection.Up red.Top -= 2 Case Movementdirection.Down red.Top += 2 Case Movementdirection.Left red.Left -= 2 Case Movementdirection.Right red.Left += 2 End Select Else ' 撞墙了,找所有可行的方向 Dim validDirections As New List(Of Movementdirection)() ' 检查四个方向是否可行 If CanMoveInDirection(Movementdirection.Up) Then validDirections.Add(Movementdirection.Up) If CanMoveInDirection(Movementdirection.Down) Then validDirections.Add(Movementdirection.Down) If CanMoveInDirection(Movementdirection.Left) Then validDirections.Add(Movementdirection.Left) If CanMoveInDirection(Movementdirection.Right) Then validDirections.Add(Movementdirection.Right) ' 如果有可行方向,随机选一个新方向并移动 If validDirections.Count > 0 Then currentDirection = validDirections(rnd.Next(validDirections.Count)) ' 选完方向后直接移动一次 Select Case currentDirection Case Movementdirection.Up red.Top -= 2 Case Movementdirection.Down red.Top += 2 Case Movementdirection.Left red.Left -= 2 Case Movementdirection.Right red.Left += 2 End Select End If End If End Sub
额外优化(可选)
如果你想让幽灵更自然,不要刚走一个方向就立刻回头(比如刚向下走,撞墙后不选向上),可以在收集可行方向时排除当前方向的反方向:
' 在收集validDirections的时候添加判断 Dim oppositeDir As Movementdirection = GetOppositeDirection(currentDirection) If CanMoveInDirection(Movementdirection.Up) AndAlso Movementdirection.Up <> oppositeDir Then validDirections.Add(Movementdirection.Up) ' 其他三个方向同理 ' 新增一个获取反方向的函数 Private Function GetOppositeDirection(dir As Movementdirection) As Movementdirection Select Case dir Case Movementdirection.Up : Return Movementdirection.Down Case Movementdirection.Down : Return Movementdirection.Up Case Movementdirection.Left : Return Movementdirection.Right Case Movementdirection.Right : Return Movementdirection.Left Case Else : Return dir End Select End Function
为什么这个方案能解决抽搐问题?
- 幽灵只有在确实撞墙的时候才会切换方向,平时会一直保持同一个方向移动,不会每帧乱跳。
- 碰撞检测是先判断再移动,避免了穿墙或者同时尝试多个方向的混乱逻辑。
- 随机方向只在需要的时候(撞墙)才生成,保证了移动的连贯性。
内容的提问来源于stack exchange,提问作者Pedro Curto
相关产品推荐
相关产品推荐

