Visual Basic中的简单弹跳球无法正常工作

时间:2014-10-04 23:56:30

标签: vb.net visual-studio-2010 bounce

我写的弹跳球的代码(过去有效,从内存中重新创建)是行不通的。当球应该从侧面反射并沿着那个方向继续时,它只是恢复并再次击中墙壁。击中球后,球在两个位置之间闪烁。

Public Class Form1
Dim XVel As Integer = 10
Dim YVel As Integer = 20
Dim XPos As Integer = 12
Dim YPos As Integer = 12

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    pbBall.Left = XPos
    pbBall.Top = YPos


    Label1.Text = XPos
    Label2.Text = YPos
    Label3.Text = YVel
    Label4.Text = XVel

    XPos += XVel
    YPos += YVel



    If pbBall.Top <= 0 Then
        YVel = YVel * -1
    End If

    If pbBall.Left <= 0 Then
        XVel = XVel * -1
    End If

    If pbBall.Bottom >= Me.Height Then
        YVel = YVel * -1
    End If

    If pbBall.Right >= Me.Width Then
        XVel = XVel * -1
    End If
End Sub
End Class

我不知道出了什么问题,而且现在已经搞错了一两个小时了。

2 个答案:

答案 0 :(得分:1)

原因:

如果Top变为0,XPos = - 1,则更改方向。 下一轮,Top变为-1,XPos = 0,然后再次更改直接。你将永远重复这一点。

解决方案:

更改所有方向时,应重新计算XPos和YPos。例如:

If pbBall.Right >= Me.Width Then
    XVel = XVel * -1
End If
XPos = pbBall.Left
YPos = pbBall.Top
XPos += XVel
YPos += YVel

答案 1 :(得分:1)

代码的作用:
比如,你的框架高度为100像素,你的球的大小(直径)为10像素 然后,你的球以20(正)的速度向下移动,当时距离顶部80像素(在底部框架上方)

调用Timer1_Tick时会发生什么:

    pbBall.Top = YPos ' which were calculated from the previous call
    ' pbBall.Top becomes 100 (which were 80 + 20)
    ' ...
    YPos += YVel ' prepares the next location, YPos becomes 100 + 20 = 120
    ' ...
    ' Then comes your conditional tests :
    If pbBall.Bottom >= Me.Height Then
        YVel = YVel * -1 ' YVel => 20 * -1 = -20
    End If
    ' pbBall.Bottom is .Top + .Size = 100 + 10 = 110
    ' so the condition is True, so YVel becomes -20
    ' Sound good isn't it ?
    ' BUT IT ISN'T !

在Timer1_Tick被称为secund时间之前,你的pbBall.Top是100,你的YVel是-20。应该上去,但它不会...

    pbBall.Top = YPos ' .. and YPos were 120,
    ' because Velocity +20 were added before it was switched to -20
    ' your ball is now way below the frame.
    ' ...
    YPos += YVel ' where YVel were switched to -20 as expected.
    ' But 120 - 20 = 100
    ' Note that top position "100" will be used the NEXT time Timer1_Tick is called,
    ' NOT at the moment the condition test performed below occurs..!

    ' ANYWAY, your If condition is True one more time :
    If pbBall.Bottom >= Me.Heigt Then ' Bottom = 120 + 10 = 130
        YVel = YVel * -1 ' YVel = -20 * - 1 = 20 => Your ball will go down again !
    End If

    ' When Timer1_Tick is called again, the Ball will rise at 110, 
    ' but next location will move it down again at 130...
    ' and again, and again...

一个简单的事情就是修复基本的算法:移动这段代码:

    XPos += XVel
    YPos += YVel
你的Timer1_Tick方法的最后

(在End Sub之前)这将更新球的NEXT位置 AFTER 速度已被切换并阻止你的球溢出边界TWICE。实际上,当你的球碰到一个边界时,你的代码不会让它立即反弹,而是让它再一次进行。所以,它被困在一个无尽的速度开关......

旁注:
这是我在StackOverflow上的第9篇文章。对不起,如果还不合适的话。对不起,如果它很长..我说法语,我不确定我写的是正确的。我不是专家,我可能错了;随便纠正我:)我只是喜欢VB,看到了这个问题,以为我可以帮忙,瞧!“

附注2:
我不知道提出建议是否合适,但是:

  • 如果你只处理一个球,为什么不使用比控制小一点的框架结构(边缘球的大小)并假设你的球是一个点(点)这允许你丢弃右,底和尺寸属性。当然,从你想要更多可以碰撞的球的那一刻起,这种方法就变得毫无用处。

  • 关于球可以溢出边界的事实(即使有修复)你可以想到更准确的球的下一个位置的计算,(XPos = XVel - 当球与左侧碰撞时的XPos边界。在右边,它有点复杂)

  • 您还可以使用IsMovingLeft As BooleanIsMovingUp)来避免每次将X / YVel乘以-1。只是一个建议虽然:)

  • 最后,我会把XVel和YVel作为Ball的属性,而不是全局变量,这样,我可以有多个不同速度的球。