# VBForums UtilityBank > UtilityBank - Tutorials >  Tutorial [Snake using Picture boxes] NMs Game tutorial 0.4

## NoteMe

This is a tutorial on how to make a basic snake game. There is plenty of ways to complete such a task. I have chosen to start off with probably one of the simplest ways I can imagine, so if you are new to games programming in VB, this is a great tutorial for you. So I think we should just jump in to it. I am using VB6 in this example. But VB 5 should do fine too. To make this game you should know a little bit about VB from before. I am using simple collision detection, and key presses, and a module. If you don't know at all how to use this from before you should try to read about it before starting. I will try to make some tutorials on the subject soon but for now this is all I got.



*Setting form properties:*

When making games it is always easier to handle the coordinates of the screen in pixels than twips (twips is the default one). So start by changing the ScaleMode property of the form to Pixels. And if you don't know it from before, it is nice to know that in VB the coordinates of your form is (0,0) in the upper left corner. It is not easy to think this way of the coordinate system at once, but you will get used to it.

----------


## NoteMe

*Start Coding:*

We will split the snake in small parts. Lets call one square of the snake for a BodyPart. The head is one BodyPart. The next square of the snake is a body part and so on. Our game has to always remember the coordinates of this BodyParts and what way they are heading (facing). This way we can get the body to follow the head. To do this we will use a User Defined Type (UDT). It is more or less the same thing as any data type like String, Integer, or Double. But with the UDT we can make our own. Do to this we first have to add a module to the game. Open up the code for the module and enter the following code.


VB Code:
'User Defined Type for a snake part. 
 Type SnakePart 
    X As Long               'X-Coordinate 
     Y As Long               'Y-Coordinate 
     Facing As Long          '1 = left, 2 = up, 3 = right, 4 = down 
 End Type


We now have made our own UDT that is called SnakePart that can hold the X,Y coordinates and the way the part is facing (1 = left, 2 = up, 3 = right, 4 = down). But we will also know how many body parts the snake has to draw it in the right length. So lets add an other line of code to the module.


VB Code:
'Length of the snake 
 Global Length As Long


That is all the code that we need to put in the module. Now we will head back to the form.

----------


## NoteMe

*Making the SnakeParts:*

We need to make some variables that can hold the SnakeParts. For that we will use an array. We don't know how long the maximum snake will be, so we probably should have made the array dynamically. But to simplify things here, lets say that it is 100. So add this line to the top of your app.


VB Code:
Dim Snake(99) As SnakePart


Now we have 100 variables of the SnakePart type that is ranged from 0 to 99. So now lets get busy with the snake.


*Drawing the snake:*

We have to decide the size of each part of the snake. You can change this later. But leave it to be 10*10 pixels for now. You can change it if you want when you understand how all the code is working.
Draw a small (10*10 pixels) drawing of a body part of a snake in MSPaint or any other paint app that you have installed. Then go back to VB and put an image control on your form. Set the name property of the image control to "imgSnake". Then place another image control on the form. And set the name property to "imgSnake". A msgbox pops up and ask you if you want to make an control array of the control. Press yes. Then go and place 4 more image controls on the form and call them "imgSnake". Now you have a control array of image controls. This is really powerful when we come to the loops in a little while.
Now go to the paint app you used to make the bodypart for the snake. And use a selection tool to select the whole picture. Then press [Ctrl]+[C] (copy). Then move to VB and choose one of the image controls that you just made and then press [Ctrl]+[V] (paste) to paste the picture to the image control. Do the same to all the image controls that you have made. That is it. You have made a snake. It may not look like a snake, but in a moment we will try to make it at least move like a snake.

----------


## NoteMe

*Writing some code:*

Now we will write some code for the game. We need first some code in the form load event. To make all the starting values of the variables. We need to tell the game the starting length of the snake, where the "head" is placed, where the body is placed, and what way the snake is moving. We also need to move all the image controls to a starting place and update all the UDT for the body. We will do this in a loop. Write down this code in the form load event:


VB Code:
'Sets the initial values of the snake 
     Dim i as Long 
 
    Length = 5 
    For i = 0 To 4 
        Snake(i).X = (120 - 10 * i) 
        Snake(i).Y = 120 
        imgSnake(i).Left = Snake(i).X 
        imgSnake(i).Top = Snake(i).Y 
        Snake(i).Facing = 3 
    Next i


The code loops from 0 to 4. That makes the loop execute 5 times, once for each part of the body. In the loop it is in the first line setting the X coordinate of the body. You can see the i in the parentheses, it will change every time the loop is executed. So the first time it will be 0 and the next 1 and so on. So the first time it is executed we change the properties of the "head". First the X coordinate, then the Y coordinate. Then it places the first image control at the X,Y coordinate. And then it tells it what way that snake part is heading. Then the loop is executed with the i as 1. It will get all the same properties fixed except the X coordinate. This time the X coordinate is (10 * i) 10 pixels more to the left. Remember the width of a body part is 10pixels. So the net time the loop is executed it will be placed 10pixels to the left of that one too. This will make all the image control line up like a snake.


*Food:*

Now we are going to think of the food for a while. First we need a picture of the food. By thinking of the size of that picture, we can simplify a lot of things here. Lets make the pic 10*10 pixels and in an other color then the body. When you have painted it, go back to VB, place a new image control on the form. Set the name property to imgFood. Go back to paint, select the pic and copy it the same way as before. Then paste it to the image control on the form in VB. Now we need to think of a place to put the food. Lets do that in code. Add this code to the form load event.


VB Code:
'Randomizing the Rnd function. 
 Randomize 
     
'Placing the food for the game to start 
 Call PlaceFood


The first statement is called and uses the time from the computer as a seed, to make the Rnd function random. So every time you start the app, the Rnd function will give a different value.
the second statement is a call to a Sub. It is calling some code that we are going to write now. The code is going to put the food a place on the form, so the snake can get it. We want to move the snake a certain amount of pixels every time, so to simplify things a bit, we will do some code in the PlaceFood sub that might seem to be a little to much. But it is actually pretty smart. OK, make a new sub and call it PlaceFood. And then add this code to it.


VB Code:
Dim Temp As Long 
   'Finds a new X-coordinate for the food. 
Do
     Temp = Rnd * (Form1.ScaleWidth - imgFood.Width) 
 Loop While (Temp Mod 10 <> 0) 
 imgFood.Left = Temp 
     
  'Finds a new Y-coordinate for the food. 
Do
   
   Temp = Rnd * (Form1.ScaleHeight - imgFood.Height) 
 Loop While (Temp Mod 10 <> 0) 
 imgFood.Top = Temp


It is made by two loops that is looping until we have found a place we can put the food so the snake can get it. The first loop, finds the X coordinate of the food. It uses the Rnd function to find a number between 0 and 1 and multiplies that number to the width of the form. It also takes away some of the width of the form, so the food is not going to be placed so some of the food is not placed out of the form. It then checks to see if we constantly moves the snake with 10 pixels, if it is possible for the snake to land on the exact same position as the food. We are using a temp variable of type long. That is because that variable is going to round the X coordinate to a whole number. So we don't get any problems with decimal precision. If it finds a X coordinate that suits, it assigns the variable to the imgFoods left property. And then a new loop are doing the exact same for the Y coordinate. When all the code in this sub is finished, it has placed the imgFood at a new place.

----------


## NoteMe

*Game Loop:*

We need a game loop that is running as long as the game is running. The simplest way to do this is to use a timer. Put a timer on the form. Set the Name property to tmrLoop, and the interval to 150, and enabled to true. This is now our game loop that is called every 0.15 second. We are going to use this "loop" to move the head of the snake, move the body, and to check if the snake found the food. Add these lines of code to the tmrLoop timer event.


VB Code:
'Check to see if the snake finds food 
     Call FindFood 
     
    'Moves the snake 
     Call MoveSnake


These lines call two subs that we are going to make soon. The first one checks to see if the snake found food. And the other one is moving the whole snake. Lets do the fun part first.


*Move Snake:*

We are going to move the body first and then the head. So the first loop is moving the body. It moves the back of the snake first, and then moves the part that is in front of that line and so on. The part of the snake that is in the rear gets the coordinates of the part that is in front of it. And it also gets the facing variable of the part in front. This movement is made in this loop. Make a Sub called MoveSnake, and then add this code:


VB Code:
Dim i As Long 
     
    'Move body 
     For i = (Length - 1) To 1 Step (-1) 
        Snake(i).X = Snake(i - 1).X 
        imgSnake(i).Left = Snake(i).X 
        Snake(i).Y = Snake(i - 1).Y 
        imgSnake(i).Top = Snake(i).Y 
        Snake(i).Facing = Snake(i - 1).Facing 
    Next i


It is first giving the x coordinate of the UDT in front of it selves, then assigning it to the image holding that snake part. Then it does the same with the Y coordinate before it gives the facing variable to it.


*Move the head:*

But we need to treat the head a bit different. Because the head has no body part in front of it to give him his coordinates. So we need to find another way of moving him. We are going to use the heads facing variable to just move it in that direction the head is facing. This is very straight forward, so just add this code under the code for the body in the same Sub.


VB Code:
'Move head 
     If Snake(0).Facing = 1 Then         'Moves left 
         Snake(0).X = Snake(0).X - 10 
        imgSnake(0).Left = Snake(0).X 
    ElseIf Snake(0).Facing = 2 Then     'Moves up 
         Snake(0).Y = Snake(0).Y - 10 
        imgSnake(0).Top = Snake(0).Y 
    ElseIf Snake(0).Facing = 3 Then     'Moves right 
         Snake(0).X = Snake(0).X + 10 
        imgSnake(0).Left = Snake(0).X 
    ElseIf Snake(0).Facing = 4 Then     'Moves down 
         Snake(0).Y = Snake(0).Y + 10 
        imgSnake(0).Top = Snake(0).Y 
    End If


If the facing variable of the head is 1 (left) then it moves 10 pixels to the left. If it 2 (up) then move 10 pixels up and so on. Nothing magical to it at all.


*Moving the head in another direction:*

But we want to be able to move the head in another direction. To do this we are going to use the arrow keys. To use the keyboard in VB we need to set the KeyPreview property of the form to true. Then we need to write some code to change the facing variable of the head. Do that in the form keydown event.


VB Code:
'Turning the face of the snake 
     If KeyCode = 37 Then            'Left 
         Snake(0).Facing = 1 
    ElseIf KeyCode = 38 Then        'Up 
         Snake(0).Facing = 2 
    ElseIf KeyCode = 39 Then        'Right 
         Snake(0).Facing = 3 
    ElseIf KeyCode = 40 Then        'Down 
         Snake(0).Facing = 4 
    End If


This code changes the heads facing variable according to the arrow that is pressed. If the left arrow (keycode 37) is pressed. The facing variable is changed to 1. And so on. This is also very straight forward. And now when you have added these lines of code you can for the first time try the game, and move the snake in the direction you want it to. But there is one thing left before the game is playable at all. That is that, the snake can at the moment not eat food and grow.

----------


## NoteMe

*Eat food:*

Start with making a Sub called FindFood. The firs thing we need to figure out is if the head of the snake is the same place as the food. And finally our hard coding work is finally paying off. Because we made sure that the food is placed exactly at a place where the snake can get, this is really easy to do. So to check if the snake found food, we only need to do a small if test. Place this code in the FindFood Sub.


VB Code:
Dim i As Long 
         
    'If the head finds food 
     If Snake(0).X = imgFood.Left And Snake(0).Y = imgFood.Top Then 
         
    End if


This if test are testing if the snakes head X and Y coordinates is at the exact same place as the foods X, Y coordinates. We now need some lines of code to make the snake bigger, and then place the new body part of the snake in a new place. To make a new image control of our array of image controls add this line of code in the If statement.


VB Code:
'Loads a new instance of the snake body 
 Load imgSnake(Length)


It is making one new image control. Then we need to place the image control at the end of the snake. Add this code in the same if statement.


VB Code:
'Placing the new body on its place 
 If Snake(Length - 1).Facing = 1 Then        'Looking left 
      Snake(Length).X = Snake(Length - 1).X - imgSnake(0).Width 
     Snake(Length).Y = Snake(Length - 1).Y 
     imgSnake(Length).Visible = True 
ElseIf Snake(Length - 1).Facing = 2 Then    'Looking up 
      Snake(Length).X = Snake(Length - 1).X 
     Snake(Length).Y = Snake(Length - 1).Y + imgSnake(0).Height 
     imgSnake(Length).Visible = True 
ElseIf Snake(Length - 1).Facing = 3 Then    'Looking right 
      Snake(Length).X = Snake(Length - 1).X - imgSnake(0).Width 
     Snake(Length).Y = Snake(Length - 1).Y 
     imgSnake(Length).Visible = True 
ElseIf Snake(Length - 1).Facing = 4 Then    'Looking down 
      Snake(Length).X = Snake(Length - 1).X 
     Snake(Length).Y = Snake(Length - 1).Y - imgSnake(0).Height 
     imgSnake(Length).Visible = True 
End If


This code is checking to see what way the back of the snake is heading. If it is heading left the new part is added to the right of the snake. If the rear is heading up, the new bodypart is added to the bottom of the snake. It is then setting the visible variable to true of that image control.
We have now added a new body part. And now we need to increase the length of the snake variable. So add this line in the If statement as well.


VB Code:
Length = Length + 1


And then we have to place the food in a new place on the form. But because we did this in another sub early in the game, we only need to write one line of code to make it work. This is a really powerful programming practice. So just add this line to the If statement as well.


VB Code:
'Placing the food an other place 
 Call PlaceFood


You have now finished the "game", and can try it. It is still tons of things that you can add to it to make it a game. But I will leave it here for now. And later when I have more time, I will add more to it. But I can make a list of things that you can try to add to the game.


- Make it impossible to walk through your own body
- A picture of an actual head of the snake.
- A picture of an actual tail of the snake.
- Make the game stop if the snake hits the outer bounds of the form.
- Make walls in the game.
- Add levels to it, with different speed and walls.
- Add a two player game.


If you have more questions, please ask in the forum, where there is probably more than just me that can answer to the questions.

Here is the "full game" zipped down in the attachment.

----------


## si_the_geek

The files within this thread (submitted: 25 Feb 2004) have been checked for malware by a moderator.

Disclaimer: _This does not necessarily mean that any compiled files (DLL/EXE/OCX etc) are completely safe, but any supplied code does not contain any obvious malware.  It also does not imply that code is error free, or that it performs exactly as described.

It is recommended that you manually check any code before running it, and/or use an automated tool such as Source Search by Minnow (available here or here).  
If you find any serious issues (ie: the code causes damage or some sort), please contact a moderator of this forum.

Usage of any code/software posted on this forum is at your own risk._


The above posts have been edited (with NoteMe's permission) to correct spelling/grammar errors.

----------


## EpicMango

Wow. Looks like I stumbled upon the most useful of ancient threads. Hopefully this will get a reply. Thanks for the tutorial, all the given code works great. I was wondering if anyone could tell me how I could generate some walls around the edge of the form as boundaries for the snake. Here's the code I have so far:



```
Option Explicit
Dim Wall(176) As Wallpart  'Wallpart is user-defined type with properties X and Y

Private Sub Form_Load()
    'Generate Walls
    
    For ib = 1 To 51       'Generate walls at the top
        Load imgWall(ib)
        Wall(ib).X = (8 + (ib * 10))
        Wall(ib).Y = 8
    Next
    For ib = 52 To 104       'Generate walls at the bottom
        Load imgWall(ib)
        Wall(ib).X = (8 + (ib * 10))
        Wall(ib).Y = 312
    Next
    For ib = 105 To 140       'Generate walls at the left
        Load imgWall(ib)
        Wall(ib).X = 8
        Wall(ib).Y = (16 + (ib * 10))
    Next
    For ib = 141 To 17       'Generate walls at the right
        Load imgWall(ib)
        Wall(ib).X = 424
        Wall(ib).Y = (16 + (ib * 10))
    Next
        
    imgWall(ib).Left = Wall(ib).X
    imgWall(ib).Top = Wall(ib).Y

End Sub
```

imgWall(0) is already loaded in the form at position Left = 8, Top = 8, and I want the border to be a 52x38 rectangle made of individual boxes 10x10 pixels in size.

When I try to run the program, the error given is "Control array element "141" doesn't exist", and the line "imgWall(ib).Left = Wall(ib).X" is highlighted.

What am I doing wrong?

Also, I believe creating these borders changes the code for the PlaceFood sub since the food has to be placed within the walls, and I'm not sure how to do that either.

----------


## NoteMe

Hehe, yeah. It brings back good old memories this thread. Been a long time since I did any VB though, and a long time since I have been on this side of the Internet  :Smilie: . 

But about your problem. I guess it is only a small typo from your side. It actually took me a few seconds to see what is wrong as I haven't had VB installed for years. I guess if I did, it would be easy to see that the wall blocks it complain about is never created because you have an ill-defined for loop.

You have:


```
For ib = 141 To 17       'Generate walls at the right
```

But I am sure you did not mean 17!

- ØØ -

----------

