-
Oct 12th, 2017, 09:37 AM
#1
Thread Starter
Registered User
how can I remove the drawn line in the panel if it didn't successfully hit the point?
Code:
Public Class Form1
Dim N As New Random
Dim X, Y As Integer
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim Mg As Drawing.Graphics = Me.Panel3.CreateGraphics
Dim Mp As New Pen(Brushes.White, 1)
Dim redBrush As New SolidBrush(Color.Red)
Dim X1, Y1, X2, Y2 As Integer
Dim V, A, T, G As Single
V = TextBox3.Text
A = TextBox4.Text
G = 9.81
X2 = 0
Y2 = 0
T = 0
Do Until T > 2 * V * Math.Sin(A * Math.PI / 180) / G
X1 = V * Math.Cos(A * Math.PI / 180) * T
Y1 = V * Math.Sin(A * Math.PI / 180) * T - (1 / 2) * G * T ^ 2
Mg.DrawLine(Mp, CInt(X2), 450 - CInt(Y2), CInt(X1), 450 - CInt(Y1))
If (CInt(X1) - 2 <= X And X <= CInt(X1) + 2) And (CInt(Y1) - 2 <= Y And Y < CInt(Y1) + 2) Then
Dim msgRslt As MsgBoxResult = MsgBox("Congratulations... You HIT the point.!" & vbNewLine & "Play Another Game? ", MsgBoxStyle.Question + MsgBoxStyle.YesNo, "Game Play")
If msgRslt = MsgBoxResult.Yes Then
MsgBox("New ball location is generated", MsgBoxStyle.Information + MsgBoxStyle.OkOnly, "New Game")
Me.Panel3.Refresh()
ElseIf msgRslt = MsgBoxResult.No Then
Me.Close()
End If
Exit Sub
End If
T = T + 0.01
X2 = X1
Y2 = Y1
Loop
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Me.Close()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.Panel3.Refresh()
Dim Mg As Drawing.Graphics = Me.Panel3.CreateGraphics
Dim Mp As New Pen(Brushes.Red, 1)
X = N.Next(450)
Y = N.Next(450)
TextBox1.Text = X
TextBox2.Text = Y
Mg.FillEllipse(Brushes.Yellow, X, 450 - Y, 3, 3)
Button2.Enabled = True
End Sub
End Class
Last edited by Shaggy Hiker; Oct 12th, 2017 at 09:40 AM.
Reason: Added CODE tags.
-
Oct 12th, 2017, 09:43 AM
#2
Re: how can I remove the drawn line in the panel if it didn't successfully hit the po
This looks like .NET, so you should be doing the drawing in the Paint event rather than in the button click. In the button click, just set up the points along the line and invalidate the panel. In the Paint event, draw the line. Then, to remove the line, just get rid of the points and Invalidate the panel. The paint event is raised whenever the panel is invalidated, so you can have it draw the lines as long as there are lines to draw (or points between which to draw lines), and just getting rid of the points will mean that no lines would draw the next time.
My usual boring signature: Nothing
-
Oct 13th, 2017, 04:27 PM
#3
Re: how can I remove the drawn line in the panel if it didn't successfully hit the po
While what Shaggy says is the way it normally should be done, you probably like the animation of the line being drawn in an arc as the projectile flies, rather than drawing the whole arc at once. Plopping the curve on the drawing is not as entertaining.
You could add points to an array a few at a time and draw the lines using the array, and refreshing the panel repeatedly to show the progress of the lines toward the target in order to use the paint event. You would have to draw the target point each time as well. And you would have to compare your generated points against your target as you add them to the array so if you hit the target you stop filling the array, refresh your drawing and then do your message box processing.
The reason to add points to the array a few at time is the animation will be a lot slower when using the paint event since you are refreshing the whole panel, so you'll likely need to draw several line segments each pass to maintain a similar animation time.
Also, you would want to switch from using a panel to using a picturebox since the picturebox is doubledbuffered by default.
Trying to repeatedly refresh a panel would blink so badly you wouldn't see the growing arc most of the time. You would have to change your code to draw in a bitmap and then draw the bitmap to the panel to implement doublebuffering. If I was going to use a panel I would actually use a BufferedGraphics object to maintain the drawing buffer but that is another, somewhat technical topic.
All in all, it is a much more challenging job to write the code to do all the drawing and animation in the Paint event. I'm not sure you have the motivation to work it out at this point.
The simple fix for the existing code is just to refresh the panel and redraw the target point each time you take a shot, before entering your line animation loop. That will erase the previous line arc (along with everything else) before showing the next shot. That is why you redraw the current target point each shot.
Code:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim Mg As Drawing.Graphics = Me.Panel3.CreateGraphics
Dim Mp As New Pen(Brushes.White, 1)
Dim redBrush As New SolidBrush(Color.Red)
Dim X1, Y1, X2, Y2 As Integer
Dim V, A, T, G As Single
V = Val(TextBox3.Text)
A = Val(TextBox4.Text)
G = 9.81
X2 = 0
Y2 = 0
T = 0
Me.Panel3.Refresh() 'Clear the panel
Mg.FillEllipse(Brushes.Yellow, X, 450 - Y, 3, 3) 'Redraw the target
Do Until T > 2 * V * Math.Sin(A * Math.PI / 180) / G
X1 = V * Math.Cos(A * Math.PI / 180) * T
Y1 = V * Math.Sin(A * Math.PI / 180) * T - (1 / 2) * G * T ^ 2
'....
Last edited by passel; Oct 13th, 2017 at 05:03 PM.
-
Oct 13th, 2017, 06:07 PM
#4
Re: how can I remove the drawn line in the panel if it didn't successfully hit the po
For the fun of it, I went ahead and changed the existing code a little bit to add using the paint event of a picturebox.
This is just one way to do it, there are many possibilities. This fits in with the existing code without too much change in the method.
I did change a number of things to make it compile with Option Strict On. You should turn that on so you get in the habit of being explicit in your variable assignments and conversions.
If you want to try the code, you should remove, or rename panel3, then add a picturebox and name it panel3 (I reused the name for the picturebox so didn't have to change the references in the code, although there probably weren't that many (looks like 4, mostly added by my changes anyway).
Since we don't know how many line segments we are going to have, I use a list of points instead of an array to add the points as we calculated them.
The animation is slower as predicted, but it doesn't necessarily detract from the game (at least on my machine). You get to watch the trajectory form with anticipation as it closes in on the target. I didn't bother to complicate the code by adding a method of speeding up the display (until I wrote this sentence, at which time I added a textbox where the user could enter a speed value between 1 and 100 (should have used an up/down control)). It is actually fairly simple. Instead of Refreshing the picturebox each time through the loop you just decrement a counter and when it reaches zero, do the refresh and reset the counter. Just needed to add an extra refresh before showing the message box when you hit the target to flush any extra points that may have been added since the last refresh.
I'll leave that extra speedup code in, but commented out so you don't have to add the extra textbox control to try the code out.
Code:
Public Class Form1
Dim N As New Random
Dim X, Y As Integer
Dim shotPoints As New List(Of Point)
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
' Dim speedCounter, speedUp As Integer
Dim X1, Y1, X2, Y2 As Integer
Dim V, A, T, G As Single
V = CSng(TextBox3.Text)
A = CSng(TextBox4.Text)
G = 9.81
X2 = 0
Y2 = 0
T = 0
' speedUp = CInt(TextBox5.Text)
' speedUp = Math.Min(100, Math.Max(1, speedUp)) 'Limit choice between 1 and 100
shotPoints.Clear() 'Clear the previous point from the list
shotPoints.Add(New Point(0, 450)) 'Add the starting point (shoot from point)
' speedCounter = speedUp
Do Until T > 2 * V * Math.Sin(A * Math.PI / 180) / G
X1 = CInt(V * Math.Cos(A * Math.PI / 180) * T)
Y1 = CInt(V * Math.Sin(A * Math.PI / 180) * T - (1 / 2) * G * T ^ 2)
shotPoints.Add(New Point(X1, 450 - Y1)) 'Add a point for the trajectory at this time interval
' speedCounter -= 1
' If speedCounter <= 0 Then
Panel3.Refresh()
'speedCounter = speedUp
' End If
If (CInt(X1) - 2 <= X And X <= CInt(X1) + 2) And (CInt(Y1) - 2 <= Y And Y < CInt(Y1) + 2) Then
Panel3.Refresh()
Dim msgRslt As MsgBoxResult = MsgBox("Congratulations... You HIT the point.!" & vbNewLine & "Play Another Game? ", MsgBoxStyle.Question Or MsgBoxStyle.YesNo, "Game Play")
If msgRslt = MsgBoxResult.Yes Then
MsgBox("New ball location is generated", MsgBoxStyle.Information Or MsgBoxStyle.OkOnly, "New Game")
GenerateTarget()
ElseIf msgRslt = MsgBoxResult.No Then
Me.Close()
End If
Exit Sub
End If
T = T + 0.01F
X2 = X1
Y2 = Y1
Loop
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Me.Close()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
GenerateTarget()
End Sub
Private Sub GenerateTarget()
X = N.Next(450)
Y = N.Next(450)
TextBox1.Text = X.ToString
TextBox2.Text = Y.ToString
shotPoints.Clear()
Panel3.Refresh()
Button2.Enabled = True
End Sub
Private Sub Panel3_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Panel3.Paint
Dim mg As Graphics = e.Graphics
mg.FillEllipse(Brushes.Yellow, X, 450 - Y, 3, 3) 'Redraw the target
Using Mp As New Pen(Brushes.White, 1)
If shotPoints.Count > 1 Then
mg.DrawLines(Mp, shotPoints.ToArray)
End If
End Using
End Sub
End Class
S
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|