我正在尝试制作一个游戏,我将一个球从地面上弹出,这是一个封闭的曲线(绿色部分),我只是不知道我将如何计算球与之间的碰撞曲线。
我在图片框中使用图形绘制了球和曲线,我想我必须以数学方式进行,因为我在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
编辑:碰撞现在适用于这些新增内容:
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
答案 0 :(得分:0)
下面的代码说明了我添加的关于使用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
它用圆圈填充该区域,其中红色的是"触摸"地面: