Understanding how AS3 manages Depths

This tutorial will explain you how to manage AS3 sprites and depths, and what's changed from AS2 to AS3.

In every Actionscript version, when two movieclips (or objects, shapes, texts...) overlap, the one with the greater depth stands in front of the other. You can think about depth as a Z coordinate.

The first difference between AS2 and AS3 is that AS2 allows you to leave "holes" in depths.

For example, you can declare the first object with a depth of 2 and the second one with a depth of 200... no matter if there isn't any object with a depth between 3 and 199. In AS3, this is no longer possible.

To add an object to the stage, you must use addChild(object_name).
addChild() assigns the first free depth available, just like AS2 MovieClip.getNextHighestDepth()

So let's add some objects to a movie:

ACTIONSCRIPT:
  1. package {
  2.     import flash.display.Shape;
  3.     import flash.display.Sprite;
  4.     public class depths extends Sprite {
  5.         public function depths() {
  6.             var blue_box:Shape = new Shape();
  7.             var red_box:Shape = new Shape();
  8.             blue_box.graphics.lineStyle(1);
  9.             blue_box.graphics.beginFill(0x0000FF, 1);
  10.             blue_box.graphics.drawRect(200,150,100,100);
  11.             red_box.graphics.lineStyle(1);
  12.             red_box.graphics.beginFill(0xFF0000, 1);
  13.             red_box.graphics.drawRect(220,170,100,100);
  14.             addChild(blue_box);
  15.             addChild(red_box);
  16.         }
  17.     }
  18. }

This is the result: the red box is in front of the blue box because the red one was the last placed on the screen.

Understanding AS3 Shapes, Sprites and Depths

If you switch line 14 with line 15, the blue one will be the one on the top:

Understanding AS3 Shapes, Sprites and Depths

Sno now we know that the first child added with addChild() is placed at depth 0, the second one is placed at depth 1, and so on.

To know the depth value of an object, you can use getChildIndex(object_name);. So if you add this line:

trace(getChildIndex(red_box));

You will get a 1 in your output window.

To add an object at a specific depth position, you can use addChildAt(object_name, depth)

So let's try this script:

ACTIONSCRIPT:
  1. package {
  2.     import flash.display.Shape;
  3.     import flash.display.Sprite;
  4.     public class depths extends Sprite {
  5.         public function depths() {
  6.             var blue_box:Shape = new Shape();
  7.             var red_box:Shape = new Shape();
  8.             blue_box.graphics.lineStyle(1);
  9.             blue_box.graphics.beginFill(0x0000FF, 1);
  10.             blue_box.graphics.drawRect(200,150,100,100);
  11.             red_box.graphics.lineStyle(1);
  12.             red_box.graphics.beginFill(0xFF0000, 1);
  13.             red_box.graphics.drawRect(220,170,100,100);
  14.             addChild(blue_box);
  15.             addChildAt(red_box,0);
  16.         }
  17.     }
  18. }

Even if the red box was added after the blue box, it's the blue one to stay on top because the red one was placed at depth zero.

Understanding AS3 Shapes, Sprites and Depths

That's because if the specified depth is already taken by an existing object, then the new object is placed behind the existing one, whose depth is increased by one. So at the end of the script, the red box has depth zero, while the blue one has depth 1

You may ask: what if I change line 14 with

addChildAt(blue_box,1);

You can't... you will get an error because as I said at the beginning of this post, you can't leave "holes" in depth. So you can't place an object at depth 1 if there isn't an object at depth 0.

Using getChildIndex in a real life example, you can change line 15 with

addChildAt(red_box,getChildIndex(blue_box));

And you will get the same result.

Now, let's see how to change depths dynamically.

ACTIONSCRIPT:
  1. package {
  2.     import flash.display.Shape;
  3.     import flash.display.Sprite;
  4.     public class depths extends Sprite {
  5.         public function depths() {
  6.             var blue_box:Shape = new Shape();
  7.             var red_box:Shape = new Shape();
  8.             blue_box.graphics.lineStyle(1);
  9.             blue_box.graphics.beginFill(0x0000FF, 1);
  10.             blue_box.graphics.drawRect(200,150,100,100);
  11.             red_box.graphics.lineStyle(1);
  12.             red_box.graphics.beginFill(0xFF0000, 1);
  13.             red_box.graphics.drawRect(220,170,100,100);
  14.             addChild(blue_box);
  15.             addChildAt(red_box,getChildIndex(blue_box));
  16.             swapChildren(red_box,blue_box);
  17.         }
  18.     }
  19. }

At line 16 the swapChildren method swaps red box's depth with the blue box one. So we'll have the red box in front again

Understanding AS3 Shapes, Sprites and Depths

Another way to change depths dynamically is changing line 16 with:

setChildIndex(blue_box,0);

Putting the blue box to depth zero again and make the red one stay on the top of the screen.

This was a brief introduction to AS3 depths. Obviously, more complex tutorials will come shortly.

Create a Flash game like Bloons tutorial

One of the moust famous Flash games ever is Bloons.

Bloons

Please, don't make me explain what I am talking about. Just play it. I really do not know why nobody tried to make a clone of such a simple game. Then I realized... that's because I never published a prototype of this game.

Now, it's time for me to give you the tools to flood the net with a million Bloons clones!

The prototype is heavily based on Create a flash artillery game - step 1, and I strongly recommend you to read it.

Then, here it is the source code, that will be commented once I will release a complete level

ACTIONSCRIPT:
  1. Mouse.hide();
  2. level = new Array();
  3. level[0] = new Array(1, 1, 1, 1, 1, 1, 1);
  4. level[1] = new Array(1, 0, 1, 1, 1, 0, 1);
  5. level[2] = new Array(1, 1, 1, 1, 1, 1, 1);
  6. level[3] = new Array(1, 1, 1, 0, 1, 1, 1);
  7. level[4] = new Array(1, 1, 1, 1, 1, 1, 1);
  8. level[5] = new Array(1, 0, 1, 1, 1, 0, 1);
  9. level[6] = new Array(1, 1, 1, 1, 1, 1, 1);
  10. for (y=0; y<=6; y++) {
  11.     for (x=0; x<=6; x++) {
  12.         if (level[y][x] == 1) {
  13.             the_bloon = _root.attachMovie("bloon", "bloon"+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:x*35+125, _y:y*35+20});
  14.             the_bloon.gotoAndStop(Math.floor(Math.random()*6+1));
  15.             the_bloon.onEnterFrame = function() {
  16.                 spike_x = cannonball._x+20*Math.cos(cannonball._rotation/180*Math.PI)
  17.                 spike_y = cannonball._y+20*Math.sin(cannonball._rotation/180*Math.PI)
  18.                 if (this.hitTest(spike_x, spike_y, true)) {
  19.                     this.removeMovieClip();
  20.                 }
  21.             }
  22.         }
  23.     }
  24. }
  25. gravity = 2;
  26. firing = 0;
  27. firepower = 0;
  28. fire_increment = 1;
  29. bullet_in_air = false;
  30. attachMovie("crosshair","crosshair",_root.getNextHighestDepth());
  31. attachMovie("tank","tank",_root.getNextHighestDepth(),{_x:230, _y:350});
  32. crosshair.onEnterFrame = function() {
  33.     this._x = _xmouse;
  34.     this._y = _ymouse;
  35. };
  36. tank.onEnterFrame = function() {
  37.     mousex = _xmouse-this._x;
  38.     mousey = (_ymouse-this._y)*-1;
  39.     angle = Math.atan2(mousey, mousex);
  40.     this.cannon._rotation = -angle*180/Math.PI;
  41.     if (firing) {
  42.         if ((firepower>50) or (firepower<0)) {
  43.             fire_increment *= -1;
  44.         }
  45.         firepower += fire_increment;
  46.         this.cannon.powermeter._width += fire_increment;
  47.     }
  48. };
  49. function onMouseDown() {
  50.     if ((!firing) and (!bullet_in_air)) {
  51.         firing = true;
  52.     }
  53. }
  54.  
  55. function onMouseUp() {
  56.     if (firing) {
  57.         firing = false;
  58.         tank.cannon.powermeter._width = 40;
  59.         fire_increment = 1;
  60.         angle = tank.cannon._rotation;
  61.         start_ball_x = tank._x+48*Math.cos(angle*Math.PI/180);
  62.         start_ball_y = tank._y+48*Math.sin(angle*Math.PI/180);
  63.         cannonball_fired = attachMovie("cannonball", "cannonball", 10000, {_x:start_ball_x, _y:start_ball_y});
  64.         cannonball_fired.dirx = Math.cos(angle*Math.PI/180)*firepower;
  65.         cannonball_fired.diry = Math.sin(angle*Math.PI/180)*firepower;
  66.         bullet_in_air = true;
  67.         cannonball_fired.onEnterFrame = function() {
  68.             this.diry += gravity;
  69.             this._x += this.dirx/2;
  70.             this._y += this.diry/2;
  71.             this._rotation = Math.atan2(this.diry, this.dirx)*180/Math.PI;
  72.             if (this._y>400) {
  73.                 bullet_in_air = false;
  74.                 this.removeMovieClip();
  75.             }
  76.         };
  77.         firepower = 0;
  78.     }
  79. }

And here it is the result:

Enjoy!!!! And download the source!!

Full Renju game with source code

Do you know what is Renju?

From Wikipedia: Renju or Lianzhu is the professional variant of Gomoku, a board game originated from Japan in Heian Period. It was named Renju by Japanese journalist Ruikou Kuroiwa in December 6, 1899 in a Japanese newspaper Yorozu chouhou.
Lianzhu is a Chinese translation of Renju. It is played with black and white stones on a 15x15 intersection Go board. Renju eliminates the "Perfect Win"-situation in Gomoku by adding special conditions for the first player (Black).

I suggest you to take a look at the rules and then you're ready to play ActionScript Notes' version.

Very goodlooking graphics and challenging AI is what you'll get playing this version of Renju

Renju is built around PureMVC framework a lightweight framework for creating applications based upon the classic Model-View-Controller design meta-pattern.

You may think this game - with fancy graphics, advanced AI and framework programming - should be protected, encrypted and whatever, but... ActionScript Notes owner released the source code... a priceless gift for us programmers.

Download this AS3 pearl and give the author some feedback, and don't forget to visit ActionScript Notes where you will find, among other interesting things, a Flash Mac Style Flash Menu with full source code.

Great job!

Create a Flash ball game using AS3

Ok... I think it's time to start talking about Actionscript 3. Even if AS2 is way to be dead, is becoming a bit obsolete... every new library like Box2DFlashAS3 only works in AS3, so sooner or later we must learn AS3.

Obviously I won't stop talking about AS2 until it's dead and stinking... but this tutorial is dedicated to AS3

I am going to create the same prototype explained at Flash game creation tutorial - part 1, just using AS3

The first thing you have to do, is creating the ball itself as a new object, and giving it the ball linkage name, as usual.

Then, in the Movie Properties panel, you must specify the document class. Also, in the Publish Settings panel, you must specify the path where you will save the class (called ClassPath) as shown in the image.

AS3

Now, you're ready to write your class file... click on the pencil next to your document class name and here it is the AS3 code:

ACTIONSCRIPT:
  1. package {
  2.     import flash.display.*;
  3.     import flash.events.*;
  4.     import flash.ui.*;
  5.     public class as3ball extends MovieClip {
  6.         var the_hero: Sprite = new ball();
  7.         var power = 0.3;
  8.         var friction = 0.95;
  9.         var xspeed = 0;
  10.         var yspeed = 0;
  11.         var up = false;
  12.         var down = false;
  13.         var left = false;
  14.         var right = false;
  15.         public function as3ball() {
  16.             addChild(the_hero);
  17.             the_hero.x = 250;
  18.             the_hero.y = 200;
  19.             stage.addEventListener(KeyboardEvent.KEY_DOWN, key_pressed);
  20.             stage.addEventListener(KeyboardEvent.KEY_UP, key_released);
  21.             addEventListener(Event.ENTER_FRAME, render);
  22.         }
  23.         function key_pressed(e:KeyboardEvent):void {
  24.             switch (e.keyCode) {
  25.                 case Keyboard.UP :
  26.                     up = true;
  27.                     break;
  28.                 case Keyboard.DOWN :
  29.                     down = true;
  30.                     break;
  31.                 case Keyboard.LEFT :
  32.                     left = true;
  33.                     break;
  34.                 case Keyboard.RIGHT :
  35.                     right = true;
  36.                     break;
  37.             }
  38.         }
  39.         function key_released(e:KeyboardEvent):void {
  40.             switch (e.keyCode) {
  41.                 case Keyboard.UP :
  42.                     up = false;
  43.                     break;
  44.                 case Keyboard.DOWN :
  45.                     down = false;
  46.                     break;
  47.                 case Keyboard.LEFT :
  48.                     left = false;
  49.                     break;
  50.                 case Keyboard.RIGHT :
  51.                     right = false;
  52.                     break;
  53.             }
  54.         }
  55.         private function render(e:Event):void {
  56.             if (up) {
  57.                 yspeed -= power;
  58.             }
  59.             if (down) {
  60.                 yspeed += power;
  61.             }
  62.             if (left) {
  63.                 xspeed -= power;
  64.             }
  65.             if (right) {
  66.                 xspeed += power;
  67.             }
  68.             xspeed *= friction;
  69.             yspeed *= friction;
  70.             the_hero.x += xspeed;
  71.             the_hero.y += yspeed;
  72.         }
  73.     }
  74. }

Line 1: declaration of the package in which we are going to build our class. Normally the syntax would be package

Line 2: importing the package that contains the core classes that the Flash Player uses to build visual displays.

Line 3: importing the package containing the classes to manage events such as keyboard events, mouse events, and more

Line 4: importing the package that contains user interface classes, such as classes for interacting with the mouse and keyboard

Line 5: declaration of the main class. Class name must be the same as the name of the .as file

Line 6: declaring a new variable called the_hero as a Sprite type (think about the sprite as an AS2 movieclip), and assigning it the ball movieclip. From now on, we will refer to the_hero everytime we want to move the ball.

Lines 7-10: declaring speed, power and friction variables as seen in the AS2 tutorial

Lines 11-14: Declaring four boolean variables, one for each direction, and setting them to false. You will understand why I am doing this later in this tutorial

Line 15: Declaration of the main function. You know this is the main function because of its name... the same as the class. Naming the function this way will make it execute once the movie is loaded

Line 16: Adding the hero to stage. addChild is the AS3 method to see a display object appear on the Stage. In this case, it displays the the_hero sprite that contains the ball movieclip

Lines 17-18: Placing the_hero movieclip in the centre of the stage.

Line 19: Adding a listener for the KEY_DOWN event (a key is pressed) and calling the key_pressed function when the event is triggered

Event listeners, which are also called event handlers, are functions that Flash Player executes in response to specific events. In this case, the specific event is "a key is pressed", and the function to be executed is key_pressed. This function will be executed every time a key is pressed.

Line 20: Adding a listener for the KEY_UP event (a key is released) and calling the key_released function when the event is triggered

Line 21: Adding a listener for the ENTER_FRAME event (the beginning of a new frame, just like the old AS2 onEnterFrame) and calling the render function when the event is triggered

Line 23: Beginning of the function to be executed every time a key is pressed

Lines 24-37: Performing a switch with the keycode of the key pressed, setting to true the boolean variable corresponding to the arrow key pressed

Lines 39-53: Same thing for the key_pressed function, but the key_released sets to false the variable corresponding to the arrow key released

These two functions may seem useless, but they are the core of the script because I can't perform the old Key.isDown... I can only see when a key is pressed and when a key is released. And remember the player can press more than a key at the same time

Line 55: Function to be executed at every frame

Lines 56-71 follow the same rules seen at Flash game creation tutorial - part 1.

And here's the result:

As you can see, AS3 learning curve is a bit harder than AS2 one, but once you understand the basics, you can achieve results that are simply impossible to get with AS2

Hope this first tutorial will make you start using AS3 just like a lot of you said Flash game creation tutorial - part 1 made you start using AS2

Download the source code and give me feedback

Playing with Box2DFlashAS3

Some time ago I told you to watch Box2DFlashAS3 physics engine.

I dont' know if you did it, but I did. While the original Box2D project come to 2.0.0 version, the AS3 porting is "still" at 1.4.3, but soon it will be upgraded.

So I think it's absolutely time to play with this library.

While I won't be able to provide a full tutorial before some days, I made an interesting prototype in only 58 lines, brackets included.

ACTIONSCRIPT:
  1. package {
  2.     import flash.display.*;
  3.     import flash.events.*;
  4.     import Box2D.Dynamics.*;
  5.     import Box2D.Collision.*;
  6.     import Box2D.Collision.Shapes.*;
  7.     import Box2D.Common.Math.*;
  8.     public class theclass extends Sprite {
  9.         var body_def:b2BodyDef;
  10.         var shape_def:b2BoxDef;
  11.         public var the_world:b2World;
  12.         public function theclass() {
  13.             var container:b2AABB = new b2AABB();
  14.             container.minVertex.Set(0.0, 0.0);
  15.             container.maxVertex.Set(500.0, 400.0);
  16.             the_world = new b2World(container, new b2Vec2(0, 300.0), true);
  17.             body_def = new b2BodyDef();
  18.             shape_def = new b2BoxDef();
  19.             shape_def.extents.Set(250,10);
  20.             shape_def.friction = 1;
  21.             body_def.position.Set(250,390);
  22.             body_def.AddShape(shape_def);
  23.             body_def.userData = new floor();
  24.             body_def.userData.width = 500;
  25.             body_def.userData.height = 20;
  26.             addChild(body_def.userData);
  27.             the_world.CreateBody(body_def);
  28.             addEventListener(Event.ENTER_FRAME, render);
  29.             addEventListener(MouseEvent.CLICK, mouse_handler);
  30.         }
  31.         private function mouse_handler(event:MouseEvent):void {
  32.             body_def = new b2BodyDef();
  33.             shape_def = new b2BoxDef();
  34.             shape_def.extents.Set(Math.floor(Math.random()*15)+15,Math.floor(Math.random()*15)+15);
  35.             shape_def.friction = 1;
  36.             shape_def.density = 1;
  37.             shape_def.restitution = 0.2;
  38.             body_def.position.Set(Math.random()*400+50,0);
  39.             body_def.AddShape(shape_def);
  40.             body_def.userData = new crate();
  41.             body_def.userData.width = shape_def.extents.x * 2;
  42.             body_def.userData.height = shape_def.extents.y * 2;
  43.             addChild(body_def.userData);
  44.             body_def.userData.gotoAndStop(Math.floor(Math.random()*6)+1);
  45.             the_world.CreateBody(body_def);
  46.         }
  47.         public function render(e:Event):void {
  48.             the_world.Step(1/30, 10);
  49.             for (var x:b2Body = the_world.m_bodyList; x; x = x.m_next) {
  50.                 if (x.m_userData is Sprite) {
  51.                     x.m_userData.x = x.m_position.x;
  52.                     x.m_userData.y = x.m_position.y;
  53.                     x.m_userData.rotation = x.m_rotation * 57.2957795;
  54.                 }
  55.             }
  56.         }
  57.     }
  58. }

And the result is really interesting, and virtually impossible to achieve without the library... just click on the floor and see what happens...

I think it's time to start learning AS3 with this interesting library... meanwhile you can download the source code with the last version of Box2DFlashAS3 library.

Creation of a platform game with Flash – step 3

To show you how hard I am going to try wiping the vaporware out of my life, I am publishing the 3rd part of the platform game tutorial.

Read parts 1 and 2 if you don't remember what I am talking about.

In this update, I introduced two new tile types: the lava tile that kills you when you walk over it (read: when you walk over it, not when you touch it), and the horizontally moving tile, that automatically (read: automatically) connects two spots.

The code needs to be cleaned, but everything seems to work

ACTIONSCRIPT:
  1. // player default speeds
  2. xspeed = 0;
  3. yspeed = 0;
  4. max_yspeed = 10;
  5. walk_speed = 4;
  6. climb_speed = 2;
  7. // am I climbing?
  8. climbing = false;
  9. // am I jumping?
  10. jumping = false;
  11. // can I jump?
  12. can_jump = true;
  13. // gravity & jump settings
  14. gravity = 1;
  15. jump_power = 10;
  16. walking_while_jumping = true;
  17. // level creation
  18. level = new Array();
  19. _root.createEmptyMovieClip("lev", _root.getNextHighestDepth());
  20. _root.createEmptyMovieClip("lad", _root.getNextHighestDepth());
  21. _root.createEmptyMovieClip("lava", _root.getNextHighestDepth());
  22. _root.createEmptyMovieClip("moving", _root.getNextHighestDepth());
  23. level[0] = new Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
  24. level[1] = new Array(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
  25. level[2] = new Array(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
  26. level[3] = new Array(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
  27. level[4] = new Array(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
  28. level[5] = new Array(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1);
  29. level[6] = new Array(1, 0, 0, 0, 0, 0, 1, 1, 1, 4, 0, 0, 1, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1);
  30. level[7] = new Array(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1);
  31. level[8] = new Array(1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1);
  32. level[9] = new Array(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1);
  33. level[10] = new Array(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1);
  34. level[11] = new Array(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1);
  35. level[12] = new Array(1, 0, 0, 0, 0, 0, 0, 1, 3, 1, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1);
  36. level[13] = new Array(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
  37. level[14] = new Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 1);
  38. for (y=0; y<=14; y++) {
  39.     for (x=0; x<=24; x++) {
  40.         if (level[y][x] == 1) {
  41.             place_brick = lev.attachMovie("block", "block_"+lev.getNextHighestDepth(), lev.getNextHighestDepth(), {_x:x*20+10, _y:y*20+10});
  42.             place_brick.gotoAndStop(level[y][x]);
  43.         }
  44.         if (level[y][x] == 2) {
  45.             ladder_brick = lad.attachMovie("block", "block_"+lad.getNextHighestDepth(), lad.getNextHighestDepth(), {_x:x*20+10, _y:y*20+10});
  46.             ladder_brick.gotoAndStop(level[y][x]);
  47.         }
  48.         if (level[y][x] == 3) {
  49.             lava_brick = lava.attachMovie("block", "block_"+lava.getNextHighestDepth(), lava.getNextHighestDepth(), {_x:x*20+10, _y:y*20+10});
  50.             lava_brick.gotoAndStop(level[y][x]);
  51.         }
  52.         if (level[y][x] == 4) {
  53.             moving_brick = moving.attachMovie("block", "block_"+moving.getNextHighestDepth(), moving.getNextHighestDepth(), {_x:x*20+10, _y:y*20+10});
  54.             moving_brick.gotoAndStop(level[y][x]);
  55.             moving_brick.dir = 1;
  56.             moving_brick.onEnterFrame = function() {
  57.                 this._x += this.dir;
  58.                 if ((_root.lev.hitTest(this._x+10, this._y, true) and (this.dir>0)) or ((_root.lev.hitTest(this._x-10, this._y, true) and (this.dir<0)))) {
  59.                     this.dir *= -1;
  60.                 }
  61.                 if (_root.player.hitTest(this._x, this._y-11, true) or _root.player.hitTest(this._x+5, this._y-11, true) or _root.player.hitTest(this._x-5, this._y-11, true)) {
  62.                     player._x += this.dir;
  63.                 }
  64.             };
  65.         }
  66.     }
  67. }
  68. _root.attachMovie("player", "player", _root.getNextHighestDepth(), {_x:40, _y:40});
  69. // end of level creation
  70. player.onEnterFrame = function() {
  71.     if (Key.isDown(Key.LEFT)) {
  72.         if (climbing) {
  73.             xspeed = -climb_speed;
  74.         } else {
  75.             if (walking_while_jumping or can_jump) {
  76.                 xspeed = -walk_speed;
  77.             }
  78.         }
  79.     }
  80.     if (Key.isDown(Key.RIGHT)) {
  81.         if (climbing) {
  82.             xspeed = climb_speed;
  83.         } else {
  84.             if (walking_while_jumping or can_jump) {
  85.                 xspeed = walk_speed;
  86.             }
  87.         }
  88.     }
  89.     if (!feet_on_ladder()) {
  90.         climbing = false;
  91.     }
  92.     if (Key.isDown(Key.UP)) {
  93.         if (feet_on_ladder()) {
  94.             yspeed = -climb_speed;
  95.             climbing = true;
  96.             jumping = false;
  97.         }
  98.     }
  99.     if (Key.isDown(Key.DOWN)) {
  100.         if (feet_on_ladder() or ladder_under_my_feet()) {
  101.             yspeed = climb_speed;
  102.             climbing = true;
  103.             jumping = false;
  104.         }
  105.     }
  106.     if ((Key.isDown(Key.SPACE)) and can_jump and !jumping and !climbing) {
  107.         yspeed -= jump_power;
  108.         jumping = true;
  109.     }
  110.     // adjusting y speed                        
  111.     if (!climbing) {
  112.         yspeed += gravity;
  113.     }
  114.     if (yspeed>max_yspeed) {
  115.         yspeed = max_yspeed;
  116.     }
  117.     if (level_under_my_feet() and !jumping and !climbing) {
  118.         yspeed = 0;
  119.     }
  120.     if (ladder_under_my_feet() and !jumping and !climbing) {
  121.         yspeed = 0;
  122.     }
  123.     forecast_x = this._x+xspeed;
  124.     forecast_y = this._y+yspeed;
  125.     // lava control
  126.     if (_root.lava.hitTest(forecast_x, forecast_y+this._height/2-1, true)) {
  127.         forecast_x = 40;
  128.         forecast_y = 40;
  129.         jumping = false;
  130.     }
  131.     // floor control            
  132.     while ((_root.lev.hitTest(forecast_x, forecast_y+this._height/2-1, true)) or (_root.moving.hitTest(forecast_x, forecast_y+this._height/2-1, true))) {
  133.         forecast_y--;
  134.         xspeed = 0;
  135.         yspeed = 0;
  136.         jumping = false;
  137.     }
  138.     // ceiling control
  139.     while (_root.lev.hitTest(forecast_x, forecast_y-this._height/2, true) or (_root.lava.hitTest(forecast_x, forecast_y-this._height/2, true)) or (_root.moving.hitTest(forecast_x, forecast_y-this._height/2, true))) {
  140.         forecast_y++;
  141.         yspeed = 0;
  142.     }
  143.     // left wall control
  144.     while (_root.lev.hitTest(forecast_x-this._width/2+1, forecast_y, true)) {
  145.         forecast_x++;
  146.         xspeed = 0;
  147.     }
  148.     // right wall control
  149.     while (_root.lev.hitTest(forecast_x+this._width/2, forecast_y, true)) {
  150.         forecast_x--;
  151.         xspeed = 0;
  152.     }
  153.     this._x = forecast_x;
  154.     this._y = forecast_y;
  155.     // adjusting speeds for next frame
  156.     xspeed = 0;
  157.     if (climbing) {
  158.         yspeed = 0;
  159.     }
  160. };
  161. function feet_on_ladder() {
  162.     return _root.lad.hitTest(player._x, player._y+player._height/2-1, true);
  163. }
  164. function level_under_my_feet() {
  165.     return _root.lev.hitTest(player._x, player._y+player._height/2, true);
  166. }
  167. function ladder_under_my_feet() {
  168.     return _root.lad.hitTest(player._x, player._y+player._height/2, true);
  169. }

and, more important, I am learning how to fight vaporware plague.

Download the source code and give me the proof I can defeat vaporware.

Wipe the vaporware out of your life

Do you know what's the so-called vaporware?

From Wikipedia: Vaporware is a software or hardware product which is announced by a developer well in advance of release, but which then fails to emerge, either with or without a protracted development cycle.

Interesting thing... they gave a name to most developers' habit... starting a project and turning it into vaporware.

One of the most famous vaporwares is Duke Nukem Forever, but I must admit I am full of vaporware

Duke Nukem Forever

I have three one-week games, about 5 one-day games and at least 10 blog posts that at the time of writing are vaporware

If a triple-A game can become vaporware because of financial issues, it's really a shame when a Flash game becomes vaporware.

What makes a Flash game disappear into vaporware?

I found 2 main reasons

1) The "I can complete it whenever I want" syndrome

2) Another more interesting game to do (that will become vaporware for another more interesting game to do, that will become...)

Remember: vaporware affects your incomes, because you worked for hours and you did not earn anything

Am I the only one affected by vaporware plague or is it pandemic?

How do you try to wipe out it?

I have some suggestions, but I will discuss about them later, or this post will become another vaporware

Make a Flash game like BoxHead – part 1

One of the most popular Flash games is BoxHead by Sean Cooper, that released the 5th game of the series called The Zombie Wars.

BoxHead

At the moment I am just giving a small prototype of the "hero" controlled with arrow keys and the "zombie" chasing the hero.

One of the interesting things about BoxHead is that all movements are based upon old 8-ways system... this means hero and zombies can walk only on 0, 45, 90, 135, 180, 225, 270 and 315 degrees.

So there is not so much trigonometry involved in it.

ACTIONSCRIPT:
  1. _root.attachMovie("hero","hero",_root.getNextHighestDepth(),{_x:250, _y:200});
  2. _root.attachMovie("zombie","zombie",_root.getNextHighestDepth(),{_x:25, _y:20});
  3. hero_speed = 1.5;
  4. zombie_speed = 1;
  5. zombie.same_rotation = 0;
  6. hero.onEnterFrame = function() {
  7.     xspeed = 0;
  8.     yspeed = 0;
  9.     if (Key.isDown(Key.LEFT)) {
  10.         xspeed -= hero_speed;
  11.     }
  12.     if (Key.isDown(Key.RIGHT)) {
  13.         xspeed += hero_speed;
  14.     }
  15.     if (Key.isDown(Key.UP)) {
  16.         yspeed -= hero_speed;
  17.     }
  18.     if (Key.isDown(Key.DOWN)) {
  19.         yspeed += hero_speed;
  20.     }
  21.     if ((xspeed != 0) and (yspeed != 0)) {
  22.         xspeed *= 0.707;
  23.         yspeed *= 0.707;
  24.     }
  25.     this._x += xspeed;
  26.     this._y += yspeed;
  27.     switch (xspeed) {
  28.         case hero_speed :
  29.             this._rotation = 90;
  30.             break;
  31.         case -hero_speed :
  32.             this._rotation = -90;
  33.             break;
  34.         default :
  35.             switch (yspeed) {
  36.                 case hero_speed :
  37.                     this._rotation = 180;
  38.                     break;
  39.                 case -hero_speed :
  40.                     this._rotation = 0;
  41.                     break;
  42.                 case hero_speed*0.707 :
  43.                     if (xspeed == hero_speed*0.707) {
  44.                         this._rotation = 135;
  45.                     }
  46.                     if (xspeed -= hero_speed*0.707) {
  47.                         this._rotation = -135;
  48.                     }
  49.                     break;
  50.                 case -hero_speed*0.707 :
  51.                     if (xspeed == hero_speed*0.707) {
  52.                         this._rotation = 45;
  53.                     }
  54.                     if (xspeed -= hero_speed*0.707) {
  55.                         this._rotation = -45;
  56.                     }
  57.                     break;
  58.             }
  59.     }
  60. };
  61. zombie.onEnterFrame = function() {
  62.     this.same_rotation++;
  63.     dist_x = this._x-hero._x;
  64.     dist_y = this._y-hero._y;
  65.     angle = Math.atan2(dist_y, dist_x);
  66.     real_rotation = angle*57.2957795-90;
  67.     this._save_rotation = this._rotation;
  68.     if (this.same_rotation>15) {
  69.         this._rotation = Math.round(real_rotation/45)*45;
  70.     }
  71.     if (this._rotation != this._save_rotation) {
  72.         this.same_rotation = 0;
  73.     }
  74.     switch (this._rotation) {
  75.         case 0 :
  76.             this._y -= zombie_speed;
  77.             break;
  78.         case 45 :
  79.             this._y -= zombie_speed*0.707;
  80.             this._x += zombie_speed*0.707;
  81.             break;
  82.         case 90 :
  83.             this._x += zombie_speed;
  84.             break;
  85.         case 135 :
  86.             this._y += zombie_speed*0.707;
  87.             this._x += zombie_speed*0.707;
  88.             break;
  89.         case -180 :
  90.             this._y += zombie_speed;
  91.             break;
  92.         case -135 :
  93.             this._y += zombie_speed*0.707;
  94.             this._x -= zombie_speed*0.707;
  95.             break;
  96.         case -90 :
  97.             this._x -= zombie_speed;
  98.             break;
  99.         case -45 :
  100.             this._y -= zombie_speed*0.707;
  101.             this._x -= zombie_speed*0.707;
  102.             break;
  103.     }
  104. };

I will comment the code later, meanwhile if you have questions post them in the comments.

Download the source code and give me feedback

Where in the world are your Flash games being played now?

It's an interesting question, isn't it?

Maybe in the near future MochiAds guys will be able to answer this question.

This is a message from JamesonH:

Here's a little feature that one of our Computer Scientists, Emad, put together to show how global Flash games are. It's still very experimental and there are a lot of ideas that can stem from this. I hope that you all can provide some feedback and insight into whether or not you, the community, would like to make some of these things yourself were we to make the data available.

Enjoy!

The service is called MochiMaps and I do not understand how does it work, but I am glad Christmas Couples is being played in France now :)

MochiMaps

MochiAds is looking for some feedback/suggestion about this feature, so let's give them some ideas!

http://maps.mochiads.com/

From zero to Bombuzal – step 4

One of the biggest problems of step 3 was Bombuzal waled sooo slowly.

So I added a variable called walk_speed where I assign the walking speed in pixels per frame.

Then, in the original game you have to think fast. You can't stay on the same tile for more than about 5 secods, or the tile where you are over will turn in a spinning tile that will spin Bombuzal in a random direction everytime it walks on it.

But it's not over: if Bombuzal stays on a tile with a bomb for more than 5 seconds, the tile won't become a spinning tile but the bomb will explode, killing Bombuzal.

If Bombuzal stays on a disappearing tile for more than 5 seconds, the disappearing tile will... disappear, making Bombuzal fall down.

A lot of exceptions for an old C64 game!

At the moment, I won't make any tile change, but I will move Bombuzal in a random direction if it stays more than 5 seconds on the same tile.

I am creating a counter called does_not_move that will count all frames passed since the last time Bombuzal moved. If the counter reaches 150, then I'll randomly move Bombuzal Read more

Next Page →

Posts