Animation in VB.NET, Part 1

The article on animation in VB6 was a big hit and taken in well. However, VB6 is an outdated, and now unsupported language, so it was time to update this article to VB.NET. In Part 1, you will cover 2D vector graphics, and the methods required to build your Asteroids game. Because stick animation is simple and pretty well covered in the VB6 article, I will not cover them in this update; however, an updated download is included.

Note: All of the downloadable files for this article are in VS 2008 format.

There are a number of new graphics methods introduced in .NET and a lot of the old methods no longer work. Where one was able, in VB6, to draw lines and arcs directly onto the pictureboxes, this is no longer a valid method in .NET. The method that I'm using is to create a Graphics object from the base image. However, I won't be using the final picturebox but a memory bitmap object, and mapping the image onto the picturebox.

Before you continue, I'd like to note that it is preferable that you have read Part 1 of the VB6 articles before continuing because this article updates the methods detailed there for use in VB.NET.

So, your first task is to create your Bitmap and your Graphics object.

Private MyImage As Bitmap
Private MyGraphic As Graphics

Private Sub Asteroids_Load(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles MyBase.Load
   Mypen = New Pen(Color.Black, 1)
   Timer1 = New Windows.Forms.Timer
   MyImage = New Bitmap(PictureBox1.Width, PictureBox1.Height)
   MyGraphic = Graphics.FromImage(MyImage)

   First = True
   Timer1.Interval = 15
   Timer1.Enabled = True
   Dead = False

End Sub

As you can see the bitmap 'MyImage' is created with the same size as the picturebox the final image will be displayed on. The Graphic object is created from this bitmap. Any draw commands from the Graphics object are automatically placed onto the bitmap image object. This object also offers you the buffering method as discussed in Part 2 of the VB6 articles.

Another difference is that you no longer have the Xor pen function that you used in VB6 to erase and redraw lines. I have spent a considerable amount of time searching for Xor pen examples in .NET with little luck. So, in this instance, you will be clearing your bitmap and drawing each game object, or Sprite, in its current position. Where you may have lost in the need to redraw everything for each frame you gain in not having to store and erase the previous locations of each sprite.

So, after all that, you can see that there was a need to overhaul the core functions of the game to work with this new method; however, the math has all stayed the same.

It's time to move on. During the form load, you set the defaults and initiated your constants and asteroids. These functions have not changed from your VB6 version, and I see no need to repeat them here again. However, in the download the asteroid coordinates have been changed, simply so that the VB6 and VB.NET versions are easier to identify when running.

One sub that has changed and is important to the Graphic methods is the Timer Tick event sub.

Private Sub Timer1_Tick1(ByVal sender As Object, _
   ByVal e As System.EventArgs) Handles Timer1.Tick
   If Not Dead Then
   End If
   PictureBox1.Image = MyImage
End Sub

Most of this is the same; however, before you begin the game core you clear the Bitmap (via the Graphics object) with white colour. Remember that any method used from the graphics object is applied to the image it was generated from; in this case, your bitmap. Once you have completed the game core, you apply your new bitmap image to the picturebox.

Some may ask why you don't simply use the picturebox to generate your graphics object and draw directly to the picturebox. Yes, in testing, I started with the method of drawing directly to the picturebox and I found one small problem. Every Draw command forced the picturebox to re-render itself, causing a terrible slowdown and image jitter. Therefore, using a bitmap to buffer the image greatly reduces the rendering time.

The next step is to now place the ship onto your image.

Private Sub Put_Ship()
   Dim Cord(2) As Cords_Type
   With Ship
      .Location.X = .Location.X - .Speed * Sin(.Direction * PI / 180)
      .Location.Y = .Location.Y + .Speed * Cos(.Direction * PI / 180)

      If .Location.X >= 640 Then .Location.X = .Location.X - 640
      If .Location.X < 0    Then .Location.X = .Location.X + 640
      If .Location.Y >= 480 Then .Location.Y = .Location.Y - 480
      If .Location.Y < 0    Then .Location.Y = .Location.Y + 480

      For Loop_1 = 0 To 2
         Cord(Loop_1).X = .Location.X - (.Len_Const(Loop_1) * _
            Sin(.Ang_Const(Loop_1) + .Angle * PI / 180))
         Cord(Loop_1).Y = .Location.Y + (.Len_Const(Loop_1) * _
            Cos(.Ang_Const(Loop_1) + .Angle * PI / 180))
      Next Loop_1

   End With
   MyGraphic.DrawLine(Mypen, Cord(0).X, Cord(0).Y, Cord(1).X, Cord(1).Y)
   MyGraphic.DrawLine(Mypen, Cord(1).X, Cord(1).Y, Cord(2).X, Cord(2).Y)
   MyGraphic.DrawLine(Mypen, Cord(2).X, Cord(2).Y, Cord(0).X, Cord(0).Y)

End Sub

Animation in VB.NET, Part 1

Nothing much has changed here, except for the fact that you no longer need to erase the previous copy of the ship. Also, the rendering methods have changed slightly. VB6 used 'Object.Line (x1, y1) - (x2, y2)' where .NET now uses 'Object.DrawLine (Pen, x1, y1, x2, y2)'. You no longer set the drawmode on your object but rather use a pen type in your drawing methods.

As you can see, this greatly simplifies your rendering and also speeds up your game core. Now, look at some of the other rendering functions.

Private Sub Put_Aster()
   Dim Cord(9) As Cords_Type
   For Loop_1 = 0 To 39
      With Asteroids(Loop_1)
         If .Vis Then

            .Location.X = .Location.X + .Speed * Sin(.Direction * PI / 180)
            .Location.Y = .Location.Y - .Speed * Cos(.Direction * PI / 180)
            .Angle = .Angle + .Rotate

            If .Location.X >= 640 Then .Location.X = .Location.X - 640
            If .Location.X < 0    Then .Location.X = .Location.X + 640
            If .Location.Y >= 480 Then .Location.Y = .Location.Y - 480
            If .Location.Y < 0    Then .Location.Y = .Location.Y + 480
            If .Angle >= 360      Then .Angle = .Angle - 360
            If .Angle < 0         Then .Angle = .Angle + 360

            For Loop_2 = 0 To 9
               Cord(Loop_2).X = .Location.X - (.Len_Const(Loop_2) * _
                  Sin(.Ang_Const(Loop_2) + .Angle * PI / 180)) / .Size
               Cord(Loop_2).Y = .Location.Y + (.Len_Const(Loop_2) * _
                  Cos(.Ang_Const(Loop_2) + .Angle * PI / 180)) / .Size
            Next Loop_2

            f .Size > 8 Then
               .Vis = False
               For Loop_2 = 0 To 8
                  MyGraphic.DrawLine(Mypen, Cord(Loop_2).X, _
                     Cord(Loop_2).Y, Cord(Loop_2 + 1).X, _
                     Cord(Loop_2 + 1).Y)
               Next Loop_2
               MyGraphic.DrawLine(Mypen, Cord(9).X, Cord(9).Y, _
                  Cord(0).X, Cord(0).Y)

               .First = False
            End If
         End If
      End With
   Next Loop_1
End Sub

Private Sub Put_Shots()
   For Loop_1 = 0 To 19
      With Shots(Loop_1)
         If .TTL > 0 Then
            .Location.X = .Location.X - .Speed * Sin(.Direction * PI / 180)
            .Location.Y = .Location.Y + .Speed * Cos(.Direction * PI / 180)
            If .Location.X >= 640 Then .Location.X = .Location.X - 640
            If .Location.X < 0    Then .Location.X = .Location.X + 640
            If .Location.Y >= 480 Then .Location.Y = .Location.Y - 480
            If .Location.Y < 0    Then .Location.Y = .Location.Y + 480
            MyGraphic.DrawRectangle(Mypen, .Location.X - 1, _
               .Location.Y - 1, 2, 2)
            .TTL = .TTL - .Speed

            .First = False
         End If
         If .TTL <= 0 And Not .First Then
            MyGraphic.DrawRectangle(DelPen, .Location.X - 1, _
               .Location.Y - 1, 2, 2)
            .TTL = 0
            .First = True
         End If
      End With
   Next Loop_1
End Sub

Compared to the VB6 version, all of these rendering subs are shorter and quicker. However, they do produce an almost identical output.

In the downloads, there is the updated .NET stick figure project that shows how to render simple sick animation using the method of erasing only parts of the image and redrawing the changes, and the updated .NET Asteroids Project as detailed in this article.

This article was originally published on June 26th, 2008

About the Author

Richard Newcombe

Richard Newcombe has been involved in computers since the time of the Commodore 64. Today, he has excelled in programming, and designs. Richard is in his mid 30's and, if or when you looking for him look no further than his computer. Always willing to help and give advice where he can in regard to computer related subjects. At present he is working as a .NET 2008 Software Developer for Syncrony Web Services, South Africa.


Most Popular Programming Stories

More for Developers

RSS Feeds

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date