Video icon 64
Build your coding skills with practical video courses from Tuts+. Start your free trial today.
Advertisement

Create an Atari Inspired Boxing Game With AS3

by

In this Premium Tutorial, you'll learn to create an entertaining retro game using Flash and ActionScript 3.0. Check out the demo - the result is based on the classic Boxing for the Atari.


Step 1: Brief Overview

Using the Flash drawing tools we'll create the graphic interface that will be powered by several ActionScript 3 classes.

The player will be able to move and fight against the opponent within the given time.


Step 2: Flash Document Settings

Open Flash and create a 320 pixels wide, 480 pixels tall document. Set the Frame rate to 24fps.


Step 3: Interface

A colorful nice looking interface will be displayed, this involves multiple shapes, MovieClips and more.

Continue to the next steps to learn how to create this GUI.


Step 4: Background

A simple green rectangle will fill the stage.

Select the Rectangle Tool (R) to create a 320x480px #649428 rectangle and center it in the stage.


Step 5: Boxing Ring


'

Using the same tool create a series of #FF9A2E rectangles to build a 290x213px ring.


Step 6: Characters

To get the pixelated effect on the characters, use the rectangle tool to create small rectangles and squares to match the image above. You might like to download this image and put it on a lower layer in your timeline, then place rectangles over it.


Step 7: Dynamic TextFields

Three Dynamic TextFields are placed in the stage, they will be used as hit counters and a timer. Check the image above and place them accordingly.


Step 8: Embed Font

In order to use a custom font in a Dynamic Textfield we will need to embed it first.

With the textfield selected, go to the Properties Panel and click on the embed button, a dialog will be presented where you can select the necessary characters used in your game. Alternatively, just check "Uppercase", "Lowercase", "Numerals", and "Punctuation".


Step 9: Instance Names

Convert the stage shapes to MovieClip and give them the instance names shown in the image.


Step 10: Tween Nano

We'll use a different tween engine from the default included in Flash, this will increase performace as well as being easier to use.

You can download Tween Nano from its official website.


Step 11: Create a New ActionScript Class

Create a new (Cmd + N) ActionScript 3.0 Class and save it as Main.as in your class folder.


Step 12: Class Structure

Create your basic class structure to begin writing your code.

 
package  
{ 
	import flash.display.Sprite; 
	 
	public class Main extends Sprite 
	{ 
		public function Main():void 
		{ 
			// constructor code 
		} 
	} 
}

Step 13: Required Classes

These are the classes we'll need to import for our class to work, the import directive makes externally defined classes and packages available to your code.

 
import flash.display.Sprite; 
import flash.utils.Timer; 
import flash.events.TimerEvent; 
import flash.events.KeyboardEvent; 
import flash.events.Event; 
import com.greensock.TweenNano; 
import flash.events.MouseEvent; 
import flash.net.navigateToURL; 
import flash.net.URLRequest;

Step 14: Variables

These are the variables we'll use, read the comments in the code to know more about them; some of their names are self-explanatory so there will be no comment there.

 
private var timer:Timer = new Timer(1000); //used to decrease the time 
private var min:int = 2; //total minutes of fight 
private var secs:int = 0; //starting seconds 
private var moveLeft:Boolean = false; //the next vars are used to move the player fluidly 
private var moveRight:Boolean = false; 
private var moveUp:Boolean = false; 
private var moveDown:Boolean = false; 
private var eTimer:Timer = new Timer(50); //the enemy movement lag

Step 15: Constructor

The constructor is a function that runs when an object is created from a class, this code is the first to execute when you make an instance of an object, or runs when the SWF loaded if part of the Document Class.

It calls the necesary functions to start the game. Check those functions in the next steps.

 
public final function Main():void 
{ 
	//code... 
}

Step 16: Stop Characters

We'll start by calling the addListeners function and stopping the characters' animations.

 
addListeners(); 
 
/* Stop MovieClips */ 
 
player.stop(); 
enemy.stop();

Step 17: Add Listeners

Next we add the necessary key and enterframe listeners.

 
private final function addListeners():void 
{ 
	stage.addEventListener(KeyboardEvent.KEY_DOWN, movePlayer); 
	stage.addEventListener(KeyboardEvent.KEY_UP, stopPlayer); 
	stage.addEventListener(KeyboardEvent.KEY_DOWN, hit); 
	stage.addEventListener(KeyboardEvent.KEY_UP, resetHit); 
	stage.addEventListener(Event.ENTER_FRAME, update);

Step 18: Add Timers

...Followed by the required timers:

 
	/* Timers */ 
	 
	timer.addEventListener(TimerEvent.TIMER, updateCounter); 
	timer.start(); 
	 
	eTimer.addEventListener(TimerEvent.TIMER, enemyUpdate); 
	eTimer.start(); 
}

Step 19: Time Counter

This function runs every second, it handles the timer in the stage.

 
private final function updateCounter(e:TimerEvent):void 
{ 
	/* Reduce Time */ 
	 
	secs--; 
	 
	if(secs < 0) 
	{ 
		secs = 59; 
		min--; 
	} 
	if(min == 0 && secs == 0) //remove listeners if out of time 
	{ 
		removeListeners(); 
	}

Step 20: Two Digit Timer

We'll add a 0 to the left of the seconds if the number is below 10 (so the timer will always have two digits).

 
	/* Two digit clock */ 
	 
	var s:String = ''; 
	 
	if(String(secs).length == 1) 
	{ 
		s = '0'; 
	} 
	else 
	{ 
		s = ''; 
	} 
	 
	time.text = String(min) + ' : ' + s + String(secs); 
}

Step 21: Move Player

Here we detect the key pressed and change the variable accordingly. We could move the player using this same function but the movement won't be smooth as if we used an enterframe event.

 
private final function movePlayer(e:KeyboardEvent):void 
{ 
	/* Movement */ 
	 
	if(e.keyCode == 37) 
	{ 
		moveRight = false; 
		moveLeft = true; 
	} 
	else if(e.keyCode == 39) 
	{ 
		moveLeft = false; 
		moveRight = true; 
	} 
	 
	if(e.keyCode == 38) 
	{ 
		moveDown = false; 
		moveUp = true; 
	} 
	else if(e.keyCode == 40) 
	{ 
		moveUp = false; 
		moveDown = true; 
	} 
}

Step 22: Stop Player

This function detects the released key to stop the player's movement.

 
private final function stopPlayer(e:KeyboardEvent):void 
{ 
	if(e.keyCode == 37) 
	{ 
		moveLeft = false; 
	} 
	else if(e.keyCode == 39) 
	{ 
		moveRight = false; 
	} 
	 
	if(e.keyCode == 38) 
	{ 
		moveUp = false; 
	} 
	else if(e.keyCode == 40) 
	{ 
		moveDown = false; 
	} 
	 
	if(e.keyCode == 90 || e.keyCode == 88) 
	{ 
		player.gotoAndStop(1); 
	} 
}

Step 23: Set Main Class

Let's stop here to make a quick test and make sure that our game code is working.

Add the class name to the Class field in the Publish section of the Properties panel to associate the FLA with the Main document class.

Now try it out. The timer should count down and the images should appear, but movement will not work yet:

Keep in mind that some lines have been commented as some functions haven't been created yet.

Remember that the Milestones are included in the source files, so if for some reason your file doesn't mimic this one take a look at the source to see what could be causing that.


Step 24: Player Attack

This function changes the frame in the player's MovieClip to the attack frame.

 
private final function hit(e:KeyboardEvent):void 
{ 
	if(e.keyCode == 90) //Z key 
	{ 
		stage.removeEventListener(KeyboardEvent.KEY_DOWN, hit); 
		player.scaleY = 1; 
		player.gotoAndPlay(2); 
	} 
	else if(e.keyCode == 88) //X key 
	{ 
		stage.removeEventListener(KeyboardEvent.KEY_DOWN, hit); 
		player.scaleY = -1; //change scale to use other arm 
		player.gotoAndPlay(2); 
	} 
}

Step 25: Stop Player Attack

Stops the player attacks.

 
private final function resetHit(e:KeyboardEvent):void 
{ 
	if(e.keyCode == 90 || e.keyCode == 88) 
	{ 
		stage.addEventListener(KeyboardEvent.KEY_DOWN, hit); 
	} 
}

Step 26: Update Function

One of the principal functions in the class, contains the logic code that will be executed on enterframe. I've broken up the explanation across the next few steps.

 
private final function update(e:Event):void 
{

Step 27: Controls

Check for the movement variables to move the player.

 
	/* Controls */ 
	 
	if(moveLeft) 
	{ 
		player.x -= 4; 
	} 
	else if(moveRight) 
	{ 
		player.x += 4; 
	} 
	 
	if(moveUp) 
	{ 
		player.y -= 4; 
	} 
	else if(moveDown) 
	{ 
		player.y += 4; 
	}

Step 28: Stage Borders (Player)

Prevent the player from leaving the ring.

 
	/* Player Borders */ 
	 
	if(player.hitTestObject(topWall)) 
	{ 
		player.y = topWall.y + topWall.height + player.height * 0.5; 
	} 
	else if(player.hitTestObject(bottomWall)) 
	{ 
		player.y = bottomWall.y - player.height  * 0.5 - bottomWall.height; 
	} 
	 
	if(player.hitTestObject(leftWall)) 
	{ 
		player.x = leftWall.x + leftWall.width + player.width * 0.5; 
	} 
	else if(player.hitTestObject(rightWall)) 
	{ 
		player.x = rightWall.x - player.width * 0.5; 
	}

Step 29: Stage Borders (Opponent)

Prevent the enemy from leaving the ring.

 
	/* Enemy Borders */ 
	 
	if(enemy.hitTestObject(topWall)) 
	{ 
		enemy.y = topWall.y + topWall.height + enemy.height * 0.5; 
	} 
	else if(enemy.hitTestObject(bottomWall)) 
	{ 
		enemy.y = bottomWall.y - enemy.height  * 0.5 - bottomWall.height; 
	} 
	 
	if(enemy.hitTestObject(leftWall)) 
	{ 
		enemy.x = leftWall.x + leftWall.width + enemy.width * 0.5; 
	} 
	else if(enemy.hitTestObject(rightWall)) 
	{ 
		enemy.x = rightWall.x - enemy.width * 0.5; 
	}

Step 30: Player-Opponent Collisions

The characters are repelled if a collision occurs (not attacking).

 
	/* Hit */ 
	 
	if(player.hitTestObject(enemy)) 
	{ 
		player.x = player.x - 5; 
		enemy.x = enemy.x + 5; 
	}

Let's make another pause to see how our code works at this point. Use arrow keys to move, and Z/X to punch:


Step 31: Player-Opponent Hits

A hit will be added to the counter when the player/enemy fist hits the head of the enemy/player.

 
	/* Head Hit */ 
	 
	if(player.currentFrame != 1 && player.fist.hitTestObject(enemy.head)) 
	{ 
		playerHits.text = String(int(playerHits.text) + 1); 
		player.x = enemy.x - player.width - 26; 
	} 
	 
	if(enemy.currentFrame != 1 && enemy.fist.hitTestObject(player.head)) 
	{ 
		enemyHits.text = String(int(enemyHits.text) + 1); 
		enemy.x = player.x + enemy.width + 26; 
	}

Step 32: Enemy AI Function

The second principal function, this time handling the enemy AI.

 
private final function enemyUpdate(e:TimerEvent):void 
{

Step 33: Enemy Movement

This lines control the enemy movement.

 
	/* Enemy Movement */ 
	 
	if(enemy.x > player.x + 40) 
	{ 
		enemy.x -= 4; 
	} 
	if(enemy.x < player.x) 
	{ 
		enemy.x += 4; 
	} 
	 
	if(enemy.y > player.y) 
	{ 
		enemy.y -= 4; 
	} 
	if(enemy.y < player.y) 
	{ 
		enemy.y += 4; 
	}

Step 34: Enemy Attack

This code handles the enemy's attack. It basically checks its position and punches when the fist can hit the player's head.

 
	/* Enemy attack */ 
	 
	if(enemy.y > player.y + 10 && enemy.y < player.y + 21) 
	{ 
		enemy.scaleY = 1; 
		enemy.gotoAndPlay(2); 
	} 
	else if(enemy.y < player.y - 10 && enemy.y > player.y - 21) 
	{ 
		enemy.scaleY = -1; 
		enemy.gotoAndPlay(2); 
	} 
	else if(player.x - enemy.x >= -40 && player.x - enemy.x <= -30) 
	{ 
		enemy.gotoAndPlay(2); 
	} 
	else 
	{ 
		enemy.gotoAndStop(1); 
	} 
}

Step 35: Remove Listeners

The listeners will be removed when the time is over.

 
private final function removeListeners():void 
{ 
	stage.removeEventListener(KeyboardEvent.KEY_DOWN, movePlayer); 
	stage.removeEventListener(KeyboardEvent.KEY_UP, stopPlayer); 
	stage.removeEventListener(KeyboardEvent.KEY_DOWN, hit); 
	stage.removeEventListener(KeyboardEvent.KEY_UP, resetHit); 
	stage.removeEventListener(Event.ENTER_FRAME, update);

Step 36: Stop Timers

...As will the timers.

 
	/* Stop Timers */ 
	 
	timer.stop(); 
	timer.removeEventListener(TimerEvent.TIMER, updateCounter); 
	eTimer.stop(); 
	eTimer.removeEventListener(TimerEvent.TIMER, enemyUpdate); 
	enemy.gotoAndStop(1); 
	 
	showAlert(); 
}

Step 37: Show Alert

An alert will be shown after that, this code instantiates the alert.

 
private final function showAlert():void 
{ 
	var alert:AlertView = new AlertView(); 
	 
	alert.x = stage.stageWidth * 0.5; 
	alert.y = stage.stageHeight * 0.5;

Step 38: Check for Win or Lose

In order to display the correct text in the alert, we check the hits counters to determine the result.

 
	/* Check for win or lose based on hits */ 
	 
	if(int(playerHits.text) > int(enemyHits.text)) 
	{ 
		alert.msg.text = 'you win!'; 
	} 
	else if(int(playerHits.text) < int(enemyHits.text)) 
	{ 
		alert.msg.text = 'you lose!'; 
	} 
	else 
	{ 
		alert.msg.text = 'draw!'; 
	} 
	 
	TweenNano.from(alert, 0.3, {scaleX: 0.5, scaleY: 0.5}); 
	alert.addEventListener(MouseEvent.MOUSE_UP, restart); 
	addChild(alert); 
}

Step 39: Restart

The next function will reload the SWF, resetting all variables and returning to the first screen.

 
private final function restart(e:MouseEvent):void 
{ 
	navigateToURL(new URLRequest(stage.loaderInfo.url), '_level0'); 
}

Step 40: Test

We are now ready to test our game and check that everything works as expected.


Conclusion

You've created a very entertaining game, try to add your own features and graphics. I hope you liked this tutorial, thank you for reading!

Advertisement