ninja star Recreating Frogger in Silverlight - Part 2

by Michael Ceranski, posted on May 06 2009

In Part 1 of this series I discussed some of the prep-work that I did before I could get to any of the coding. This included a little bit of image manipulation using GIMP and some basic layout work in XAML. Now its time to discuss the mechanics of the game engine. Let me start by giving you the definition of a Sprite:

In computer graphics a sprite is a two-dimensional/three-dimensional image or animation that is integrated into a larger scene.

Sprites were originally invented as a method of quickly compositing several images together in two-dimensional video games using special hardware. As computer performance improved, this optimization became unnecessary and the term evolved to refer specifically to the two dimensional images themselves that were integrated into a scene. That is, figures generated by either custom hardware or by software alone were all referred to as sprites. As three-dimensional graphics became more prevalent, the term was used to describe a technique whereby flat images are seamlessly integrated into complicated three-dimensional scenes.

More specifically in my game, the logs, vehicles and turtles are all considered sprites. In order to make my things simpler to program I leveraged a common base class called SpriteBase. Using a common base class allows you to leverage code reuse and more importantly polymorphism. This is an important factor when you are trying to move around large amounts of objects and applying collision detection algorithms to each one. For example if you want to move a sprite around on the screen, you need to do it by changing the X and Y coordinates of that object. Therefore, the SpriteBase class has an X and Y property:

   1:  /// <summary>
   2:  /// The Y position of the sprite
   3:  /// </summary>
   4:  public virtual double Y
   5:  {
   6:     get { return (double)this.GetValue(Canvas.TopProperty); }
   7:     set { this.SetValue(Canvas.TopProperty, value); }
   8:  }

 

Moving on, we have now established that the sprites are the basic building blocks of the game. So the first step is to get the sprites on to the screen. Since we want the game to be challenging we do not want to hard code the locations of each sprite, therefore we will have to use a randomizer. The randomizer will be used to make the cars to move at different speeds, determine if items move left to right or right to left. In addition, we want a variety of different cars, logs and turtles on the screen.

Now, going back to part 1 of the article I discussed how I used Rectangles to create logical boundaries for how the various sprites would move in the game. Basically what I did, was overlay rectangles on the background image to create "Lanes" for the road and water. Each Rectangle was defined in the XAML file and has a unique name. I reference each unique name in my code and add it to array inside my code. Now, I realize that I could have just dynamically created these items in code but I like being able to see the layout of the game in design mode. Of course, I do not want the end-user to see all of the red outlining on the game when they are playing so I just loop through the elements when the game starts and change the stroke to a transparent color.

Here is the section of the XAML file which created the lanes on the road.

Now that I have an array with the Rectangles added to it, I can rely on the X and Y coordinates of those rectangles to control the placement of each sprite. Now, I create a nested for loop that iterates over each Rectangle and adds a random number of vehicles to each "Lane". Each lane is assigned a random speed and direction for the vehicles to move in. Also, the cars in each lane are randomly assigned. Here is the code:

   1:  private void CreateVehicles()
   2:  {
   3:      //add some vehicles to each lane using some random logic
   4:      for (int i = 1; i <= 5; i++)
   5:      {
   6:   
   7:          Boolean rightToLeft = (_randomizer.Next(0, 11) % 2 == 0);
   8:          Double startX = _randomizer.Next(0, 150);
   9:          Double speed = (double)_randomizer.Next(5, 20) * .1;
  10:   
  11:          for (int j = 0; j < 4; j++)
  12:          {
  13:              VehicleType vType = (VehicleType)_randomizer.Next(0, 5);
  14:              Vehicle vehicle = new Vehicle(vType, rightToLeft);
  15:   
  16:              if ((startX + vehicle.ActualWidth) >= this.Width) break;
  17:   
  18:              vehicle.Lane = i;
  19:              vehicle.X = startX;
  20:              vehicle.XSpeed = speed;
  21:              vehicle.Y = GetNewYLocation(vehicle, i);
  22:   
  23:              this.LayoutRoot.Children.Add(vehicle);
  24:              _sprites.Add(vehicle);
  25:   
  26:              int spacing = _randomizer.Next((int)(_frog.ActualWidth * 3), (int)(_frog.ActualWidth * 4));
  27:              startX += (vehicle.ActualWidth + spacing);
  28:          }
  29:      }
  30:  }

You will also notice that the cars are randomly spaced apart. I used the width of the frog as a basic unit of measure for this. After all, the frog needs to be able to fit between the cars if it wants to make across the road. Also, note that each new sprite is assigned a Lane. This is important because it helps me determine what items are in which lane. Since, the frog moves forward or backward only one lane at a time I can easily determine which objects the frog can potentially collide with.

The Logs and Turtles are created in a very similar fashion. The newly created sprites are all added to a private list named _sprites. Having the sprites in a collection allows me to easily iterate over them for animation and collision detection purposes. In Part 3 of this series I will discuss in detail how I animated the sprites and did collision detection. The Frogger game actually is interesting in the fact that the frog must avoid collisions with the vehicles on the road but it needs to hop on the logs in the river. So the two possible ways for the frog to die are getting hit by a car or jumping in the water.

Go To Part 1 | Go to Part 3

 

Download The Source Code - 2.94 MB

Play the Game (Opens in new window)

blog comments powered by Disqus

About the author

MikeMichael Ceranski is a developer specializing in the .NET stack. I have spent time as a DBA, Web Developer and even a network engineer. Up til now most of my career has revolved around the .NET stack but I have recently taken an interest in microcontrollers which has forced me to get acquainted with lower level languages such as C, and C++.

View my resume

Sponsors