Results 1 to 4 of 4

Thread: how can I remove the drawn line in the panel if it didn't successfully hit the point?

  1. #1

    Thread Starter
    Registered User
    Join Date
    Oct 2017
    Posts
    3

    Question 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.

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    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

  3. #3
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    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.

  4. #4
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    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
  •  



Click Here to Expand Forum to Full Width