from Emanuele Feronato

Create a Flash game like Gold Miner - step 2 (Fri, 10 Oct 2008 14:02:17 +0000)

I received a lot of emails asking me to add left-right movement to my Gold Miner clone and requiring more information about manually placing the boulders.

In order to add left-right movement, you need to check for left and right arrow keys and move the hook in the proper direction.

Just remember you don't have to let the hook move out of the stage and to update the starting/ending points of the rope.

When you want to manually place boulders, you need an array.

In the one I created, every boulder is an array made this way

[x position, y position, diameter]

Then I created an array containing n boulder arrays where n is the number of boulder I wanted to be in the stage.

Here it is the commented code:

ACTIONSCRIPT:
  1. // boulders are stored in an array
  2. // [0] is x pos
  3. // [1] is y pos
  4. // [2] is the width
  5. // don't make boulders too large (<50) or the rewind won't work
  6. // until you change slowdown formula
  7. boulders = [[100, 100, 30], [200, 100, 40], [300, 100, 40], [400, 100, 30], [100, 200, 30], [200, 200, 40], [300, 200, 40], [400, 200, 30], [100, 300, 30], [200, 300, 40], [300, 300, 40], [400, 300, 30]];
  8. for (x=0; x<boulders.length; x++) {
  9.     // creating the boulders
  10.     bould = _root.attachMovie("boulder", "boulder_"+_root.getNextHighestDepth(), _root.getNextHighestDepth());
  11.     // placing them in random positions and with random dimensions
  12.     bould._x = boulders[x][0];
  13.     bould._y = boulders[x][1];
  14.     bould._width = boulders[x][2];
  15.     bould._height = boulders[x][2];
  16.     // setting picked attribute as false
  17.     // picked = false => the boulder has not been picked by the hook
  18.     // picked = true => the boulder has been picked
  19.     bould.picked = false;
  20.     // function to be executed at every frame for the boulder
  21.     bould.onEnterFrame = function() {
  22.         // if it's not been picked...
  23.         if (!this.picked) {
  24.             // check if the hook is in shoot mode and touched the boulder
  25.             // you'll see later what do hot_spot_x and hot_spot_y mean
  26.             if (pod_status == "shoot" and this.hitTest(hot_spot_x, hot_spot_y, true)) {
  27.                 // set the hook on rewind mode
  28.                 pod_status = "rewind";
  29.                 // mark this boulder as picked
  30.                 this.picked = true;
  31.                 // determining the slowdown according to boulder size
  32.                 slowdown = Math.floor(this._width/5);
  33.             }
  34.         } else {
  35.             // the boulder has been picked, so move it as the hook moves
  36.             this._x = hot_spot_x;
  37.             this._y = hot_spot_y;
  38.             // if the hook status changed to rotate
  39.             // (this means: if the hook took a boulder and pulled it out to surface...
  40.             if (pod_status == "rotate") {
  41.                 // remove the boulder
  42.                 this.removeMovieClip();
  43.             }
  44.         }
  45.     };
  46. }
  47. // placing the hook on stage
  48. _root.attachMovie("pod", "pod", _root.getNextHighestDepth(), {_x:250});
  49. // creating an empty movie clip to draw the rope
  50. _root.createEmptyMovieClip("rod", _root.getNextHighestDepth());
  51. // this is the rotation direction and speed
  52. rotation_dir = 2;
  53. // hook initial status
  54. pod_status = "rotate";
  55. // slowdown malus
  56. slowdown = 0;
  57. // hook movement speed
  58. pod_speed = 4;
  59. // function the hook will execute at every frame
  60. pod.onEnterFrame = function() {
  61.     // getting pod status
  62.     switch (pod_status) {
  63.     case "rotate" :
  64.         // moving the hook to the left if player presses left
  65.         if (Key.isDown(Key.LEFT)) {
  66.             this._x -= pod_speed;
  67.             if (this._x<20) {
  68.                 this._x = 20;
  69.             }
  70.         }
  71.         // moving the hook to the right if player presses left   
  72.         if (Key.isDown(Key.RIGHT)) {
  73.             this._x += pod_speed;
  74.             if (this._x>480) {
  75.                 this._x = 480;
  76.             }
  77.         }
  78.         // if the status is rotate, just rotate the hook according to rotation_dir     
  79.         this._rotation += rotation_dir;
  80.         if (this._rotation == 80 or this._rotation == -80) {
  81.             // invert rotation_dir if the hook reaches its minimum (or maximum) rotation allowed
  82.             rotation_dir *= -1;
  83.         }
  84.         break;
  85.     case "shoot" :
  86.         // the hook has ben shoot
  87.         // (re)set slowdown malus to zero
  88.         slowdown = 0;
  89.         // moving the hook using trigonometry
  90.         this._x += 10*Math.cos(dir);
  91.         this._y += 10*Math.sin(dir);
  92.         // determining the hot spot of the hook
  93.         // the hot spot is the lowest corner of the hook (that acts like an harpoon in this case)
  94.         hot_spot_x = this._x+40*Math.cos(dir);
  95.         hot_spot_y = this._y+40*Math.sin(dir);
  96.         // if the hot spot goes off the stage
  97.         if (hot_spot_y>400 or hot_spot_x<0 or hot_spot_x>500) {
  98.             // then rewind the hook
  99.             pod_status = "rewind";
  100.         }
  101.         // draw a line from the hook starting position to its actual position       
  102.         // this will simulate the rope
  103.         rod.clear();
  104.         rod.lineStyle(1, 0x000000);
  105.         // once it started from (250,0), now that hook can move I am starting from (start_rope_x, 0)
  106.         rod.moveTo(start_rope_x, 0);
  107.         rod.lineTo(this._x, this._y);
  108.         break;
  109.     case "rewind" :
  110.         // clearing the rope
  111.         rod.clear();
  112.         // rewinding the hook...
  113.         // it may seem a nonsense determining the hot spot now, but I need id
  114.         // to move the boulder (if I have any boulder attached to the hook)
  115.         hot_spot_x = this._x+40*Math.cos(dir);
  116.         hot_spot_y = this._y+40*Math.sin(dir);
  117.         // moving the hook with slowdown malus (if any)
  118.         this._x -= (10-slowdown)*Math.cos(dir);
  119.         this._y -= (10-slowdown)*Math.sin(dir);
  120.         // if the hook returns in its initial position...
  121.         if (this._y<0) {
  122.             // then reset its position and set its status to rotate
  123.             this._y = 0;
  124.             this._x = start_rope_x;
  125.             pod_status = "rotate";
  126.         } else {
  127.             // drawing a line as seen in shoot status, but only if the hook is still in the air   
  128.             rod.lineStyle(1, 0x000000);
  129.             rod.moveTo(start_rope_x, 0);
  130.             rod.lineTo(this._x, this._y);
  131.         }
  132.         break;
  133.     }
  134. };
  135. // when the mouse is clicked...
  136. _root.onMouseDown = function() {
  137.     // if the status is rotate...
  138.     if (pod_status == "rotate") {
  139.         // save hook heading and convert it to radians
  140.         dir = (pod._rotation+90)*0.0174532925;
  141.         // setting rope start position... the last hook position
  142.         start_rope_x = pod._x;
  143.         // set pod status to shoot
  144.         pod_status = "shoot";
  145.     }
  146. };

And here it is the result...

Left/right arrows to move, mousebutton to fire.

Download the source code and enjoy

from Franto

AS3.0 KeyboardEvent WooDoo (Fri, 10 Oct 2008 13:43:47 +0000)

WTF? I don’t know what’s wrong, and if this is a bug or anything, but I came across interesting issue. Let me first tell, that it seems it’s bug on Windows, or maybe just my...

[[ This is a content summary only. Visit my website for full links, other content, and more! ]]416808178

from Emanuele Feronato

Put a banner with your MochiAds stats in your blog (Thu, 09 Oct 2008 16:32:22 +0000)

Let's imagine you made an awesome game and monetize it with MochiAds, and want to show your readers/the world how much your game rocks, now you have an interesting option.

Thanks to Rhu from Blargh now you can have a banner showing your game stats.

I am talking about something like this

You can find an easy wizard at the official page and some more suggestions in this MochiAds forum thread.

I asked Rhu to give me more information about this project and this is what he said:

« Gathering data can be done through JSON, the link for which can be found here for example:

https://www.mochiads.com/share/stats/plant-life/2b23e0751a87928d/json/impressions?start_date=2008-10-01&end_date=2008-10-06

It works equally as well if you just type in (last time I checked, they just changed to the above format recently I noticed):

https://www.mochiads.com/share/stats//json/impressions?start_date=2008-10-01&end_date=2008-10-06

The start/end dates will obviously need to be changed.

Graphics are all done through PHP, and are updated in the morning (the JSON stats suffer from the limitation of being updated once daily :) ). I also just got told that they're probably going to make it into an officially supported API sometime soon, so everyone should be able to make their own stats programs without much hassle (and without worry of them changing the JSON format :p ) »

That's really nice, I should consider developing a WP widget showing game stats...

from Emanuele Feronato

Basic level editor for a tile based game (Wed, 08 Oct 2008 10:43:00 +0000)

I am sharing with you a basic level editor made for the platform engine but easily adaptable to any tile based game made by Daniel Felipe Rodriguez

Your recent set of tutorials about the platform engine inspired me so I decide to contribute to your cause, I made a really really basic level editor but I'm sure it will help the level design, and maybe some future projects because the editor can be adapted really easy to any game.

In a future I will do a better editor, but this was just a quickly one, because really love this tutorials, continue with the good work!

The editor is made in AS3

ACTIONSCRIPT:
  1. var currentTile:int = 0;
  2.  
  3. var horizontalTiles:int = 20;
  4. var verticalTiles:int = 10;
  5.  
  6. var totalTiles:int = mcCurrentTile.totalFrames;
  7.  
  8. var levelTilesContainer:Sprite = new Sprite();
  9.  
  10. makeSelectionTiles();
  11. makeLevelTiles();
  12.  
  13. function makeSelectionTiles():void {
  14.     var container:Sprite = new Sprite();
  15.     container.x = 200;
  16.     container.y = 20;
  17.  
  18.     for (var i:int; i<totalTiles; i++) {
  19.         var tile:Tile = new Tile();
  20.         tile.gotoAndStop(i + 1);
  21.         container.addChild(tile);
  22.         tile.x = (tile.width - 1) * i;
  23.         tile.addEventListener(MouseEvent.MOUSE_DOWN, selectionClick);
  24.     }
  25.     addChild(container);
  26. }
  27.  
  28. function selectionClick(evt:MouseEvent):void {
  29.     currentTile = evt.currentTarget.currentFrame;
  30.     updateCurrentTile();
  31. }
  32.  
  33.  
  34. function updateCurrentTile():void {
  35.     mcCurrentTile.gotoAndStop(currentTile);
  36. }
  37.  
  38.  
  39. function makeLevelTiles():void {
  40.     var xPos:Number = 0;
  41.     var yPos:Number = 0;
  42.  
  43.     for (var i:int=0; i<verticalTiles; i++) {
  44.         for (var j:int=0; j<horizontalTiles; j++) {
  45.             var tile:Tile = new Tile();
  46.             tile.x = xPos;
  47.             tile.y = yPos;
  48.             tile.name = "" + i + j;
  49.             tile.addEventListener(MouseEvent.MOUSE_DOWN, levelClick);
  50.             levelTilesContainer.addChild(tile);
  51.             xPos += (tile.width - 1);
  52.         }
  53.         yPos += (tile.height - 1);
  54.         xPos = 0;
  55.     }
  56.     levelTilesContainer.x = 50;
  57.     levelTilesContainer.y = 100;
  58.  
  59.     addChild(levelTilesContainer);
  60.  
  61. }
  62.  
  63. function levelClick(evt:MouseEvent):void {
  64.     evt.currentTarget.gotoAndStop(currentTile);
  65. }
  66.  
  67. btnGenerate.addEventListener(MouseEvent.MOUSE_DOWN, generateClick);
  68.  
  69.  
  70. function generateClick(evt:MouseEvent):void {
  71.     var array:String = "[ ";
  72.  
  73.     for (var i:int=0; i<verticalTiles; i++) {
  74.         array += "[";
  75.         for (var j:int=0; j<horizontalTiles; j++) {
  76.             var target:DisplayObject = levelTilesContainer.getChildByName("" + i + j);
  77.  
  78.             if (j == (horizontalTiles - 1)) {
  79.                 array += (MovieClip(target).currentFrame  - 1);
  80.             } else {
  81.                 array += (MovieClip(target).currentFrame - 1) + ", ";
  82.             }
  83.         }
  84.         if (i == (verticalTiles - 1)) {
  85.             array += "] ]";
  86.         } else {
  87.             array += "],n";
  88.         }
  89.     }
  90.     trace(array);
  91. }

And this is the result: once you click on "Generate" the script will trace the array.

For this reason there is no way to see the result online, you have to download the source and execute it inside Flash.

from Razorberry

World of Cars (Tue, 07 Oct 2008 20:42:40 +0000)

Friend and ex-colleague Jon Ross directed me towards his team’s latest achievement, World of Cars. Based on the movie Cars, its a pretty cool 3D racing game and car customizer done in Flash. Jon tells me they used their own proprietary 3D engine, along with an isometric scrolling tile engine for the game itself. I particularly like [...]

from Emanuele Feronato

New tile based platform engine - part 9 - coins n’ spikes (Tue, 07 Oct 2008 11:31:35 +0000)

You asked for coins and spikes, and here they are...

As usual I had to define some rules... in this case spikes are deadly only when the player has both feet on it... later I will make a lava (or electric) tile that will kill the player even if he only has one foot on it.

At the moment the player just restarts when he dies, later I will manage real deaths.

Coins are... well... coins... just collect them.

Fix for the fix for infamous Ladder Bug in the Platform Tutorials

In New tile based platform engine - more theory I said superdean fixed the ladder bug... that's not completely true because with his code the player cannot climb down a ladder when he's walking over it.

So the correct if statement to perform when the player presses DOWN is neither mine

if (over == "ladder") {

nor superdean's one

if (top_right == 6 or bottom_right == 6 or top_left == 6 or bottom_left == 6){

but

if ((over == "ladder") or (top_right == 6 or bottom_right == 6 or top_left == 6 or bottom_left == 6)) {

Now grab the source code:

ACTIONSCRIPT:
  1. tile_size = 20;
  2. ground_acceleration = 1;
  3. ground_friction = 0.8;
  4. air_acceleration = 0.5;
  5. air_friction = 0.7;
  6. ice_acceleration = 0.15;
  7. ice_friction = 0.95;
  8. treadmill_speed = 2;
  9. max_speed = 3;
  10. xspeed = 0;
  11. yspeed = 0;
  12. falling = false;
  13. gravity = 0.5;
  14. jump_speed = 6;
  15. climbing = false;
  16. climb_speed = 0.8;
  17. level = new Array();
  18. enemy = new Array();
  19. coin = new Array();
  20. level[0] = [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];
  21. level[1] = [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];
  22. level[2] = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 1, 0, 0, 0, 0, 1];
  23. level[3] = [1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 1];
  24. level[4] = [1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 1];
  25. level[5] = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 1];
  26. level[6] = [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 1, 0, 0, 0, 0, 0, 1];
  27. level[7] = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 1];
  28. level[8] = [1, 1, 1, 1, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 7, 0, 0, 6, 0, 0, 0, 0, 7, 0, 1];
  29. level[9] = [1, 1, 1, 1, 1, 1, 1, 2, 2, 8, 8, 8, 8, 1, 1, 3, 3, 1, 4, 4, 1, 8, 1, 8, 1];
  30. player = [5, 8];
  31. enemy[0] = [10, 3, -2];
  32. enemy[1] = [3, 3, -2];
  33. coin[0] = [2, 2];
  34. coin[1] = [23, 4];
  35. coin;
  36. function create_level(l) {
  37.     _root.createEmptyMovieClip("level_container", 1);
  38.     level_height = l.length;
  39.     level_width = l[0].length;
  40.     for (y=0; y<level_height; y++) {
  41.         for (x=0; x<level_width; x++) {
  42.             if (l[y][x] != 0) {
  43.                 t = level_container.attachMovie("tile", "t"+y+"_"+x, _root.level_container.getNextHighestDepth(), {_x:x*tile_size, _y:y*tile_size});
  44.                 t.gotoAndStop(l[y][x]);
  45.             }
  46.         }
  47.     }
  48.     place_player();
  49.     for (x=0; x<coin.length; x++) {
  50.         coin_mc = level_container.attachMovie("coin", "coin_"+_root.level_container.getNextHighestDepth(), _root.level_container.getNextHighestDepth(), {_x:coin[x][0]*tile_size+tile_size/2, _y:coin[x][1]*tile_size+tile_size/2+1});
  51.         coin_mc.onEnterFrame = function() {
  52.             if (this.hitTest(level_container.hero._x, level_container.hero._y, true)) {
  53.                 this.removeMovieClip();
  54.             }
  55.         };
  56.     }
  57.     for (x=0; x<enemy.length; x++) {
  58.         foe = level_container.attachMovie("patrol", "patrol_"+_root.level_container.getNextHighestDepth(), _root.level_container.getNextHighestDepth(), {_x:enemy[x][0]*tile_size+tile_size/2, _y:enemy[x][1]*tile_size+tile_size/2+1});
  59.         foe.speed = enemy[x][2];
  60.         foe.onEnterFrame = function() {
  61.             this.x_pos = this._x;
  62.             this.y_pos = this._y;
  63.             this.x_pos += this.speed;
  64.             this.left_foot_x = Math.floor((this.x_pos-6)/tile_size);
  65.             this.right_foot_x = Math.floor((this.x_pos+5)/tile_size);
  66.             this.foot_y = Math.floor((this.y_pos+9)/tile_size);
  67.             this.bottom = Math.floor((this.y_pos+8)/tile_size);
  68.             this.left_foot = level[this.foot_y][this.left_foot_x];
  69.             this.right_foot = level[this.foot_y][this.right_foot_x];
  70.             this.left = level[this.bottom][this.left_foot_x];
  71.             this.right = level[this.bottom][this.right_foot_x];
  72.             if (this.left_foot != 0 and this.right_foot != 0 and this.left == 0 and this.right == 0) {
  73.                 this._x = this.x_pos;
  74.             } else {
  75.                 this.speed *= -1;
  76.             }
  77.         };
  78.     }
  79. }
  80. create_level(level);
  81. _root.onEnterFrame = function<