This is a tutorial on how to make a BitBlt snake game. This is not the simples way to do it. If you are completly new to game programming in VB. You should try to look at part 1 of my game programming tutorials. It is using pictureboxes. It is a little bit easier. If you have read that tutorial, this one should be easy. This one is not that much longer, but it is using one API call. But if you feel ready, I think we should just jump in to it. I am using VB6 in this example. But VB5 should do fine too.

Setting form properties:

When making games it is always easier to handle the coordinates of the screen in pixels then 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 coordinat system at once, but you will get used to it.

Start Coding:

We will splitt 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 anny data type like String, Integer, or Double. But the with 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.

'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 coordiantes 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.

'Length of the snake
Global Length As Long

When we are uisng BitBlt we also need some way to know where the food is on the form. So we have to add one more UDT. It only holds the X and Y coordinate. And it looks like this

'User Defined Type for the food
Type FoodXY
    X As Long               'X-Coordinate
    Y As Long               'Y-Coordinate
End Type

Now the tricky part comes. You can place the next bit of code in the top of the module. It is the API call. You need to declear it so VB knows where to look for it. It looks like this.

Public Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long

It's not pretty, but it is just copy paste material. You don't have to remember this. You declear it as public because it is in a module rather then the same form as you are writing the rest of the code in. The GDI32 part tells VB in witch library it shal look for the function that is called BitBlt. In the paranteses you have the parameters this function is using. The first one is a hDC. If you don't know what that is, don't get panic. It is just a referance to a memory location, that you are going to use to copy the picture. The second and third one is the X and Y coordinate where you want to copy the image too. The forth and fifth parameter is the width and hight of the picture you want to copy. The sixth and seventh parameter is the X and Y coordinate of the uper left point of the picture where you are copying from. Most ofthen this is 0 and 0, that meens the whole picture. And the last parameter is the type of copying you want to use. We are only going to use one way (vbSrcCopy), it is only copying what you are seeing, to where you want it. Simple as that. 

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



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 propably should have made the array dynamicaly. But to simplify things here, lets say that it is 100. So add this line to the top of your app.

Dim Snake(99) As SnakePart

Now we have 100 variables of the SnakePart type that is ranged from 0 to 99. So now lets get bussy with the snake.

We also need to make a variable for the food coordinates. you do that like this:

Dim Food As FoodXY



Drawing the snake:

        We have to deside 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 picture box on your form. Set the name property of the image controll to "imgSnake".
       Now go to the paint app you used to make the a 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 picture box. Then set the autosize property of the picture box to true, and the autoredraw property to true, then set the visible property to false. You don't want it to be visible. That's 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.



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 needs 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:

    'Sets the initial values of the snake
    Length = 5
    For i = 0 To 4
        Snake(i).X = (120 - 10 * i)
        Snake(i).Y = 120
        BitBlt Form1.hDC, Snake(i).X, Snake(i).Y, imgSnake.Width, imgSnake.Height, imgSnake.hDC, 0, 0, vbSrcCopy
        Snake(i).Facing = 3
    Next i

the code loops from 0 to 4. That makes the loop execute 5 times. One 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 paranthese, 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 contoll 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 coordinat. This time the X coordinate is (10 * i) 10 pixels more to the left. Remeber 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 controll line up like a snake. The new part here is the BitBlt call. It has a lot of parameters, but it is really simple. As I said earlier the first parameter is the memory location where we want the picture to be copied to. This time it is the Form, but it could be lot of other things. The of the form is what we are suing. It holds the memoryloaction where we want to copy it to. The two next parameters is the X and Y coorinates for that body part. Remember i is increasing every time, so the first time it is the first parts X and Y coordinate and the second time it is the seconds part and so on. Then it is the width and hight of the copy we want to copy. And then the memory loaction of the source image. We are using the imgSnakes hDC to get it. Then we tell that we want to copy the entire picture, hence the 0,0. And last but not least what way we want to copy it. We use vbSrcCopy. The normal way to do it.


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 picture box 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 controll on the form in VB. Then set the autosize property of the picture box to true, and the autoredraw property to true, then set the visible property to false. You don't want it to be visible. Now we need to think of a place to put the food. Lets do that in code. Add this code to the form load event.

'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 diffrent 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 simplifi 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.

    
    'Finds a new X-coordinat for the food.
    Do
        Food.X = Rnd * (Form1.ScaleWidth - imgFood.Width)
    Loop While (Food.X Mod 10 <> 0)
    
    'Finds a new Y-coordinat for the food.
    Do
        Food.Y = Rnd * (Form1.ScaleHeight - imgFood.Height)
    Loop While (Food.Y Mod 10 <> 0)
    
    BitBlt Form1.hDC, Food.X, Food.Y, imgFood.Width, imgFood.Height, imgFood.hDC, 0, 0, vbSrcCopy
    
    

It is made by two loops that is looping untill 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 numer 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 constantli moves the snake with 10 pixels, if it is possible for the snake to land on the exsact same position as the food. The Food coordinate variable earlier is storing the values so we can use it in the BitBlt function afterwards. As you can see the destination in the BitBlt function is still the form. The coordinates and size is now for the food and not the snake. And the hDC is also from the food picture box. The rest is the same as before. 



Game Loop:

We need a game loop that is running as long as the game is running. The simples way to do this is to use a timer. Put a timer on the form. Sat 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 this lines of code to the tmrLoop timer event. We also need to clear the screen. Because we have already copyed pictures to it. And don't want them there any more. Only the new one. The form has a function called Cls for doing this, so we will use that one. 


    'Clear the screen
    Form1.Cls
    
    'Check to see if the snake finds food
    Call FindFood
    
    'Moves the snake
    Call MoveSnake
    

These lines calles 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. Lets 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 one 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:

    Dim i As Long
    
    'Move body
    For i = (Length - 1) To 1 Step (-1)
        Snake(i).X = Snake(i - 1).X
        Snake(i).Y = Snake(i - 1).Y
        Snake(i).Facing = Snake(i - 1).Facing
        BitBlt Form1.hDC, Snake(i).X, Snake(i).Y, imgSnake.Width, imgSnake.Height, imgSnake.hDC, 0, 0, vbSrcCopy
    Next i

It is first giving the x coordinat 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 coordinat before it gives the facing variable to it. Then we once again use the BitBlt function to copy all the body parts.



Move the head:

But we need to treet the head a bit diffrent. Becuase the head has no body part in front of it to give him his coordinates. So we need to find an other 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 strigth forward, so just add this code under the code for the body in the same Sub.


    'Move head
    If Snake(0).Facing = 1 Then         'Moves left
        Snake(0).X = Snake(0).X - 10
    ElseIf Snake(0).Facing = 2 Then     'Moves up
        Snake(0).Y = Snake(0).Y - 10
    ElseIf Snake(0).Facing = 3 Then     'Moves right
        Snake(0).X = Snake(0).X + 10
    ElseIf Snake(0).Facing = 4 Then     'Moves down
        Snake(0).Y = Snake(0).Y + 10
    End If
    
    'Draw the head
    BitBlt Form1.hDC, Snake(0).X, Snake(0).Y, imgSnake.Width, imgSnake.Height, imgSnake.hDC, 0, 0, vbSrcCopy

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. We are aslo here using the BitBlt fuction to draw the head. 


The last thing we are going to do here is to draw the food again. Yes we have done that earlier, but we cleared the screen remember? So once again we are using the coordinates of the food to draw it again like this.

    'Draw the food again on the same place, because we cleared the screen
    BitBlt Form1.hDC, Food.X, Food.Y, imgFood.Width, imgFood.Height, imgFood.hDC, 0, 0, vbSrcCopy

Moving the head in an other direction:

But we want to be able to move the head in an other 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.


    '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 arrao (keycode 37) is pressed. The facing variable is changed to 1. And so on. This is also very stright 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.


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 finaly our hard coding work is finaly 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 thest. Place this code in the FindFood Sub.


    Dim i As Long
        
    'If the head finds food
    If Snake(0).X = Food.X And Snake(0).Y = Food.Y Then
        
    End if

This if test are testing if the snakes head X and Y coordiantes 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. 

We don't need to make any new body part, we will just add one more to the length and then place it on the end of the snake. You do that like this.

        'Placing the new body on it's place
        If Snake(Length - 1).Facing = 1 Then        'Looking left
            Snake(Length).X = Snake(Length - 1).X - imgSnake.Width
            Snake(Length).Y = Snake(Length - 1).Y
        ElseIf Snake(Length - 1).Facing = 2 Then    'Looking up
            Snake(Length).X = Snake(Length - 1).X
            Snake(Length).Y = Snake(Length - 1).Y + imgSnake.Height
        ElseIf Snake(Length - 1).Facing = 3 Then    'Looking right
            Snake(Length).X = Snake(Length - 1).X - imgSnake.Width
            Snake(Length).Y = Snake(Length - 1).Y
        ElseIf Snake(Length - 1).Facing = 4 Then    'Looking down
            Snake(Length).X = Snake(Length - 1).X
            Snake(Length).Y = Snake(Length - 1).Y - imgSnake.Height
        End If
        
        'increase the length of the snake
        Length = Length + 1
        

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 bootom of the snake. It is then setting the visible variable to true of that image controll.

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

	  '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 a actual head of the snake.
- A picture of a 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 diffrent speed and wals.
- Add a two player game.

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