Virtual Developer Workshop: Containerized Development with Docker
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 Set_Default() Timer1.Interval = 15 Timer1.Enabled = True Dead = False Init_const() Init_Ast() 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 MyGraphic.Clear(Color.White) If Not Dead Then Check_Input() Put_Ship() Else Check_Space() End If Put_Shots() Put_Aster() Hit_Aster() Check_Stage() Do_Score() 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