Author Topic: [Tutorial] Snow in XNA 4.0 (C#)  (Read 5333 times)

0 Members and 1 Guest are viewing this topic.

Offline BlakPilar

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 734
  • Rating: +44/-1
    • View Profile
[Tutorial] Snow in XNA 4.0 (C#)
« on: September 10, 2011, 04:32:06 pm »
I'm writing a game in XNA 4.0 (my first huge computer game for both XNA and C#), and one of the things I wanted to do for the main menu was add a snow effect because the game is called Tundra and a tundra is a cold and snowy place and, well, I think you get the idea. I thought it looked pretty cool when it was done, and figured maybe the function I created could be used for something else by somebody else, so here it is!

First, for ease, what I did was create two public properties to be equal to the width and height of the game window. Basically, it looked like this:
Code: [Select]
private int w, h;
public int Width { get { return this.w; } }
public int Height { get { return this.h; } }

protected override void Initialize()
{
    this.w = this.Window.ClientBounds.Width;
    this.h = this.Window.ClientBounds.Height;

    //There's more code in here, just not needed for this tutorial
}
Just try to remember to not assign to h or w ;)

After that, I made some variables all dealing with the snow. I made them private because I'm more than likely not going to use them specifically outside of my method to draw the snow, but you can feel free to make them public.
Code: [Select]
private Point[] snow = new Point[225];  //You can increase/decrease this number depending on the density you want
private bool isSnowing = false;           //I only set this to true (so far) in the main menu
private Texture2D snowTexture;           //Our texture for each snow particle. I'll attach mine, though it's very simple
private Point quitPoint;                       //The point at which we need to recycle the snow particle
private Point startPoint;                     //The point where the snow particle gets recycled to
private Random random;                    //Will be used for generating new random numbers
For quitPoint and startPoint, we'll only be using their Y-coordinate.

Now, go to the LoadContent method. Here we'll load the snow's texture as well as the quit and start points. If you do these points in Initialize, you'll get a NullReference error because XNA calls LoadContent after Initialize (in case you didn't know).
Code: [Select]
protected override void LoadContent()
{
    //Load our texture. I placed it in a folder called "Textures," if you don't put it in any folder, don't use "Textures\\"
    //or if you use a different folder, replaces Textures with its name.
    this.snowTexture = this.Content.Load<Texture2D>("Textures\\snow");

    //Set the snow's quit point. It's the bottom of the screen plus the texture's height so it looks like the snow goes completely off screen
    this.quitPoint = new Point(0,
        this.Height + this.snowTexture.Height);

    //Set the snow's start point. It's the top of the screen minus the texture's height so it looks like it comes from somewhere, rather than appearing
    this.startPoint = new Point(0,
        0 - this.snowTexture.Height);
}

If you want to be exactly like me, somewhere in your code, make a method called DrawSnow that doesn't take any parameters. We'll come back to that in a second. Head on over to your draw function and call DrawSnow between where you begin and end the sprite batch. Also, change the clear color from CornFlowerBlue to White.
Spoiler For Clarification:
Code: [Select]
public void DrawSnow()
{
}

protected override void Draw()
{
    GraphicsDevice.Clear(Color.White);

    this.spriteBatch.Begin();

    this.DrawSnow();

    base.Draw(gameTime);

    //I was told sometime that putting this after base.Draw(...) was better
    this.spriteBatch.End();
}

Now for the meat and potatoes of this tutorial!

I'm just going to copy and paste my code, but I'm adding comments that will tell you what's going on.
Code: [Select]
public void DrawSnow()
{
    //If it's not supposed to be snowing, exit
    if (!isSnowing)
        return;

    //This will be used as the index within our snow array
    int i;

    //NOTE: The following conditional is not exactly the best "initializer."
    //If snow has not been initialized
    if (this.snow[0] == new Point(0, 0))
    {
        //Make the random a new random
        this.random = new Random();

        //For every snow particle within our snow array,
        for (i = 0; i < this.snow.Length; i++)
            //Give it a new, random x and y. This will give the illusion that it was already snowing
            //and won't cluster the particles
            this.snow[i] = new Point(
                (random.Next(0, (this.Width - this.snowTexture.Width))),
                (random.Next(0, (this.Height))));
    }

    //Make the random a new random (again, if just starting)
    this.random = new Random();

    //Go back to the beginning of the snow array
    i = 0;

    //Begin displaying the snow
    foreach (Point snowPnt in this.snow)
    {
        //Get the exact rectangle for the snow particle
        Rectangle snowParticle = new Rectangle(
            snowPnt.X, snowPnt.Y, this.snowTexture.Width, this.snowTexture.Height);

        //Draw the snow particle (change white if you want any kind of tinting)
        this.spriteBatch.Draw(this.snowTexture, snowParticle, Color.White);

        //Make the current particle go down, but randomize it for a staggering snow
        this.snow[i].Y += random.Next(0, 5);

        //Make sure the point's location is not below quit point's
        if (this.snow[i].Y >= this.quitPoint.Y)
            //If it is, give it a random X value, and the starting point variable's Y value
            this.snow[i] = new Point(
                (random.Next(0, (this.Width - this.snowTexture.Width))),
                this.startPoint.Y);

        //Increment our position in the array ("go to the next snow particle")
        i++;
    }
}

Voila! You now have snow in your program! If you need something explained more, feel free to ask. If you have imporvements, say so and I'll add them. If you want to use this somewhere (not necessarily in C#/XNA), feel free to go ahead and do so! In this, I only change the Y position of the snow particles. If you want to do something with the X to make it more realistic, go right ahead.

I've attached a gif of what it looks like in Tundra ;) but thanks for your time :)

P.S. - If this is in the wrong category, please move it to the appropriate one. I've had problems with that in the past lol
« Last Edit: September 10, 2011, 04:56:41 pm by BlakPilar »

Offline DJ Omnimaga

  • Clacualters are teh gr33t
  • CoT Emeritus
  • LV15 Omnimagician (Next: --)
  • *
  • Posts: 55943
  • Rating: +3154/-232
  • CodeWalrus founder & retired Omnimaga founder
    • View Profile
    • Dream of Omnimaga Music
Re: [Tutorial] Snow in XNA 4.0 (C#)
« Reply #1 on: October 17, 2011, 03:03:39 am »
This looks nice. By the way does Xbox 360 versions of XNA games requires heavy changes to the code?

Offline Juju

  • Incredibly sexy mare
  • Coder Of Tomorrow
  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 5730
  • Rating: +500/-19
  • Weird programmer
    • View Profile
    • juju2143's shed
Re: [Tutorial] Snow in XNA 4.0 (C#)
« Reply #2 on: October 17, 2011, 03:30:36 am »
Looks pretty nice.

This looks nice. By the way does Xbox 360 versions of XNA games requires heavy changes to the code?
No, don't think so.

Remember the day the walrus started to fly...

I finally cleared my sig after 4 years you're happy now?
THEGAME
This signature is ridiculously large you've been warned.

The cute mare that used to be in my avatar is Yuki Kagayaki, you can follow her on Facebook and Tumblr.

Offline BlakPilar

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 734
  • Rating: +44/-1
    • View Profile
Re: [Tutorial] Snow in XNA 4.0 (C#)
« Reply #3 on: October 17, 2011, 07:08:00 am »
I haven't tried it, but AFAIK, no. If you make a Windows game, you can have Visual Studio make a copy for the 360 for you (and Windows Phone).

But thanks! :D
« Last Edit: October 17, 2011, 07:08:45 am by BlakPilar »

Offline DJ Omnimaga

  • Clacualters are teh gr33t
  • CoT Emeritus
  • LV15 Omnimagician (Next: --)
  • *
  • Posts: 55943
  • Rating: +3154/-232
  • CodeWalrus founder & retired Omnimaga founder
    • View Profile
    • Dream of Omnimaga Music
Re: [Tutorial] Snow in XNA 4.0 (C#)
« Reply #4 on: October 17, 2011, 03:41:46 pm »
Ah ok, that's good I guess.