【问题标题】:VB: Check if Object has “Class” then Execute CodeVB:检查对象是否有“类”然后执行代码
【发布时间】:2017-01-03 01:19:42
【问题描述】:

我希望在 Visual Basic 中找到一些基本说明,如果某物与某个类的某物发生冲突,它会执行代码。我可能没有使用正确的术语,所以当我说对象时,我的意思是像一个标签或图片框,而一个类......我猜它就像 HTML 中的一个类,就像一个具有特征的对象。

伪代码如下所示:

If object.Bounds.IntersectsWith([object with certain class]) Then execute code

否则,游戏的“if”语句会不堪重负……另外我是 Visual Basic 语言的新手,所以请尽量保持简单。

这是我已经拥有的:

    If carblue.Bounds.IntersectsWith(boundary1.Bounds) And directiona = 1 Then
        directiona = 0
        carblue.Top += 2
    ElseIf carblue.Bounds.IntersectsWith(boundary1.Bounds) And directiona = 2 Then
        directiona = 0
        carblue.Left += 2
    ElseIf carblue.Bounds.IntersectsWith(boundary1.Bounds) And directiona = 3 Then
        directiona = 0
        carblue.Top -= 2
    ElseIf carblue.Bounds.IntersectsWith(boundary1.Bounds) And directiona = 4 Then
        directiona = 0
        carblue.Left -= 2
    End If

其中 carblue 是被控制的对象,boundary1 是阻止汽车移动(碰撞时)的障碍物,directiona 是汽车行驶方向的值(1 向上,2 向左等)。

(从 S.A. Programmers 网站移出)

【问题讨论】:

    标签: vb.net vba visual-studio


    【解决方案1】:

    没有可使用的实际示例代码,很难提供具体的解决方案。我不知道你有多少控制移动,是2? 10? 10,000?假设您有 10 多个控件在移动,这就是我的处理方式。

    我会使用数据表来记录每个移动或可碰撞的控件的边界。控件移动后,更新数据表中的该行,查找碰撞,然后检查对象类型以确定碰撞对象的类,然后根据需要运行代码。

        Public MovingControls As DataTable
    
        Sub Main()
            'Build the DataTable
            MovingControls = New DataTable("ControlBounds")
            MovingControls.Columns.Add("Name", GetType(String))
            MovingControls.Columns.Add("x1", GetType(Integer))
            MovingControls.Columns.Add("x2", GetType(Integer))
            MovingControls.Columns.Add("y1", GetType(Integer))
            MovingControls.Columns.Add("y2", GetType(Integer))
        End Sub
    
        'Call this only when a control/object is created
        Sub MovingControlAdded(sender As Control)
            Dim Row As DataRow = MovingControls.NewRow
            Row("Name") = sender.Name
            Dim BoundsRect As Drawing.Rectangle = sender.Bounds
            Row("x1") = sender.Bounds.Left
            Row("x2") = sender.Bounds.Right
            Row("y1") = sender.Bounds.Bottom
            Row("y2") = sender.Bounds.Top
            MovingControls.Rows.Add(Row)
        End Sub
    
        'Call this only when a control/object has moved
        Sub MovingControlMoved(sender As Control)
            'Update the location of this Control
            Dim Row() As DataRow = MovingControls.Select("Name = '" & sender.Name & "'")
            'Select returns an array of Rows but there should only be 1 row for each Control
            Row(0)("x1") = sender.Bounds.Left
            Row(0)("x2") = sender.Bounds.Right
            Row(0)("y1") = sender.Bounds.Bottom
            Row(0)("y2") = sender.Bounds.Top
            'Collision check
            Dim CollidedRows() As DataRow = MovingControls.Select("(" & sender.Bounds.Right & " >= x1)" &
                                                                  "AND (" & sender.Bounds.Left & " <= x2)" &
                                                                  "AND (" & sender.Bounds.Bottom & " <= y2)" &
                                                                  "AND (" & sender.Bounds.Top & " >= y1)" &
                                                                  "AND (Name <> '" & sender.Name & "'")
            'Determine the object type and execute necessary code
            For Each CollidedRow As DataRow In CollidedRows
                Dim CollidedControl As Control = Me.Controls.Item(CollidedRow("Name"))
                If CollidedControl.GetType = GetType(Label) Then
                    'Do stuff for labels
                ElseIf CollidedControl.GetType = GetType(Button) Then
                    'Do stuff for buttons
                End If
            Next
        End Sub
    

    警告:假设一次有 1 个控件在移动。如果控件 A 移入控件 B 但控件 B 同时移开,则即使避免了碰撞,此代码仍将调用碰撞。如果您有多个控件在移动,您可能希望将 MovingControlMoved 方法拆分为 2 个方法,一个用于更新表格,一个用于碰撞检查。先处理所有运动,然后处理所有碰撞。

    根据复杂性,您可能希望为继承碰撞接口的可碰撞控件创建自定义类。您可以使用 System.Reflection 来调用 RunMeOnCollision。这将消除 If 语句列表。

    Interface iCollidableBase
        Sub RunMeOnCollision()
    End Interface
    
    Public Class CollidableLabel
        Inherits Label
        Implements iCollidableBase
    
        Public Sub RunMeOnCollision() Implements iCollidableBase.RunMeOnCollision
            Me.Text = "I have been collided"
        End Sub
    
    End Class
    
    Public Class CollidableButton
        Inherits Button
        Implements iCollidableBase
    
        Public Sub RunMeOnCollision() Implements iCollidableBase.RunMeOnCollision
            Me.Text = "Ouch, that collision hurt!"
        End Sub
    
    End Class
    

    同样,由于不了解此处的完整上下文,我无法针对您的代码测试我的解决方案。如果您可以发布一些其他详细信息,我可能会提供更多帮助。

    -E

    【讨论】:

    • 感谢您的详细回复-我一定会通过它几次。第二个解决方案看起来很有趣,它可能是我正在寻找的。我将使用表单中的代码更新问题。
    【解决方案2】:

    我使用数组从我的编程老师那里找到了我需要的东西。

    在公共子中: Dim walls(17) As PictureBox 其中 17 是表单具有的(在这种情况下)边界数。还将 PictureBox 更改为您正在使用的对象(例如标签)。 然后在您的表单中加载:

     For i = 1 To 17
            walls(i) = Me.Controls("boundary" & i)
        Next
    

    老实说,我对此不是 100% 确定的,但“边界”字符串是我的 PictureBox 名称的一部分,它们充当边界。名称有边界 1、边界 2 等。因此您可以将“边界”更改为对象的名称。

    接下来,当你想使用边界检查某些东西时,声明

     For i = 1 To 17
    

    那么当你想关闭检查时,

    Next
    

    为了检查碰撞,使用这个:

    If object.Bounds.IntersectsWith(walls(i).Bounds) Then
    

    所以在这种情况下,If 语句将位于 For 和 Next 行之间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-21
      • 2022-11-25
      • 1970-01-01
      • 2017-09-26
      • 2021-08-17
      相关资源
      最近更新 更多