|
|
Title | Make a game where you control a cannon ball's angle and speed to try to hit a house in VB .NET |
Description | This example shows how to get disk information including serial number in VB .NET by using the GetVolumeInformation API function. |
Keywords | cannon, simulation, gravity, animation |
Categories | Algorithms, Graphics |
|
|
The program randomly places a target. Then when you click the Fire button, it gets angle and speed information for the cannon and enables a timer. To keep the graphics and timing simple, the program uses a scale of 1 pixel = 1 meter.
If you set the compile-time variable DEBUGGING to True, then the program draws the position where the cannon ball should ideally cross the Y coordinate where it was launched. If the ball started at ground level and the ground were flat, this is where the ball would land. It calculates this position using the formula:
Distance = 2 * V^2 * Sin(T) * Cos(T) / g
Here g is the acceleration due to gravity, which is 9.8 meters per second. The program redraws TICKS_PER_SECOND times per second so the acceleration per tick is 9.8/(TicksPerSecond^2).
|
|
Private Sub cmdFire_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdFire.Click
Dim gr As Graphics = picCanvas.CreateGraphics()
' Redraw.
DrawField(gr)
' Get the speed.
Dim speed As Single
Try
speed = CSng(txtSpeed.Text)
Catch ex As Exception
MessageBox.Show("Invalid speed", "Invalid Speed", _
MessageBoxButtons.OK, _
MessageBoxIcon.Exclamation)
Exit Sub
End Try
If speed < 1 Then
MessageBox.Show("Speed must be at least 1 mps", _
"Invalid Speed", MessageBoxButtons.OK, _
MessageBoxIcon.Exclamation)
Exit Sub
End If
' Get the speed components in meters per tick.
m_Vx = speed * System.Math.Cos(m_Theta) / _
TICKS_PER_SECOND
m_Vy = -speed * System.Math.Sin(m_Theta) / _
TICKS_PER_SECOND ' Negative to go up.
' Disable UI elements.
cmdFire.Enabled = False
txtDegrees.Enabled = False
txtSpeed.Enabled = False
Cursor = Cursors.WaitCursor
Application.DoEvents()
#Const DEBUGGING = True
#If DEBUGGING Then
' Draw the location where the cannon ball
' should pass the Y position where it started.
' Distance = 2 * V^2 * Sin(T) * Cos(T) / g = V^2 *
' Sin(2*T) / g
gr.DrawEllipse(Pens.Blue, _
CSng(m_BulletX + 2 * speed ^ 2 * Sin(m_Theta) * _
Cos(m_Theta) / 9.8), _
CSng(m_BulletY), CANNON_HGT, CANNON_HGT)
#End If
' Start moving the cannon ball.
tmrMoveShot.Enabled = True
End Sub
|
|
The program keeps track of the cannon ball's position and velocity with the variables m_BulletX, m_BulletY, m_Vx, and m_Vy. When the timer event occurs, the program moves the cannon ball. It uses the velocity components to update the balls position and then redraws the ball.
|
|
' Acceleration in meters per tick squared.
Private Const m_YAcceleration As Single = 9.8 / _
TICKS_PER_SECOND ^ 2
Private m_BulletX As Double
Private m_BulletY As Double
Private m_Vx As Double
Private m_Vy As Double
Private Sub tmrMoveShot_Tick(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles tmrMoveShot.Tick
' Erase the cannon ball's previous position.
Dim gr As Graphics = picCanvas.CreateGraphics()
Dim br As New SolidBrush(picCanvas.BackColor)
gr.FillEllipse(br, _
CSng(m_BulletX), CSng(m_BulletY), _
CANNON_HGT, CANNON_HGT)
br.Dispose()
' Move the cannon ball.
m_Vy = m_Vy + m_YAcceleration
m_BulletX = m_BulletX + m_Vx
m_BulletY = m_BulletY + m_Vy
' Draw the new cannon ball.
gr.FillEllipse(Brushes.Black, _
CSng(m_BulletX), CSng(m_BulletY), _
CANNON_HGT, CANNON_HGT)
' See if we should stop.
If (m_BulletY > picCanvas.ClientRectangle.Height) Or _
(m_BulletX > picCanvas.ClientRectangle.Width) Then _
' Stop running.
tmrMoveShot.Enabled = False
' Re-enable UI elements.
cmdFire.Enabled = True
txtDegrees.Enabled = True
txtSpeed.Enabled = True
Me.Cursor = Cursors.Default
End If
End Sub
|
|
Some improvements you could make include hit detection to know when the ball hits the target and drawing a nice irregular ground.
|
|
|
|
|
|