Tutorials

February 8, 2009

AS3 Flash Games for Beginners: Level Mechanics and Animated Backgrounds

More articles by »
Written by: Par
Tags: , , , ,
basics1_tn

Share on TwitterShare on TumblrSubmit to StumbleUponSave on DeliciousDigg ThisSubmit to reddit

Okay, so your character is designed, moving correctly, and all around pretty fun to control… but when you move off the screen, he just disappears.  So you want to make him always stay on the screen… Maybe an invisible wall that bounces him back… maybe he flips to the other side of the screen.  And your background, it’s cool and simple but you want something that has some movement. This tutorial is about making your character interact with the level correctly and look good doing it.

Like the other articles in this series, if you haven’t been keeping up here’s the previous article: More Advanced Character Movement.

And here’s the source code from the previous article: More Advanced Character Movement Source Code

Okay, let’s get started.

Step 1: Making your Character “Jump” to the Other Side of the Game Screen.

Okay so really this is simple, if you think about it, you probably know how to do this yourself and my help is entirely useless. So I’ll make it quick and the explanation simple.  We want our character, when at an x position less the the left side of the screen (0) to move to the right side of the screen (stageRef.stageWidth) and visa versa.  The same applies for y.  So, I’ve taken the liberties of slightly rearranging the Ship class (for clarity’s sake) and adding some new code to make this work.  Feel free to just copy and paste this code over your current Ship class.

package com.asgamer.basics1
{
 
	import flash.display.MovieClip;
	import flash.display.Stage;
	import com.senocular.utils.KeyObject;
	import flash.ui.Keyboard;
	import flash.events.Event;
 
	public class Ship extends MovieClip
	{
 
		private var stageRef:Stage;
		private var key:KeyObject;
		private var speed:Number = 0.5;
		private var vx:Number = 0;
		private var vy:Number = 0;
		private var friction:Number = 0.93;
		private var maxspeed:Number = 8;
 
		public function Ship(stageRef:Stage)
		{
			this.stageRef = stageRef;
			key = new KeyObject(stageRef);
 
			addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
		}
 
		public function loop(e:Event) : void
		{
			//keypresses
			if (key.isDown(Keyboard.LEFT))
				vx -= speed;
			else if (key.isDown(Keyboard.RIGHT))
				vx += speed;
			else
				vx *= friction;
 
			if (key.isDown(Keyboard.UP))
				vy -= speed;
			else if (key.isDown(Keyboard.DOWN))
				vy += speed;
			else
				vy *= friction;
 
			//update position
			x += vx;
			y += vy;
 
			//speed adjustment
			if (vx > maxspeed)
				vx = maxspeed;
			else if (vx < -maxspeed)
				vx = -maxspeed;
 
			if (vy > maxspeed)
				vy = maxspeed;
			else if (vy < -maxspeed)
				vy = -maxspeed;
 
			//ship appearance
			rotation = vx;
			scaleX = (maxspeed - Math.abs(vx))/(maxspeed*4) + 0.75;
 
			//stay inside screen
			if (x > stageRef.stageWidth)
				x = 0;
			else if (x < 0)
				x = stageRef.stageWidth;
 
			if (y > stageRef.stageHeight)
				y = 0;
			else if (y < 0)
				y = stageRef.stageHeight;
 
		}
 
	}
 
}

So the new code is everything after the stay inside screen comment. Simple code, huh? Awesome. Here’s the breakdown.

  • if (x > stageRef.stageWidth). Well simple if x is greater than stageRef.stageWidth then… do something. In our case just make x = 0.  The rest of the conditionals are the same idea. So if you understand this.  You should understand the whole thing.

Here’s the running swf.

Step 1 Revisited: Doing this Backwards…. Cool Free Bouncy Effect Included!

Alright so the above works great, but let’s do it again this time making our ship bounce back when it hits the wall.  The idea is simple, if x is greater than the stage’s width then let’s make our ship stop and bounce back from the way it came.  Can you figure it out? Well we just need to change the code after our stay inside screen comment. Here’s the difference:

			//stay inside screen
			if (x > stageRef.stageWidth)
			{
				x = stageRef.stageWidth;
				vx = -vx;
			}
			else if (x < 0)
			{
				x = 0;
				vx = -vx;
			}
 
			if (y > stageRef.stageHeight)
			{
				y = stageRef.stageHeight;
				vy = -vy;
			}
			else if (y < 0)
			{
				y = 0;
				vy = -vy;
			}

And the SWF:

And the breakdown:

  • So first we added {} around our conditionals. This is because now we need more than one statement to be excuted if the condition is met. So we have to wrap them in curly brackets to make the code work. I left this out on a big project a day ago and about pulled my hair out trying to find the error, so be careful.
  • The main difference though is instead of setting our x and y to the opposite side the screen we just force it back to the end of the screen our character is trying to leave.
  • And to make our character bounce, simple, we just negate the velocity.  Simple idea, the speed at which we hit our invisible wall is forced back in the opposite direction, it’s perfect… I mean it’s Newtonian. Which is perfect enough for me.

Step 2: Creating a Starscape/Spacedust Moving Background.

Alright, you’ll love this, at least I do. It’s great when you can do something super simple and create an awesome effect with it. This, in my opinion, is an excellent effect and requires very little programming or art to acheive it. We’re going to create a starscape, spacedust, or whatever you want to call it.  So in terms of art all we need to do is create a new movieclip, named Star, of a small white dot.  This should be easy to make, just grab the Oval Tool (O) and draw a circle. Hold shift and drag to constrain your drawing to a circle instead of oval.  Then once finished in your properties window (CTRL+F3) set the circles height and width to 6 and it’s x and y to -3.   This will make the circle directly in the center of the registration point (Your registration point is always at 0,0 from inside the MovieClip). Great, now if you want you can add a radial gradient of a 100% alpha white to 0% alpha white with the Paint Bucket Tool (K) for a different effect.

Alright take our Star movieclip and right click it and select Linkage… Export it for actionscript let’s make it’s class be com.asgamer.basics1.Star. Click OK. Below’s a shot of the Linkage setup:

Linkage setup for our Star MovieClip

Linkage setup for our Star MovieClip

If it says it doesn’t exist, it’s because it doesn’t, don’t worry click OK. Now let’s create that class so it does exist.  Just make a new Star.as class in the com/asgamer/basics1 folder.  And copy and paste this bunch of code into it.

package com.asgamer.basics1
{
 
	import flash.display.MovieClip;
	import flash.display.Stage;
	import flash.events.Event;
 
	public class Star extends MovieClip
	{
 
		private var stageRef:Stage;
		private var speed:Number;
 
		public function Star(stageRef:Stage)
		{
			this.stageRef = stageRef;
			setupStar(true);
 
			addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
		}
 
		public function setupStar(randomizeY:Boolean = false) : void
		{
			//inline conditional, looks complicated but it's not.
			y = randomizeY ? Math.random()*stageRef.stageHeight : 0;
			x = Math.random()*stageRef.stageWidth;
			alpha = Math.random();
			rotation = Math.random()*360;
			scaleX = Math.random();
			scaleY = Math.random();
 
			speed = 2 + Math.random()*2;
		}
 
		public function loop(e:Event) : void
		{
			y += speed;
 
			if (y > stageRef.stageHeight)
				setupStar();
 
		}
 
	}
}

Wow. There’s quite a bit of code there. Don’t be overwhelmed, if you’ve followed through this series from the beginning you’ll understand the most of it.

Let’s break it down:

  • We’ve got a list of imports, our Star class extends MovieClip and two class variables… stageRef which will hold our stage (we’ve used it like this before) and a speed variable.
  • setupStar(true); Here we are just calling the function setupStar and sending the Boolean true into it. Booleans are variables that store one of two things, true or false.  But why are we sending true? We will get to that.
  • public function setupStar(randomizeY:Boolean = false). So our function setupStar catches one variable randomizeY ,it’s  a boolean, that equals false? Well if inside a functions parameters we set it equal to a value then if nothing is passed into the function parameter, it will take the value it is set equal to.  In our constructor function where we passed true as randomizeY, randomizeY will take a value of true. But if we had just called setupStar() then randomizeY would be false.
  • y = randomizeY ? Math.random()*stageRef.stageHeight : 0; What is this gibberish? Well it’s a inline conditional. Much like our if else conditionals we’ve done in the past except this one runs on one line.  In english this reads:  y if randomizeY is true equals Math.random() times the stage height otherwise y equals 0.
  • Math.random(). This is a Flash function that return a random number between 0 and 1.  We can use it to make things seem uncontrolled, spontaneous, or more appropriately random.
  • Since alpha, scaleX, scaleY all are 100% of their original values at 1. We can set them to Math.random() and get a nice set of different stars.
  • speed = 2 + Math.random()*2. Creates some variety in the speed of the stars.  Then can be moving between between 2 and 4 pixels per frame.
  • if (y > stageRef.stageHeight) setupStar(); Simple… if our star moves off the stage, we setup the Star again and make it start all over.  The difference this time is we don’t pass anything into randomizeY so it defaults to false. Which means y will be set to 0.

Alright so we broke it down… One more thing to do. We have to add some Stars to the background.  So let’s open our Engine class and in the constructor function after we position ourShip let’s add this code:

			for (var i:int = 0; i < numStars; i++)
			{
				stage.addChildAt(new Star(stage), 1);
			}

First of all you’ll notice numStars in the first line of the new code.  You’ll need to add a new class variable named numStars… make it be an int of value 80.

		private var numStars:int = 80;

Let’s break down the for loop:

  • for (var i:int = 0; i < numStars; i++). Alright so a for loops through the code inside it until the conditional inside the for statement is met.  There are 3 parts to a basic for loop, initializing the variable being used. We create an int variable named i and set it to 0 (An int is a integer and is best to use when your number variable is always going to be a whole number.) Then we check if i is greater than numStars… which we set to 80… so yeah it’s not greater than numStars.  Last we tell Flash what to do at the end of each loop until our condition is met.  So this fo rloop is ran 80 times.  We could write this same code if we wrote the stage.addChildAt line 80 times but the for loop makes it a lot simplier.
  • stage.addChildAt(new Star(stage), 1); addChildAt is the same as addChild except it let’s us set where is the displayList we want to drop our DisplayObject in the second parameter. When our game is ran, our background is automatically dropped in spot 0 then ourShip is placed at spot 1.  So if we add our stars at spot 1 our ship will be used up 1 each time. We could use stage.getChildIndex(ourShip) to get the position of our ship and drop the star there.
  • new Star(stage). before when we created our ship we wrote var ourShip:Ship = new Ship(stage) and passed ourShip into addChild.  The only difference here is that we have no variable holding each of our new stars. They are simply created and dropped onto the stage.

Alright! your engine class should look like this now:

//our package... simply put, the directory structure to this file
package com.asgamer.basics1
{
	//list of our imports these are classes we need in order to
	//run our application.
	import flash.display.MovieClip;
	import flash.display.Stage;
 
	//our Engine class it extends MovieClip
	public class Engine extends MovieClip
	{
 
		private var numStars:int = 80;
		//our constructor function. This runs when an object of
		//the class is created
		public function Engine()
		{
			//create an object of our ship from the Ship class
			var ourShip:Ship = new Ship(stage);
			//add it to the display list
			stage.addChild(ourShip);
 
			ourShip.x = stage.stageWidth / 2;
			ourShip.y = stage.stageHeight / 2;
 
			for (var i:int = 0; i < numStars; i++)
			{
				stage.addChildAt(new Star(stage), 1); //OR stage.addChildAt(new Star(stage), stage.getChildIndex(ourShip));
			}
 
		}
 
	}
 
}

And your SWF:

Pretty awesome huh? We have a plenty of tertiary animation with our moving background.  Alright that’s all for this part… join the rss and get updates when the next tutorial is released because next time we are learning to shoot bullets with timeouts using AS3 Timers.
Subscribe to the RSS Feed

here’s the source code:
Level Mechanics and Animated Backgrounds Source Code Zip Archive

Continue on to the next tutorial in the series:
Firing Weapons with Delay

Similar Posts:


Share on TwitterShare on TumblrSubmit to StumbleUponSave on DeliciousDigg ThisSubmit to reddit


About the Author

Par
Hey! Don't be surprised, I'm a flash developer. While Flash is definitely one of my favorite languages to develop in, most of all I just like making games. If you want to see the games I've developed so far head over to my website, DigitallyBold, in the link below. If you want to know more about what I'm working on now and in the future be sure to follow me on twitter.




33 Comments


  1. bresson

    great tuts. building my own game based on these tuts. do have a question – how can i make the stars responsive to the speed of the ship? for instance, if the up key is pressed, i want the stars to fly by the ship faster. thanks!!!


  2. Par

    You’d need to make the each of the stars get their speed from a variable that is related to the ship. So you could pass the ship variable into each of the stars and then add ship.vy to the speed of each of the stars.


  3. bresson

    Thank you for responding. How can I reference the Star instance in Engine.as? My thinking is to pass ship.vy into the Engine class through a getVY function and then reference it with _starInstance.setVY but I’m a bit lost on how to reference the star instances. Thank again -


  4. Par

    inside the for loop

    stage.addChildAt(new Star(stage, ourShip), 1);

    Now inside the Star class

    public function Star(stageRef:Stage, ship:Ship)
    {
    this.ship = ship; // make it a class variable
    this.stageRef = stageRef;
    setupStar(true);

    addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
    }

    Then in the loop function

    y += speed + ship.vy;


  5. bresson

    thanks – the stars are now responsive to ship speed. i do notice that performance drops significantly – can reach moments when the stars and ship just freeze. otherwise it works great. thanks again.


  6. Par

    yeah, it’s definitely not the most optimal way of doing this but it does work.


  7. Jonhatan

    I get the following error:

    ArgumentError: Error #1063: Argument count mismatch on com.asgamer.basics1::Star$iinit(). Expected 1, got 0.
    at flash.display::Sprite/flash.display:Sprite::constructChildren()
    at flash.display::Sprite$iinit()
    at flash.display::MovieClip$iinit()
    at com.asgamer.basics1::Engine$iinit()


  8. so do i get the #1063 error!


  9. Rish

    Im getting 1063 error! Spent hours trying to fix it, but doesnt work! help!


  10. DinoLando

    Code works fine for me.. using Flash CS4.

    @Jonhatan,Adrian,Rish:
    Make sure you keep the file structure inside the source code zip intact. So create a new folder and unzip there. Open basics1.fla and run. Hopefully that helps :)


  11. memyselfandmetoo

    I am trying to sort of replicate your edge of the stage effect. My movieclip is 6x wider than the stage – I am using

    var scrollSpeed=20;
    stage.addEventListener(Event.ENTER_FRAME, pan);
    function pan(evt:Event):void {
    MovieClip(root).gallery_mc.x -= (stage.mouseX – (stage.stageWidth/2)) / scrollSpeed;
    }

    to scroll my clip – which is working great. I can’t find anything that tells me how to stop the clip when the edges reach the edges of the stage. My clip just scrolls off into infinity (on either side) unless the mouse is used to bring it back by going to the opposite edge of the stage. It is probably something simple and maybe I can no longer see the forest for the trees but I have been searching and experimenting for 3 days and cannot figure it out. Appreciate any guidance/help you might be able to offer! I think you tutorial is very well written!


  12. memyselfandmetoo

    Disregard previous – I finally figured it out. Just as I suspected – easy fix after I left it alone for awhile and came back to it.


  13. How do I use the same Math.random output for 2 different variables? Basically I don’t like how X and Y are random independent of each other – some stars are extremely squished. They should both be using the same value so the stars are kept circular. I tried a few different things but all are giving me error (scaleY + scaleX = Math.random, or scaleY, scaleX = ..etc.)

    Thanks for the great tutorial!


  14. David G

    I was getting the #1063 errors, too, until I realized I left a copy of the Star movie clip on the stage. Once I deleted the clip (so that the stage is completely empty) the error was fixed. Hope this helps other who have the same problem.

    And thanks for the great tutorials! My Flash Actionscript skills have been very out of date and these are helping me get caught up finally.


  15. aceofspadez619

    I’m loving this tutorial! Of all the Flash Game Tuts out there, I find it to be the right balance of simplicity for beginners, but complex enough to make a nice game and really get a taste of how to code properly in AS3. Other stuff out there is either TOO simple (how to make Flash Pong, yeah!!, poorly designed/coded (put your action script on each frame, yeah!!), or assuming you are coming over from a coding background and know C# already.

    I’m a 1st timer in game dev and coding, but fairly familiar with Flash and found that this taught the concepts very well, showed how to utilize the IDE when appropriate and how to easily link and store code in external files. Great job!

    Okay, to my (really simple) question:
    On the create moving stars step of the tut, you used the addChildAt method and needed to specify a number (1) for the second param when placing the stars. I can look up more about what a display list is and how it works, but what I don’t get is why you continued to add the stars to ‘spot 1′ when you explained that the background is at ‘spot 0′ and the ship at ‘spot 1′. Does everything need to be at 1 for simplicity’s sake (I haven’t gotten to the enemyships yet, so maybe I’ll see there.

    Thanks for ‘breaking it down’.


  16. aceofspadez619

    …adding to my previous post.

    In some ways answered my own question. I forgot that I had added the background to the stage at runtime as you had suggested in Step one, so when I copied your code into my Engine.as file, I lost the background! I had forgot what I had done so at first I tried this (I have a Background.as file with an empty constructor function, which i’m guessing is all that’s needed since the background does nothing):

    //add background to the stage
    stage.addChild(new Background());

    which brought back my background, but (as I’m sure you know) no stars!! I guessed they were covered up, so I used the addChildAt to set the level to 0:

    //add background to the stage
    stage.addChildAt(new Background(), 0);

    and my stars are back! So I’m guessing this displayList number corresponds to the “level” of the object, similar to the layer list on the timeline (objects in layers above cover up objects below)?


  17. emb03

    @memyselfandmetoo

    I am having this issue. You said it was easy, but how did you get the background to stop panning at the edge of the stage?

    Thanks!


  18. johno

    Hi, im trying to get the stars to go from right to left iv managed to do this fairly easily but once the first wave appears no more come i have managed to make the stars go left to right fine but cant seem to get them to carry on producing from the right to left any ideas?


  19. MrKrackham

    @johno

    I tried doing that too. Just switch all occurrences of WidthHeight, xy and randomizeYrandomizeX. Seemed to work fine :)

    package com.asgamer.basics1
    {
    import flash.display.MovieClip;
    import flash.display.Stage;
    import flash.events.Event;

    public class Star extends MovieClip
    {
    private var stageRef:Stage;
    private var speed:Number;

    public function Star(stageRef:Stage)
    {
    this.stageRef = stageRef;
    setupStar(true);

    addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
    }

    public function setupStar(randomizeX:Boolean = false) : void
    {
    //inline conditional, looks complicated but it’s not.
    x = randomizeX ? Math.random()*stageRef.stageWidth : 0;
    y = Math.random()*stageRef.stageHeight;
    alpha = Math.random();
    rotation = Math.random()*360;
    scaleY = Math.random();
    scaleX = Math.random();

    speed = 2 + Math.random()*2;
    }

    public function loop(e:Event) : void
    {
    x += speed;

    if (x > stageRef.stageWidth)
    setupStar();
    }
    }
    }


  20. Ollie

    Yes, I have the same problem as johno. I can’t get the stars to be reproduced when having them scroll horizontally.


  21. mikehart

    I’m getting a strange error when I try to compile. its on the line in the for loop

    1136:Incorrect number of arguments. Expected 0.


  22. Unsafe Creations

    In case anyone was having touble with johno’s problem…(Just posting this because it took me like 30 minutes to figure out…I might just be dumb, though)

    If you want the Stars to go from left to right, use MrKrackham’s example above. If you want them to go from right to left, and your stars aren’t respawning, and if you’re an AS noob like me, here’s the problems.

    public function setupLine(randomizeX:Boolean = false) : void
    {
    //inline conditional, looks complicated but it’s not.
    x = randomizeX ? Math.random()*stageRef.stageWidth : 750; **has to be 750, this is where they respawn**
    y = Math.random()*stageRef.stageHeight;
    alpha = Math.random();
    scaleX = Math.random();
    scaleY = Math.random();

    speed = 2 + Math.random()*2;
    }

    public function loop(e:Event) : void
    {
    x -= speed; ****has to be a minus sign, so they go left****

    if (x < 0) ****this is where it got. don’t know why. it just did.****
    setupLine();

    }

    }
    }


  23. cnicoletti

    First let me start off by saying how cool this is!

    Anyway, I have setup the stars and they are flowing rather well.

    My question is, how do you get them to stop?

    removeChild? If so, How does that work with multiple stars on stage at once?


  24. Here, Daniël here.
    I have the same problem as mikehart, getting an 1136 error..
    Even after I compared all the codes written by me with the final .zip of this tut, I cant find it.

    The only thing I have “customized”, is the player code to get a smaller boundary for the ship to fly in.
    Its really weird and frustrating to still get the message
    “1136: Incorrect number of arguments. Expected 0.”

    Can anybody help me?


  25. Gary

    Hi,

    This is a great tutorial. I was wondering if the code for the Starfield background can be modified to look like a 1st person point of view? In otherwords, we are traveling towards the stars and the stars are zooming past us?

    This is terrific. Thanks very much.

    Best,
    Gary


  26. and another one finished, thx 4 the wisdom ^^ and thx for aceofspadez619, i added the background while running, so i had to change the addChildAt-level for adding stars to 2 and all was fine…

    peace
    jesta (turns the page)


  27. Robbert Bruggeman

    It’s a pretty good tutorial, for sure.

    However, about the bouncing-on-the-edges-of-the-screen part, I’ve used this instead:

    And found that it works a bit better. Now the values here are dependant on the stage size, but with the code from the tutorial, half of the ship goes out of the screen before it bounces.

    //STAY IN THE SCREEN
    if ( x > 480 )
    {
    vx = -vx;
    }

    else if ( x 370 )
    {
    vy = -vy;
    }

    else if ( y < 30 )
    {
    vy = -vy;
    }


  28. nevena

    Hi!:)
    Thank you so much for this tutorial, it’s really great. Rarely there is anything similar, which explains everything so well.
    In this line of thought… I have two questions, I couldn’t find a solution to (what I tried didn’t work).
    1. How can I randomise the colour, hue or saturation of the stars?
    2. I made a background where the ship is within a boundary which is weirdly shaped (one side is flat, the other curved). I was wondering how can I create a frame where the ship moves inside only?
    Thank you again!
    n


  29. Tanner

    Mine is working, but alil-bit off how it’s supposed to be. Finally I got it to work, but once the game starts 1 star is created, it falls down until out of view. Once it leaves the view all the rest of 79 stars are created and it works normally?

    I think its because i dont have “setupStar()” in my “Star()” function, but every time i add it and try to run it i get: TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at Star/setupStar()
    at Star()
    at Engine()

    any suggestions?


  30. Tristan

    Hello,

    This is a great tutorial into knowing the basics.
    I have been following this up to now.
    I added the background with the help of actionscript like you mentioned at the first lesson. However, I can’t see the animated stars now because the background is overlapping it. I tried to fix it, but eventually I removed the actionscript for the background, and just placed the movieclip in the stage manually.

    question 1 : I would like to know how to get the background ‘with’ actionscript, and how to properly layer it.

    question 2 : I tried to make the stars move according to my ship speed. I did what you told to get that, but it still doesn’t work. it gives this error :
    1178: Attempted access of inaccessible property vy through a reference with static type com.asgamer.basics.Schip1

    could someone help me with these two questions ?
    Thanks in advance,
    Tristan.


  31. Bram

    How to remove the stars in the Main class?

    thanks


  32. Tristan,

    Your answer to question 1 can be found in the earlier tutorials in this series, and some of the first comments on this thread. I believe it was the first or second tutorial, in which he mentions that you could also easily call up the background with AS only. As far as question2, i think you might have miss-spelled Ship (you have schip1). Pay closer attention to spelling and Capitalization, everywhere Ship is referenced (be sure to see how it is named when exported in the library as well). I hope this helps you out.

    To the author of this tutorial: MANY KUDOS!


  33. Loren Helgeson

    Thank you very much for the tutorial. I had the friction part down, but was banging my head against the wall for several hours trying to figure out the “bounce back” function.

    It’s so simple in hindsight.



Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">


Advertisement