Creating a Asteroids Flash Game Part 10: Changing Vector Images to Bitmaps

This article is about loading your own graphics into your asteroids game created in the asteroids tutorial.

Adding images to what we already have is actually simpler than creating the vector drawings.

There are two ways to do this – embed the image, or use a loader to load externally.
I personally like loading them externally on run time, with filenames stored in an external xml for larger projects.

But since the last asteroids article was for Kongregate, we’ll have to only end up with one packaged swf, to be able to upload it to their servers.

Since we’re doing the ’embed’ method of adding textures, we’ll just embed them all at the top of every class we want to apply the texture to.

Loading and Using a Space Background Bitmap

So first, we’ll add a background. NASA seems like a good place to get a ‘space’ background, so I found one I liked at www.nasaimages.org.

Next, I used a photo editing program (photoshop, but gimp or even paint works ok for this) to get rid of the stuff around the image, and to resize and crop the image down to 640×480 (the size of our stage in project settings).

Now create a new folder under your ‘src’ folder called ‘resources’, and a folder under that called ‘images’ (or where ever you want to place images, it’s just personal preference).

Save your edited image under here, then open up your ‘Game’ class. Under all your variable declarations, before your constructor (first function) enter in this code:

Excerpt for Game.as

[Embed(source = 'resources/images/background_space.jpg')]
private var tex_background:Class;
private var background:Bitmap;

Line 1: This is the embed tag, used to point to what you want to embed in your swf (images, sounds, ect).
Line 2: This is the class that will be assigned your embedded image. It has to be a class, and basically just has to be beneath your ‘Embed’ tag.
Line 3: This is what we will use as our actual image when rendering in the game. This will be instantiated in the constructor with the type of the embedded class (Exp: background = new tex_background();).

Now, we just need to instantiate our bitmap, which we’ll do at the end of our constructor function / ‘function Game()’.

Excerpt for Game.as

background = new tex_background();

Thats all you need to load a bitmap into your program! Now all we have to do is render it to be able to see it:

Excerpt for Game.as

//this method also works, but the draw function is supposed to be slower than using copyPixels, so I use it when I have the choice
//Renderer.draw(background, new Matrix(1, 0, 0, 1, 0 , 0 ));
//call to render out our background
Renderer.copyPixels(background.bitmapData, new Rectangle(0, 0, background.width, background.height), new Point(0, 0));

We’ll want to insert this into our ‘Render’ function after:
‘Renderer.fillRect(new Rectangle(0, 0, Renderer.width, Renderer.height), 0x000000);’
and before:
‘if (state == PLAYING || state == PAUSED)’

So basically just after the start or the ‘Render’ function, after re-clearing the screen. You could even save a step and comment out clearing the background to black, since right afterwards you write over it with your bitmap background.

Next we’ll do the same for the ship and asteroids.

Creating Bitmaps For the Ship

We could either create these in a paint program, in a vector art program like Flash IDE or Illustrator, or just cut up images out there to use in the game. I don’t reccomend using some elses images in your game, but to create quick tests, or personal projects, you can find quite a few out there that you can cut apart and create things you need.

So I’ll look for a spaceship on google images and istockphoto, and for the asteroids on NASA’s site, as well as the other two, to find a couple different asteroid types.

I decided to look for a stargate ship, and found an overhead view of one at ‘http://www.sharenator.com/Stargate/Stargate_Daedalus_Final_by_Mallacore-118561.html’.
I then imported this into photoshop, cropped just the top view, rotated it 90 degrees clockwise, used the magic eraser to remove the background, and resized down to my new ship size of 20width x 30height, and saved as a png to preserve transparency.
I resized the image because the ship was too small to really see with my background well. I also added a white stroke (outline) to the ship to make it easier to see.

Because of the new size, I also had to move my level text on screen down a little bit, as well as change the width/height and position when creating the ship in the game constructor.

Now open up your ‘Ship’ class, and add the image in the same was as you had in the “Game” class, and this time it’s even easier since you only need to change it in the constructor.
Comment out, or remove the code that draws the vector image, and replace with the bitmap code, as shown below:

Excerpt for Ship.as

public class Ship extends GameSprite
	{
		private var rotate_amount:int;
		
		public var speed:Point;
		private var speed_multi:Number = .5;
		private var friction:Number = .95;
		
		public var ship_death_time:Number;
		
		[Embed(source = '../resources/images/ship.png')]
		private var tex_ship:Class;
		
		public function Ship(x:int, y:int, width:int, height:int)
		{
			super(x, y, width, height);
			image_sprite = new Sprite();
			//image_sprite.graphics.lineStyle(2, 0xFFFFFF);
			rotate_amount = 15;
			speed =  new Point(0, 0);
			rotate_offset = new Point(width / 2, height / 2);
			
			var temp_bitmap:Bitmap = new tex_ship();
			image_sprite.addChild(temp_bitmap);
			
			//create the ship drawing
			/*image_sprite.graphics.moveTo(0, height);
			image_sprite.graphics.lineTo(width / 2, 0);
			image_sprite.graphics.lineTo(width, height);
			
			//draw the line across
			image_sprite.graphics.moveTo((7*height/8 -height)/(-height/(width/2)), 7*height/8 );
			image_sprite.graphics.lineTo((7 * height / 8 -height) / (height / (width / 2)) + width, 7 * height / 8);
			*/
			ship_death_time = 0;
		}

Line 20: This is where we embed the ship bitmap into the swf(‘../’ is used to go up one folder).

Line 21: The class we will store the loaded image in

Line 32: The temporary bitmap to put the image into.

Line 33: Since our sprite doesn’t have methods to just draw directly on it, we add the bitmap as a child to out ships sprite image.

Creating Bitmaps For the Asteroids

For this, I’ll just find 2 generic asteroid images online and embed them. I’ll need them to be roughly square shapes in order for the collision detection code to remain the same.

Excerpt for Asteroid.as

		[Embed(source = '../resources/images/asteroid1.png')]
		private var tex_asteroid1:Class;
		
		[Embed(source = '../resources/images/asteroid2.png')]
		private var tex_asteroid2:Class;
		
		public function Asteroid(x:int, y:int, size:Number, direction:Number, type:int)
		{
			super(x, y, Sizes[size], Sizes[size], 0);
			this.size = size;
			this.type = type;
			this.direction = direction = Directions[direction];
			this.speed = new Point( -Speeds[size] * Math.cos(direction), -Speeds[size] * Math.sin(direction));
			trace("speed asteroid, x, y = "+(-Speeds[size] * Math.cos(direction))+", "+(-Speeds[size] * Math.sin(direction))+", direction = "+direction );
			
			image_sprite = new Sprite();
			this.type = type;
			
			if (type == 0)
			{
				var temp_bitmap:Bitmap = new tex_asteroid1();
				temp_bitmap.width = temp_bitmap.height = Sizes[size];
				image_sprite.addChild(temp_bitmap);
				
			}
			else if (type == 1)
			{
				var temp_bitmap2:Bitmap = new tex_asteroid2();
				temp_bitmap2.width = temp_bitmap2.height = Sizes[size];
				image_sprite.addChild(temp_bitmap2);			
			}
			trace("size = "+Sizes[size]);
		}

Line 25: Here we are embedding our image like we did previously for our ship.

Line 26: And this is the class again that will have the image embedded to.

Line 45: We create a temp bitmap, because we need to use it to add to our sprite, because we can’t draw directly to it.

Line 46: Next we scale the bitmap to whatever size the current asteroid is going to be.

Line 47: lastly we add our bitmap with our asteroid image onto our image sprite.

So now we have the background in our game, ship, and asteroids all having bitmap graphics.
You could change the explosion over to bitmap as well, but then you would have to use a sprite sheet, and change your rendering functions to render out frame based renders. The methods for doing this will be another article soon.

But, lets go all out and change the menu and the start button to a bitmap graphic. Based on your current knowledge, you should be able to figure this out, but I’ll also go over what I did.

Changing the Menu and Start Button to Bitmap Graphics

This takes a little modification to the existing ‘Screen’ class, as well as creating a new ‘ImageButton’ class.

Excerpt for Screen.as

		private var image_background:Boolean;
		
		public function Screen(x:Number = 0, y:Number = 0, width:int = 10, height:int = 10, background:Boolean = true, bg_color:uint = 0x888888, image_background:Boolean=false, image:BitmapData=null) 
		{
			super(x, y, width, height, background, bg_color);
			texts = new Array();
			buttons = new Array();
			this.image_background = image_background;
			if(image!=null)
				this.image = image;
		}

Line 19: We add an option whether there will be a background image.

Line 21: We need to add two parameters in the constructor function, ‘image_background’ will set whether we will have the render function render out the image, and image to pass in a bitmapdata to render.

Line 27: If there was no image passed in for this screen, don’t overwrite it with the null image

Next, we need to update the render function to render out the background image.

Excerpt for Screen.as

		override public function Render(Renderer:BitmapData):void 
		{			
			if (!visible)
				return;
			
			if (background)
				image.fillRect(new Rectangle(0, 0, width, height), bg_color);
			else if(image_background)
				Renderer.copyPixels(image, new Rectangle(0, 0, width, height), new Point(x, y));

Line 59-60: We just have to check if we specified that we would use a background image, and render it out instead of a solid background color.

And lastly we just have to add a function to add our new ‘ImageButton’ object.

Excerpt for Screen.as

		public function AddImageButton(x:Number = 0, y:Number = 0, bg_image:BitmapData=null, bg_image_over:BitmapData = null, func:Function=null):void
		{
			buttons.push(new ImageButton(x, y, bg_image, bg_image_over, func));
		}

You’ll notice this is almost the same function as the one used to add our ‘TextButton’ objects. The main differences are that we just pass the two possible images (normal and over states), and we don’t need to pass the width and height because we’ll get that from the bitmapdata objects.

So, lets create the ‘ImageButton’ class.

ImageButton.as

package UI 
{
	import flash.display.BitmapData;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	public class ImageButton extends UI_element 
	{
		private var bg_image:BitmapData;
		private var bg_image_over:BitmapData;
		
		public var hovered:Boolean;
		public var clicked:Boolean;
		public var func:Function;
		
		public function ImageButton(x:Number = 0, y:Number = 0, bg_image:BitmapData=null, bg_image_over:BitmapData = null, func:Function=null):void
		{
			super(x, y, bg_image.width, bg_image.height);
			
			this.bg_image = bg_image;
			this.bg_image_over = bg_image_over;
			
			hovered = false;
			clicked = false;
			this.func = func;
		}
		override public function Render(Renderer:BitmapData):void 
		{
			if (!visible)
				return;
			if(!hovered||bg_image_over==null)
				Renderer.copyPixels(bg_image, new Rectangle(0, 0, width, height), new Point(x, y));
			else
				Renderer.copyPixels(bg_image_over, new Rectangle(0, 0, width, height), new Point(x, y));
		}
		override public function Update():void 
		{
			if (clicked)
			{
				trace("button Clicked!");
				if (func != null)
					func();
				clicked = false;
			}
			hovered = false;
		}
		
	}

}

Line 12-13: We define the two bitmapdata objects to hold our button normal and over states.

Line 19: We changed the constructor to pass in the images, as well as removed needing the width and the height of the button.

Line 21: The width and height are used from the first image bitmapdata.

Line 34-37: We just use the previous ‘TextButton’ code, but also add checking to make sure we have an ‘over’ image before allowing it to render, and rendering that instead if the button is in the ‘over’ state.

Now that we have our classes changed to allow rendering images, we just need to call the functions to actually create them from our game class.

Creating the Bitmap Menu from Game.as

For the main menu and buttons background, we’ll have to embed their images, so we’ll add the same code above the constructor for embedding the images.

Excerpt for Game.as

		[Embed(source = 'resources/images/chrismweb_menu_bg.jpg')]
		private var tex_menu_bg:Class;
		
		[Embed(source = 'resources/images/btn_start_game1.png')]
		private var tex_btn_start_game1:Class;
		
		[Embed(source = 'resources/images/btn_start_game2.png')]
		private var tex_btn_start_game2:Class;

Same thing as before, but we don’t need bitmaps defined here for the buttons. We’ll just create temporary ones in the constructor, since all we need access to are the bitmapdatas.

So in the constructor, we’ll need to change the menu creation call to add the background, and add the image button.

Excerpt for Game.as

			var temp_menu_bg:Bitmap = new tex_menu_bg();
			var temp_bitmap1:Bitmap = new tex_btn_start_game1();
			var temp_bitmap2:Bitmap = new tex_btn_start_game2();
			
			main_menu_screen = new Screen(0, 0, Renderer.width, Renderer.height,false, 0x000000, true, temp_menu_bg.bitmapData);

			main_menu_screen.AddImageButton(
			Renderer.width / 2 - 84, 100, 
			temp_bitmap1.bitmapData, temp_bitmap2.bitmapData,
			StartGame);

Line 160-163: We create the temporary bitmaps from the embedded image classes.

Line 164: The main menu screen is created passing in the main menu background.

Line 166: Now the ImageButton can be added to the screen.

As you might notice, I also got rid of the text and the other button that were being created before. I instead put the welcome text on the background bitmap, and we replaced the TextButton with the ImageButton.

Now you should be able to run the game and see whatever beautiful graphics you want to create for it!

I just used quick fill-in graphics for the tutorial, but I would reccomend makign some cool looking stylized vector or pixel art.

Let me know what cool looking Asteroid clones you create!
I am also planning on going back and adding some interesting extra game play changes to the game, making cartoony graphics, and have a new Asteroids clone with a new twist!

Tutorial Demo

Where to go from here

You should try creating your own cool graphics to the game, adding new game play options to the game (say space ship seeking asteroids in later levels?), or using this as a base for a totally different type of game.
I will also soon be writing an article on how to do frame based animation, which could be used to create animations for the asteroids, ship, lasers powering up, button animation, explosions, or anything in the game.

Download the source Code and please leave me any comments or feedback you have.

Other Articles in this Series

Bookmark the permalink.

21 Comments

  1. Hey Chris, i think that you missed an ‘s’ at clas word here:
    Line 3: This is what we … embed­ded clas (Exp: back­ground = new tex_background();).

    I can’t see the line of the codes when you say about it at the tutorial, i would have to count the lines…i don’t know if you already know about this script:
    Syntax Highlighter – http://alexgorbatchev.com

    Could be an option.

    Thanks for the great tutorials!

    • Hey Thanks again Tadeu!

      yeah, strange- the plugin I use for wordpress has line numbers, but for some reason they didn’t show the first time I pasted the text in.

      It should be in there now- Thanks again for checking out the posts and helping fix any issues!

  2. Great tutorial! I have been looking to redo my old version of Asteroids using AS3. I did this about 5 years ago and while it plays well the programming is in AS2 and the code is brutal to even look at! http://retropunk.com/test/makai/asteroids/
    Thanks for posting and reminding me! I’m looking forward to going through your tutorial.
    – Patrick

  3. Hey Chris, Excellent tutorial for getting started writing games in AS3. Have used it as a base to create a graphic menu app.

    I’m having trouble with the alpha layer in my image buttons though. I have two screens and when I switch from one screen to another the alpha layer doesn’t want to clear and shows the previous screen’s bitmap, but only in the alpha area of the button. All else works great. Compared all render() methods and everything seems to match your original. Any ideas what I might be missing or overlooking?

    Thanks!
    Jim

    • Thanks for checking out the tutorial!

      Are you using the ‘image.fillRect(new Rectangle(0, 0, width, height), bg_color);’ to “clear the screen” before you render to it?

      The nice thing about blitting is you don’t have to deal with the display list to add/remove stuff from the screen, so I think it’s easier to debug 😀

      If you want, you can email a zip of the project over and I can check it out (chris@ mydomain.com)

      • Hey Chris, Thanks for responding so quickly.

        Yeah, I’ve used fillRect and copyPixels methods to clear/setup the main screen before rendering the other screens.

        I agree with you regarding blitting, it’s very straightforward coding and easy to follow and debug. I’ve used similar methods in Python and PyGame.

        I’ll send my project over so you can take a look. I’m sure its something really simple I’m just not seeing it.

        Thanks,
        Jim

  4. Hi Chris,

    Thanks for the great tutorial for programming a game in Flash Develop. I’ve read most of the flash programming books, but all of them only use the IDE, except for one, so this tutorial was fantastic!

    What I was most interested in was how to embed the graphics, but the whole tutorial was great, including the info on how to draw.

  5. http://jonnielsen.net/playfish.html

    With small explosions, sounds and point in pixel algorithms to detect collisions with asterioids.

    Oh and a UFO which moves randomly and shoots.

    Enjoy.

  6. I added the code to use a .jpg for my background. When FD loads it there are no errors shown but as soon as Adobe opens up the program crashes and I get “[Fault] exception, information=TypeError: Error #1009: Cannot access a property or method of a null object reference.” in the output box. I used FD’s Embed Code option so I know my file path is right and I copy pasted all the necessary code from the tutorial and tried it again but no change. any ideas what could be causing this?

    • The lines:
      “[Embed(source = ‘resources/images/background_space.jpg’)]
      private var tex_background:Class;”

      should assign the class to the jpg – so you could try just putting the jpg in your ‘src’ folder, and then linking instead to “[Embed(source = ‘image.jpg’)]” to see if it is having trouble finding the image relative to the path.

      If that doesn’t work, you could zip up your project and send it, and I can check it out (chris at chrismweb)

      • Chris,

        I found the problem, I had dropped the “background = new tex_background();” line in the wrong function. Thank you for your quick response. I did want to ask about part 9 though, when I go to the page there’s nothing on it but the Kongragate logo and a block of text, will this portion of the tutorial be back up in the future?

  7. Hello Chris,

    i wanted to thank you for your excellent Tutorial but i’ve run into a problem and i wondered if you could help me out.

    I’m trying to change the vector-drawn Bullets into bitmap-drawn ones.

    i tried to do it in a similiar way, like you did with the Asteroid class. basically i include

    [Embed(source=’../resources/images/rocket_small.png’)]
    private var tex_bullet:Class;
    private var temp_bitmap:Bitmap;

    before the class declaration, and try to load it into the constructor.

    first i put the image_sprite variable as a Sprite(), then i use the temp_bitmap variable to create a new instance of the tex_bullet class.
    afterwards i use image_sprite.addChild(temp_bitmap) to add the new bullet as a child.

    in the render() method i use basically the exact same procedure like in the Astroid class. so it looks like this :
    Game.Renderer.draw(image_sprite);

    Now the problem is, the bullet obviously gets created, but the bitmap i try to include stays in the top left corner (x:0,y:0). it vanishes like a normal vector bullet after a short time.
    i can shoot stuff, but sadly it isn’t as satisfying when you can’t see the rocket connect with an Asteroid.

    any ideas? Did i miss something obvious?

    • fixed it today. i didn’t correctly translate the x and y values for the bitmap.
      next problem was getting to shoot the rocket at an angle, but i figured it out.

      thanks again for the awesome tutorial

  8. Hi, great tutorial. I recently finished a game based on it, using original graphics, RPG elements, and several other new features. It’s located at:

    http://www.kongregate.com/games/clasher235/space-ace

    • Awesome! It looks and plays very nice! I like the unique gameplay, and how far you brought it. Graphics are good too- it looks very finished.
      Probably the best asteroids game I’ve played!

      I’m not sure if it will get as many views as deserves though, because asteroids is not as addicting of a game as it used to be.

      How long did it take you to make?

      Keep me updated on your games!

  9. I’m not sure exactly how long it took me to make, it was sort of an on – off thing, what with the end of the year tests, essays, etc. I’m not really concerned about views, it was my first game, and I just wanted to get a working program out on the web. Anyways, thanks for the encouragement.

  10. Whilst I have spent many years programming application on various platforms I have always envied those who can create games. Your fantastic tutorial is opening up a whole new lease of programming life for me. Thank you so much.

    Penfound

Leave a Reply

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