This is a short tutorial where we are going to make a simple game in Flash Action Script 3 (AS3), highlighting some easy, but powerful tricks into making an interactive experience which we can expand upon later – adding more advanced techniques.
It is also possible to easily make this work in other programming languages like Java, C#, etc. Also, the code will not be optimized, so you can probably find better ways of doing things, but this will hopefully get you started.
In short our goal is to make a variant of the classic Pong game, where a ball or other object is hit between two opposing players – like so:
We will make this game by adding layers of behaviour – just like I suggest you do when you start your projects. Make one thing work before you try another one. Don’t try to fix the whole problem in one go. If you don’t love error messages, that is.
Overview:
- Setup
- Movement in the x-direction
- Movement in the y-direction
- Adding player one (mouse)
- Adding player two (keyboard)
- Adding a crash or game over
- New assignments/expansions
- Artificial intelligence
OK, let’s start.
First we will make a playing area of let’s say 1280×720. We will make an object that should bounce around the playing area, not by direct animation but more automatically (automagically?). I will call this symbol instance «ball», something which we will refer to many times during our code. Be sure to place the center/origo of the instance in the middle of your ball (enter your movieclip and move the graphics so that the plus-sign (+) is in the middle of your circle). Have a look at the example file if you don’t know how to do this.
When you have this covered we need to start adding some code to make things happen. Make an empty layer and put in the following code:
var speedX:int = 5; // how much/fast our ball will travel in the x-direction
stage.frameRate = 25; // fps = 25
// The following code will run as often as the indicated fps
stage.addEventListener(Event.ENTER_FRAME, everyFrame);
function everyFrame(evt:Event):void {
ball.x = ball.x + speedX;
}
So far we have a ball that is going in the right direction. Try changing the speed by adjusting the variable «speedX».
Notice that it just keeps going on even though it hits the wall. To make it stop, or even better turn the other way, we will have to add an easy if-sentence, like so:
[code]
if(ball.x >= 1280) {
speedX = -speedX;
}
ball.x = ball.x + speedX;
[/code]
Based on mathematics the speed will turn to a negative value when the ball’s x-position hits the stage’s maximum value at 1280 pixels, because
[code]
+- equals – (and a negative x value will get the ball going in the left direction).
Further, -+ also equals -, ++ equals +, and — equals +.
[/code]
By now you probably have found out that we need to something similar at the other side, making it turn the other way again by changing the speedX-variable, like so:
[code]
if(ball.x >= 1280 || ball.x <= 0) {
speedX = -speedX;
}
ball.x = ball.x + speedX;
[/code]
If you don’t like the fact that the ball goes halfway into the wall before it turns you have to make some adjustments. The x-position of the ball is estimated from the middle point, origo, if you have done the same as me so far. By subtracting or adding the radius of the ball in the if-sentence we avoid our «problem».
[code]
// 1280 is the width of the play area. It could also be found dynamically
// by using stage.width
if(ball.x >= (1280 – (ball.width/2)) || ball.x <= (0 + (ball.width/2))) {
speedX = -speedX;
}
ball.x = ball.x + speedX;
[/code]
Now for the y-direction (up and down), which also makes it possible for the ball to go in all directions when combined with movement in the x-direction. This is done in more or less the exact same way, so try it yourself before you look at my finished code.
Simply add a variable for the speed in the y-direction and be sure to make the ball change its y-coordinates at the same time and pace as the x-ones. Note that Flash AS3 have the 0,0 point start in the upper left corner of your window, so positive y-values makes our ball go down on the screen. Don’t ask.
First define the speed in the y-direction:
[code]
var speedY:int = 5; // how much/fast our ball will travel in the y-direction
[/code]
Then add similar codes for the y-direction as for the x-direction:
[code]
// 720 is the height of the play area. It could also be found dynamically using stage.height
if(ball.y >= (720 – (ball.width/2)) || ball.y <= (0 + (ball.width/2))) {
speedY = -speedY;
}
ball.y = ball.y + speedY;
[/code]
That’s it. You now have a ball that bounces around the screen without you doing anything actively to get it to do so, all in one frame. In the next part we will introduce the possibility for two different players to move around an object that also interacts with the ball.
Download the FLA-file for the project code and symbols so far.
For the next part we will add the possibility for a player to interfere with the ball. The controller will be the mouse (player two will use the keyboard).
First we’ll make the object with which the player will try to hit the ball. I have made a rectangular object which i call «wall», and the instance I drag out into the game field is called «playerOne».
To move this around we can do something similar to the ball movement. We add a listener in the same way:
[code]
stage.addEventListener(Event.ENTER_FRAME, movePlayerOne);
[/code]
And for the function we easily make the y-coordinates of the wall follow the mouse. Since this happens according to the framrate (25 fps) it will be checked often enough.
[code]
function movePlayerOne(evt:Event):void {
// Sets the y-value (up and down) of the wall/player one to where the mouse is.
// If the player moves it up and down the «wall» moves up and down.
playerOne.y = mouseY;
}
[/code]
So far the wall of player one doesn’t do anything – meaning the ball will go right through it. As you have probably guessed you will have to add this to the differents tests we perform in the «did it crash in the wall and go the other way»-part, located in the function «everyFrame». Add the following there:
[code]
// Does the ball hit playerOne? Player one is at the right side
if(ball.hitTestObject(playerOne)) {
speedX = -speedX;
}
[/code]
This code checks to see if the ball hits player one. «hitTestObject» is a built-in function in AS3 which basically checks the location in the coordinate system (x- and y-values) and returns «true» if the objects is at the same values/in the same area, and false if not. As before we change the direction of the speed when a hit is detected.
A visual note is to remove the mouse cursor in the game area, since it can make it harder to see what’s going on. A simple code will suffice. Place the following code all the way at the top where you have other general definitions and rules set up.
[code]
Mouse.hide(); // Makes the mouse cursor invisible in the game area
[/code]
For the next part we will add player two, which will be controlled by the keyboard’s up and down arrows. First you will need something to move around, which I suggest could be a new instance of the wall. This time we’ll call it «playerTwo». Place it in the game area and give it the suggested name.
After that is done you need to add a listener for using the keyboard:
[code]
stage.addEventListener(KeyboardEvent.KEY_DOWN, movePlayerTwo);
[/code]
Now for what happens when you actually use the keyboard, calling the function «movePlayerTwo». Every push of the up-arrow should move the wall up (which is a negative y-value), and every push of the down-arrow should move the wall down (which is a positive y-value):
[code]
function movePlayerTwo(evt:KeyboardEvent):void {
// Sets the y-value (up and down) of the wall/player two to a value
// manipulated by the keyboard.
if(evt.keyCode == Keyboard.UP) {
playerTwo.y = playerTwo.y – 20;
}
if(evt.keyCode == Keyboard.DOWN) {
playerTwo.y = playerTwo.y + 20;
}
}
[/code]
How far the wall of player two is moved by each push of the button is easily adjusted by changing the number 20 to something else.
Again we need to make this new wall actually behave as it it was there, making it hit the ball if it is in the way. This is done exactly as we did for player one:
[code]
// Does the ball hit playerTwo? Player one is at the left side
if(ball.hitTestObject(playerTwo)) {
speedX = -speedX;
}
[/code]
It wouldn’t be game if no one could win (could it?), so let’s add a possibility for the game ending – meaning the ball will crash into the wall and stop if the player doesn’t hit it. It’s not hard to get this working. Remember what we did in the everyFrame-function? The ball got turned the other way if it hit both the right wall and the left wall, so we need to change something there.
Let’s start at the right end of the game board, where originally the ball turned around if it tried to go over the value of 1280 pixels (x-coordinates). Remove this from the original if-test, and move this to a new one:
[code]
// In the x-directions we check to see if the ball tries to go out over
// the game area, and if so we stop the ball. For visual effect I’ve
// also added an «unhappy ball» by jumping to the second frame of the
// movieclip which contains a smile turned upside down.
if(ball.x >= (1280 – (ball.width/2))) {
speedX = 0;
speedY = 0;
ball.gotoAndStop(2);
}
[/code]
You can try to do the same thing on the other side of the board, yourself. We wouldn’t want player two to win every time, now, would we?
What we’ve got so far can be found in the new FLA-file (version 2).
Tips for new assignments:
- Add a possiblity to restart the game after a player has won, and maybe also a start up screen where the player can set some options (difficulty, speed, players, etc.).
- More visual flare.
- Physics. Make the ball go faster after it hits something. Hint: Just add a constant to the speed every time the ball hits something. Not much is needed (low value)!
- Artificial intelligence (See tips under).
Note that this is a simple solution, but it can be interesting as a starting point.
Declare a variable with a specific value. This is the speed of the opponent (CPU).
[code]
var cpuSpeed:int = 14;
[/code]
Add this to your enter_frame-function:
[code]
if(playerTwo.y < ball.y – 40){
playerTwo.y += cpuSpeed;
}
else if(playerTwo.y > ball.y + 40){
playerTwo.y -= cpuSpeed;
}
[/code]
Note that it can be smart to add an acceleration for the ball each time it hits one of the players. This makes it possible to defeat the opponent.
—
More might be coming.. Let me know if you have any problems in the comments below.
And, share your project if you make something!
Leave a Reply