Saturday, July 3, 2010

My first tutorial - How to make a simple ball game in AS 3.0

Here it is guyzz !! The much not !(awaited) tutorial by me on my blog. This tutorial is basically for all those people who are passionate about game development, specially in Flash, but did not knew how to start off. Doing this game tutorial will expose you to the basic flow of a game and how the elements of the game interact with each other.
Well without much talk lets start off the business.


What are we going to develop ?

In this tutorial we'll go through the procedure to develop a basic game similar to my game BOUNCY.


What are the pre-requisites ?

  1. Adobe Flash CS3 or higher

  2. Basic knowledge of Actionscript 3.0

  3. Basic understanding of OOPS concepts


But how how how ?

So here starts the real game development. This tutorial is divided into 2 parts:
PART 1 and PART 2.

PART 1


The first part will discuss the basic ball movement and collisions.

Fire up your Flash IDE and open a new AS 3.0 file

Create 2 Movieclips for Ball and Ground each. You can name them anything you like.

Draw simple shapes for the 2 movieclips (circle for ball and rectangle bar for ground). Finally drag them
to your stage from the library and name them ball_mc and ground_mc.

Now create 2 Actionscript files : Game.as and Ball.as and SAVE YOUR WORK.

Game.as Code :
Open the Game.as file and put the following code :

/*
Game.as
*/

package{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.*;
import flash.geom.Point;

public class Game extends MovieClip{
var GRAVITY:Number = 0.5;
// elasticity coefficient
var E:Number = 0.7;
var EPSILON:Number = 0.7;

// ctor
public function Game(){
addEventListener(Event.ENTER_FRAME, gameLoop);
}

function gameLoop(e:Event):void{
var radius = ball_mc.width/2;
var forecast_x = ball_mc.x+ball_mc.speed_x;
var forecast_y = ball_mc.y+radius+ball_mc.speed_y;

// relection of ball from left and right sides
if((forecast_x-radius < ground_mc.x-ground_mc.width/2) || (forecast_x+radius > ground_mc.x+ground_mc.width/2)){
ball_mc.speed_x = -(ball_mc.speed_x*E);
}

// calculate the contact point
var pnt:Point = new Point(ball_mc.x, forecast_y);
// convert it to stage cordinate system
pnt = this.localToGlobal(pnt);
// check collision of ground and ball contact point
if(ground_mc.hitTestPoint(pnt.x, pnt.y)){
ball_mc.speed_y = -(ball_mc.speed_y*E);
// if y-speed is very small...stop it
if(Math.abs(ball_mc.speed_y) < EPSILON){
ball_mc.speed_y = 0;
// add friction as ball rolls on ground
ball_mc.speed_x *= 0.85;
}
}
else{
ball_mc.speed_y += GRAVITY;
}
// move the ball after making all calculations
ball_mc.move();
}
}//eof class
}//eof package

Code Explanation :


  1. This class is the Document class of our game. Just incase you dont know how to attach a Document class :
    [ To attach a Document class : Click anywhere on empty stage and open property panel. Put the class name in the Document Class: text box. ]

    We declare 3 variables :
    GRAVITY : As the name suggests, it is the amount to add to ball's y-speed while in air.
    E : This variable defines the elasticity co-efficient for the collision between ball and ground.
    EPSILON : Its the smallest amount of y-speed that ball can attain before coming to rest.


  2. Next we define the class constructor. Here we add an event listener for every frame (MouseEvent.ENTER_FRAME).

    The listener function is called gameLoop().


  3. Now comes the core function of our Game class..gameLoop().
    The first 3 lines calculates few things. The radius of ball, the ball's next x coordinate (current x + x-speed) and similarly its next y coordinate (current x + x-speed + radius).

    Notice that we add radius while calculating forecast_y so that we get
    the bottom contact point instead of center of ball.



  4. // relection of ball from left and right sides
    if((forecast_x-radius < ground_mc.x-ground_mc.width/2) || (forecast_x+radius > ground_mc.x+ground_mc.width/2)){
    ball_mc.speed_x = -(ball_mc.speed_x*E);
    }

    We then check the collision of ball(Ball_mc) with the left and right boundaries. In this case we take the boundaries as the end of our ground. The collision is a simple check that if the x coordinate of the leftmost point of the ball goes , beyond the left and right extremes of the ground, we reverse the x-speed of the ball. Simple...isn't it ?




  5. // calculate the contact point
    var pnt:Point = new Point(ball_mc.x, forecast_y);
    // convert it to stage cordinate system
    pnt = this.localToGlobal(pnt);

    To calculate the collision between ball and ground we check if the lowermost point of the ball is hitting the ground or not.
    The function that serves our purpose is hitTestPoint(p:Point) which takes in a Point class object.

    But the thing to notice here is that this function needs coordinates in the global space i.e. in the Stage coordinate system. So we transform the point (ball_mc.x,forecast_y) to stage coordinate system through the function localToGlobal().
    [ localToGlobal() : This function takes in a Point Class object and return the cordinates in the coordinate system of the calling object. ]

    We get the point to check in variable pnt.




  6. // check collision of ground and ball contact point
    if(ground_mc.hitTestPoint(pnt.x, pnt.y)){
    ball_mc.speed_y = -(ball_mc.speed_y*E);
    // if y-speed is very small...stop it
    if(Math.abs(ball_mc.speed_y) < EPSILON){
    ball_mc.speed_y = 0;
    // add friction as ball rolls on ground
    ball_mc.speed_x *= 0.85;
    }
    }
    else{
    ball_mc.speed_y += GRAVITY;
    }

    This is actual code where we check the collision between the ground and ball's lowest point that we now have in pnt. The hitTestPoint() called from ground_mc takes in the coordinates of the point to check for collision.

    If the hitTestPoint() returns true (Collision occured), we simply reverse the ball's y-speed after multiplying it with E (cooefficient of restitution).

    Note here that as E is less than 1, multiplying it to the y-speed decreases it. After several such bounces the y-speed becomes lesser and lesser and the ball kind of vibrates on the ground due to very small y-speed.
    The situation is shown below. To see more clearly, RClick on the swf, Zoomin on the contact point.



    To correct this problem, we put a restriction on the bouncing through an if condition. We check if the magnitude of y-speed of the ball has reached a predefined amount defined by EPSILON (a small number) variable.
    When the y-speed becomes less than EPSILON, we stop the ball.

    Also we add friction to the ball when the ball stops by just decreasing the x-speed of ball (by multiplying with cooefficient of friction).



  7. Finally, we call the ball's move() in order to move it. The move() function of ball will be defined later in this part.


Ball.as Code :
Open the Ball.as file and put the following code :

/*
Ball.as
*/

package{
import flash.display.Sprite;
import flash.events.*;

public class Ball extends Sprite{

var speed_x:Number;
var speed_y:Number;

// ctor
public function Ball(){
speed_x = 0;
speed_y = 0;
}

function move():void{
this.x += speed_x;
this.y += speed_y;
}

}//eof class
}//eof package


Code Explanation :



  1. This is a very simple class for the ball in our game.

    Firstly we declare 2 variables : speed_x and speed_y. Their use is simply what they mean. Not much here.

    Next is the constructor which initialises the two speeds to 0.



  2. Lastly, we define a function called move() which was called from within the Game.as as we saw before. This function just updates the position of the ball by adding the speeds to the current position.

    Dats all !


This is all we need to do to embed collision and basic movement of ball in our game.

Now save your work and run your flash movie (CTRL + Enter).
You should see something like this :



What to expect in PART 2 ?
Well, PART 2 is not much of a tutorial. Its a small part of the game that is left as an exercise for you guyzz. The only thing remaining in our game is to code the ball's mouse interaction. Our ball (ball_mc) should bounce when we click on it.

The readers are recommended to write this code themselves. And incase you are not able to do it, don't panic. I'll be posting the solution snippet in the coming days. Till then try to play with the codes given here and make it more of a complete game by putting elements like :

  1. Scoring system

  2. Game Menus

  3. Better graphics




Download the source code here

Your comments are most welcome. They'll help me to write better tutorials in future.

Happy Flashing !!

8 comments:

  1. hey man amazing tutorial.... finally it has begun...the era of game tutorials...now i am sure i can do what i was planning earlier.. ;)

    ReplyDelete
  2. thanx all reading and commenting :)

    ReplyDelete
  3. Well done Kushagra,

    Good Tutorial, you are born PRO in what ever you do. Congrats!!!

    One thing I like to mention is you should write part 2, when people come to your site they expect to learn something, if you give part 2 as exercise, I doubt less number of people will try it. This is my personal opinion.
    Best of luck. Keep up the good work.

    ReplyDelete
  4. Hi Chin,

    I really like this tutorial and gives me good idea of the ball behavior in the air while kicked or anything related to motion.

    If you have time, try replying on my comment I have some ideas about games involving bouncy ball motion and your knowledge and my idea could get us somewhere. Since I just started developing in Flash it would be great if we could collaborate.
    Regards

    ReplyDelete
  5. @Yubs: Glad I could help you. Actually I am already occupied with some projects rite now. We could collaborate some other time. Till then keep developing flash games and best of luck for it.

    Cheers

    ReplyDelete
  6. Thanks for replying so promptly.
    I will keep developing my skills, and perhaps one day soon we'll do something interesting.
    I checked your new website, I really like it.

    Sincerely, you're an inspiration to me. Keep up the great work.
    Just like you, I prefer practice over theory.

    Cheers mate

    ReplyDelete

What do u feel ?