Deprecated: Assigning the return value of new by reference is deprecated in /var/www/www.webgamemagazine.com/www/wp-settings.php on line 468

Deprecated: Assigning the return value of new by reference is deprecated in /var/www/www.webgamemagazine.com/www/wp-settings.php on line 483

Deprecated: Assigning the return value of new by reference is deprecated in /var/www/www.webgamemagazine.com/www/wp-settings.php on line 490

Deprecated: Assigning the return value of new by reference is deprecated in /var/www/www.webgamemagazine.com/www/wp-settings.php on line 526

Deprecated: Assigning the return value of new by reference is deprecated in /var/www/www.webgamemagazine.com/www/wp-includes/cache.php on line 103

Deprecated: Assigning the return value of new by reference is deprecated in /var/www/www.webgamemagazine.com/www/wp-includes/query.php on line 21

Deprecated: Assigning the return value of new by reference is deprecated in /var/www/www.webgamemagazine.com/www/wp-includes/theme.php on line 618

Deprecated: Assigning the return value of new by reference is deprecated in /var/www/www.webgamemagazine.com/www/wp-content/plugins/wp-o-matic/wpomatic.php on line 2072
Web-Game Magazine - the best free action/adventure web games and casual games, reviewed daily » Flash Tutorials

Great Games

Bow Street RunnerQuadradiusSeven Deadly SinsMore BeerAgent Wing DefendersChromaBlastSomething AmissChick Chick BOOMIvan Drago: Justice EnforcerSnow LineRed BaronNewgrounds Rumble

Worth Checking Out

Bumper CraftSpace Runner 2Matrix RampageFive 'tilNFL BandwagonSnake ClassicMax Mesiria RPGStar IslandRail of WarJames The Circus ZebraGo Squirrel Go!!!World Domination BattleMindfields 2204MiniballAquacubesToast of WarBlokkosCrusader Tank

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
  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 11th, 2008

Create a Flash game like Deflection - Posted by Emanuele Feronato

Today I spent some time with a game called Deflection.

Deflection

According to his author, it’s an addictive physics based game where the objective is to deflect the ball into the goal by creating deflection walls.

I bet I scared most of you with the word “physics”. This means a physics engine, massive AS3 coding, and so on.

Although I am seriously determined to start a tutorial series about latest physics engines, I played a bit with Deflection and I noticed the only physics involved in the game is used to determine the bounce of a regular shape (a circle - the ball) when collides with a line.

So I thought there was another way to create an engine like this one without using physics libraries.

The answer lies in an old vector tutorial made by Tony Pa called Ball in the corner.

I suggest you to read all Tony’s vector tutorials to understand the math behind the engine.

I made some changes to the tutorial in order to make it more “AS2 like” (it’s an old AS1 tutorial) and to manage an arbitrary number of lines.

In this step you will only see the engine working with 4 lines and no user interaction, but it’s really easy to add lines at runtime with the mouse (I’ll cover it in the next step).

Moreover, this is another good example about how to use a Flash game tutorial to make your own game.

Ok, now it’s time to show you the modified 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.     // reset object to other side if gone out of stage
  75.     if (ob.p1.x>game.stageW+ob.r) {
  76.         ob.p1.x = -ob.r;
  77.     } else if (ob.p1.x<-ob.r) {
  78.         ob.p1.x = game.stageW+ob.r;
  79.     }
  80.     if (ob.p1.y>game.stageH+ob.r) {
  81.         ob.p1.y = -ob.r;
  82.     } else if (ob.p1.y<-ob.r) {
  83.         ob.p1.y = game.stageH+ob.r;
  84.     }
  85.     // draw it       
  86.     drawAll(ob);
  87.     // make end point equal to starting point for next cycle
  88.     ob.p0 = ob.p1;
  89.     // save the movement without time
  90.     ob.vx = ob.vx/ob.timeFrame;
  91.     ob.vy = ob.vy/ob.timeFrame;
  92. }
  93. // function to find all parameters for the vector
  94. function updateVector(v, frompoints) {
  95.     // x and y components
  96.     if (frompoints) {
  97.         v.vx = v.p1.x-v.p0.x;
  98.         v.vy = v.p1.y-v.p0.y;
  99.     } else {
  100.         v.p1.x = v.p0.x+v.vx;
  101.         v.p1.y = v.p0.y+v.vy;
  102.     }
  103.     // length of vector
  104.     v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
  105.     // normalized unti-sized components
  106.     if (v.len>0) {
  107.         v.dx = v.vx/v.len;
  108.         v.dy = v.vy/v.len;
  109.     } else {
  110.         v.dx = 0;
  111.         v.dy = 0;
  112.     }
  113.     // right hand normal
  114.     v.rx = -v.dy;
  115.     v.ry = v.dx;
  116.     // left hand normal
  117.     v.lx = v.dy;
  118.     v.ly = -v.dx;
  119.     return v;
  120. }
  121. function updateObject(v) {
  122.     // find time passed from last update
  123.     var thisTime = getTimer();
  124.     var time = (thisTime-v.lastTime)/100;
  125.     // we use time, not frames to move so multiply movement vector with time passed
  126.     v.vx *= time;
  127.     v.vy *= time;
  128.     // add gravity, also based on time
  129.     v.vy = v.vy+time*game.gravity;
  130.     v.p1 = {};
  131.     // find end point coordinates
  132.     v.p1.x = v.p0.x+v.vx;
  133.     v.p1.y = v.p0.y+v.vy;
  134.     // length of vector
  135.     v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
  136.     // normalized unti-sized components
  137.     v.dx = v.vx/v.len;
  138.     v.dy = v.vy/v.len;
  139.     // right hand normal
  140.     v.rx = -v.vy;
  141.     v.ry = v.vx;
  142.     // left hand normal
  143.     v.lx = v.vy;
  144.     v.ly = -v.vx;
  145.     // save the current time
  146.     v.lastTime = thisTime;
  147.     // save time passed
  148.     v.timeFrame = time;
  149. }
  150. // find intersection point of 2 vectors
  151. function findIntersection(v1, v2) {
  152.     // vector between center of ball and starting point of wall
  153.     var v3 = {};
  154.     v3.vx = v1.p1.x-v2.p0.x;
  155.     v3.vy = v1.p1.y-v2.p0.y;
  156.     // check if we have hit starting point
  157.     var dp = v3.vx*v2.dx+v3.vy*v2.dy;
  158.     if (dp<0) {
  159.         // hits starting point
  160.         var v = v3;
  161.     } else {
  162.         var v4 = {};
  163.         v4.vx = v1.p1.x-v2.p1.x;
  164.         v4.vy = v1.p1.y-v2.p1.y;
  165.         // check if we have hit side or endpoint
  166.         var dp = v4.vx*v2.dx+v4.vy*v2.dy;
  167.         if (dp>0) {
  168.             // hits ending point
  169.             var v = v4;
  170.         } else {
  171.             // it hits the wall
  172.             // project this vector on the normal of the wall
  173.             var v = projectVector(v3, v2.lx, v2.ly);
  174.         }
  175.     }
  176.     return v;
  177. }
  178. // find new vector bouncing from v2
  179. function bounce(v1, v2) {
  180.     // projection of v1 on v2
  181.     var proj1 = projectVector(v1, v2.dx, v2.dy);
  182.     // projection of v1 on v2 normal
  183.     var proj2 = projectVector(v1, v2.lx, v2.ly);
  184.     var proj = {};
  185.     // reverse projection on v2 normal
  186.     proj2.len = Math.sqrt(proj2.vx*proj2.vx+proj2.vy*proj2.vy);
  187.     proj2.vx = v2.lx*proj2.len;
  188.     proj2.vy = v2.ly*proj2.len;
  189.     // add the projections
  190.     proj.vx = v1.f*v2.f*proj1.vx+v1.b*v2.b*proj2.vx;
  191.     proj.vy = v1.f*v2.f*proj1.vy+v1.b*v2.b*proj2.vy;
  192.     return proj;
  193. }
  194. // project vector v1 on unit-sized vector dx/dy
  195. function projectVector(v1, dx, dy) {
  196.     // find dot product
  197.     var dp = v1.vx*dx+v1.vy*dy;
  198.     var proj = {};
  199.     // projection components
  200.     proj.vx = dp*dx;
  201.     proj.vy = dp*dy;
  202.     return proj;
  203. }

and this is the result… your own AS2 deflection engine ready for you to create a game.

If you want to write the code for player interaction, I will be happy to publish it, otherwise wait for me to do it.

Download the source code and enjoy.

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

July 11th, 2008

Fine tune your Flash game with First Impressions service - Posted by Emanuele Feronato

“How do I make my game better?” is the number one question Flash developers ask. Perhaps you’ve finished the game and think you’re done… but no sponsors are interested. Or perhaps you have a rough version of the game finished but have no idea how to turn it into a polished gem of a game. How do you improve your game?

First Impressions are the answer! We ask arbitrary users with wildly different gaming backgrounds to play your game for 5 minutes and give you their first impressions. They each write a paragraph of comments, along with some ratings on things like graphics quality and intuitiveness. Once you’ve gotten ten or twenty fresh opinions about your game, you’re bound to have a better idea of what to do next. And once you’ve made improvements, you can get more first impressions to see how people reacted to your changes.

First Impressions

With these words FlashGameLicense crew introduce their new service, called First Impressions (FI from now on).

If you don’t know what is FlashGameLicense (FGL from now on…), it’s a marketplace where Flash game developers and sponsor can meet. Read my review about it.

But now we are talking about the FI service. Basically, you are paying for people to play and review your game.

At this time, you may wonder why should you pay for a review when you can freely submit your game to a portal that allows people to review games and get reviews for free.

While it’s true that you could have some reviews at no cost, remember once your game is published, it’s not an unreleased game anymore… and this is important when you are looking for a sponsorship.

Also, most of the reviews people leave on portals are something like “Awesome! I enjoyed a lot! Thanx mate!” or “Boring. 2/5″… after playing your game for less than 30 seconds.

So, if you are looking to keep your game unreleased and have good quality reviews, you should consider purchasing the FI service.

Let’s make a test drive

You know I like to try and test everything… so I ordered 20 reviews for an one-week game that is about to be released.

Once you purchase your reviews, people start reviewing it very quickly… you will suffer the so-called “refresh syndrome” because you will find yourself reloading the page again and again just to see another review.

FI reviewers are paid to play and review, and this is the reason why reviews are always appropriate.

While I cannot show you all the reviews because most of them contain descriptions and spoilers about the game (that’s not already published), I want to show you a couple of screens where you will see how players reviewed the game.

I blurred off descriptions and comments

Only you can read these First Impressions and see the scores that reviewers give you. They are entirely private.

Final considerations

At $1 per review, it may seem a bit expensive, but you can fine-tune and polish a complex game with no more than 20 or 30 reviews, that will cost you less than a paid API integration or less than 100,000 plays if you will embed MochiAds ads.

So it’s definitively a good buy, expect an high return of investment from this feature.

To start ordering reviews and make your game better, just sign in to FlashGameLicense and you’re ready to make better games.

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

July 11th, 2008

Create a Flash game like Deflection - Posted by Emanuele Feronato

Today I spent some time with a game called Deflection.

Deflection

According to his author, it’s an addictive physics based game where the objective is to deflect the ball into the goal by creating deflection walls.

I bet I scared most of you with the word “physics”. This means a physics engine, massive AS3 coding, and so on.

Although I am seriously determined to start a tutorial series about latest physics engines, I played a bit with Deflection and I noticed the only physics involved in the game is used to determine the bounce of a regular shape (a circle - the ball) when collides with a line.

So I thought there was another way to create an engine like this one without using physics libraries.

The answer lies in an old vector tutorial made by Tony Pa called Ball in the corner.

I suggest you to read all Tony’s vector tutorials to understand the math behind the engine.

I made some changes to the tutorial in order to make it more “AS2 like” (it’s an old AS1 tutorial) and to manage an arbitrary number of lines.

In this step you will only see the engine working with 4 lines and no user interaction, but it’s really easy to add lines at runtime with the mouse (I’ll cover it in the next step).

Moreover, this is another good example about how to use a Flash game tutorial to make your own game.

Ok, now it’s time to show you the modified 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.     // reset object to other side if gone out of stage
  75.     if (ob.p1.x>game.stageW+ob.r) {
  76.         ob.p1.x = -ob.r;
  77.     } else if (ob.p1.x<-ob.r) {
  78.         ob.p1.x = game.stageW+ob.r;
  79.     }
  80.     if (ob.p1.y>game.stageH+ob.r) {
  81.         ob.p1.y = -ob.r;
  82.     } else if (ob.p1.y<-ob.r) {
  83.         ob.p1.y = game.stageH+ob.r;
  84.     }
  85.     // draw it       
  86.     drawAll(ob);
  87.     // make end point equal to starting point for next cycle
  88.     ob.p0 = ob.p1;
  89.     // save the movement without time
  90.     ob.vx = ob.vx/ob.timeFrame;
  91.     ob.vy = ob.vy/ob.timeFrame;
  92. }
  93. // function to find all parameters for the vector
  94. function updateVector(v, frompoints) {
  95.     // x and y components
  96.     if (frompoints) {
  97.         v.vx = v.p1.x-v.p0.x;
  98.         v.vy = v.p1.y-v.p0.y;
  99.     } else {
  100.         v.p1.x = v.p0.x+v.vx;
  101.         v.p1.y = v.p0.y+v.vy;
  102.     }
  103.     // length of vector
  104.     v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
  105.     // normalized unti-sized components
  106.     if (v.len>0) {
  107.         v.dx = v.vx/v.len;
  108.         v.dy = v.vy/v.len;
  109.     } else {
  110.         v.dx = 0;
  111.         v.dy = 0;
  112.     }
  113.     // right hand normal
  114.     v.rx = -v.dy;
  115.     v.ry = v.dx;
  116.     // left hand normal
  117.     v.lx = v.dy;
  118.     v.ly = -v.dx;
  119.     return v;
  120. }
  121. function updateObject(v) {
  122.     // find time passed from last update
  123.     var thisTime = getTimer();
  124.     var time = (thisTime-v.lastTime)/100;
  125.     // we use time, not frames to move so multiply movement vector with time passed
  126.     v.vx *= time;
  127.     v.vy *= time;
  128.     // add gravity, also based on time
  129.     v.vy = v.vy+time*game.gravity;
  130.     v.p1 = {};
  131.     // find end point coordinates
  132.     v.p1.x = v.p0.x+v.vx;
  133.     v.p1.y = v.p0.y+v.vy;
  134.     // length of vector
  135.     v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
  136.     // normalized unti-sized components
  137.     v.dx = v.vx/v.len;
  138.     v.dy = v.vy/v.len;
  139.     // right hand normal
  140.     v.rx = -v.vy;
  141.     v.ry = v.vx;
  142.     // left hand normal
  143.     v.lx = v.vy;
  144.     v.ly = -v.vx;
  145.     // save the current time
  146.     v.lastTime = thisTime;
  147.     // save time passed
  148.     v.timeFrame = time;
  149. }
  150. // find intersection point of 2 vectors
  151. function findIntersection(v1, v2) {
  152.     // vector between center of ball and starting point of wall
  153.     var v3 = {};
  154.     v3.vx = v1.p1.x-v2.p0.x;
  155.     v3.vy = v1.p1.y-v2.p0.y;
  156.     // check if we have hit starting point
  157.     var dp = v3.vx*v2.dx+v3.vy*v2.dy;
  158.     if (dp<0) {
  159.         // hits starting point
  160.         var v = v3;
  161.     } else {
  162.         var v4 = {};
  163.         v4.vx = v1.p1.x-v2.p1.x;
  164.         v4.vy = v1.p1.y-v2.p1.y;
  165.         // check if we have hit side or endpoint
  166.         var dp = v4.vx*v2.dx+v4.vy*v2.dy;
  167.         if (dp>0) {
  168.             // hits ending point
  169.             var v = v4;
  170.         } else {
  171.             // it hits the wall
  172.             // project this vector on the normal of the wall
  173.             var v = projectVector(v3, v2.lx, v2.ly);
  174.         }
  175.     }
  176.     return v;
  177. }
  178. // find new vector bouncing from v2
  179. function bounce(v1, v2) {
  180.     // projection of v1 on v2
  181.     var proj1 = projectVector(v1, v2.dx, v2.dy);
  182.     // projection of v1 on v2 normal
  183.     var proj2 = projectVector(v1, v2.lx, v2.ly);
  184.     var proj = {};
  185.     // reverse projection on v2 normal
  186.     proj2.len = Math.sqrt(proj2.vx*proj2.vx+proj2.vy*proj2.vy);
  187.     proj2.vx = v2.lx*proj2.len;
  188.     proj2.vy = v2.ly*proj2.len;
  189.     // add the projections
  190.     proj.vx = v1.f*v2.f*proj1.vx+v1.b*v2.b*proj2.vx;
  191.     proj.vy = v1.f*v2.f*proj1.vy+v1.b*v2.b*proj2.vy;
  192.     return proj;
  193. }
  194. // project vector v1 on unit-sized vector dx/dy
  195. function projectVector(v1, dx, dy) {
  196.     // find dot product
  197.     var dp = v1.vx*dx+v1.vy*dy;
  198.     var proj = {};
  199.     // projection components
  200.     proj.vx = dp*dx;
  201.     proj.vy = dp*dy;
  202.     return proj;
  203. }

and this is the result… your own AS2 deflection engine ready for you to create a game.

If you want to write the code for player interaction, I will be happy to publish it, otherwise wait for me to do it.

Download the source code and enjoy.

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

July 10th, 2008

Learning AS2 Classes Part 3 - Posted by Psycho Goldfish

In the last 2 parts we covered simple classes using object and static methods. Today I’m going to go over class extensions.Extending classes is really useful when you want to make a bunch of classes that have independent functionality but also share a lot of common functions.

One of the most useful ways to use class extensions in game development is to extend the MovieClip class, and that’s just what we’re going to do now!

MovieClips are a built in class type, so you can add all sorts of custom functionality to them.

To start, open up a new Flash Movie and just make a circle about 100 pixels wide/tall.

Select the circle then press F8 to bring up the ‘convert to symbol’ panel. Call the symbol ‘ball’ and select ‘MovieClip’. Press the ‘Advanced’ button, then check ‘Export for ActionScript.

In the AS 2.0 class box, type ‘BouncingClip’ and hit OK.

If you test your movie now you will get an error: “The class or interface ‘BouncingClip’ could not be loaded.”

I guess we better create the class then.

Save your Flash Movie somewhere like C:\flash_tutorial\bouncing_ball.fla

Open up a new ActionScript File, and put the following code in:

class BouncingClip extends MovieClip {

var gravity:Number = 10;
var velocity:Number = 0;
var terminal_velocity:Number = 100;
var friction = 90;

function onEnterFrame()
{

this._y += this.velocity
if (this._y + (this._height/2) > Stage.height) {

this._y = Stage.height - (this._height/2);
this.velocity *= -(this.friction/100);

}

this.velocity += this.gravity;
if (this.velocity > this.terminal_velocity) {

this.velocity = this.terminal_velocity;

}

}

}

As you see in the first line, we are extending the MovieClip class. All of the properties of movieclip can be accessed by our new class, but for this example all we are using is _y. We can also override any of the built-in methods. In this case we are overriding onEnterFrame, the function that is called on every frame of a movieclip.

Looking at the code you have probably figured out that we are telling this movieclip to fall and bounce when it hits the bottom of the stage.

Save the file in the same folder as your FLA and call it BouncingClip.as (C:\flash_tutorial\BouncingClip.as in this example).

Now when you test your movie, your ball will bounce.

For shits and giggle, go ahead and drag some more balls from your library.. maybe scale them do different sizes…. put them at different heights on the stage… then test again.

All the balls just work with that one common class!

So now that you have extended the MovieClip Class, let’s kick things up a notch.

In your Flash Movie, make a new circle, preferable a different color. Select it and hit F8… do the whole instance name deal again… hit advanced… etc etc…

This time, make the ActionScript 2.0 class “FlyingClip”.

Save your file, then open a new ActionScript File.

In the AS file, put the following code:

class FlyingClip extends BouncingClip {

var propulsion:Number = 12;

function onEnterFrame()
{

if (Key.isDown(Key.SPACE)) {

this.velocity -= this.propulsion;

}

}

}

Now we are extending the BouncingClip class. This means FlyingClip will have the same properties (velocity, gravity etc..) as BouncingClip, and will have access to all the MovieClip properties as well.

In this class we are overriding the onEnterFrame function again. In this function we are having the ball’s velocity decrease when the space bar is pressed making it go up.

Test your movie… you will see the ball does go up when you press space, but that’s all it does. This is because we overwrote the onEnterFrame function. Fortunately, this doesn’t completely eliminate the onEnterFrame function from the BouncingClip class, we can still call that using ’super’.

If you update your code to look like:

class FlyingClip extends BouncingClip {

var propulsion:Number = 12;

function onEnterFrame()
{

if (Key.isDown(Key.SPACE)) {

this.velocity -= this.propulsion;

}
super.onEnterFrame();

}

}

Now we are telling the clip to run the onEnterFrame function from the super class (the class that this class is extending), BouncingClip.

Test your movie now, and the new ball will fly when you press space, and will fall and bounce when you let go.

As you can imagine, extending classes this way can be very useful for developing game sprites that share common functionality such as collision detection, hit points, etc…, while having the freedom to add custom AI and user input as needed.

So there is your primer on using AS2 classes. As you can see, they are very useful in expanding the functionality of Flash, keeping your work organized and avoiding redundant and bloated code in your timelines.

Here’s the sample files, Enjoy!

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

July 10th, 2008

Learning AS2 Classes Part 2 - Posted by Psycho Goldfish

In the last lesson we went over what a class is, touched on the types of functions you can do and created a static class with some commonly used math routines.

This time we’ll get into object based classes.

Object based classes are built the same way as any class. The main difference is in the way you declare and call their functions.

Here is an example of an object class:

class StopWatch {

var brand:String = ‘Timex’;
private var startTime:Number;
private var stopTime:Number;
private var displayTime:String;
private var memory:Number;

function StopWatch()
{

resetTimer();

}

function startTimer()
{

var date:Date = new Date();
if (!this.startTime and !this.stopTime) {

this.startTime = date.getTime();

} else if (this.stopTime) {

this.startTime = date.getTime()-this.memory;
this.stopTime = null;

}

}

function stopTimer()
{

if (!this.stopTime) {

var date:Date = new Date();
this.stopTime = date.getTime();
this.memory = this.stopTime-this.startTime;

}

}

function resetTimer()
{

this.displayTime = “00:00:00.00″;
this.startTime = null;
this.stopTime = null;

}

function readTimer()
{

var total_time:Number;

if (this.startTime) {

if (this.stopTime) {

total_time = this.stopTime - this.startTime;

} else {

var date:Date = new Date();
total_time = date.getTime() - this.startTime;

}
var seconds:Number = total_time/1000;
total_time = (total_time/1000)-seconds;

// round decimals to 2 places
seconds = Math.round(seconds*100)/100;

var minutes:Number = total_time%60;
total_time = (total_time-minutes)/60;

var hours:Number = total_time;

var secondparts:Array = String(seconds).split(”.”);
if (!secondparts[1]) {

secondparts[1] = “00″;

}

var s_seconds:String = formatNumber(secondparts[0])+”.”+formatNumber(secondparts[1]);
var s_minutes:String = formatNumber(minutes);
var s_hours:String = formatNumber(hours);

this.displayTime = s_hours+”:”+s_minutes+”:”+s_seconds;

}

return (this.displayTime);

}

private function formatNumber(number)
{

var string:String = String(number);
while (string.length < 2) {

string = ‘0′+string;

}
return(string);

}

}

This class is the brains of a stopwatch. If you save this into your classpath folder as StopWatch.as you can use it as an object on your timeline (or in other classes ).

Open up a new Flash Movie and put this code on your timeline:

watch = new StopWatch();

Now, anytime you use the variable ‘watch’ on this part of your movie, it will have all the methods and properties of your class.

To see what brand the watch is, run this code:

watch = new StopWatch();

trace(”my watch is a “+watch.brand);

At the start of the StopWatch class you see we have “var brand:String = ‘Timex’;”. Because we didn’t define it as a private var (yes, vars can be private just like functions!), we are able to access it from outside of the class.

The next few lines are our private vars. These keep track of all the timestamps the watch uses to get the nice readable display.

After our variable declarations, we have a function called StopWatch. This function has the same name as the class and it is called a constructor. Constructor functions automatically run whenever you make an instance of the class.

So, when we put “watch = new StopWatch();”, the StopWatch class runs the resetTimer() function, which sets the display time to “00:00:00.00″.

So we now have our var defs and our constructor, the rest of the class contains our methods. You will notice none of the functions have the word ’static’ in them.

Static functions could be thought of as global functions. No matter where in your movie you are, or what variable you are using, they run from the base class and will always behave the same.

Non-static functions are carbon copied for each instance. If you were to add “clock = new StopWatch();”, for example, it would be able to run without effecting any of the settings in ‘watch’.

Additionally, you can’t call non static functions directly through the class; StopWatch.startTimer() would do nothing.

So, lets try this code out on our timeline:

watch = new StopWatch();
trace(”I am starting my “+watch.brand+” watch”);
watch.startTimer();

Key.addListener(this);
onKeyDown = function() {

if (Key.getCode() == Key.SPACE) {

watch.stopTimer();
trace(”You stopped the watch at “+watch.readTimer());
trace(”restarting the timer…”);
watch.resetTimer();
watch.startTimer();

}

}

When you test your movie, an instance of the stopwatch class gets created, it tells you what brand the watch is, and it starts the timer.

When you hit space, the timer is stopped and you are told how much time has passed. Then the timer is reset and started again.

If we change the code to look like this:

watch = new StopWatch();
trace(”I am starting my “+watch.brand+” watch”);
watch.startTimer();

clock = new StopWatch();
trace(”I am starting my “+clock.brand+” clock”);
clock.startTimer();

Key.addListener(this);
onKeyDown = function() {

if (Key.getCode() == Key.SPACE) {

watch.stopTimer();
trace(”You stopped the watch at “+watch.readTimer());
trace(”restarting the watch…”);
watch.resetTimer();
watch.startTimer();

}

if (Key.getCode() == Key.SHIFT) {

clock.stopTimer();
trace(”You stopped the clock at “+clock.readTimer());
trace(”restarting the clock…”);
clock.resetTimer();
clock.startTimer();

}

}

Now we have the same setup, but we have added an instance of StopWatch called ‘clock’, and can control it with the SHIFT key. Testing this script will show you how object based classes use a common rule-set, but run independently.

Grab the sample file for this tutorial and you can see this class in a more practical application.

In the next lesson, we’ll get into extending classes!

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

« Previous Entries