Click here to Skip to main content
Click here to Skip to main content

Building a Scrolling Sprite-based Star Field Background with C# and MonoGame

By , 7 Jan 2014
Rate this:
Please Sign up or sign in to vote.

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Masoud Darvishian

Iran (Islamic Republic Of) Iran (Islamic Republic Of)
Interested in Game Programming, GameDev, Video Game, Math, Physics, CryEngine, Crytek, Music, Coffee, Planning, Learning, Reading and Writing.
 
Envision ● Enable ● Achieve

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web03 | 2.8.140415.2 | Last Updated 7 Jan 2014
Article Copyright 2014 by Masoud Darvishian
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid