Page 1 of 1

Creating games with VB.NET

#1 SixOfEleven  Icon User is offline

  • using Caffeine;
  • member icon

Reputation: 942
  • View blog
  • Posts: 6,342
  • Joined: 18-October 08

Posted 21 November 2009 - 05:27 PM

You VB.NET programmers might like to create games as well. So, I thought I would write tutorials for you on how to do it as well at the same time as the C# programers are as well. Unfortunately C# and VB.NET aren't quite the same so things will be done a little differently.

To get started go a head and create a new VB.NET Windows Forms application. I called mine VBGameProgramming. Now you will want to add a single Picture Box control to the form and call it pbSurface. What you will want to do next is set two properties of pbSurface. The first one will be the Dock property. You want to set the to be Fill. The other property you want to set is the BackColor property. Set that to be Black. There is just one other thing that I want to do in the designer. I want to create an event handler for the Shown event for when the form is first open. Click on the Title bar of the form to make sure that it is selected. Now, click the little lightning bolt in the properties window to bring up the list of event handlers. Create a new event for the Shown event. You can create the default event by double clicking the word Shown. That is all I'm going to do with the designer. For the rest of the tutorial I will be working in code.

I'm not going to create a class for the timer. I'm just going to use the Stopwatch class. There are some variables that you will want to add to the code for Form1. In my tutorials I like to show the code and then explain the way things work.

	Dim timer As Stopwatch
	Dim backBuffer As Image
	Dim graphics As Graphics
	Dim clientWidth As Integer
	Dim clientHeight As Integer
	Dim interval As Long
	Dim startTick As Long
	Dim imageRect As Rectangle
	Dim direction As Point



The first field timer will be used to have the game run at the same speed on different computers. If you don't preform timing and your computer is a slower or faster than a friend's computer and you try and run it on their computer it would be too fast if yours is much slower or too slow if your is much faster. It is typically better to draw to a back buffer and then flip the back buffer to the screen. This will help to reduce flicker. That is why there is a variable called backBuffer and is of type Image. To do the rendering with GDI+, which is slow by the way, you need an object of the Graphics class. That is what the next variable is for. The next two variables, clientWidth and clientHeight, will hold the size of the drawing area. I will need them frequently and it is usually better to assign the values to variables rather than using magic numbers. The next two fields will be used to control the speed at which the game runs. The interval variable will hold how long to pause the game for. The startTick variable will hold in microseconds when each pass through the game loop starts. The next two variables are for drawing a rectangle on the screen and bouncing it around the screen. The imageRect will be the actual rectangle and direction will control the speed at which the rectangle moves around the screen.

You need to set up a few things in the Form1_Load event and initialize a few variables. This is the code for the Form1_Load event.

	Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
		Me.DoubleBuffered = True
		Me.MaximizeBox = False
		Me.FormBorderStyle = Windows.Forms.FormBorderStyle.FixedSingle
		timer = New Stopwatch()
		clientWidth = 300
		clientHeight = 300
		interval = 16
		Me.ClientSize = New Size(clientWidth, clientHeight)
		backBuffer = New Bitmap(clientWidth, clientHeight)
		graphics = graphics.FromImage(backBuffer)
		direction = New Point(2, 3)
		imageRect = New Rectangle(0, 0, 55, 65)
	End Sub



The first line sets the DoubleBuffered property of the form to True to keep it from flickering. I don't want the size of the form to change so I set the MaximizeBox property to False and the FormBorderStyle property to FixedSingle. Since timer is an object you need to create a new instance for it. I set the clientWidth and the clientHeight variables to 300. I then set the interval variable to 16. That is 16 milliseconds which is about 1/60 of a second giving a frame rate of about 60 frames per second. I set the ClientSize property of the form to be 300 by 300. I also create a new Bitmap for backBuffer to be the same size. There is no constructor for the Graphics class. I use the FromImage method using the backBuffer image for this. I then set the direction of rectangle to be (2, 3). That means the X position of the rectangle will initially move 2 pixels to the right. This is because when you are drawing the X axis increases as you move from the left side of the screen to the right side. The rectangle will also move 3 pixels down the screen initially because Y increases as you move from the top of the screen down. I know this is different than in math. I also create a rectangle that will start at X and Y coordinate (0, 0) and is 55 pixels wide and 65 pixels high.

There is only one line of code in the Form1_Shown event handler. It just calls a sub that I will right that will handle the game loop. You can create games using the Timer control that comes with the .NET framework. A game loop is just more accurate as the accuracy of the Timer control isn't as good as the accuracy of the Stopwatch. This is the code for the Form1_Shown event handler

	Private Sub Form1_Shown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
		GameLoop()
	End Sub



The GameLoop sub is where I will control the game. In a game there is always a game loop. What happens in the game loop is that you update any objects in the game. You then draw the objects of the game. You preform any events that are in the event queue and you preform your timing to control the speed the game runs at. This is the code for the GameLoop sub.

	Private Sub GameLoop()
		timer.Start()
		Do While (Me.Created)
			startTick = timer.ElapsedMilliseconds
			GameLogic()
			RenderScene()
			Application.DoEvents()
			Do While timer.ElapsedMilliseconds - startTick < interval

			Loop
		Loop
	End Sub



What this code does is first start the timer so that it is running and I can use it to control the speed at which the game runs. Now comes the actual game loop. What happens here is that this will loop while the form is in existence. The first thing you need to do is determine which millisecond the loop starts at. You then call the GameLogic sub, which I will show you shortly, to perform the logic of the game. Next you call the RenderScene sub, which I will show you shortly, to draw the scene. The next line will process any events that are of interest to the form. The next loop will just loop until the current millisecond of the timer minus the startTick is less than the interval variable. This is what has the game run at a constant speed on slower and faster computers. I will let you know that using GDI+ is slow. Having a frame rate of 60 frames per second for a large game that draws a lot of objects will not be possible. You will more than likely have to go for a lower frame rate. There are a few tricks that you can do to speed this up a little. I will get into that in future tutorials.

Now it is time for the GameLogic sub. Like I mentioned, this sub is where I will control the moving of the object on the screen. This is the code for the GameLogic sub.

	Private Sub GameLogic()

		imageRect.X += direction.X
		imageRect.Y += direction.Y

		If imageRect.X < 0 Then
			imageRect.X = 0
			direction.X *= -1
		End If

		If imageRect.Y < 0 Then
			imageRect.Y = 0
			direction.Y *= -1
		End If

		If imageRect.X + imageRect.Width > clientWidth Then
			imageRect.X = clientWidth - imageRect.Width
			direction.X *= -1
		End If

		If imageRect.Y + imageRect.Height > clientHeight Then
			imageRect.Y = clientHeight - imageRect.Height
			direction.Y *= -1
		End If

	End Sub



If you are not used to game programming that might look a little intimidating. What this does is each time the code runs is add the X and Y properties of direction to the X and Y properties of imageRect. If this was to continue the rectangle would eventually disappear. So I will do some bounds checks to see when the rectangle reaches the edges of the window. Checking for the left hand side and top of the form are the easiest cases. You know the X and Y coordinates of the rectangle because they are properties of the rectangle. To see if the rectangle will go off the left side of the screen you check to see if the X property is less than zero. If it is you set it to zero to keep it from going off the screen. Just staying in the same position is boring though. So what I do is multiply direction.X by -1 which will reverse the direction. To keep it from going off the top of the screen what you do I check to see if the Y property is less than 0. If it is set it 0 and then multiply direction.Y to reverse the direction the square is traveling. Checking for the right hand side is a little more difficult what you do is check to see if the X property plus the width of the rectangle is greater than the width of the client area. If it is set it to the X property to the width of the client area minus the width of the rectangle and again reverse the direction. Finally for the bottom of the window you check to see if the Y property of the rectangle plus the height is greater than the height of the client area. If it is set the Y property to the height of the client are minus the height of the rectangle and reverse the direction.

That just leaves the RenderScene sub. This is the code for that sub.

	Private Sub RenderScene()
		backBuffer = New Bitmap(clientWidth, clientHeight)
		graphics = graphics.FromImage(backBuffer)
		pbSurface.Image = Nothing
		graphics.FillRectangle(Brushes.Blue(), imageRect)
		pbSurface.Image = backBuffer
	End Sub



This is the code that does the actual drawing. Each frame I create a new image for the backBuffer. What this does is create a blank drawing surface to draw to. Since I created a new image I need to create a new graphics object to draw with. I then set the Image property of pbSurface to be Nothing and that will remove the image from pbSurface effectively erasing the image. I then draw a filled rectangle to the image using a blue brush and the rectangle. I then set the Image property of pbSurface to be the new image drawn backBuffer.

Well, that is it for this tutorial. I plan to write a few more of these to help those VB.NET programmers that would like to create games with VB.NET.

Is This A Good Question/Topic? 1
  • +

Replies To: Creating games with VB.NET

#2 tweaksource  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 13
  • Joined: 19-August 09

Posted 24 November 2009 - 11:01 AM

SixOfEleven

This is a great tutorial. Thank you very much.

It has been very helpful.

I have drawn another rectangle which I am able to move with KeyDown events.

In declarations

Dim Player As Rectangle
Dim Playerdirection As Point



In Form_Load
Player = New Rectangle(100, 100, 20, 20)



In RenderScene
graphics.FillRectangle(Brushes.Blue(), Player)




and

 Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown

		Player.X += Playerdirection.X
		Player.Y += Playerdirection.Y

		Select Case e.KeyCode
			Case Keys.Up
				If Not Player.Y = 0 Then
					Player.Y -= 10
				End If

			Case Keys.Down
				If Not (Player.Y + Player.Height >= Me.Height - 30) Then
					Player.Y += 10
				End If

			Case Keys.Left
				If Not Player.X = 0 Then
					Player.X -= 10
				End If

			Case Keys.Right
				If Not (Player.X + Player.Width >= Me.Width - 10) Then
					Player.X += 10
				End If

		End Select
	End Sub



I hope this helps someone else.

I also have a question.

Should collision detection happen in the GameLogic, KeyDown block or another sub/Function?

Any help is appreciated.

This post has been edited by tweaksource: 24 November 2009 - 12:13 PM

Was This Post Helpful? 0
  • +
  • -

#3 lesPaul456  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 173
  • View blog
  • Posts: 729
  • Joined: 16-April 09

Posted 25 November 2009 - 05:55 AM

Collision detection needs to be added in the GameLogic method. It's very important that you check for collisions each frame.
Was This Post Helpful? 0
  • +
  • -

#4 `bob`  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 14
  • Joined: 04-May 11

Posted 11 May 2011 - 04:01 PM

how about the vb6 version of this might help
Was This Post Helpful? 0
  • +
  • -

#5 Dominator3026  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 27
  • Joined: 13-February 12

Posted 11 April 2012 - 05:08 PM

I have done you tutorial and it helped me understand alot but is there any way insted of useing a rectangel, to use an image like a gif and make it move automatically like the rectangel any help is much appriciated

This post has been edited by Dominator3026: 11 April 2012 - 05:10 PM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1