Flash game creation tutorial - part 5.3

Let's go with another step.

In this part, we'll learn how to (almost) complete our first game... a tunnel race game.

Read tutorials from 1 to 5.2 if you haven't done it already and follow me in the game creation.

I'll continue from the code optimization seen in part 5.2, to continue adding features to the scrolling game.

Adding a timer

If you plan to make a racing game, the timer is very important. Some of the topics covered in this example are taken from the Flash simple timer/countdown tutorial.

ACTIONSCRIPT:
  1. // attaching movies
  2. _root.attachMovie("kira", "kira", 8000, {_x:234, _y:159});
  3. _root.attachMovie("wall", "wall", 10000, {_x:240, _y:0, _width:5700, _height:5700});
  4. _root.attachMovie("bg", "bg", 2000, {_x:240, _y:0, _width:5700, _height:5700});
  5. _root.attachMovie("count_down", "count_down", 12000, {_x:0, _y:0});
  6. // kira setup
  7. yspeed = 0;
  8. xspeed = 0;
  9. wind = 0.00;
  10. power = 0.65;
  11. gravity = 0.1;
  12. upconstant = 0.75;
  13. friction = 0.99;
  14. // timer setup
  15. start_time = getTimer();
  16. countdown = 60000;
  17. kira.onEnterFrame = function() {
  18.     // timer
  19.     elapsed_time = getTimer()-start_time;
  20.     _root.count_down.time_left.text = time_to_string(_root.countdown-elapsed_time);
  21.     // keys
  22.     if (Key.isDown(Key.LEFT)) {
  23.         xspeed = xspeed-power;
  24.     }
  25.     if (Key.isDown(Key.RIGHT)) {
  26.         xspeed = xspeed+power;
  27.     }
  28.     if (Key.isDown(Key.UP)) {
  29.         yspeed = yspeed-power*upconstant;
  30.     }
  31.     if (Key.isDown(Key.DOWN)) {
  32.         yspeed = yspeed+power*upconstant;
  33.     }
  34.     // speed calculation 
  35.     xspeed = (xspeed+wind)*friction;
  36.     yspeed = yspeed+gravity;
  37.     if (xspeed>0) {
  38.         this.kira.gotoAndStop(1);
  39.     } else {
  40.         this.kira.gotoAndStop(2);
  41.     }
  42.     // screen update
  43.     _root.wall._y -= yspeed;
  44.     _root.wall._x -= xspeed;
  45.     _root.bg._y -= yspeed;
  46.     _root.bg._x -= xspeed;
  47.     // collision
  48.     if (_root.wall.hitTest(this._x, this._y, true)) {
  49.         xspeed = 0;
  50.         yspeed = 0;
  51.         _root.wall._x = 240;
  52.         _root.wall._y = 0;
  53.         _root.bg._x = 240;
  54.         _root.bg._y = 0;
  55.     }
  56. };
  57. function time_to_string(time_to_convert) {
  58.     elapsed_hours = Math.floor(time_to_convert/3600000);
  59.     remaining = time_to_convert-(elapsed_hours*3600000);
  60.     elapsed_minutes = Math.floor(remaining/60000);
  61.     remaining = remaining-(elapsed_minutes*60000);
  62.     elapsed_seconds = Math.floor(remaining/1000);
  63.     remaining = remaining-(elapsed_seconds*1000);
  64.     elapsed_fs = Math.floor(remaining/10);
  65.     if (elapsed_hours<10) {
  66.         hours = "0"+elapsed_hours.toString();
  67.     } else {
  68.         hours = elapsed_hours.toString();
  69.     }
  70.     if (elapsed_minutes<10) {
  71.         minutes = "0"+elapsed_minutes.toString();
  72.     } else {
  73.         minutes = elapsed_minutes.toString();
  74.     }
  75.     if (elapsed_seconds<10) {
  76.         seconds = "0"+elapsed_seconds.toString();
  77.     } else {
  78.         seconds = elapsed_seconds.toString();
  79.     }
  80.     if (elapsed_fs<10) {
  81.         hundredths = "0"+elapsed_fs.toString();
  82.     } else {
  83.         hundredths = elapsed_fs.toString();
  84.     }
  85.     return minutes+":"+seconds+":"+hundredths;
  86. }

Line 4: Nothing to do with the timer, but I added a background to the cavern. The way I added the background is the same I added the main cavern. Look at the depth (0)... the background is behind all other objects

Line 5: Here I add the movieclip that will contain the timer. Look at the depth (12000)... the timer is in front of all aother objects. In the timer object I have a textarea called time_left that will be updated. We will add all texts covered in this tutorial in the same way

Lines 15-16: Timer setup... I want the level to be completed in 60 secods = 60,000 milliseconds. Again I strongly recommend to read the Flash simple timer/countdown tut.

Line 19: Determining elapsed time

Line 20: The text area time_left inside the movieclip count_down is updated according to the function time_to_string (lines 56-87). You can find this function fully explained... guess where?... Yes, at Flash simple timer/countdown tutorial!

You will notice nothing happens if the time reaches zero... I wanted it to fully test the game. You hould always test the game in a "god mode" to verify all levels are designed correctly, then start testing it in "normal mode".

The energy

Now, let's imagine we do not want the player to die if he hits the wall, but we want instead he to lose "energy" or "shields" or "bananas" until it reaches zero.

ACTIONSCRIPT:
  1. // attaching movies
  2. _root.attachMovie("kira", "kira", 8000, {_x:234, _y:159});
  3. _root.attachMovie("wall", "wall", 10000, {_x:240, _y:0, _width:5700, _height:5700});
  4. _root.attachMovie("bg", "bg", 2000, {_x:240, _y:0, _width:5700, _height:5700});
  5. _root.attachMovie("count_down", "count_down", 12000, {_x:0, _y:0});
  6. // kira setup
  7. yspeed = 0;
  8. xspeed = 0;
  9. wind = 0.00;
  10. power = 0.65;
  11. gravity = 0.1;
  12. upconstant = 0.75;
  13. friction = 0.99;
  14. energy = 100;
  15. count_down.energy_left.text = "Shield left: "+energy;
  16. // timer setup
  17. start_time = getTimer();
  18. countdown = 60000;
  19. kira.onEnterFrame = function() {
  20.     // timer
  21.     elapsed_time = getTimer()-start_time;
  22.     _root.count_down.time_left.text = time_to_string(_root.countdown-elapsed_time);
  23.     // keys
  24.     if (Key.isDown(Key.LEFT)) {
  25.         xspeed = xspeed-power;
  26.     }
  27.     if (Key.isDown(Key.RIGHT)) {
  28.         xspeed = xspeed+power;
  29.     }
  30.     if (Key.isDown(Key.UP)) {
  31.         yspeed = yspeed-power*upconstant;
  32.     }
  33.     if (Key.isDown(Key.DOWN)) {
  34.         yspeed = yspeed+power*upconstant;
  35.     }
  36.     // speed calculation   
  37.     xspeed = (xspeed+wind)*friction;
  38.     yspeed = yspeed+gravity;
  39.     if (xspeed>0) {
  40.         this.kira.gotoAndStop(1);
  41.     } else {
  42.         this.kira.gotoAndStop(2);
  43.     }
  44.     // screen update
  45.     _root.wall._y -= yspeed;
  46.     _root.wall._x -= xspeed;
  47.     _root.bg._y -= yspeed;
  48.     _root.bg._x -= xspeed;
  49.     // collision
  50.     if (_root.wall.hitTest(this._x, this._y, true)) {
  51.         energy -= Math.round(Math.sqrt(xspeed*xspeed+yspeed*yspeed));
  52.         _root.count_down.energy_left.text = "Shield left: "+energy;
  53.         xspeed = 0
  54.         yspeed = 0
  55.         _root.wall._y = old_y;
  56.         _root.wall._x = old_x;
  57.         _root.bg._y = old_y;
  58.         _root.bg._x = old_x;
  59.     } else {
  60.         old_x = _root.wall._x+2*xspeed;
  61.         old_y = _root.wall._y+2*yspeed;
  62.     }
  63. };
  64. function time_to_string(time_to_convert) {
  65.     elapsed_hours = Math.floor(time_to_convert/3600000);
  66.     remaining = time_to_convert-(elapsed_hours*3600000);
  67.     elapsed_minutes = Math.floor(remaining/60000);
  68.     remaining = remaining-(elapsed_minutes*60000);
  69.     elapsed_seconds = Math.floor(remaining/1000);
  70.     remaining = remaining-(elapsed_seconds*1000);
  71.     elapsed_fs = Math.floor(remaining/10);
  72.     if (elapsed_hours<10) {
  73.         hours = "0"+elapsed_hours.toString();
  74.     } else {
  75.         hours = elapsed_hours.toString();
  76.     }
  77.     if (elapsed_minutes<10) {
  78.         minutes = "0"+elapsed_minutes.toString();
  79.     } else {
  80.         minutes = elapsed_minutes.toString();
  81.     }
  82.     if (elapsed_seconds<10) {
  83.         seconds = "0"+elapsed_seconds.toString();
  84.     } else {
  85.         seconds = elapsed_seconds.toString();
  86.     }
  87.     if (elapsed_fs<10) {
  88.         hundredths = "0"+elapsed_fs.toString();
  89.     } else {
  90.         hundredths = elapsed_fs.toString();
  91.     }
  92.     return "Time left: "+minutes+":"+seconds+":"+hundredths;
  93. }

Line 14: Set the starting energy at 100

Line 15: Display player energy on screen

Line 51: In case of collision, the player does not die but his energy drains according to player speed. The higher the speed, the bigger the damage

Line 55-58: wall and background are resetted to their last position where no collision was detected

Lines 59-62: if there wasn't a collision, save actual position (with a little offset due by player speed)

These last lines remind a bit the collision checking seen in flash draw game tutorial part 4.

Now, next feature...

The brakes

I want the player to have the capability of using brakes, even if for a limited amount of time.

ACTIONSCRIPT:
  1. // attaching movies
  2. _root.attachMovie("kira", "kira", 8000, {_x:234, _y:159});
  3. _root.attachMovie("wall", "wall", 10000, {_x:240, _y:0, _width:5700, _height:5700});
  4. _root.attachMovie("bg", "bg", 2000, {_x:240, _y:0, _width:5700, _height:5700});
  5. _root.attachMovie("count_down", "count_down", 12000, {_x:0, _y:0});
  6. // kira setup
  7. yspeed = 0;
  8. xspeed = 0;
  9. wind = 0.00;
  10. power = 0.65;
  11. gravity = 0.1;
  12. upconstant = 0.75;
  13. friction = 0.99;
  14. energy = 100;
  15. brakes = 100;
  16. count_down.energy_left.text = "Shield left: "+energy;
  17. count_down.brake_left.text = "Brakes left: "+brakes;
  18. // timer setup
  19. start_time = getTimer();
  20. countdown = 60000;
  21. kira.onEnterFrame = function() {
  22.     // timer
  23.     elapsed_time = getTimer()-start_time;
  24.     _root.count_down.time_left.text = time_to_string(_root.countdown-elapsed_time);
  25.     // keys
  26.     if (Key.isDown(Key.LEFT)) {
  27.         xspeed = xspeed-power;
  28.     }
  29.     if (Key.isDown(Key.RIGHT)) {
  30.         xspeed = xspeed+power;
  31.     }
  32.     if (Key.isDown(Key.UP)) {
  33.         yspeed = yspeed-power*upconstant;
  34.     }
  35.     if (Key.isDown(Key.DOWN)) {
  36.         yspeed = yspeed+power*upconstant;
  37.     }
  38.     if ((Key.isDown(Key.SPACE))and(brakes> 0)) {
  39.         yspeed = yspeed/2;
  40.         xspeed = xspeed/2;
  41.         brakes --;
  42.         count_down.brake_left.text = "Brakes left: "+brakes;
  43.     }
  44.     // speed calculation   
  45.     xspeed = (xspeed+wind)*friction;
  46.     yspeed = yspeed+gravity;
  47.     if (xspeed>0) {
  48.         this.kira.gotoAndStop(1);
  49.     } else {
  50.         this.kira.gotoAndStop(2);
  51.     }
  52.     // screen update
  53.     _root.wall._y -= yspeed;
  54.     _root.wall._x -= xspeed;
  55.     _root.bg._y -= yspeed;
  56.     _root.bg._x -= xspeed;
  57.     // collision
  58.     if (_root.wall.hitTest(this._x, this._y, true)) {
  59.         energy -= Math.round(Math.sqrt(xspeed*xspeed+yspeed*yspeed));
  60.         _root.count_down.energy_left.text = "Shield left: "+energy;
  61.         xspeed = 0
  62.         yspeed = 0
  63.         _root.wall._y = old_y;
  64.         _root.wall._x = old_x;
  65.         _root.bg._y = old_y;
  66.         _root.bg._x = old_x;
  67.     } else {
  68.         old_x = _root.wall._x+2*xspeed;
  69.         old_y = _root.wall._y+2*yspeed;
  70.     }
  71. };
  72. function time_to_string(time_to_convert) {
  73.     elapsed_hours = Math.floor(time_to_convert/3600000);
  74.     remaining = time_to_convert-(elapsed_hours*3600000);
  75.     elapsed_minutes = Math.floor(remaining/60000);
  76.     remaining = remaining-(elapsed_minutes*60000);
  77.     elapsed_seconds = Math.floor(remaining/1000);
  78.     remaining = remaining-(elapsed_seconds*1000);
  79.     elapsed_fs = Math.floor(remaining/10);
  80.     if (elapsed_hours<10) {
  81.         hours = "0"+elapsed_hours.toString();
  82.     } else {
  83.         hours = elapsed_hours.toString();
  84.     }
  85.     if (elapsed_minutes<10) {
  86.         minutes = "0"+elapsed_minutes.toString();
  87.     } else {
  88.         minutes = elapsed_minutes.toString();
  89.     }
  90.     if (elapsed_seconds<10) {
  91.         seconds = "0"+elapsed_seconds.toString();
  92.     } else {
  93.         seconds = elapsed_seconds.toString();
  94.     }
  95.     if (elapsed_fs<10) {
  96.         hundredths = "0"+elapsed_fs.toString();
  97.     } else {
  98.         hundredths = elapsed_fs.toString();
  99.     }
  100.     return "Time left: "+minutes+":"+seconds+":"+hundredths;
  101. }

Line 15: Set the starting amount of brakes to 100

Line 17: Display player brakes on screen

Line 38: Checking if the player is braking (or pressing spacebar...) and the player has brakes left

Lines 39-42: Player speed is reduced by a half, brakes are reduced and new brakes value is displayed on the screen

Now we have all the information required on screen. Time to show them in a clearer way.

Text styles

Let's see how to give some style to our texts

ACTIONSCRIPT:
  1. // attaching movies
  2. _root.attachMovie("kira", "kira", 8000, {_x:234, _y:159});
  3. _root.attachMovie("wall", "wall", 10000, {_x:240, _y:0, _width:5700, _height:5700});
  4. _root.attachMovie("bg", "bg", 2000, {_x:240, _y:0, _width:5700, _height:5700});
  5. _root.attachMovie("count_down", "count_down", 12000, {_x:0, _y:1});
  6. // kira setup
  7. yspeed = 0;
  8. xspeed = 0;
  9. wind = 0.00;
  10. power = 0.65;
  11. gravity = 0.1;
  12. upconstant = 0.75;
  13. friction = 0.99;
  14. energy = 100;
  15. brakes = 100;
  16. with (count_down.brake_left) {
  17.     text = "Brakes: "+brakes;
  18.     textColor = 0x00ff00;
  19.     background = true;
  20.     border = true;
  21.     borderColor = 0xffffff;
  22.     backgroundColor = 0x000000;
  23.     _alpha = 80;
  24. }
  25. with (count_down.energy_left) {
  26.     text = "Shield: "+energy;
  27.     textColor = 0x00ff00;
  28.     background = true;
  29.     border = true;
  30.