Page 1 of 1

Tutorial: Make a space background in AS3

PostPosted: July 21st, 2013, 12:18 pm
by Blablob
Okay, so, one of the more unanimously acclaimed aspects of my game Beat It was the background design. I've gone ahead and improved the look of this design in my new game, which I hope to release in the coming months. With that said, I'd like to provide a simple walkthrough for anyone who wants to create a space background of their own, but don't know how to do so.

The code is actually very simple, but like anything in programming, it can be done a million ways. This is the look we're aiming for: http://www.newgrounds.com/dump/item/521 ... 6116469a9c

By the way, this tutorial is designed with absolute beginners in mind. If you're acquainted with the basics of AS3, everything is probably going to sound super redundant to you.

Anyway's, let's begin.

To start off, you need 2 classes. The first is just where you plan on adding the background (I put mine in my Preloader class...you can just use your Main class.) The second class will be used for actually designing the background. To add a new class, just go to File < New < AS3 Document. I use FlashDevelop but I think the process is the same in Flash. Anyways, name it Background or something to that effect.

Now I'm going to assume you know the proper structure of a class. That is:
package
{
.....public class Background
.....{
..........public function Background()
..........{
..........}
.....}
}


Ignoring the periods of course. Anyways, replace the line public class Background with public class Background extends Sprite. Basically, the entire class is treated as something we call a Sprite. That is, we can draw basic objects, add them to our game, and interact with them in a number of ways.

Now, if you checked out the link above you saw a bunch of different stars flying around (500 to be exact), but for our Background class, we treat it as if we're only adding 1 star to the game. This is because in our Main class, where we actually add the background, we can use a loop to add the Background as many times as we like. More on that later, of course. Just keep in mind that as we design our Background class, we're treating it as if there's only 1 star.

We're going to go ahead and add three variables to our Background class. They should go right after the Public class Background line (after the curly brace, of course). Add these three lines of code:
private var star:Sprite = new Sprite;
private var size:Number;
private var speed:Number = .5;


"star" is what I was talking about earlier. It's the one star we need in our Background class, and we can add many of them in our Main class.

"size" is the size of the star, which the game will determine randomly every time a star is added.

"speed" is not actually the speed of the star. It's the default speed of the star which will increase or decrease based on size. Bigger stars give the impression that they're closer, so they should move faster.

By the way, at the top of the class, right above public Class Background extends Sprite, we need to add some lines of code. Just two this time. Here they are:
import flash.display.Sprite;
import flash.events.Event;


The ends of these lines is what matters. "Sprite" lets us access Sprite objects in the class, and "Event" lets us use basic events like moving.

Right now your code should look something like this (without periods):
package
{
.....import flash.display.Sprite;
.....import flash.events.Event;

.....public class Background extends Sprite
.....{
..........private var star:Sprite = new Sprite;
..........private var size:Number;
..........public static var speed:Number = .5;

..........public function Background()
..........{
................//THIS IS WHERE WE'LL CODE NEXT.
..........}
.....}
}


See that line "THIS IS WHERE WE'LL CODE NEXT"? Can you guess what that means?

In this function, we need to do 4 things: Set the variable "size" to be random, design the star, add the star, and add an event listener that moves the star.

First off, the "size" variable. In order to make something random, you need to set it to Math.random() and then multiply it by the highest possible number you want to have. Go ahead and add the line size = Math.random() * 2.5;
This will make sure that "size" can only be a number from 0 to 2.5, including decimals.

Next we'll create our star and add it to the class. This only takes 3 lines of code and I will explain them one at a time.

star.graphics.beginFill(0xE8E8E8);
star.graphics.drawCircle(0, 0, size);
addChild(star);


For the first 2 lines of code, you'll notice the "graphics" property. Obviously, this is what we use to design the graphics of the star. "beginFill" is basically another way of saying "color", but it takes 2 parameters. A parameter is just a way to identify something. In the case of beginFill, its 2 parameters are color and alpha. But in our case, the only one that matters is color because we don't need to mess with the alpha (alpha is visibility - everything is fully visible by default). Also, since alpha already has a default value, we don't need to include it in the parameter.

Also, colors in AS3 are defined through hexadecimal. You may have to look up another tutorial for that one. Here's the basic premise: 0x000000 is black, 0xFFFFFF is white, and everything else falls in between.

"drawCircle" takes 3 parameters, and does exactly what it sounds like. Its first 2 parameters are its x and y positions relative to its registration point (basically its registration point in reverse). I use 0 for both because the registration point for what we're doing is negligible. The third parameter, the radius, is where "size" comes in. Remember, "size" is a random number between 0 and 2.5. So if we set the radius to "size" instead of just some number, then the radius of the star will be different every time we add it.

"addChild" is the function used to add an object to the class. Its parameter is whatever object you want to add. So in our case, it would be the star.

So the star is set up, graphically. Next we need to add this line of code: addEventListener(Event.ENTER_FRAME, move)

This will allow us to work with a function, title "move", which is called every frame. (Your code runs x frames a second...In my case, 30 frames a second.)

And that's it for this function!Your code should look something like this now:
package
{
.....import flash.display.Sprite;
.....import flash.events.Event;

.....public class Background extends Sprite
.....{
..........private var star:Sprite = new Sprite;
..........private var size:Number;
..........public static var speed:Number = .5;

..........public function Background()
..........{
...............size = Math.random() * 2.5;

...............star.graphics.beginFill(0xE8E8E8);
...............star.graphics.drawCircle(0, 0, size);
...............addChild(star);

...............addEventListener(Event.ENTER_FRAME, move);
..........}
.....}
}


Does everything make sense so far? I hope so. But now we have to create a new function. If you tested your code now, you would get an error saying that "move" is undefined. So let's define it. Under your Background function, under all the code we just added, add this:
private function move(e:Event):void
{
//THIS IS WHERE WE'LL CODE NEXT.
}


Our parameter, e:Event, means that our function will be treated as an Event. Specifically, an ENTER_FRAME Event. (Runs every frame; remember that?) void means that we're not returning anything (Big words, big words! They hurt!) What now? Well, in this function, we need to do 2 things: Move the stars, and check when they're offscreen. When they move offscreen, we're just going to bump them up to the top of the screen. So first things first, add these lines of code:
this.x -= (speed * size) / 2;
this.y += (speed * size) / 2;


"this" refers to the class. The first thing you should notice is that we're moving the class down and left every frame. Is it a problem that we're moving the entire class as opposed to just the star itself? It can be depending on what you're doing, but in our case it isn't. Moving the class moves all the objects in that class, but since the only object we have is the star, it doesn't matter. For our intents and purposes, "this" and "star" are the same thing.

So, the x and y speed are defined by a certain value that you get when you multiply the speed (0.5) and the size (between 0 and 2.5) of the star. Then we divide by 2 just to slow it down a bit more. So now your star can move. Unfortunately, when it leaves the screen, it doesn't come back. We have to fix that.

Below what we just added, add this:

if (this.x < -20 || this.y > stage.stageHeight+20)
{
.....this.y = 0;
.....this.x = Math.random() * (stage.stageWidth*2);
}


Let's examine this line by line. The first line starts with an "if" statement, which is a painfully simple concept to learn: If the condition is met, do whatever is in the code. In our case, the condition is whether the star leaves the screen. Since the star is moving down and left, we check if the star reaches the far-left of the screen (this.x < -20) or the bottom of the screen (this.y > stage.stageHeight+20). The "||" literally means "OR" so that you may have multiple conditions and so that any of them can be met. Also stage.stageHeight is exactly what it sounds like.

So what happens when we meet one of these conditions? Well, first things first, we should bump it back to the top of the screen with this.y = 0;
But if we want to maintain the illusion that this is all randomized (even if it isn't 100% necessary), we should go ahead and randomize the x coordinate. You have to be careful with this because it's easy enough to write
this.x = Math.random()*stage.stageWidth and have the star pop up somewhere we could see. But remember: as well as moving down, our stars are moving to the left as well, and if the furthest point your star can spawn is in the top-right corner, then it can never touch the lower-right of your stage. Ever. This is especially noticeable when you have 500 stars flying around and one area that's completely blank.
To fix this you just need to increase the maximum range that your number can end up being. In my case I simply multiplied the stageWidth by 2.

Alright, that about does it for this class. This is what your final code for the Background class should resemble:
package
{
.....import flash.display.Sprite;
.....import flash.events.Event;

.....public class Background extends Sprite
.....{
..........private var star:Sprite = new Sprite;
..........private var size:Number;
..........public static var speed:Number = .5;

..........public function Background()
..........{
...............size = Math.random() * 2.5;

...............star.graphics.beginFill(0xE8E8E8);
...............star.graphics.drawCircle(0, 0, size);
...............addChild(star);

...............addEventListener(Event.ENTER_FRAME, move);
..........}

..........private function move(e:Event):void
..........{

...............this.x -= (speed * size) / 2;
...............this.y += (speed * size) / 2;

...............if (this.x < -20 || this.y > stage.stageHeight+20)
...............{
....................this.y = 0;
....................this.x = Math.random() * (stage.stageWidth*2);
...............}
..........}
.....}

}


But if you test your code, nothing happens! Well, now is where the magic happens. We need to go back to the Main class, and in the main function we're going to use a "for" loop in order to generate 500 stars on the stage. A "for" loop will execute some code over and over as long as a condition is met. Similar to an "if", except that it's more suited towards looping code. It takes 3 parameters: A counter, a condition, and an action. It looks like this (and you should add this):
for (var i:int = 0; i < 500; i++)
{
.....//MORE CODE TO ADD
}


The counter is an integer called i that starts at 0; the condition is that i must be less than 500; the action is that i counts up by 1 every time the code executes. Long story short, this code will execute 500 times. What code will we execute, you ask? Time to add the background.

Right in that for loop (and I promise this is the last code you'll have to write), add these lines:
var bg:Background = new Background;
bg.x = Math.random() * (stage.stageWidth*2);
bg.y = Math.random() * stage.stageHeight;
addChild(bg);


Basically, every time the code runs, it will create a new variable called "bg", which if you noticed is just the Background class, it sets the background location randomly, and it adds the background to stage.

Try your project now? Does it work?
(Yes, it does. ;) )

Hopefully if you're new to AS3 and you wanted to create a background effect such as this, I've been helpful to you. Your job now is to improve this background however you see fit, and use what you know to create some unique backgrounds of your own.

I told you it was simple.