Столкновение шара и кривой как графических объектов - PullRequest
0 голосов
/ 01 мая 2018

Я пытаюсь сделать игру, в которой я отскакиваю от земли мяч, который изображен в виде замкнутой кривой (зеленая часть), я просто не знаю, как бы я рассчитал столкновение между мячом и кривая.

picture of the graphics

Я нарисовал и шарик, и кривую, используя графику в графическом окне, я думаю, что мне нужно сделать это математически, поскольку я не могу найти встроенную функциональность в Visual Basic, которая позволяет мне это делать.

Мой код:

Public Class Form1

    Dim BallSpeedY, BallSpeedX As Double
    Dim BallLoc As Point

    Dim Start As Boolean = False

    Dim gameTime As Decimal = 60.1
    Dim gameTimeFont As New Font("Arial", 24, FontStyle.Bold)



    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        Me.WindowState = FormWindowState.Maximized

        'Size of the picturebox that is being drawn on
        PictureBox1.Width = Me.Width
        PictureBox1.Height = Me.Height - 24

        DrawGame(False, False, True)

    End Sub

    Private Sub DrawGame(refreshMap As Boolean, drawBall As Boolean, drawTime As Boolean)

        Dim g As Graphics = Graphics.FromImage(PictureBox1.Image)

        Static startcornerpt As PointF
        Static firstpt As PointF
        Static pt2 As PointF
        Static pt3 As PointF
        Static pt4 As PointF
        Static pt5 As PointF
        Static lastpt As PointF
        Static Endcornerpt As PointF



        ' Clears the window
        g.Clear(Color.White)

        If refreshMap Then
            Randomize() ' The rnd seed would always be the same if this is not done

            ' Creates 5 points chosen at random positions on the window within certain parameters
            startcornerpt = New PointF(0, Me.Height)
            pt2 = New PointF(Me.Width * 0.2, Me.Height * ((39 * Rnd() + 30) / 100))
            firstpt = New PointF(0, pt2.Y * 0.5 * 2)
            pt3 = New PointF(Me.Width * 0.4, Me.Height * ((39 * Rnd() + 30) / 100))
            pt4 = New PointF(Me.Width * 0.6, Me.Height * ((39 * Rnd() + 30) / 100))
            pt5 = New PointF(Me.Width * 0.8, Me.Height * ((39 * Rnd() + 30) / 100))
            lastpt = New PointF(Me.Width, pt5.Y * 0.5 * 2)
            Endcornerpt = New PointF(Me.Width, Me.Height)
        End If

        ' Draws the map with the 5 points
        Dim curvepoints As PointF() = {startcornerpt, firstpt, pt2, pt3, pt4, pt5, lastpt, Endcornerpt}
        g.FillClosedCurve(Brushes.PaleGreen, curvepoints)




        If drawBall Then
            ' Draws the ball
            g.DrawEllipse(Pens.Blue, BallLoc.X, BallLoc.Y, 20, 20)
            g.FillEllipse(Brushes.Blue, BallLoc.X, BallLoc.Y, 20, 20)

            ' Accelerates speed
            BallSpeedY = BallSpeedY - 1

            ' Update position
            BallLoc = New Point(BallLoc.X + BallSpeedX, BallLoc.Y - BallSpeedY)



        End If

        If drawTime Then

            gameTime = gameTime - 0.1
            gameTime.ToString()

            g.DrawString(gameTime, gameTimeFont, Brushes.Black, Me.Width / 2 - 120, Me.Height * 0.025) ' Draws the gametime on screen, 
            ' Width is set to be around the middle of the screen while height is just under the strip menu.

        End If

        PictureBox1.Refresh()

    End Sub

    Private Sub StartToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles StartToolStripMenuItem.Click

        If Start = False Then

            gameTime = 60.1

            'Resets ball for testing
            BallLoc.X = 800
            BallLoc.Y = 300
            BallSpeedY = 0

            'Starts the timers
            Gravity.Start()
            Movement.Start()

            Start = True

        ElseIf Start = True Then

            ' Resets the ball
            Dim ballloc As New Point(800, 300)


            Gravity.Stop()
            Movement.Stop()

            Start = False

        End If

    End Sub

    Private Sub NewMapToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles NewMapToolStripMenuItem.Click

        ' Creates a new map
        DrawGame(True, False, False)
        Start = False

    End Sub

    Private Sub Movement_Tick(sender As Object, e As EventArgs) Handles Movement.Tick

        ' Starts movement of the ball
        DrawGame(False, True, True)

    End Sub
End Class

РЕДАКТИРОВАТЬ: Collision теперь работает со следующими дополнениями:

Dim wider = CType(ground.Clone(), GraphicsPath)
    Using widenizer As Pen = New Pen(Color.Black, ballDiameter)
        wider.Widen(widenizer)
    End Using

И

 If ground.IsVisible(BallLoc) OrElse wider.IsVisible(BallLoc) Then
            BallSpeedY = BallSpeedY + 50 ' rebound on collision

        End If

1 Ответ

0 голосов
/ 01 мая 2018

Приведенный ниже код иллюстрирует комментарий, который я добавил об использовании Widen(), чтобы вы могли проверить, используя центр шара.

Прошло много лет с тех пор, как я работал с любым VB.NET, но это действительно показывает идею:

Imports System.Drawing.Drawing2D

Partial Public Class Form1
    Inherits Form

    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
        Dim diameter As Integer = 10
        Dim path As GraphicsPath = New GraphicsPath()
        path.AddCurve(New Point() {New Point(0, 100), New Point(200, 200), New Point(400, 100)})
        path.AddLines(New Point() {New Point(400, 400), New Point(0, 400)})
        path.CloseAllFigures()
        e.Graphics.FillPath(Brushes.Green, path)
        Dim wider = CType(path.Clone(), GraphicsPath)
        Using widenizer As Pen = New Pen(Color.Black, diameter)
            wider.Widen(widenizer)
        End Using

        For x As Integer = 0 To 400 Step diameter
            For y As Integer = 0 To 400 Step diameter

                If path.IsVisible(x, y) OrElse wider.IsVisible(x, y) Then
                    e.Graphics.DrawEllipse(Pens.Red, CType(x - diameter / 2, Single), CType(y - diameter / 2, Single), diameter, diameter)
                Else
                    e.Graphics.DrawEllipse(Pens.Blue, CType(x - diameter / 2, Single), CType(y - diameter / 2, Single), diameter, diameter)
                End If

            Next y
        Next x
    End Sub
End Class

Заполняет область кругами, где красные "касаются" земли:

enter image description here

...