'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.
'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.
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.
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 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 an other 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 3 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 comes to the loops in a little while.
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 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.
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
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. 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 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. 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 thinhs 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.
Dim Temp As Long
'Finds a new X-coordinat for the food.
Do
Temp = Rnd * (Form1.ScaleWidth - imgFood.Width)
Loop While (Temp Mod 10 <> 0)
imgFood.Left = Temp
'Finds a new Y-coordinat 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.
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.
'Check to see if the snake finds food
Call FindFood
'Moves the snake
Call MoveSnake
These lines calls 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 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:
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
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 straight 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
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 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 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.
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.
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.
'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.
'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(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.
Length = Length + 1
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 powerful
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.
- 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 different speed and walls.
- Add a two player game.
Here is a complete
download of my version of the game:
SnakePic.zip
----------------------------------------------------------------------------------------------------------------------------
Written by Øyvind
Østlund.
To contact Øyvind, write an E-Mail to [email protected]