Great Games

Bow Street RunnerQuadradiusMore BeerSeven Deadly SinsAgent Wing DefendersChick Chick BOOMSomething AmissChromaBlastBlue Rabbit's Climate ChaosDragon Fist 3Railway To HeavenRed Baron

Worth Checking Out

Pirates & TreasureJames The Christmas ZebraNewgrounds RumbleMissile Game 3D HSGatewayCosmic CrushPlaying Field 2ObversityGateway 2BlokkosNFL BandwagonOsiris IICereus PeashyGo Squirrel Go!!!James The Deep Sea Zebra(Spin Docter)Bow Man 2Go.

Link to us

Here are some button images you can download. We have buttons for fans, and buttons for developers that have been featured on the site.


 

Recent Visitors


July 15th, 2008

Make a game like Lumines with Flash - part 3 - Posted by Emanuele Feronato

Now it’s time to make bricks disappear if they group in a 2×2 square.

Read part 1 and 2 if you did not already.

It’s not difficult to check if bricks form a 2×2 square… and it’s not difficult to remove them from the stage.

The tricky part is making bricks fill the empty spaces left by disappeared bricks and managing combos (fallen bricks can make another 2×2 square, generating more falling bricks, and so on).

I preferred not to have an onEnterFrame on every brick to check if it’s over an empty space and eventually move it, so I created another array called bricks_in_field saving the depth of the brick in that position, so when I remove some bricks I just have to put in the moveable_bricks the depth found in the bricks_in_field array and the “engine” does the rest.

Here it is the actionscript:

ACTIONSCRIPT:

  1. // declaring some setup variables
  2. // number of horizontal cells
  3. grid_width = 16;
  4. // number of vertical cells
  5. grid_height = 10;
  6. // size of the cell
  7. tile_size = 30;
  8. // offset in pixels fron the left side of the stage
  9. x_offset = 10;
  10. // offset in pixels from the top side of the stage
  11. y_offset = 10;
  12. // number of different colors that can be displayed in a brick
  13. different_colors = 3;
  14. // boolean values saying if I should wait for the left (or right, up…) key to be released
  15. // this is used to make the player move bricks tapping arrow keys instead of just pressing them
  16. wait_left = false;
  17. wait_right = false;
  18. wait_up = false;
  19. wait_down = false;
  20. // flag indicating if blocks are falling
  21. falling = false;
  22. // array containing the game field data
  23. field = new Array();
  24. // array containing bricks position
  25. bricks_in_field = new Array();
  26. // array containing the bricks I can move
  27. moveable_bricks = new Array();
  28. // initializing and drawing the play field and the bricks position fields
  29. for (x=0; x<grid_width; x++) {
  30.     field[x] = new Array();
  31.     bricks_in_field[x] = new Array();
  32.     for (y=0; y<grid_height; y++) {
  33.         field[x][y] = 0;
  34.         bricks_in_field[x][y] = 0;
  35.         // look how I det ermine cells position according to tile size and offsets
  36.         cell = _root.attachMovie(“brick”, “brick_”+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:x*tile_size+x_offset, _y:(y+2)*tile_size+y_offset});
  37.         // first frame = empty cell
  38.         cell.gotoAndStop(1);
  39.     }
  40. }
  41. // calling the function that will place four bricks on the stage
  42. place_bricks();
  43. // main function, to be executed at every frame
  44. _root.onEnterFrame = function() {
  45.     // if blocks aren’t falling
  46.     if (!falling) {
  47.         // checking if a block is the upper left one of a four block square
  48.         for (x=0; x<grid_width; x++) {
  49.             for (y=0; y<grid_height; y++) {
  50.                 if (field[x][y] != 0 and field[x][y] == field[x+1][y] and field[x][y] == field[x+1][y+1] and field[x][y] == field[x][y+1]) {
  51.                     // physically removing the bricks
  52.                     _root[“brick_”+bricks_in_field[x][y+1]].removeMovieClip();
  53.                     _root[“brick_”+bricks_in_field[x][y+2]].removeMovieClip();
  54.                     _root[“brick_”+bricks_in_field[x+1][y+1]].removeMovieClip();
  55.                     _root[“brick_”+bricks_in_field[x+1][y+2]].removeMovieClip();
  56.                     // updating field array
  57.                     field[x][y] = 0;
  58.                     field[x][y+1] = 0;
  59.                     field[x+1][y+1] = 0;
  60.                     field[x+1][y] = 0;
  61.                     // checking upper bricks to make them fall
  62.                     start_y = y-1;
  63.                     while (field[x][start_y]>0) {
  64.                         moveable_bricks.push(bricks_in_field[x][start_y+1]);
  65.                         start_y–;
  66.                     }
  67.                     start_y = y-1;
  68.                     while (field[x+1][start_y]>0) {
  69.                         moveable_bricks.push(bricks_in_field[x+1][start_y+1]);
  70.                         start_y–;
  71.                     }
  72.                     falling = true;
  73.                 }
  74.             }
  75.         }
  76.         // place new bricks only if no bricks are falling
  77.         if (!falling and moveable_bricks.length == 0) {
  78.             place_bricks();
  79.         }
  80.         // this is how I detect if a key was tapped:     
  81.         // when it’s pressed, I wait for it to be released (in this case: not pressed)
  82.         // thanks to the wait_<direction> variable
  83.         if (Key.isDown(Key.LEFT)) {
  84.             wait_left = true;
  85.         } else {
  86.             if (wait_left) {
  87.                 // if the left key has been tapped, move the four bricks on the left
  88.                 for (x=0; x<4; x++) {
  89.                     // this "if" is used to determine if the bricks are still inside the game field
  90.                     if ((_root[“brick_”+moveable_bricks[x]]._x-x_offset)/tile_size-_root[“brick_”+moveable_bricks[x]].pos%2>0) {
  91.                         _root[“brick_”+moveable_bricks[x]]._x -= tile_size;
  92.                     }
  93.                 }
  94.                 // reset variable, now I must wait again for a key to be pressed
  95.                 wait_left = false;
  96.             }
  97.         }
  98.         // same routine for the right key
  99.         if (Key.isDown(Key.RIGHT)) {
  100.             wait_right = true;
  101.         } else {
  102.             if (wait_right) {
  103.                 for (x=0; x<4; x++) {
  104.                     if ((_root[“brick_”+moveable_bricks[x]]._x-x_offset)/tile_size-_root[“brick_”+moveable_bricks[x]].pos%2<14) {
  105.                         _root[“brick_”+moveable_bricks[x]]._x += tile_size;
  106.                     }
  107.                 }
  108.                 wait_right = false;
  109.             }
  110.         }
  111.         // when the DOWN arrow is pressed, I must rotate the bricks clockwise
  112.         // block 0: moves to the right and becomes block 1
  113.         // block 1: moves down and becomes block 3
  114.         // block 2: moves up and becomes block 0
  115.         // block 3: moves to the left and becomes block 2
  116.         if (Key.isDown(Key.DOWN)) {
  117.             wait_down = true;
  118.         } else {
  119.             if (wait_down) {
  120.                 for (x=0; x<4; x++) {
  121.                     switch (_root[“brick_”+moveable_bricks[x]].pos) {
  122.                     case 0 :
  123.                         _root[“brick_”+moveable_bricks[x]].pos = 1;
  124.                         _root[“brick_”+moveable_bricks[x]]._x += tile_size;
  125.                         break;
  126.                     case 1 :
  127.                         _root[“brick_”+moveable_bricks[x]].pos = 3;
  128.                         _root[“brick_”+moveable_bricks[x]]._y += tile_size;
  129.                         break;
  130.                     case 2 :
  131.                         _root[“brick_”+moveable_bricks[x]].pos = 0;
  132.                         _root[“brick_”+moveable_bricks[x]]._y -= tile_size;
  133.                         break;
  134.                     case 3 :
  135.                         _root[“brick_”+moveable_bricks[x]].pos = 2;
  136.                         _root[“brick_”+moveable_bricks[x]]._x -= tile_size;
  137.                         break;
  138.                     }
  139.                 }
  140.                 wait_down = false;
  141.             }
  142.         }
  143.         // when the UP arrow is pressed, I must rotate the bricks counter-clockwise
  144.         // block 0: moves down the right and becomes block 2
  145.         // block 1: moves to the left and becomes block 0
  146.         // block 2: moves to the right and becomes block 3
  147.         // block 3: moves up and becomes block 1
  148.         if (Key.isDown(Key.UP)) {
  149.             wait_up = true;
  150.         } else {
  151.             if (wait_up) {
  152.                 for (x=0; x<4; x++) {
  153.                     switch (_root[“brick_”+moveable_bricks[x]].pos) {
  154.                     case 0 :
  155.                         _root[“brick_”+moveable_bricks[x]].pos = 2;
  156.                         _root[“brick_”+moveable_bricks[x]]._y += tile_size;
  157.                         break;
  158.                     case 1 :
  159.                         _root[“brick_”+moveable_bricks[x]].pos = 0;
  160.                         _root[“brick_”+moveable_bricks[x]]._x -= tile_size;
  161.                         break;
  162.                     case 2 :
  163.                         _root[“brick_”+moveable_bricks[x]].pos = 3;
  164.                         _root[“brick_”+moveable_bricks[x]]._x += tile_size;
  165.                         break;
  166.                     case 3 :
  167.                         _root[“brick_”+moveable_bricks[x]].pos = 1;
  168.                         _root[“brick_”+moveable_bricks[x]]._y -= tile_size;
  169.                         break;
  170.                     }
  171.                 }
  172.                 wait_up = false;
  173.             }
  174.         }
  175.         // when SPACE key is pressed, I don’t wait for its release but I detect the key at once
  176.         if (Key.isDown(Key.SPACE)) {
  177.             // letìs made bricks fall…
  178.             falling = true;
  179.         }
  180.     } else {
  181.         //if the blocks are falling
  182.         // blocks_landed variable will count the number of bricks that already touched the ground
  183.         // or that cannot fall anymore because they are over other bricks
  184.         blocks_landed = 0;
  185.         for (x=0; x<moveable_bricks.length; x++) {
  186.             // calculating x and y position of the brick in the array
  187.             x_pos = (_root[“brick_”+moveable_bricks[x]]._x-x_offset)/tile_size;
  188.             y_pos = (_root[“brick_”+moveable_bricks[x]]._y-y_offset)/tile_size-1;
  189.             // determining if the block can fall. There are two conditions:
  190.             // 1: its position is less than zero. It means the block is outside the grid, in its starting position
  191.             // 2: its position is lower than the grid height and the tile under the block is empty
  192.             if ((y_pos<0) or ((y_pos<grid_height) and (field[x_pos][y_pos] == 0))) {
  193.                 // updating field array
  194.                 field[x_pos][y_pos] = _root[“brick_”+moveable_bricks[x]]._currentframe;
  195.                 field[x_pos][y_pos-1] = 0;
  196.                 // physically moving the brick
  197.                 _root[“brick_”+moveable_bricks[x]]._y += tile_size;
  198.             } else {
  199.                 // if the brick cannot move down, increase the number of blocks landed
  200.                 blocks_landed++;
  201.             }
  202.         }
  203.         // if all four bricks landed successfully…
  204.         if (blocks_landed == moveable_bricks.length) {
  205.             for (x=0; x<moveable_bricks.length; x++) {
  206.                 x_pos = (_root[“brick_”+moveable_bricks[x]]._x-x_offset)/tile_size;
  207.                 y_pos = (_root[“brick_”+moveable_bricks[x]]._y-y_offset)/tile_size-1;
  208.                 // saving in the brick array the name of the brick landed on (x_pos,y_pos)
  209.                 bricks_in_field[x_pos][y_pos] = moveable_bricks[x];
  210.             }
  211.             // reset variable to false
  212.             falling = false;
  213.             // reset moveable_bricks array
  214.             moveable_bricks = new Array();
  215.         }
  216.     }
  217. };
  218. // function to place four bricks on the stage
  219. function place_bricks() {
  220.     // placing the four bricks
  221.     for (x=0; x<4; x++) {
  222.         // again, look how I determine bricks position according to tile size and offsets
  223.         brk = _root.attachMovie(“brick”, “brick_”+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:(grid_width/2+(x%2))*tile_size+x_offset, _y:y_offset+tile_size*Math.floor(x/2)});
  224.         // setting a random color for the brick (frames 2 to different_colors+1)
  225.         brk.gotoAndStop(Math.floor(Math.random()*different_colors)+2);
  226.         // saving brick position
  227.         // 0: up left
  228.         // 1: up right
  229.         // 2: bottom left
  230.         // 3: bottom right
  231.         brk.pos = x;
  232.         // saving the depth of the brick into the moveable_bricks array
  233.         // if you look how did I assign brick names, you’ll see that I can determine a brick name
  234.         // starting from its depth. It’s simply "brick_"+<the_depth>
  235.         moveable_bricks[x] = brk.getDepth();
  236.     }
  237. }

And this is the result:

Now wait for the next step to handle timing events.

Download the source.

Bookmark this page on Digg, Kinja, FURL, Redit & other sites

July 15th, 2008

Wordpress 2.6 installed and kicking - Posted by Emanuele Feronato

Today WordPress.org team released version 2.6 with these notes:

I’m happy to announce that version 2.6 of WordPress.org is now available, almost a month ahead schedule. Version 2.6 “Tyner,” named for jazz pianist McCoy Tyner, contains a number of new features that make WordPress a more powerful CMS: you can now track changes to every post and page and easily post from wherever you are on the web, plus there are dozens of incremental improvements to the features introduced in version 2.5.

If you are the kind of blogger that waits for others to install latest releases before upgrading his own blog… well, I installed it and everything is working great.

You can check new features in this video:

I am finding really useful theme previews, because I am going to revamp the theme and keep new look secret until it’s finished.

Have no fear and install it.

Bookmark this page on Digg, Kinja, FURL, Redit & other sites

July 14th, 2008

Create a Flash game like Deflection - part 2 - Posted by Emanuele Feronato

In the 1st part I showed you how to make a deflection engine starting from an old tutorial, now it’s time to let the player draw walls.

The idea comes from Srdjan Susnic, a reader who runs the blog Ask For Game Task.

The main task Srdjan accomplished was to add a mouse control so a player can draw lines from which the ball will bounce.

After collision between the ball and a line drawn by mouse, that line must be removed

The code is clear and well commented, but it seems to suffer a bug if the player just clicks the mouse without drawing.

It’s just a minor issue I fixed in a moment, and if you already read the original post, I just added the control if the player drew a line when he releases the mouse button with player_drew variable.

Anyway, this is the actionscript:

ACTIONSCRIPT:

  1. // create game object
  2. game = {gravity:0, dragging:false, clip:_root.game_mc, stageW:500, stageH:400, maxV:20};
  3. // create object
  4. // point p0 is its starting point in the coordinates x/y
  5. _root.attachMovie(“ball”, “ball”, 1);
  6. game.myOb = {clip:ball, airf:1, b:1, f:1, r:20, lastTime:getTimer()};
  7. game.myOb.p0 = {x:150, y:80};
  8. // vectors x/y components
  9. game.myOb.vx = 8;
  10. game.myOb.vy = 12;
  11. // create first vector
  12. // point p0 is its starting point in the coordinates x/y
  13. // point p1 is its end point in the coordinates x/y
  14. game.v = new Array();
  15. game.v[0] = {p0:{x:50, y:40}, p1:{x:450, y:40}, b:1, f:1};
  16. game.v[1] = {p0:{x:50, y:40}, p1:{x:50, y:360}, b:1, f:1};
  17. game.v[2] = {p0:{x:50, y:360}, p1:{x:450, y:360}, b:1, f:1};
  18. game.v[3] = {p0:{x:100, y:80}, p1:{x:400, y:320}, b:1, f:1};
  19. _root.createEmptyMovieClip(“lines”, 2);
  20. lines.lineStyle(1, 0xff0000);
  21. // draw and calculate all parameters for the wall vectors
  22. for (x=0; x<game.v.length; x++) {
  23.     lines.moveTo(game.v[x].p0.x, game.v[x].p0.y);
  24.     lines.lineTo(game.v[x].p1.x, game.v[x].p1.y);
  25.     updateVector(game.v[x], true);
  26. }
  27. _root.onEnterFrame = function() {
  28.     _root.runMe();
  29. };
  30. // function to draw the points, lines and show text
  31. function drawAll(v) {
  32.     // place ob mc
  33.     v.clip._x = v.p1.x;
  34.     v.clip._y = v.p1.y;
  35. }
  36. // main function
  37. function runMe() {
  38.     // start to calculate movement
  39.     var ob = game.myOb;
  40.     // add air resistance
  41.     ob.vx *= ob.airf;
  42.     ob.vy *= ob.airf;
  43.     // dont let it go over max speed
  44.     if (ob.vx>game.maxV) {
  45.         ob.vx = game.maxV;
  46.     } else if (ob.vx<-game.maxV) {
  47.         ob.vx = -game.maxV;
  48.     }
  49.     if (ob.vy>game.maxV) {
  50.         ob.vy = game.maxV;
  51.     } else if (ob.vy<-game.maxV) {
  52.         ob.vy = -game.maxV;
  53.     }
  54.     // update the vector parameters
  55.     updateObject(ob);
  56.     // check the walls for collisions
  57.     for (x=0; x<game.v.length; x++) {
  58.         var w = game.v[x];
  59.         var v = findIntersection(ob, w);
  60.         v = updateVector(v, false);
  61.         var pen = ob.r-v.len;
  62.         // if we have hit the wall
  63.         if (pen>=0) {
  64.             // move object away from the wall
  65.             ob.p1.x += v.dx*pen;
  66.             ob.p1.y += v.dy*pen;
  67.             // change movement, bounce off from the normal of v
  68.             var vbounce = {dx:v.lx, dy:v.ly, lx:v.dx, ly:v.dy, b:1, f:1};
  69.             var vb = bounce(ob, vbounce);
  70.             ob.vx = vb.vx;
  71.             ob.vy = vb.vy;
  72.         }
  73.     }
  74.     /********************************************************************/
  75.     // CODE ADDED BY SRDJAN SUSNIC
  76.     // check the lines created by mouse for collisions
  77.     x = 0;
  78.     while (x<game.mouseV.length) {
  79.         var w = game.mouseV[x];
  80.         var v = findIntersection(ob, w);
  81.         v = updateVector(v, false);
  82.         var pen = ob.r-v.len;
  83.         // if we have hit the wall
  84.         if (pen>=0) {
  85.             // move object away from the wall
  86.             ob.p1.x += v.dx*pen;
  87.             ob.p1.y += v.dy*pen;
  88.             // change movement, bounce off from the normal of v
  89.             var vbounce = {dx:v.lx, dy:v.ly, lx:v.dx, ly:v.dy, b:1, f:1};
  90.             var vb = bounce(ob, vbounce);
  91.             ob.vx = vb.vx;
  92.             ob.vy = vb.vy;
  93.             // remove the clip and vector array of the collided line
  94.             game.mouseV[x].lineClip.removeMovieClip();
  95.             game.mouseV.splice(x, 1);
  96.         } else {
  97.             x++;
  98.         }
  99.     }
  100.     // END OF CODE ADDED BY SRDJAN SUSNIC   
  101.     /********************************************************************/
  102.     // reset object to other side if gone out of stage
  103.     if (ob.p1.x>game.stageW+ob.r) {
  104.         ob.p1.x = -ob.r;
  105.     } else if (ob.p1.x<-ob.r) {
  106.         ob.p1.x = game.stageW+ob.r;
  107.     }
  108.     if (ob.p1.y>game.stageH+ob.r) {
  109.         ob.p1.y = -ob.r;
  110.     } else if (ob.p1.y<-ob.r) {
  111.         ob.p1.y = game.stageH+ob.r;
  112.     }
  113.     // draw it
  114.     drawAll(ob);
  115.     // make end point equal to starting point for next cycle
  116.     ob.p0 = ob.p1;
  117.     // save the movement without time
  118.     ob.vx = ob.vx/ob.timeFrame;
  119.     ob.vy = ob.vy/ob.timeFrame;
  120. }
  121. // function to find all parameters for the vector
  122. function updateVector(v, frompoints) {
  123.     // x and y components
  124.     if (frompoints) {
  125.         v.vx = v.p1.x-v.p0.x;
  126.         v.vy = v.p1.y-v.p0.y;
  127.     } else {
  128.         v.p1.x = v.p0.x+v.vx;
  129.         v.p1.y = v.p0.y+v.vy;
  130.     }
  131.     // length of vector
  132.     v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
  133.     // normalized unti-sized components
  134.     if (v.len>0) {
  135.         v.dx = v.vx/v.len;
  136.         v.dy = v.vy/v.len;
  137.     } else {
  138.         v.dx = 0;
  139.         v.dy = 0;
  140.     }
  141.     // right hand normal
  142.     v.rx = -v.dy;
  143.     v.ry = v.dx;
  144.     // left hand normal
  145.     v.lx = v.dy;
  146.     v.ly = -v.dx;
  147.     return v;
  148. }
  149. function updateObject(v) {
  150.     // find time passed from last update
  151.     var thisTime = getTimer();
  152.     var time = (thisTime-v.lastTime)/100;
  153.     // we use time, not frames to move so multiply movement vector with time passed
  154.     v.vx *= time;
  155.     v.vy *= time;
  156.     // add gravity, also based on time
  157.     v.vy = v.vy+time*game.gravity;
  158.     v.p1 = {};
  159.     // find end point coordinates
  160.     v.p1.x = v.p0.x+v.vx;
  161.     v.p1.y = v.p0.y+v.vy;
  162.     // length of vector
  163.     v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
  164.     // normalized unti-sized components
  165.     v.dx = v.vx/v.len;
  166.     v.dy = v.vy/v.len;
  167.     // right hand normal
  168.     v.rx = -v.vy;
  169.     v.ry = v.vx;
  170.     // left hand normal
  171.     v.lx = v.vy;
  172.     v.ly = -v.vx;
  173.     // save the current time
  174.     v.lastTime = thisTime;
  175.     // save time passed
  176.     v.timeFrame = time;
  177. }
  178. // find intersection point of 2 vectors
  179. function findIntersection(v1, v2) {
  180.     // vector between center of ball and starting point of wall
  181.     var v3 = {};
  182.     v3.vx = v1.p1.x-v2.p0.x;
  183.     v3.vy = v1.p1.y-v2.p0.y;
  184.     // check if we have hit starting point
  185.     var dp = v3.vx*v2.dx+v3.vy*v2.dy;
  186.     if (dp<0) {
  187.         // hits starting point
  188.         var v = v3;
  189.     } else {
  190.         var v4 = {};
  191.         v4.vx = v1.p1.x-v2.p1.x;
  192.         v4.vy = v1.p1.y-v2.p1.y;
  193.         // check if we have hit side or endpoint
  194.         var dp = v4.vx*v2.dx+v4.vy*v2.dy;
  195.         if (dp>0) {
  196.             // hits ending point
  197.             var v = v4;
  198.         } else {
  199.             // it hits the wall
  200.             // project this vector on the normal of the wall
  201.             var v = projectVector(v3, v2.lx, v2.ly);
  202.         }
  203.     }
  204.     return v;
  205. }
  206. // find new vector bouncing from v2
  207. function bounce(v1, v2) {
  208.     // projection of v1 on v2
  209.     var proj1 = projectVector(v1, v2.dx, v2.dy);
  210.     // projection of v1 on v2 normal
  211.     var proj2 = projectVector(v1, v2.lx, v2.ly);
  212.     var proj = {};
  213.     // reverse projection on v2 normal
  214.     proj2.len = Math.sqrt(proj2.vx*proj2.vx+proj2.vy*proj2.vy);
  215.     proj2.vx = v2.lx*proj2.len;
  216.     proj2.vy = v2.ly*proj2.len;
  217.     // add the projections
  218.     proj.vx = v1.f*v2.f*proj1.vx+v1.b*v2.b*proj2.vx;
  219.     proj.vy = v1.f*v2.f*proj1.vy+v1.b*v2.b*proj2.vy;
  220.     return proj;
  221. }
  222. // project vector v1 on unit-sized vector dx/dy
  223. function projectVector(v1, dx, dy) {
  224.     // find dot product
  225.     var dp = v1.vx*dx+v1.vy*dy;
  226.     var proj = {};
  227.     // projection components
  228.     proj.vx = dp*dx;
  229.     proj.vy = dp*dy;
  230.     return proj;
  231. }
  232. /********************************************************************/
  233. // CODE ADDED BY SRDJAN SUSNIC
  234. // declare starting point of the current drawing line
  235. var lineX1, lineY1;
  236. // declare ending point of the current drawing line
  237. var lineX2, lineY2;
  238. // flag that states if we can draw line or not
  239. can_draw = false;
  240. // flag that states if the player drew a line
  241. player_drew = false;
  242. // next movie depth for the current drawing line
  243. nextLineDepth = 0;
  244. // create array for vectors of lines drawn by mouse
  245. game.mouseV = new Array();
  246. // create a movie which represents a line drawn by mouse
  247. _root.createEmptyMovieClip(“mouseLine”, 3);
  248. // when we click…
  249. onMouseDown = function () {
  250.     // get starting point of line according to current mouse position
  251.     lineX1 = _root._xmouse;
  252.     lineY1 = _root._ymouse;
  253.     // set drawing flag so we can draw a line when mouse is moved
  254.     can_draw = true;
  255. };
  256. // when we move mouse…
  257. onMouseMove = function () {
  258.     if (can_draw) {
  259.         // the player is drawing!
  260.         player_drew = true;
  261.         // get ending point of line according to current mouse position
  262.         lineX2 = _root._xmouse;
  263.         lineY2 = _root._ymouse;
  264.         // clear the previous line drawn by mouse
  265.         mouseLine.clear();
  266.         // set the drawing style
  267.         mouseLine.lineStyle(2, 0×00dd00);
  268.         // move the pen to the starting position
  269.         mouseLine.moveTo(lineX1, lineY1);
  270.         // draw the line to the ending position
  271.         mouseLine.lineTo(lineX2, lineY2);
  272.     }
  273. };
  274. // when we release…
  275. onMouseUp = function () {
  276.     if (player_drew) {
  277.         // clear the line drawn by mouse
  278.         mouseLine.clear();
  279.         // create a new movie clip which contains the line previously drawn by mouse
  280.         var tmp = createEmptyMovieClip(“newLine”, 10+nextLineDepth);
  281.         tmp.lineStyle(5, 0×0000ff);
  282.         tmp.moveTo(lineX1, lineY1);
  283.         tmp.lineTo(lineX2, lineY2);
  284.         // increase movie depth for the next line
  285.         nextLineDepth++;
  286.         // add the parameters of previously created line to the end of line vectors array
  287.         // lineClip parameter is used to store previously created line movie clip
  288.         // so we can remove it when ball bounces from it
  289.         index = game.mouseV.length;
  290.         game.mouseV[index] = {p0:{x:lineX1, y:lineY1}, p1:{x:lineX2, y:lineY2}, b:1, f:1, lineClip:tmp};
  291.         // calculate all parameters for the created line vector
  292.         updateVector(game.mouseV[index], true);
  293.         // set drawing flag so we can’t draw a line when mouse is moved
  294.         player_drew = false;
  295.     }
  296.     can_draw = false;
  297. };
  298. // END OF CODE ADDED BY SRDJAN SUSNIC   
  299. /********************************************************************/

And this is the result:

Now you can draw lines with the mouse and the only thing we need in order to have a complete game engine is handling the exit.

Any idea?

Download the source code and play.

Bookmark this page on Digg, Kinja, FURL, Redit & other sites

July 14th, 2008

Flash and search engines: the revolution - Posted by Emanuele Feronato

You know Flash content is invisible to search engines. In order to have your Flash page (or game) indexed, you have to create an HTML page with some keywords, and pray.

Until yesterday.

Today, something is changing in Search Engines Optimization (SEO) techniques.

Look what Google and Adobe have to say

From Adobe

Adobe is providing optimized Adobe Flash Player technology to Google and Yahoo! to enhance search engine indexing of the Flash file format (SWF) and uncover information that is currently undiscoverable by search engines. This will provide more relevant automatic search rankings of the millions of dynamic content that run in Adobe Flash Player.

Without additional changes to content, developers can continue to provide experiences that are possible only with Adobe Flash technology without the trade-off of a loss in search indexing.

It will also positively affect the Search Engine Optimization community, which will develop best practices for building content utilizing Adobe Flash technologies, and enhance the ability to find and monetize SWF content.

Source: SWF searchability FAQ

From Google

Q: What do I need to do to get Google to index the text in my Flash files?
Basically, you don’t need to do anything. The improvements that we have made do not require any special action on the part of web designers or webmasters. If you have Flash content on your website, we will automatically begin to index it, up to the limits of our current technical ability.

That said, you should be aware that Google is now able to see the text that appears to visitors of your website. If you prefer Google to ignore your less informative content, such as a “copyright” or “loading” message, consider replacing the text within an image, which will make it effectively invisible to us.

Source: Improved Flash indexing

How can I get benefits from that?

If a successful SWF file will link to some external sites, maybe this will affect PageRank or at least help sites ranking.

A link to a sponsor in a successful game probably will get more valuable, and maybe people that look for your game will be able to find it in the official page and not in one portal with better ranking than your one.

Just rambling of course, but I am very very interested in it…

Bookmark this page on Digg, Kinja, FURL, Redit & other sites

July 14th, 2008

Create a Flash game like Deflection - part 2 - Posted by Emanuele Feronato

In the 1st part I showed you how to make a deflection engine starting from an old tutorial, now it’s time to let the player draw walls.

The idea comes from Srdjan Susnic, a reader who runs the blog Ask For Game Task.

The main task Srdjan accomplished was to add a mouse control so a player can draw lines from which the ball will bounce.

After collision between the ball and a line drawn by mouse, that line must be removed

The code is clear and well commented, but it seems to suffer a bug if the player just clicks the mouse without drawing.

It’s just a minor issue I fixed in a moment, and if you already read the original post, I just added the control if the player drew a line when he releases the mouse button with player_drew variable.

Anyway, this is the actionscript:

ACTIONSCRIPT:

  1. // create game object
  2. game = {gravity:0, dragging:false, clip:_root.game_mc, stageW:500, stageH:400, maxV:20};
  3. // create object
  4. // point p0 is its starting point in the coordinates x/y
  5. _root.attachMovie(“ball”, “ball”, 1);
  6. game.myOb = {clip:ball, airf:1, b:1, f:1, r:20, lastTime:getTimer()};
  7. game.myOb.p0 = {x:150, y:80};
  8. // vectors x/y components
  9. game.myOb.vx = 8;
  10. game.myOb.vy = 12;
  11. // create first vector
  12. // point p0 is its starting point in the coordinates x/y
  13. // point p1 is its end point in the coordinates x/y
  14. game.v = new Array();
  15. game.v[0] = {p0:{x:50, y:40}, p1:{x:450, y:40}, b:1, f:1};
  16. game.v[1] = {p0:{x:50, y:40}, p1:{x:50, y:360}, b:1, f:1};
  17. game.v[2] = {p0:{x:50, y:360}, p1:{x:450, y:360}, b:1, f:1};
  18. game.v[3] = {p0:{x:100, y:80}, p1:{x:400, y:320}, b:1, f:1};
  19. _root.createEmptyMovieClip(“lines”, 2);
  20. lines.lineStyle(1, 0xff0000);
  21. // draw and calculate all parameters for the wall vectors
  22. for (x=0; x<game.v.length; x++) {
  23.     lines.moveTo(game.v[x].p0.x, game.v[x].p0.y);
  24.     lines.lineTo(game.v[x].p1.x, game.v[x].p1.y);
  25.     updateVector(game.v[x], true);
  26. }
  27. _root.onEnterFrame = function() {
  28.     _root.runMe();
  29. };
  30. // function to draw the points, lines and show text
  31. function drawAll(v) {
  32.     // place ob mc
  33.     v.clip._x = v.p1.x;
  34.     v.clip._y = v.p1.y;
  35. }
  36. // main function
  37. function runMe() {
  38.     // start to calculate movement
  39.     var ob = game.myOb;
  40.     // add air resistance
  41.     ob.vx *= ob.airf;
  42.     ob.vy *= ob.airf;
  43.     // dont let it go over max speed
  44.     if (ob.vx>game.maxV) {
  45.         ob.vx = game.maxV;
  46.     } else if (ob.vx<-game.maxV) {
  47.         ob.vx = -game.maxV;
  48.     }
  49.     if (ob.vy>game.maxV) {
  50.         ob.vy = game.maxV;
  51.     } else if (ob.vy<-game.maxV) {
  52.         ob.vy = -game.maxV;
  53.     }
  54.     // update the vector parameters
  55.     updateObject(ob);
  56.     // check the walls for collisions
  57.     for (x=0; x<game.v.length; x++) {
  58.         var w = game.v[x];
  59.         var v = findIntersection(ob, w);
  60.         v = updateVector(v, false);
  61.         var pen = ob.r-v.len;
  62.         // if we have hit the wall
  63.         if (pen>=0) {
  64.             // move object away from the wall
  65.             ob.p1.x += v.dx*pen;
  66.             ob.p1.y += v.dy*pen;
  67.             // change movement, bounce off from the normal of v
  68.             var vbounce = {dx:v.lx, dy:v.ly, lx:v.dx, ly:v.dy, b:1, f:1};
  69.             var vb = bounce(ob, vbounce);
  70.             ob.vx = vb.vx;
  71.             ob.vy = vb.vy;
  72.         }
  73.     }
  74.     /********************************************************************/
  75.     // CODE ADDED BY SRDJAN SUSNIC
  76.     // check the lines created by mouse for collisions
  77.     x = 0;
  78.     while (x<game.mouseV.length) {
  79.         var w = game.mouseV[x];
  80.         var v = findIntersection(ob, w);
  81.         v = updateVector(v, false);
  82.         var pen = ob.r-v.len;
  83.         // if we have hit the wall
  84.         if (pen>=0) {
  85.             // move object away from the wall
  86.             ob.p1.x += v.dx*pen;
  87.             ob.p1.y += v.dy*pen;
  88.             // change movement, bounce off from the normal of v
  89.             var vbounce = {dx:v.lx, dy:v.ly, lx:v.dx, ly:v.dy, b:1, f:1};
  90.             var vb = bounce(ob, vbounce);
  91.             ob.vx = vb.vx;
  92.             ob.vy = vb.vy;
  93.             // remove the clip and vector array of the collided line
  94.             game.mouseV[x].lineClip.removeMovieClip();
  95.             game.mouseV.splice(x, 1);
  96.         } else {
  97.             x++;
  98.         }
  99.     }
  100.     // END OF CODE ADDED BY SRDJAN SUSNIC   
  101.     /********************************************************************/
  102.     // reset object to other side if gone out of stage
  103.     if (ob.p1.x>game.stageW+ob.r) {
  104.         ob.p1.x = -ob.r;
  105.     } else if (ob.p1.x<-ob.r) {
  106.         ob.p1.x = game.stageW+ob.r;
  107.     }
  108.     if (ob.p1.y>game.stageH+ob.r) {
  109.         ob.p1.y = -ob.r;
  110.     } else if (ob.p1.y<-ob.r) {
  111.         ob.p1.y = game.stageH+ob.r;
  112.     }
  113.     // draw it
  114.     drawAll(ob);
  115.     // make end point equal to starting point for next cycle
  116.     ob.p0 = ob.p1;
  117.     // save the movement without time
  118.     ob.vx = ob.vx/ob.timeFrame;
  119.     ob.vy = ob.vy/ob.timeFrame;
  120. }
  121. // function to find all parameters for the vector
  122. function updateVector(v, frompoints) {
  123.     // x and y components
  124.     if (frompoints) {
  125.         v.vx = v.p1.x-v.p0.x;
  126.         v.vy = v.p1.y-v.p0.y;
  127.     } else {
  128.         v.p1.x = v.p0.x+v.vx;
  129.         v.p1.y = v.p0.y+v.vy;
  130.     }
  131.     // length of vector
  132.     v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
  133.     // normalized unti-sized components
  134.     if (v.len>0) {
  135.         v.dx = v.vx/v.len;
  136.         v.dy = v.vy/v.len;
  137.     } else {
  138.         v.dx = 0;
  139.         v.dy = 0;
  140.     }
  141.     // right hand normal
  142.     v.rx = -v.dy;
  143.     v.ry = v.dx;
  144.     // left hand normal
  145.     v.lx = v.dy;
  146.     v.ly = -v.dx;
  147.     return v;
  148. }
  149. function updateObject(v) {
  150.     // find time passed from last update
  151.     var thisTime = getTimer();
  152.     var time = (thisTime-v.lastTime)/100;
  153.     // we use time, not frames to move so multiply movement vector with time passed
  154.     v.vx *= time;
  155.     v.vy *= time;
  156.     // add gravity, also based on time
  157.     v.vy = v.vy+time*game.gravity;
  158.     v.p1 = {};
  159.     // find end point coordinates
  160.     v.p1.x = v.p0.x+v.vx;
  161.     v.p1.y = v.p0.y+v.vy;
  162.     // length of vector
  163.     v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
  164.     // normalized unti-sized components
  165.     v.dx = v.vx/v.len;
  166.     v.dy = v.vy/v.len;
  167.     // right hand normal
  168.     v.rx = -v.vy;
  169.     v.ry = v.vx;
  170.     // left hand normal
  171.     v.lx = v.vy;
  172.     v.ly = -v.vx;
  173.     // save the current time
  174.     v.lastTime = thisTime;
  175.     // save time passed
  176.     v.timeFrame = time;
  177. }
  178. // find intersection point of 2 vectors
  179. function findIntersection(v1, v2) {
  180.     // vector between center of ball and starting point of wall
  181.     var v3 = {};
  182.     v3.vx = v1.p1.x-v2.p0.x;
  183.     v3.vy = v1.p1.y-v2.p0.y;
  184.     // check if we have hit starting point
  185.     var dp = v3.vx*v2.dx+v3.vy*v2.dy;
  186.     if (dp<0) {
  187.         // hits starting point
  188.         var v = v3;
  189.     } else {
  190.         var v4 = {};
  191.         v4.vx = v1.p1.x-v2.p1.x;
  192.         v4.vy = v1.p1.y-v2.p1.y;
  193.         // check if we have hit side or endpoint
  194.         var dp = v4.vx*v2.dx+v4.vy*v2.dy;
  195.         if (dp>0) {
  196.             // hits ending point
  197.             var v = v4;
  198.         } else {
  199.             // it hits the wall
  200.             // project this vector on the normal of the wall
  201.             var v = projectVector(v3, v2.lx, v2.ly);
  202.         }
  203.     }
  204.     return v;
  205. }
  206. // find new vector bouncing from v2
  207. function bounce(v1, v2) {
  208.     // projection of v1 on v2
  209.     var proj1 = projectVector(v1, v2.dx, v2.dy);
  210.     // projection of v1 on v2 normal
  211.     var proj2 = projectVector(v1, v2.lx, v2.ly);
  212.     var proj = {};
  213.     // reverse projection on v2 normal
  214.     proj2.len = Math.sqrt(proj2.vx*proj2.vx+proj2.vy*proj2.vy);
  215.     proj2.vx = v2.lx*proj2.len;
  216.     proj2.vy = v2.ly*proj2.len;
  217.     // add the projections
  218.     proj.vx = v1.f*v2.f*proj1.vx+v1.b*v2.b*proj2.vx;
  219.     proj.vy = v1.f*v2.f*proj1.vy+v1.b*v2.b*proj2.vy;
  220.     return proj;
  221. }
  222. // project vector v1 on unit-sized vector dx/dy
  223. function projectVector(v1, dx, dy) {
  224.     // find dot product
  225.     var dp = v1.vx*dx+v1.vy*dy;
  226.     var proj = {};
  227.     // projection components
  228.     proj.vx = dp*dx;
  229.     proj.vy = dp*dy;
  230.     return proj;
  231. }
  232. /********************************************************************/
  233. // CODE ADDED BY SRDJAN SUSNIC
  234. // declare starting point of the current drawing line
  235. var lineX1, lineY1;
  236. // declare ending point of the current drawing line
  237. var lineX2, lineY2;
  238. // flag that states if we can draw line or not
  239. can_draw = false;
  240. // flag that states if the player drew a line
  241. player_drew = false;
  242. // next movie depth for the current drawing line
  243. nextLineDepth = 0;
  244. // create array for vectors of lines drawn by mouse
  245. game.mouseV = new Array();
  246. // create a movie which represents a line drawn by mouse
  247. _root.createEmptyMovieClip(“mouseLine”, 3);
  248. // when we click…
  249. onMouseDown = function () {
  250.     // get starting point of line according to current mouse position