Introduction
In this simple tutorial, we want to create a scrolling sprite-based star field background using Xamarin Studio and the MonoGame that is an open source implementation of the Microsoft XNA 4.x Framework. This page lists the requirements for creating a MonoGame project on Windows.
Creating the Project
In this simple tutorial, we want to create a scrolling sprite-based star field background using Xamarin Studio and the MonoGame that is an open source implementation of the Microsoft XNA 4.x Framework. This page lists the requirements for creating a MonoGame project on Windows.
Open Xamarin Studio and create a new MonoGame Windows OpenGL Application project called TwoDimensionalStarField
. Open Microsoft Paint or your favourite image editor and create a new 2 by 2 pixel image and fill it with white. Save the image as STAR.BMP in a temporary location. Back in Xamarin Studio, right-click on Content folder and select Add | Add Files. Browse to the image you created and click on Ok. Add TitleScreen.PNG to your project too.
Add declarations to the Game1
class for game states and textures:
enum GameStates {TitleScreen, Playing};
GameStates gameState = GameStates.TitleScreen;
Texture2D titleScreen;
Texture2D star;
Update the LoadContent()
method to load textures:
star = Content.Load(@"STAR");
titleScreen = Content.Load (@"TitleScreen");
You need to add a basic template for the Update()
method before to call base.Update()
:
switch(gameState)
{
case GameStates.TitleScreen:
if ((Keyboard.GetState ().IsKeyDown (Keys.Space))) {
gameState = GameStates.Playing;
}
break;
case GameStates.Playing:
break;
}
Add a basic template for the Draw()
method before the call to base.Draw()
and put it between spriteBatch.Begin()
and spriteBatch.End()
methods:
if (gameState == GameStates.TitleScreen) {
spriteBatch.Draw (
titleScreen,
new Rectangle(0, 0,
this.Window.ClientBounds.Width,
this.Window.ClientBounds.Height),
Color.White
);
}
if(gameState == GameStates.Playing) {
}
Up to this point, we have created the skeleton of our Update()
and Draw()
method. Now you can execute your project (hit Ctrl + F5) to see that the title screen is displayed.
Building the Star Class
Add a new class to the project called Star.cs
and then include the following declarations to the class’ using area:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
Add the following properties to the Star
class:
private Texture2D Texture { get; set; }
public Color TintColor { get; set; }
public Vector2 Location { get; set; }
private Vector2 Velocity { get; set; }
private Rectangle InitialFrame { get; set; }
The TintColor
member stores color of each star that will be used when the star is drawn. The location of the star will be tracked via the Location
vector while the speed and direction at which the star is moving is stored in Velocity
.
Add the following constructor to the
Star
class:
public Star(
Vector2 location,
Texture2D texture,
Rectangle initialFrame,
Vector2 velocity)
{
Location = location;
Texture = texture;
InitialFrame = initialFrame;
Velocity = velocity;
}
This constructor just directly sets the members to the passed parameter values. Now you need to add the following property and methods to the Star
class:
public Rectangle Destination
{
get {
return new Rectangle (
(int)Location.X, (int)Location.Y,
InitialFrame.Width, InitialFrame.Height
);
}
}
public void Update(GameTime gameTime)
{
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
Location += (Velocity * elapsed);
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw (
Texture, Destination, InitialFrame, TintColor
);
}
The Destination
property builds a new Rectangle
based on the star’s current screen location and the width
and height
of the InitialFrame
. The Update()
method adds the sprite’s velocity to the sprite’s location. Since velocity is stored as the change over one second, multiplying it by the gameTime.ElapsedGameTime.TotalSeconds
(If the game is running at 60 frames per second, the value is likely to be 1 / 60 = 0.0166 seconds) determines the distance moved over a single frame. The Draw()
method consists of a single call to the SpriteBatch.Draw()
method using third overload of the method.
Building the StarField Class
Let’s put our Star
class to use by creating a scrolling star field. We can use an empty white sprite in combination with the TintColor
parameter of the SpriteBatch.Draw()
method to draw squares of any color we wish. This is why we have created STAR.BMP. For creating the star field, we will create 300 stars and place them on the screen randomly. They will have a velocity that will slowly draw them down the screen. The StarField
class will be responsible for creating the stars and determining when they reach the bottom of the screen. When this happens, they will be created again at the top of the screen at a random location.
Add a new class called StarField
and then add the following using
directives to the class’ using area:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
Add the following declarations to the StarField
class:
private List stars = new List();
private int ScreenWidth { get; set; }
private int ScreenHeight { get; set; }
private Random rand = new Random();
private Color[] colors = {
Color.White, Color.Yellow, Color.Red
};
Add a constructor to the StarField
class:
public StarField(
int screenWidth,
int screenHeight,
int starCount,
Vector2 starVelocity,
Texture2D texture,
Rectangle initialFrame
)
{
ScreenWidth = screenWidth;
ScreenHeight = screenHeight;
for(int x = 0; x < starCount; x++)
{
stars.Add (
new Star(
new Vector2(rand.Next(0, screenWidth),
rand.Next(0, screenHeight)),
texture,
initialFrame,
starVelocity)
);
}
foreach (Star star in stars) {
star.TintColor = colors[rand.Next(0, colors.Length)];
star.TintColor *= (float)(rand.Next (30, 80) / 100f);
}
}
We will store each star in the stars list. It makes it simple to update and draw them using a foreach
loop. When the stars are created, a color will be selected randomly from the colors array for each star. In the class constructor, we will create 300 stars and each star is assigned a random location. The TintColors
are then multiplied by a random value between 0.30f and 0.79f, making the star semi-transparent. Add the Update()
and Draw()
methods to the StarField
class:
public void Update(GameTime gameTime)
{
foreach (Star star in stars)
{
star.Update (gameTime);
if (star.Location.Y > ScreenHeight) {
star.Location = new Vector2 (rand.Next(0, ScreenWidth),0);
}
}
}
public void Draw(SpriteBatch srriteBatch)
{
foreach(Star star in stars)
{
star.Draw(srriteBatch);
}
}
A foreach
loop updates each star in the stars list. The method then checks the star’s Location
property’s Y
to determine if the star has reached the bottom of the screen. If it happens, the star’s location is assigned a new Location
with a random X
and a Y
component of zero, putting the star at a random location at the top of the screen. The Draw()
method simply uses a foreach
loop to passes along the spriteBatch
object to each of the individual stars in the stars list.
Viewing the StarField in Action
Add the following declaration to the Game1
class:
StarField starField;
In the Draw()
method, change the background color from Color.CornflowerBlue
to Color.Black
. Still in the Draw()
method, call the Draw()
method of starField
and place it to the if block containing GameStates.Playing
:
starField.Draw (spriteBatch);
Now run the project and observe the star
field.
The Final Result
In order to observe the final result, you can see the video on my Youtube channel or check out my blog.