Windows Phone 7 - Snakes on a Phone Part 1
Written by Harry Fairhead   
Monday, 13 September 2010
Article Index
Windows Phone 7 - Snakes on a Phone Part 1
Building the Snake
Animating the snake

Banner

Building the Snake

Our first major task is to build an initial snake at a starting location. The best way of doing this is to implement a Snake class - this separates the snake logic from the rest of the program and allows us to instantiate as many Snake objects as required, hence Snakes on a Phone.

The Snake constructor has to build an initial snake at a given starting location. For simplicity we will start the snake from a fixed location stored in head the current position of he head of the snake - modifying this to a random or specified location is easy. We also need a private variable to store a reference to the Grid that the snake is to be drawn on, its size, the initial size of the snake and an instance of a Queue to store the locations of each of the snake's body segments:

class snake
{
private Point head = new Point(5, 5);
private Grid _grid;
private Int32 GridSize;
private Int32 Len = 6;
private Queue<Ellipse> Positions =
new Queue<Ellipse>();

The only strange thing here is the choise of storing Ellipses in the queue that is being used to record where each segment of the snake is. You might have expected to use a queue of Point objects recording just the positions. The reason for using a graphical object is that the Grid doesn't have an easy way to find out what is stored in a cell at a given row and column number. As a result is is actually easier to store a reference to a graphics object which does know the row and column it is stored in by way of the Row and Col attached properties it recieves from the Grid. How this works witll a become clear as we move on to consider the animation.


The constructor accepts the Grid to draw on as its only parameter:

public snake(Grid grid)
{
GridSize = grid.ColumnDefinitions.
Count();
_grid = grid;
for (Int32 i = 0; i < Len; i++)
{
addHead(new Point(5 + i, 5));
}
}

The snake is created by calling a new method - addHead(x,y) - which as its name suggests simply adds a head segment at the specified position in the grid and adds it to the queue:

private void addHead(Point head)
{
Ellipse el = new Ellipse();
el.Fill = new SolidColorBrush(
Colors.Red);
Grid.SetColumn(el, (Int32)head.X);
Grid.SetRow(el, (Int32)head.Y);
_grid.Children.Add(el);
Positions.Enqueue(el);
}

You can see that this is very simple. First we create a red ellipse and set its location. Then we add it to the grid and the queue using the Enqueue method which adds to the end of the queue.

Notice the need to cast the doubles in the Point structure to integers. As the co-ordinates are all integers it would have been better to use an integer based Point structure - but this can be modified later.

Now all we need is to create a snake in the constructor:

 S = new snake(PlayArea);

If you run the program at this point what you have is a grid with a stationary snake at its initial position.

initial

 

Animation

Now all that remains is to make the snake move. 

In nearly all cases it is a good idea to define a horizontal and vertical velocity for a sprite and a snake is no exception - the velocity is, of course, in this case the velocity of the head: 

private Point velocity = new Point(1, 0);

Initially the velocity is set to a horizontal motion to the right.

Next we need an Update method to move the snake using the current position and velocity of the head.

public void UpdateSnake()
{
head.X = (head.X + velocity.X +
GridSize) % GridSize;
head.Y = (head.Y + velocity.Y +
GridSize) % GridSize;
addHead(head);
removeOldTail();
}

We add the components of the velocities to the corresponding components of the old position to get the new position. Then we call addHead to create the new head segment at the correct location and a new method removeOldTail to remove the tail segment from the queue and the screen.

 

Banner

<ASIN:0735643350>

<ASIN:1449388361>

<ASIN:0470886595>

<ASIN:1430232196>



Last Updated ( Sunday, 19 September 2010 )