Category: Games


Playing Blind

Terry Garrett plays through Abe’s Exoddus despite blindness

After reading an interview with Terry Garrett on Oddworld.com I couldn’t help but make a quick blog post. Terry Garrett, with a bit of help from a friend or his brother to navigate menus or describe a cut scene, is able to play through all of the Oddworld classic, Abe’s Exoddus. He is able to do this with the Oddworld game better than most for a couple of reasons. Firstly, Abe makes a sound for every interaction he has with the environment, from talking with other characters, to bumping his head. And secondly the game, whilst exploring some very complex puzzles and interaction is relatively simple. Abe’s steps are all the same, the screen is always a set number of steps across and the position of objects can be easily memorized and visualized by Terry’s mind’s eye. This combined with the fact that Exoddus has a quicksave feature as I expect he dies a lot as he learns the layout of each screen.

I find this story fascinating on a couple of levels. First off, from a game design perspective, without meaning to, the folks at Oddworld Inhabitants have made the game playable for a blind guy. How awesome is that!? The details they have put into all the different sounds, including the music which is used to convey imminent danger, all help to create the scene. The second interesting thing is that Terry can actually navigate 3D game worlds with a bit of help. With sound design in 3D spaces being what it is today combined with a create speaker system, Terry can create a picture in his head of the virtual game world just from the sound.

I leave you with a playthrough / interview with Terry of one of my favourite games, Abe’s Exoddus.

Unity3D is a platform for creating real-time, interactive 3D (I could have just said games, but I wanted to be more general). Not only is it easy to use and learn, but can be exported for practically every platform under the sun (iPhone, Android, PC, Mac and even an browser web player). Although I have only made a simple tutorial, I gather from the range of projects out there, that it is just as robust as any development program.

Brick Blaster

The little “game” I want to show you how to make is basically shooting balls at a wall of blocks. A simple concept, but potentially the basis for an entire game. What we will need is a floor, a camera, a light, a wall made of separate blocks and our balls to shoot at the wall. The balls and the wall are going to be created with code, but the rest of the elements will be setup in Unity’s 3D editing environment. Creating the elements is pretty straight forward. The floor is created from the menu with GameObject > Create Other > Plane. I have also created an empty object called SpawnPoint to attach our wall to.

Unity3D scene from top view

Unity3D scene from top view

In order to create game objects from code, they need to exist in the library as “Prefabs”. This is how to create a prefab, directly from the site.

  1. Choose GameObject->Create Other->Cube
  2. Choose Component->Physics->Rigidbody
  3. Choose Assets->Create Prefab
  4. In the Project View, change the name of your new Prefab to “Brick”
  5. Drag the cube you created in the Hierarchy onto the “Brick” Prefab in the Project View
  6. With the Prefab created, you can safely delete the Cube from the Hierarchy (Delete on Windows, Command-Backspace on Mac)
Unity3D project view of all assets

Unity3D project view of all assets

With these prefabs in our library, we can now “Instantiate” those objects dynamically in the games runtime. For this game we want to achieve 3 different functionalities, and we will have 3 scripts for that. One script will build the wall, and will be attached to the empty SpawnPoint object. Another will control the aim of the camera with the arrow keys, and the final will control the firing of the balls from the point of view of the camera. Now lets take a look at our 3 scripts. All three are in JavaScript, but you can code in a few different languages, and even chop and change between languages within Unity. I will show the scripts first, with code comments, and then I have a few notes for the end.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//To be attached to the Main Camera
var moveSpeed : int; //The speed of camera movement
 
//The Update function is run every step or frame of the game
function Update () { 
    //The following 4 if statements test if the arrow keys are being
    //pressed and rotate the camera in the right direction
    if (Input.GetAxis("Horizontal") > 0) {
        //In unity, transform refers to the object to which the script
        //attached. Essentially like referring to "this" in javascript
        transform.Rotate(Vector3.up * Time.deltaTime * moveSpeed);
    }
    if (Input.GetAxis("Horizontal") < 0) {
        transform.Rotate(Vector3.down * Time.deltaTime * moveSpeed);
    }
    if (Input.GetAxis("Vertical") > 0) {
        transform.Rotate(Vector3.left * Time.deltaTime * moveSpeed);
    }
    if (Input.GetAxis("Vertical") < 0) {
        transform.Rotate(Vector3.right * Time.deltaTime * moveSpeed);
    }
}

The axis mentioned above is basically an input and is defined in Edit > Project Settings > Input. Unity has preset most inputs that you would want, and is quite clever about how they are setup. Each input has backup keys, sensitivities and all sorts of other stuff that I don’t understand yet. When they say Axis though, it should be understood that it includes a control that works in two different directions. For example, the left and right keys (and as a backup the A and D keys) are represented by the “Horizontal” axis. To test if the Horizontal is going left or right, we test if it is positive or negative.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var bulletPrefab : Transform; //The bullet object
var shootForce = 10.0; //The force of the bullet
 
//Our function to instantiate and fire a ball
function FireRocket () {
    //Instantiate the object at the cameras position
    var instanceBullet = Instantiate(bulletPrefab, transform.position, Quaternion.identity);
    //Add a force to the ball in the direction the camera is facing
    instanceBullet.rigidbody.AddForce(transform.forward * shootForce);
}
 
// Calls the fire method when holding down ctrl or mouse
function Update () {
    //Test if the fire1 button has been pressed
    if (Input.GetButtonDown("Fire1")) {
        FireRocket();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//Attached to the SpawnPoint empty object
 
//This is left variable and is defined in Unity's user interface
var prefab : GameObject; 
var gridX = 5; //How many columns
var gridZ = 5; //How many rows
var spacing = 3; // Space between rows and columns
 
//The Start function is called when the object enters the scene
function Start () {
    for (var z = 0; z < gridZ; z++) {
        for (var x=0;x<gridX;x++) {
            //Create a position variable based on the position of SpawnPoint
            //and the position in the grid
            var pos = transform.position + (Vector3 (x, z, 0) * spacing);
            //Instantiate a clone of the chosen prefab object
            Instantiate(prefab, pos, Quaternion.identity);
        }
    }
}

Ok, well that looks like it. I nice simple tutorial dealing with a few basic concepts of Unity3D. There is obviously a tonne of other stuff to look at, for instance, the physics is very basic at the moment (the cannon balls don’t even bounce) and there are no textures, but I am sure there will be other tutorials.

The final product. Hitting the scales at less than 50kb. Arrow keys to aim, and mouse 1 or left ctrl to shoot.

It can be very easy to get carried away with the fun part of the game and forget all the usability stuff like the menu and game shell (the chrome on the outside of the play area). I want to very quickly discuss a bit of structure for our display list and create a simple intro animation followed by a menu (just a play button for now).

Conceptual layers

Using sprites as layers in AS3

Organising the display list

A great feature of AS3 is the display list. As we go along, we may want to add new objects to the physics engine, or bring up a pop up menu mid game. In order to make this all run smoothly, so that the right objects are always on top of each other, we are going to create blank Sprites for each of our layers now. Then when we add objects throughout the game, we can just add them to the right Sprite.

Within the class definition, before any functions, we create our layers and instantiate our Intro object (just a movieclip in the library with limited code inside)

1
2
3
4
5
6
7
8
9
// Sprite containing the background objects
private var bgObjects:Sprite = new Sprite();
// Sprite containing the physics world and graphics
private var m_sprite:Sprite = new Sprite();
// Sprite containing the gameShell
private var gameShell:Sprite = new Sprite();
 
//The game introduction
private var intro:MovieClip = new Intro();

So basically you can think of the first three Sprites as being a bit like photoshop layers or groups. Alone they will have no visual presence, but instead will have other sprites added to them. The last object is an instance of a movieclip in the Flash library and has a timeline, a button and a tiny bit of code.

1
2
3
4
5
6
7
8
public function TileGame()
{
    //... other code for the came
 
    addChild(bgObjects);
    addChild(m_sprite);
    addChild(gameShell);
}

This is just a part of the instantiating function of our main class and demonstrates each of our empty Sprites being added to the display list. The last to be added will be considered to be on top of the one before. In theory, we may want to leave gameShell only to the interface of the game and make another “layer” for menus, but we can always do that later on if we feel things become complex enough to justify it.

1
2
3
4
5
6
7
8
9
10
11
12
13
private function setup(e:Event=null):void
{
    //Intro is added and setup
    gameShell.addChild(intro);
    intro.addEventListener(Event.ENTER_FRAME, findEnd);
 
    //Background is added and setup
    var background1:Sprite = new Background();
    background1.y = 100;
    background1.x = 150;
    background1.blendMode = BlendMode.MULTIPLY;
    bgObjects.addChild(background1);
}

Above, not only can you see our intro being added to the gameShell layer, but you can also see a Background MovieClip being instantiated and positioned within the bgObjects layer. Also take note of the event listener we added to the intro, as you will see next, this is designed to detect when the intro ends.

1
2
3
4
5
6
7
8
9
private function findEnd(e:Event=null):void
{
    if (intro.currentFrame == intro.totalFrames) 
    {
        intro.removeEventListener(Event.ENTER_FRAME, findEnd);
        gameShell.removeChild(intro);
        loadSettings();
   }
}

By simply detecting the end of the intro MovieClip, we make dealing with the Intro much cleaner. We don’t have to pass variables back and forth between our main class and this imported MovieClip. We can do whatever we want in the Intro, and when we are done, just let the end of the clip play out. This function above will detect when the timeline ends, remove the intro, and continue the program.

With this system in place, making our button work in the Intro MovieClip is as easy as putting a stop() command in before the end of the timeline, and a play() command on the button.

See the wonderful play button in action

Get Adobe Flash player

Pétanque or Garden Bowls game

In my last post I spoke about a platform called PlayerIO which can be used to make multi-player flash games. Using the Box2D AS3 tile based game engine that I have been working on, I have created the basic outline for a Lawn Bowls type of game. You get four shots to get as close as you can to the small ball, also known as the “Jack”. There are movable obstacles that can get in your way, and a terrain to navigate. Obviously I will create a more fun way of throwing the balls, at the moment you just choose a vertical and horizontal thrust to give the ball.

After you throw the four balls, the game calculates the distances of all your balls from the “Jack”. In a multi-player version, the two players would take turns, and throw different coloured balls. It could be very fun given the right level design. Bowls is always interesting when you get down to the last few balls and need to throw a Kamikaze death ball at the end to try to knock out the enemies balls.

Anyway, have a look, and I will be researching PlayerIO a bit and try to get some multi-player action going. All I need to be able to do is pass the force impacting the ball from one client to another. Oh and you probably have to click in the flash window to interact with it.
 

Get Adobe Flash player

PlayerIO logo

PlayerIO allows multiplayer Flash games

Just a quick post to share something that I am going to be experimenting with over the next few weeks (whenever I get a chance). It is a website called PlayerIO which hosts all sorts of services for Flash game developers for free. They will host your databases for games scoreboards, they’ll store your files, but more interestingly you can get your own access to a server capable of executing custom server side game logic. In short, since instances of Flash can’t communicate with each other by themselves, they give you the server capable of sending and receiving messages between them. Setting up and maintaining a server like this by your self would be a costly and time consuming venture, so this is really very good news.

This is gonna require some C#

The only downside could be the fact that the server only communicates in full programming languages like C#. I think, this is kinda cool though, as it gives us all an incentive to learn a bit. Luckily, it is very similar to AS3, and depending on the complexity of the game, you can get away with only a little C# just to pass the messages back and forth between the Flash clients.

An idea for a turn based Petanque game

An idea for a turn based Petanque game

Luckily for us, there is a very comprehensive AS3/C# tutorial already on the site. I am going to be experimenting with this site and trying to make a turn based Pétanque style game with my physics engine. I can create terrain and obstacles with my engine, and then give the players turns to take shots. Each turn the player chooses an angle and velocity of shot to try to get as close as possible to the goal (in the case of Petanque it is the Jack).

In my last post I showed off round one of the design for the game. While I am sure that the design will go through many rounds of changes before it is ready, now it a good time to explore a method for getting those graphics into the game engine. I am going to start with the static objects, as they are the simplest to implement. Because the static objects don’t move once they are placed I can simply place the graphic in the right place when creating the physics object.

Separating code from design

The library of objects

The library of objects

Because this is the first encounter with any type of graphics, I want to make sure I do it right. I want to create a clear line between the world of the flash designer and the world of the flash developer. Obviously using Flex would create this division for me, but within flash alone, I find it helpful to think of the Library as the designer’s territory. In this way, we can still keep the stage clean of anything (design or code).

I have created a library of 2 types of static block and 2 types of ramp. Each has a name beginning with an underscore which I do to distinguish export objects from the others. They have also been given export names which basically attaches a blank class to the movieclip. In this way, the objects can be instantiated with some pretty simple code.

1
2
var block1:Sprite = new BlockType1(); // Create a block as a Sprite
addChild(block1); //Add the block to the display list

Let’s make this a bit more object oriented

At the moment, all of our object creation is in the TileGame.as class. What would be better, instead of a messy block of code in the TileGame.as class every time an object needs to be created, would be a call to an external class. Ultimately, we want to be able to create our objects with pieces of code like this.

124
125
126
127
128
129
130
131
case "1": //When we want to create a block
    var block:Block = new Block(levelB, i, j, m_physScale, 1, STD_FRICTION, STD_RESTITUTION, this);
    m_sprite.addChild(block);						
break;
case "2": //When we want to create a ramp
    var rampa:Ramp = new Ramp(levelB, i, j, m_physScale, 1, STD_FRICTION, STD_RESTITUTION, this);
    m_sprite.addChild(rampa);					
break;

Isn’t that a lot simpler than the big block of code we had before. Basically, we are creating a new Block or Ramp object, and passing the necessary variables through the object instantiation. To better understand these variables, lets have a look inside the block class, which is defined in the seperate actionscript file Block.as.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class Block extends Sprite 
    {
        private var body:b2Body; //The body we want to attach the block to
        private var base:Object; //The base object or root of this object
        private var row:int; //The row this tile is to be placed at
        private var column:int; //The column this tile is to placed at
        private var m_physScale:int; //The physics scale of the world
        private var type:int; //The type of block. This is used for placing different graphics.
        private var bFriction:Number; //The friction of the block
        private var bRes:Number; //The bounce of the block
 
        public function Block(bd:b2Body, r:int, c:int, p:int, t:int, f:Number, res:Number, bs:Object)
        {   //Here we attribute the received values to our object
            body = bd;
            base = bs;
            row = r;
            column = c;
            m_physScale = p;
            bFriction = f;
            bRes = res;
            type = t;
            //Now we begin the function that builds the block
            addBlock();
        }

And now to have a quick look at the addBlock class. I won’t spend time commenting the Box2d code as we have examined this before. More important is the part of the code that deals with the graphics. In order to deal with multiple block with different graphics, a switch statement is used after the physics of the block has been created. This saves time creating different block classes when the only thing that changes is the graphics.

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
public function addBlock():void 
{
    var wallFd:b2FixtureDef = new b2FixtureDef();
    var wallSd:b2PolygonShape= new b2PolygonShape();						
    var wallBd:b2BodyDef = new b2BodyDef();
    wallBd.position.Set(column/ m_physScale*30, row/ m_physScale*30);
    wallBd.type = b2Body.b2_staticBody;
    wallFd.friction = bFriction;
    wallFd.restitution = bRes;
    wallFd.shape = wallSd;
 
    //Create an object with the name of the object and a reference to the root
    var dataObj:Object = new Object();
    dataObj.name = "BLOCK";
    dataObj.base = base;
    //This object is stored in the Fixture Definition userData object
    wallFd.userData = dataObj;
 
    wallSd.SetAsBox(15 / m_physScale, 15 / m_physScale);	//Dimensions of the block					
    body = base.m_world.CreateBody(wallBd); //Add the body to the physics world
    body.CreateFixture(wallFd);
    var xyPos:b2Vec2 = body.GetPosition(); //Gets the postion of the physics object
    this.x = xyPos.x*30; //Converts the physics position into normal pixels so when...
    this.y = xyPos.y*30; //...we place our object it will already be in the right place.
    switch(type) //Remember that type was a value passed in at the start
    {
        case 1: //This value decided what graphics the block uses
            var block1:Sprite = new BlockType1(); //Instantiate a BlockType1 as a sprite
            addChild(block1); //Add the block to the Display List
        break;
 
        case 2: //This is a different style of block
            var block2:Sprite = new BlockType2();
            addChild(block2);
        break;
    }		
}

And that is all there is to it. When these objects are instantiated, they will have both physical and graphical presence. Obviously this won’t work with dynamic objects as we only set the position of the graphic one time at the object creation. I won’t bother explaining the Ramp.as file as it is the same idea as the Block class. The only difference is that because different ramps face different ways, I had to include the structural code in a switch statement. Feel free to check out the full source code or just a simple version for editing levels in XML.

The Result

Note: The Box2d decoding graphics are still present behind our new graphics. If these were turned off now, you wouldn’t be able to see the moving objects.

Get Adobe Flash player

Box2d Game – Design Round 1

A partnership

I would like to take some time today to introduce the very talented designer I am working with on the Box2d game project. John Reyes and I have been working on story, game play, and discussing the general look of the project. After the brainstorming, I take over with the Actionscript, and he works on the visuals. He must be working hard on the look as he is yet to finish his own website, but when it is up and running, it will be at www.morigami.com.au.

Round 1 of the game graphics

Round 1 of the game graphics


So we finally have a hero and a princess in need of rescuing (who knows, maybe she is the hero). Although I am quite liking the look and feel, John assures me that he is still experimenting with visual styles, and wants to explore some more oriental styling, particularly for the ocean and the backgrounds. One thing I am sure of, there will be many more rounds of design, John is a bit of a perfectionist.

Let’s not forget story

Since both John and I are big computer game fans from way back, we know the importance of story. Despite the fact that this is planned to be a simple platformer, we want to give it a compelling and original story to tie the levels together. Something simple and elegant that can account for the fact that you basically aim for the same goal each level (and no, “Your princess is in another castle” will not suffice). We have something brewing, but will have to share it when it is finished (or at least when we make an intro).

Anyway, hope you enjoyed round one of design. The next game tutorial is going to revolve around getting some of these lovely graphics integrated into the Box2d engine.

Box2d Game – Game goals

Last post we looked at restarting the level and I spoke about how the same code could be used to also kill the player and return them to the start of the level, as well as progress the player to the next level when they reach their goal.

To setup the game engine to have goals and multiple levels, we need to refer back to some previous posts. First up, we need to make sure our XML has multiple levels included. In the post dealing with the XML data of the game, you can see that our code is already setup to parse multiple levels. All of the level data is fed into an array of objects found inside our Levels Object declared in TileGame.as.

54
private var L:Levels = new Levels("levels.xml");

This object can be used to refer to any particular level by number.

1
2
3
4
5
6
var lvlArray:Array = L.levels[0].data;
var lvlArray:Array = L.levels[1].data;
var lvlArray:Array = L.levels[2].data;
 
//Here the number is replaced by a variable to hold the current level
var lvlArray:Array = L.levels[lvlCurrent-1].data;

The next thing we need is a goal for the player to reach. When want this object to be able to detect collisions, but not be effected by them. Luckily, Box2d has just such an object type. They are called sensors, and they are fixed shapes that register contact from moving objects. Let have a look at the code needed to add a goal sensor into the game engine. In the XML, the goal object will be represented by a capital “G”.

187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
case "G":
    //Standard Box2d code for setting up a circle with 30 radius
    var goalBd:b2BodyDef = new b2BodyDef();
    goalBd.position.Set(j/ m_physScale*30, i/ m_physScale*30);
    var goalSd:b2CircleShape=new b2CircleShape(14 / m_physScale);
    var goalFd:b2FixtureDef = new b2FixtureDef();
 
    //To be able to refer to the goal we need to give it a name.
    //We put this name into an object in the userData of the Fixture
    //definition in case we want to add other information to it later.
    //I have also stored the object's base to I can refer to it later.
    dataObj = new Object();
    dataObj.name = "GOAL";
    dataObj.base = this;
    goalFd.userData = dataObj;
 
    //No density or friction as the object doesn't interact physically
    goalFd.shape=goalSd;
    goalFd.isSensor=true; //This is where we define the goal as a Sensor
    levelB = m_world.CreateBody(goalBd);
    levelB.CreateFixture(goalFd);
break;

Before we move on, I should point out that I have also added names to both the player object and the dynamic block objects. They are called “PLAYER” and “DBLOCK” respectively.

The Contact Listener

Now that we have a sensor to listen for, we need to create a class to listen for contacts, and take actions depending on which objects have been contacted. For full documentation of the the b2ContactListener class click here.

When we use the b2ContactListener class, we don’t actually create an instance of it, we create a new class that extends the original. We will create a new class in CustomCL.as that has all of the properties of b2ContactListener, with some custom code just for the game engine. Let’s take a look at that class in detail.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package {
    import Box2D.Dynamics.*;
    import Box2D.Collision.*;
    import Box2D.Collision.Shapes.*;
    import Box2D.Dynamics.Joints.*;
    import Box2D.Dynamics.Contacts.*;
    import Box2D.Common.*;
    //Note this class extends the b2ContactListener
    public class CustomCL extends b2ContactListener
    {
        //We want to over ride the BeginContact function which is
        //called every time two objects make contact
        override public function BeginContact(contact:b2Contact):void
        {			
            //Every contact involves two objects only, we refer to the
            //objects by as fixtures within the contact listener
            var fixtureA:b2Fixture=contact.GetFixtureA();
            var fixtureB:b2Fixture=contact.GetFixtureB();
            var base:Object = new Object();			
            var userDataA:Object = new Object();
            var userDataB:Object = new Object();
 
            //We only want to test for sensor contacts to save CPU time
            if (fixtureB.IsSensor() || fixtureA.IsSensor()) 
            {				
                //Get the user data from the fixtures
                userDataA = fixtureA.GetUserData();
                userDataB = fixtureB.GetUserData();
                //The base of each object has been stored in the user data
                base = userDataA.base;
                //The following switch statement handles all interactions
                switch(userDataA.name)
                {
                    case "PLAYER":
                        switch(userDataB.name)
                        {
                            //If the player contacts the goal then
                            //increase the level and initiate a reset
                            case "GOAL":
                                base.lvlCurrent++;
                                base.reset = true;
			    break;
                        }
                    break;
                    case "DBLOCK":
                        switch(userDataB.name)
                        {
                            //If a block contacts the goal then just initiate
                            //a reset, forcing the player to start again
                            case "GOAL":
                                base.reset = true;
                            break;
                        }
                    break;
                }
            }
        }
    }
}

While it may look silly using switch statements to for such a simple logic tree, I want this script to have room to grow. With some more complicate elements, such as enemies, boost tiles and other interactions, it will need to be robust.

Also note that the goal is always the fixtureB. I need to do some more research, but I think this is because it is static, I am not sure what the result would be if it could also move.

Source files

Here is the source code, and here is a simpler version where you can edit levels, but not the original source code.

The challenges we face

For a while, I have wanted to have a reset button for this game. Often, I will get the player stuck in some position, or lose him all together off the map, and will have to restart the flash file to restart. What I realised, is that by building a reset button, I would also be creating the code I need to progress levels, and to send the player back to the start if he dies.

Because the game uses a combination of physics objects and normal movieclips, we need to be able to clear the entire level of both of these before we can rebuild another level over the top. Another important thing to remember, is that the game is constantly running cycles of the physics engine. You can’t remove objects mid cycle, so we will need to find the right place to stop and check if the reset button has been hit.

Let’s look at the code

First off, we setup reset and the current level as global variables in TileGame.as.

16
17
18
19
public class TileGame extends MovieClip
    {
        public var lvlCurrent:int = 1;
        public var reset:Boolean = false;

Then I added a new key to listen for in my key_pressed() event listener function

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
function key_pressed(event:KeyboardEvent):void {
    if (event.keyCode == 37) {
        rightKeyDown = true;
    }
    if (event.keyCode == 39) {
        leftKeyDown = true;
    }
    if (event.keyCode == 38) {
        upKeyDown = true;
    }			
    if (event.keyCode == 40) {
        downKeyDown = true;
    }	
    //The new reset key is a lowercase "r"
    if (event.keyCode == 82) {
        reset = true;
    }	
}

So now we have function that sets the reset variable to true every time the “r” key is pressed. But how do we translate that into actually resetting the level? As I said before, we need to make sure we do our resetting in the right place. We need to do it at the start of a physics cycle to make sure that no physics calculations are happening when we start destroying the level. So we check for a level reset at the start of the run() function which basically runs the entire engine.

324
325
326
327
328
329
330
331
332
private function run(e:Event):void
{
    if(reset)
    {
        destroyLvl();
    }
 
    // The rest of the function updates physics etc etc
}

Below is a detailed look at the destroyLvl() function. Before destroying any objects though, the game engine needs to be stopped. By removing the ENTER_FRAME event listener, the game no longer calls the run() function, and we can begin deleting the objects that make up the level. We do not need to restart this listener, as that is done at the end of the createLvl() function which we call at the end.

244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
private function destroyLvl()
{
    //Temporarily stops the game running
    removeEventListener(Event.ENTER_FRAME, run); 
 
    //Put the value back to false for when the game starts again
    reset = false;
 
    //Gets a list of every physics object created
    var node:b2Body = m_world.GetBodyList();
 
    //Loops through each object and destroys it
    while (node)
    {
        var b:b2Body = node;
        node = node.GetNext();
        m_world.DestroyBody(b);
    }
 
    //Loops through every sprite in the level and destroys it
    while (m_sprite.numChildren)
    {
        m_sprite.removeChildAt(0);
    }
 
    //Recreate the level from scratch
    //Note: null needed because at the moment, createLvl is an 
    //event function but this will be fixed in later versions
    createLvl(null);
}

We can also use this destroyLvl() function to progress to the next level, all you need to do is increase the lvlCurrent variable before you change the reset variable to true. For an example, see below.

1
2
lvlCurrent++;
reset = true;

When our level gets created, we use the lvlCurrent variable to tell it which level to build from our Levels array.

81
82
83
84
85
86
private function createLvl(e:Event):void
    {
        //The -1 is needed as arrays always start at 0
        var lvlArray:Array = L.levels[lvlCurrent-1].data;
 
        //... createLvl function continues as normal

Next post we will look into object collision detection within the Box2d physics engine, and how it can be used to create game goals, enemies and other effects.

Source files

Here is the source code, and here is a simpler version where you can edit levels, but not the original source code.

The game engine (remember to double click inside the box to play)

Don’t forget to try the “r” key to reset the level

Get Adobe Flash player

Hello again, I am back from my holiday and am now living near Milan Italy. The last post I made showed a lot of improvements to the game engine, but I did not have time to describe the additions in detail. Today I will be describing in more detail the new camera movement being used in the game Please refer to the last post for game source files.

The reason I had to write a smarter camera into the code is because the old camera would follow the player no matter where it went. If the player is near the edge of the screen, or the whole level fits within the screen, we don’t want the camera to follow. When the camera should and shouldn’t follow can be a little confusing to put into code, so lets look at it in a diagram first.

Camera Movement Diagram

This diagram shows how the program calculates camera movement

The rules of camera movement

In this diagram, X equals the screen or stage width, and Y is the height. When the player’s X position is more than half of the stage width, the camera begins to follow. If however, the player becomes close to the other side of the level (when the player’s X position is greater than the level width minus half the stage width) the camera ceases to follow again.

Visually, when the player’s position is in the lightest grey areas, the camera doesn’t follow at all. When the player is in the medium grey areas, the camera follows the X or Y movement of the player, and when the player is in the darkest grey area, the camera follows both the X and Y movement of the player. Whew! I knew it would be difficult to explain in words. Let’s have a look at it in the code.

The following extract of code is found in the TileGame.as file at line 269 of last weeks source code files.

Camera Movement Code

269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
//Please note: m_sprite is basically a container for the whole level
//and WORLD_OFFSET is a constant used to adjust the level positioning.
 
private function moveWorld()
{
	var vect:b2Vec2 = player.GetPosition(); //Sprite position in Vect format
 
        //This statement deals with the player X position
	if(m_sprite.width>stage.stageWidth)
	{
                //If X position is away from the edges of the level
		if(vect.x*30 < (m_sprite.width - stage.stageWidth/2) && vect.x*30 > stage.stageWidth/2)
		{
                        //Notice there is no camera to move but the
                        //sprite containing the level which moves
			m_sprite.x = -(vect.x*30)+(stage.stageWidth/2);
		}
                //If the X position goes near the right edge
		else if(vect.x*30 >= (m_sprite.width - stage.stageWidth/2))
		{
                        //Set the camera to hold on the right edge
			m_sprite.x = -(m_sprite.width - stage.stageWidth);
		}
                //If the X position is close to the left edge
		else
		{
                        //Set the camera to hold on the left edge
			m_sprite.x = 0;
		}
                //An offset constant is added to place the camera exactly
		m_sprite.x = m_sprite.x+WORLD_OFFSET;
	}
 
        //We repeat the process with the Y position
	if(m_sprite.height>stage.stageHeight)
	{
		if(vect.y*30 < (m_sprite.height - stage.stageHeight/2) && vect.y*30 > stage.stageHeight/2)
		{
			m_sprite.y = -(vect.y*30)+(stage.stageHeight/2);
		}
		else if(vect.y*30 >= (m_sprite.height - stage.stageHeight/2))
		{
			m_sprite.y = -(m_sprite.height - stage.stageHeight);
		}
		else
		{
			m_sprite.y = 0;
		}
		m_sprite.y = m_sprite.y+WORLD_OFFSET;
	}
}

As you can see in the flash example from last week, we now have a camera that moves with the player, but will not pan so far as to expose the world beyond the edge of the level. See you soon for more details on game goals and creating multiple levels.

Powered by WordPress. Theme: Motion by 85ideas.