Sunday, August 16, 2009

Creating a game with APE - APEOut - Part 3

In the third and final part of this tutorial, we'll finish off this game by adding collision detection and scoring.Before we start, make sure you've read the first and the second part of this series. So, lets get to it.

Adding collision detection :

In order to add collision detection, we'll need to add an Event listener to the ball. After the ball defnition, add the following code :

ball.addEventListener(CollisionEvent.COLLIDE, onCollision);

Now, we have to code what happens if a collision occurs. Create the onCollision event handler as follows :

private function onCollision(e:CollisionEvent):void
{
var collidingItem:* = e.collidingItem;

if (collidingItem != topWall && collidingItem != bat &&
collidingItem != leftWall && collidingItem != rightWall)
{
--brickCount;
group.removeParticle(collidingItem);
}
}


Here the collidingItem will refer to the object that comes in contact with the ball. Now, we have to remove the object if it is a brick or do nothing if its the bat or the walls. So, we check if the collidingItem is not one of the walls or the bat, then we remove it from the group and reduce the brickCount.

Finishing up the game :

Now, run the game, our bat is moving with the mouse, the ball is bouncing and destroying the bricks that it comes in contact with. Everything is working as it is supposed to. But every good game needs scores, right, so declare a score variable as a Number and a TextField to display the score.We also need a Boolean variable to see if the game is over or not. Here's the final full code :

package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;

import org.cove.ape.APEngine;
import org.cove.ape.CircleParticle;
import org.cove.ape.CollisionEvent;
import org.cove.ape.Group;
import org.cove.ape.RectangleParticle;
import org.cove.ape.VectorForce;

/**
* APEOut - A Breakout clone using the ActionScript Physics Engine (APE)
* @author Pradeek
*/

[SWF(width = 600, height = 400)]
public class APEOut extends Sprite
{
private var group:Group;
private var leftWall:RectangleParticle;
private var rightWall:RectangleParticle;
private var topWall:RectangleParticle;
private var bat:RectangleParticle;
private var ball:CircleParticle;
private var brickCount:Number;

private var score:Number;
private var scoreText:TextField;
private var gameOver:Boolean;

public function APEOut():void
{
initAPE();
initObjects();
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}

private function initAPE():void
{
APEngine.init();
APEngine.container = this;
APEngine.addForce(new VectorForce(false, 0, 4));
}

private function initObjects():void
{
gameOver = false;

score = 0;
scoreText = new TextField();
scoreText.x = 400;
scoreText.y = 25;
addChild(scoreText);

group = new Group(true);

leftWall = new RectangleParticle( -10, 0, 10, 1000, 0, true, 1, 0.3, 1);
rightWall = new RectangleParticle(610, 0, 10, 1000, 0, true, 1, 0.3, 1);
topWall = new RectangleParticle(0, -10, 1200, 10, 0, true, 1, 0.3, 1);

bat = new RectangleParticle(250, 325, 125, 10, 0, true, 1, 0.50, 1);
bat.alwaysRepaint = true;
bat.setFill(0x0000FF);

ball = new CircleParticle(220, 225, 15, false, 1, 0.65, 1);
ball.setFill(0xFF0000);
ball.addEventListener(CollisionEvent.COLLIDE, onCollision);

var rows:int = 5;
var cols:int = 8;

brickCount = rows * cols;

var currentX:Number = 100;
var currentY:Number = 100;

var brickWidth:Number = 50;
var brickHeight:Number = 10;

for (var i:uint = 0; i < uint =" 0;" rectangleparticle =" new" currentx =" 100;" px =" mouseX;" text = "Score : "> 400)
{
gameOver = true;
group.removeParticle(ball);
scoreText.text = "Game Over. \nYou lose. \nFinal Score : " + score.toString();
}

if (brickCount == 0)
{
gameOver = true;
group.removeParticle(ball);
scoreText.text = "Game Over. \nYou win. \nFinal Score : " + score.toString();
}
}
}
}


Hope the series was a bit useful to you. If you have any questions or suggestions, please drop a comment. Thanks for reading :D

Creating a game with APE - APEOut - Part 2

In part 2 of this tutorial, we're going to add the bricks and add motion for the bat. Make sure you've read the first part of this tutorial and lets get going.

Creating the bricks :

Add the following code to the initObjects method after creating the ball.Also create a private variable brickCount for the number of bricks in the stage.
var rows:int = 5;
var cols:int = 8;

brickCount = rows * cols;

var currentX:Number = 100;
var currentY:Number = 100;

var brickWidth:Number = 50;
var brickHeight:Number = 10;

for (var i:uint = 0; i < rows; i++)
{
for (var j:uint = 0; j < cols; j++)
{
var brick:RectangleParticle = new RectangleParticle(currentX, currentY, rickWidth, brickHeight, 0, true, 1, 0.3, 1);
brick.setFill(Math.random() * 0xFFFFFF);
group.addParticle(brick);
currentX += brickWidth + 5;
}
currentX = 100;
currentY += brickHeight + 5;
}
What we're doing here is simply creating a brick at the position (currentX,currentY) and incrementing with the brickWidth and a gap value. We also set a random color for the bricks. Run the file. You'll see a ball bouncing on the bat and about 40 bricks lined up in 5 rows. When the ball collides with the brick, it just bounces off. Moving the bat : To move the bat just add the line
bat.px = mouseX;
before the APEngine.step() call in the onEnterFrame event handler. If you run the game now, you'll see that the image of the bat doesn't move but if you move your mouse, the ball will fall down. So, add the following line under the bat defnition.
bat.alwaysRepaint = true;

Now, it looks something like a game. We have the bat, the ball and the bricks. All we need is to add collision detection and scores. We'll do that in the next post.
Stay tuned.

Saturday, August 15, 2009

Creating a game with APE - APEOut - Part 1

Following up on my introductory blog post on APE, Today we are going to create a simple Breakout clone with APE. I'm going to call this APEOut having just 1 level. I'll split this tutorial into 3 parts. In the first part, we'll create a bat, ball and the boundaries. In the second part, we'll create the bricks and add movement for the bat. In the third part, we'll add collision detection and scores.
So, lets get started.

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

import org.cove.ape.APEngine;
import org.cove.ape.Group;
import org.cove.ape.VectorForce;

/**
* APEOut - A Breakout clone using the ActionScript Physics Engine
* @author Pradeek
*/

[SWF(width = 600, height = 400)]
public class APEOut extends Sprite
{
private var group:Group;

public function APEOut():void
{
initAPE();
initObjects();
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}

private function initAPE():void
{
APEngine.init();
APEngine.container = this;
APEngine.addForce(new VectorForce(false, 0, 4));
}

private function initObjects():void
{
group = new Group(true);
APEngine.addGroup(group);
}

private function onEnterFrame(e:Event):void
{
APEngine.step();
APEngine.paint();
}

}

}

The above code is similar to the one we wrote in the last post. Basically, we're setting up the engine, creating a group and updating and drawing on the ENTER_FRAME event. Next, we create the 3 boundaries - top, left and right and the bat and the ball. Create objects of the RectangleParticle class for topWall, leftWall , rightWall and bat and the CircleParticle class for the ball. Modify the initObjects method as follows :

private function initObjects():void
{
group = new Group(true);

leftWall = new RectangleParticle( -10, 0, 10, 1000, 0, true, 1, 0.3, 1);
rightWall = new RectangleParticle(610, 0, 10, 1000, 0, true, 1, 0.3, 1);
topWall = new RectangleParticle(0, -10, 1200, 10, 0, true, 1, 0.3, 1);

bat = new RectangleParticle(250, 325, 125, 10, 0, true, 1, 0.50, 1);
bat.setFill(0x0000FF);

ball = new CircleParticle(220, 225, 15, false, 1, 0.65, 1);
ball.setFill(0xFF0000);

group.addParticle(leftWall);
group.addParticle(rightWall);
group.addParticle(topWall);

group.addParticle(bat);

group.addParticle(ball);

APEngine.addGroup(group);
}


A little code explanation :
We position three rectangular blocks on the top, left and the right sides. Since they are walls, we're hiding them. We create a bat and a ball and position them appropriately.
Try to run this. You should see the ball bouncing on the bat. If you wait a bit, you'll see that it hits the top and bounces back.
The next step is creating the bricks and making the bat move. We'll do that in the next post. If you have any questions, please post it in the comments. Thanks for reading.

Friday, August 14, 2009

Getting started with Physics in AS3 : APE Tutorial

Today, we're going to see a very simple tutorial for using the Actionscript Physics Engine (APE). There are several Physics engines in the AS3 but APE is probably the easiest to use. So, download the library via SVN here and lets get started.
Here is the code :

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

import org.cove.ape.APEngine;
import org.cove.ape.CircleParticle;
import org.cove.ape.Group;
import org.cove.ape.RectangleParticle;
import org.cove.ape.VectorForce;

[SWF(width = 600, height = 400, backgroundColor='0x000000')]
public class APExample Sprite
{
public function APExample():void
{
initAPE();

initObjects();

addEventListener(Event.ENTER_FRAME, onEnterFrame);
}

private function initAPE():void
{
// Initialize APE
APEngine.init();

// Set the container for APE
APEngine.container = this;

// Add gravity
APEngine.addForce(new VectorForce(false, 0, 2));
}

private function initObjects():void
{
// Create a group to hold all the objects with collision
var group:Group = new Group(true);

// Create a rectangle for rhe floor
var floor:RectangleParticle = new RectangleParticle(0, 400, 1200, 25, 0, true);

// Create a circle
var circle:CircleParticle = new CircleParticle(225, -100, 25);

// Add the floor to the group
group.addParticle(floor);

// Add the circle to the group
group.addParticle(circle);

// Add the group to the engine
APEngine.addGroup(group);
}

private function onEnterFrame(e:Event):void
{
// Update and Draw
APEngine.step();
APEngine.paint();
}

}

}
Compile and run. You should see a white rectangle at the bottom as the "floor" and the ball will fall down. Experiment a little bit by chaanging the gravity value for some interesting results. For example, you could set a positive value for x which would make the ball move sideways. But still, one ball falling down and bouncing isn't much of an example. In the coming tutorials, we'll be developing a simple game using APE. Stay tuned. :D

UPDATE : Certain compiler errors occur (changes in several classes) if you are using the given download link in the APE homepage. The one i am using here is from svn.
I've also uploaded the project with the APE files for those without SVN. You can download it here. Sorry for the mmistake.

Monday, August 3, 2009

Getting started with Away3D

Today, I decided to play with Away3D and immediately found it to be much better than Papervision. Comparatively, Away3D is much faster than Papervision ( implementation of FP10 features ). So, here is a simple tutorial to get you up and going with Away3D.
In this tutorial, I'll be using Flex Builder to create an ActionScript project. I'm naming it Away3DTest. Now download the latest Away3D build from here. Extract the source to the src folder and type in the following code :


package
{
import away3d.cameras.Camera3D;
import away3d.containers.Scene3D;
import away3d.containers.View3D;
import away3d.core.math.Number3D;
import away3d.core.render.Renderer;
import away3d.materials.BitmapMaterial;
import away3d.primitives.Cube;

import flash.display.Bitmap;
import flash.display.Sprite;
import flash.events.Event;

[SWF( backgroundColor = '0x000000')]
public class Away3DTest extends Sprite
{
[Embed(source='texture.jpg')]
private var Texture:Class;

private var scene:Scene3D;
private var camera:Camera3D;
private var view:View3D;

private var cube:Cube;

public function Away3DTest()
{
initAway3D();
initObjects();
}

private function initAway3D():void
{
camera = new Camera3D();
camera.x = 100;
camera.y = 100;
camera.z = -1000;
camera.lookAt( new Number3D() );

scene = new Scene3D();

view = new View3D();
view.x = 200;
view.y = 200;
view.scene = scene;
view.camera = camera;
view.renderer = Renderer.BASIC;
addChild(view);
}

private function initObjects():void
{
cube = new Cube();
cube.material = new BitmapMaterial(Bitmap(new Texture()).bitmapData);
scene.addChild(cube);

addEventListener(Event.ENTER_FRAME, onEnterFrame);
}

private function onEnterFrame(e:Event):void
{
cube.rotationX += 1;
cube.rotationY += 1;
cube.rotationZ += 1;

view.render();
}

}
}



Here I assume you have a file named texture.jpg in your source directory.Now an explanation of the code :
  1. We create variables for the View3D, Camera3D and the Scene3D class and assign the scene and the camera variable to the view variable. This is setting up the Away3D engine and is written as a seperate function initAway3D()
  2. We create a cube and create a new BitmapMaterial for it using the embedded texture.
  3. We create an ENTER_FRAME event listener which does the rendering using the view.render() method. Meanwhile we'll also rotate the cube on all 3 axes.
  4. Save and run you should get a cube with the texture rotating on all the axes.
Hope that was useful to anyone starting Away3D. Happy coding. :D