Make a game like Lumines with Flash - part 2

In the first part we managed to move and rotate a 2x2 square made (obviously) by 4 bricks.

Now we'll see how to make them fall when we press SPACE key.

Notice that you move and rotate blocks by tapping arrow keys, but you make them fall by pressing SPACE.

This because timing is essential, and we want to make blocks fall as the player touches the spacebar.

The code does not have anything difficult, I just have to check if there are empty spaces under falling bricks.

No "game over" check at the moment, it will be covered later.

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 the bricks I can move
  25. moveable_bricks = new Array();
  26. // initializing and drawing the play field
  27. for (x=0; x<grid_width; x++) {
  28.     field[x] = Array();
  29.     for (y=0; y<grid_height; y++) {
  30.         field[x][y] = 0;
  31.         // look how I determine cells position according to tile size and offsets
  32.         cell = _root.attachMovie("brick", "brick_"+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:x*tile_size+x_offset, _y:(y+2)*tile_size+y_offset});
  33.         // first frame = empty cell
  34.         cell.gotoAndStop(1);
  35.     }
  36. }
  37. // calling the function that will place four bricks on the stage
  38. place_bricks();
  39. // main function, to be executed at every frame
  40. _root.onEnterFrame = function() {
  41.     // if blocks aren't falling
  42.     if (!falling) {
  43.         // this is how I detect if a key was tapped:
  44.         // when it's pressed, I wait for it to be released (in this case: not pressed)
  45.         // thanks to the wait_<direction> variable
  46.         if (Key.isDown(Key.LEFT)) {
  47.             wait_left = true;
  48.         } else {
  49.             if (wait_left) {
  50.                 // if the left key has been tapped, move the four bricks on the left
  51.                 for (x=0; x<4; x++) {
  52.                     // this "if" is used to determine if the bricks are still inside the game field
  53.                     if ((_root["brick_"+moveable_bricks[x]]._x-x_offset)/tile_size-_root["brick_"+moveable_bricks[x]].pos%2>0) {
  54.                         _root["brick_"+moveable_bricks[x]]._x -= tile_size;
  55.                     }
  56.                 }
  57.                 // reset variable, now I must wait again for a key to be pressed
  58.                 wait_left = false;
  59.             }
  60.         }
  61.         // same routine for the right key
  62.         if (Key.isDown(Key.RIGHT)) {
  63.             wait_right = true;
  64.         } else {
  65.             if (wait_right) {
  66.                 for (x=0; x<4; x++) {
  67.                     if ((_root["brick_"+moveable_bricks[x]]._x-x_offset)/tile_size-_root["brick_"+moveable_bricks[x]].pos%2<14) {
  68.                         _root["brick_"+moveable_bricks[x]]._x += tile_size;
  69.                     }
  70.                 }
  71.                 wait_right = false;
  72.             }
  73.         }
  74.         // when the DOWN arrow is pressed, I must rotate the bricks clockwise
  75.         // block 0: moves to the right and becomes block 1
  76.         // block 1: moves down and becomes block 3
  77.         // block 2: moves up and becomes block 0
  78.         // block 3: moves to the left and becomes block 2
  79.         if (Key.isDown(Key.DOWN)) {
  80.             wait_down = true;
  81.         } else {
  82.             if (wait_down) {
  83.                 for (x=0; x<4; x++) {
  84.                     switch (_root["brick_"+moveable_bricks[x]].pos) {
  85.                     case 0 :
  86.                         _root["brick_"+moveable_bricks[x]].pos = 1;
  87.                         _root["brick_"+moveable_bricks[x]]._x += tile_size;
  88.                         break;
  89.                     case 1 :
  90.                         _root["brick_"+moveable_bricks[x]].pos = 3;
  91.                         _root["brick_"+moveable_bricks[x]]._y += tile_size;
  92.                         break;
  93.                     case 2 :
  94.                         _root["brick_"+moveable_bricks[x]].pos = 0;
  95.                         _root["brick_"+moveable_bricks[x]]._y -= tile_size;
  96.                         break;
  97.                     case 3 :
  98.                         _root["brick_"+moveable_bricks[x]].pos = 2;
  99.                         _root["brick_"+moveable_bricks[x]]._x -= tile_size;
  100.                         break;
  101.                     }
  102.                 }
  103.                 wait_down = false;
  104.             }
  105.         }
  106.         // when the UP arrow is pressed, I must rotate the bricks counter-clockwise
  107.         // block 0: moves down the right and becomes block 2
  108.         // block 1: moves to the left and becomes block 0
  109.         // block 2: moves to the right and becomes block 3
  110.         // block 3: moves up and becomes block 1
  111.         if (Key.isDown(Key.UP)) {
  112.             wait_up = true;
  113.         } else {
  114.             if (wait_up) {
  115.                 for (x=0; x<4; x++) {
  116.                     switch (_root["brick_"+moveable_bricks[x]].pos) {
  117.                     case 0 :
  118.                         _root["brick_"+moveable_bricks[x]].pos = 2;
  119.                         _root["brick_"+moveable_bricks[x]]._y += tile_size;
  120.                         break;
  121.                     case 1 :
  122.                         _root["brick_"+moveable_bricks[x]].pos = 0;
  123.                         _root["brick_"+moveable_bricks[x]]._x -= tile_size;
  124.                         break;
  125.                     case 2 :
  126.                         _root["brick_"+moveable_bricks[x]].pos = 3;
  127.                         _root["brick_"+moveable_bricks[x]]._x += tile_size;
  128.                         break;
  129.                     case 3 :
  130.                         _root["brick_"+moveable_bricks[x]].pos = 1;
  131.                         _root["brick_"+moveable_bricks[x]]._y -= tile_size;
  132.                         break;
  133.                     }
  134.                 }
  135.                 wait_up = false;
  136.             }
  137.         }
  138.         // when SPACE key is pressed, I don't wait for its release but I detect the key at once
  139.         if (Key.isDown(Key.SPACE)) {
  140.             // letìs made bricks fall...
  141.             falling = true;
  142.         }
  143.     } else {
  144.         //if the blocks are falling
  145.         // blocks_landed variable will count the number of bricks that already touched the ground
  146.         // or that cannot fall anymore because they are over other bricks
  147.         blocks_landed = 0;
  148.         for (x=0; x<4; x++) {
  149.             // calculating x and y position of the brick in the array
  150.             x_pos = (_root["brick_"+moveable_bricks[x]]._x-x_offset)/tile_size;
  151.             y_pos = (_root["brick_"+moveable_bricks[x]]._y-y_offset)/tile_size-1;
  152.             // determining if the block can fall. There are two conditions:
  153.             // 1: its position is less than zero. It means the block is outside the grid, in its starting position
  154.             // 2: its position is lower than the grid height and the tile under the block is empty
  155.             if ((y_pos<0) or ((y_pos<grid_height) and (field[x_pos][y_pos] == 0))) {
  156.                 // updating field array
  157.                 field[x_pos][y_pos] = _root["brick_"+moveable_bricks[x]]._currentframe;
  158.                 field[x_pos][y_pos-1] = 0;
  159.                 // physically moving the brick
  160.                 _root["brick_"+moveable_bricks[x]]._y += tile_size;
  161.             } else {
  162.                 // if the brick cannot move down, increase the number of blocks landed
  163.                 blocks_landed++;
  164.             }
  165.         }
  166.         // if all four bricks landed successfully...
  167.         if (blocks_landed == 4) {
  168.             // reset variable to false
  169.             falling = false;
  170.             // place four more bricks
  171.             place_bricks();
  172.         }
  173.     }
  174. };
  175. // function to place four bricks on the stage
  176. function place_bricks() {
  177.     // placing the four bricks
  178.     for (x=0; x<4; x++) {
  179.         // again, look how I determine bricks position according to tile size and offsets
  180.         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)});
  181.         // setting a random color for the brick (frames 2 to different_colors+1)
  182.         brk.gotoAndStop(Math.floor(Math.random()*different_colors)+2);
  183.         // saving brick position
  184.         // 0: up left
  185.         // 1: up right
  186.         // 2: bottom left
  187.         // 3: bottom right
  188.         brk.pos = x;
  189.         // saving the depth of the brick into the moveable_bricks array
  190.         // if you look how did I assign brick names, you'll see that I can determine a brick name
  191.         // starting from its depth. It's simply "brick_"+<the_depth>
  192.         moveable_bricks[x] = brk.getDepth();
  193.     }
  194. }

And this is the result... arrow keys to move/rotate and SPACE to drop

Download the source

Improve the blog rating this post
Tell me what do you think about this post. I'll write better and better entries.
1 Star2 Stars3 Stars4 Stars5 Stars (31 votes, average: 3.97 out of 5)
Loading ... Loading ...

» Flash Templates provided by Template Monster are pre-made web design products developed using Flash technology.
They can be easily customized to meet the unique requirements of your project.

One Response to “Make a game like Lumines with Flash - part 2”

Leave a Reply




Trackbacks

  1. Make a game like Lumines with Flash - part 3 : Emanuele Feronato - italian geek and PROgrammer on July 15th, 2008 10:31 am

    [...] part 1 and 2 if you did not [...]