Step by step AS3 translation of Creation of a platform game with Flash – step 1.5

According to Bart de Boer, this is the step 1.5 of the Step by step AS3 translation of Creation of a platform game with Flash.

He fixed the jump issue and improved the collision engine.

As in the previous example, the file Script.as is the main class:

ACTIONSCRIPT:
  1. /*____________________________________________________
  2. |______________ register of functions _______________|
  3. |____________________________________________________|
  4.  
  5. - main()            only calling to update_hero() (every frame)
  6.  
  7. - create_hero()     creates hero as the var "Hero"
  8.  
  9. - update_hero()     check collision an move
  10.  
  11. - BuildMap()        load and create the level
  12.  
  13.  
  14. extern
  15.  
  16. Data.as
  17. - Setup()           create levels
  18.  
  19. collision_manager.as
  20. - Setup(size,map,hero)      setup the map
  21.  
  22. - Solve_all(forecastx,forecasty)        solves the collsions and checks for a jump
  23. */
  24.  
  25.  
  26. package{                                                //The begin of an .as file
  27.     import flash.display.MovieClip;                     //import some libraries
  28.     import flash.events.Event;
  29.     import flash.events.KeyboardEvent;
  30.  
  31.     public class Script extends MovieClip{              // start the script
  32.    
  33.     private const gravity:int = 1;
  34.     private const max_speed:int = 8;
  35.    
  36.     private const walkspeed:int = 4;
  37.     private const jumpspeed:int = 10;
  38.    
  39.     private var forecast_x:int;
  40.     private var forecast_y:int;
  41.    
  42.     private const start_x:int = 50;
  43.     private const start_y:int = 50;
  44.    
  45.     private var left:Boolean;
  46.     private var up:Boolean;
  47.     private var right:Boolean;
  48.     private var space:Boolean;
  49.        
  50.     private var level:Array = new Array();
  51.     private var tiles:Array = new Array();
  52.    
  53.     private var Map_data:Data = new Data;               // create a version of the Data.as
  54.     private var Hero_col:collision_manager = new collision_manager;
  55.    
  56.     private var Hero:hero = new hero;
  57.    
  58.         public function Script(){                       // the init (will only be runned once)
  59.             BuildMap();
  60.             create_hero();
  61.             addEventListener(Event.ENTER_FRAME, main);
  62.             stage.addEventListener(KeyboardEvent.KEY_DOWN, key_down);
  63.             stage.addEventListener(KeyboardEvent.KEY_UP, key_up);
  64.            
  65.             Hero_col.Setup(25,level,Hero);
  66.         }
  67.        
  68.         private function main(event:Event){
  69.             update_hero();
  70.         }
  71.        
  72.         private function key_down(event:KeyboardEvent){
  73.             if(event.keyCode == 37){
  74.                 left = true;
  75.             }
  76.             if(event.keyCode == 38){
  77.                 up = true;
  78.             }
  79.             if(event.keyCode == 39){
  80.                 right = true;
  81.             }
  82.         }
  83.        
  84.         private function key_up(event:KeyboardEvent){
  85.             if(event.keyCode == 37){
  86.                 left = false;
  87.             }
  88.             if(event.keyCode == 38){
  89.                 up = false;
  90.             }
  91.             if(event.keyCode == 39){
  92.                 right = false;
  93.             }
  94.         }
  95.                                
  96.            
  97.        
  98. /*
  99. ///    ///      /////////   ///////////     ///////////
  100. ///    ///      ///         ////    ///     ///     ///
  101. ///    ///      ///         ////    ///     ///     ///
  102. //////////      /////////   //////////      ///     ///
  103. //////////      /////////   ////    ///     ///     ///
  104. ///    ///      ///         ////    ///     ///     ///
  105. ///    ///      ///         ////    ///     ///     ///
  106. ///    ///      /////////   ////    ///     ///////////
  107. */
  108.         private function create_hero(){
  109.             addChild(Hero);
  110.             Hero.x = start_x;
  111.             Hero.y = start_y;
  112.             Hero.x_speed = 0;
  113.             Hero.y_speed = 0;
  114.         }
  115.        
  116.         private function update_hero(){
  117.             Hero.y_speed += gravity;
  118.             if(left){
  119.                 Hero.x_speed = -walkspeed;
  120.             }
  121.             if(right){
  122.                 Hero.x_speed = walkspeed;
  123.             }
  124.             if(up && Hero_col.can_jump){
  125.                 Hero.y_speed = -jumpspeed;
  126.             }
  127.            
  128.             if(Hero.y_speed> max_speed){
  129.                 Hero.y_speed = max_speed;
  130.             }
  131.            
  132.             forecast_y = Hero.y + Hero.y_speed;
  133.             forecast_x = Hero.x + Hero.x_speed;
  134.            
  135.             Hero_col.solve_all(forecast_x, forecast_y);
  136.            
  137.            
  138.             Hero.x_speed = 0;
  139.         }
  140.    
  141.    
  142. /*
  143. |||||||||||      |||||||||||      ||||||||||    ||||||||||
  144. ||||||||||||    ||||||||||||     ||||    ||||   ||||    |||
  145. ||||    ||||| |||||     ||||     ||||||||||||   ||||||||||
  146. ||||      |||||||       ||||     ||||    ||||   ||||
  147. ||||        |||         ||||    ||||      ||||  ||||
  148. ||||                    ||||    ||||      ||||  ||||
  149. */
  150.                
  151.         private function BuildMap(){
  152.             Map_data.Setup();                                               // setup data from extern file
  153.            
  154.             level = Map_data.level1;                                        // get data from extern file
  155.            
  156.             for(var t = 0; t <level.length; t++){
  157.                 for(var u = 0; u <level[t].length; u++){
  158.                     if(level[t][u] != 0){                                   //if the data is not null
  159.                         var new_tile:platform_tile = new platform_tile;     //than build a tile
  160.                        
  161.                         addChild(new_tile);                                 //put it on the screen
  162.                        
  163.                         new_tile.gotoAndStop(1);
  164.                         new_tile.x = u * 25;
  165.                         new_tile.y = t * 25;
  166.                        
  167.                         tiles.push(new_tile);                               //put it in an array
  168.                     }
  169.                 }
  170.             }
  171.         }
  172.     }
  173. }
  174.  
  175. // You may not post this on any other site than: http://www.emanueleferonato.com or http://www.frozenhaddock.com. You may not claim that you wrote this code. I'm not responsible for any nuclear activity that may be caused by this script.

The level is stored in the Data.as

ACTIONSCRIPT:
  1. package{
  2.    
  3.     public class Data{
  4.        
  5.     public var level1:Array = new Array();
  6.         public function Setup(){
  7.             level1 = [
  8.                       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
  9.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  10.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  11.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  12.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  13.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1],
  14.                       [1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  15.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  16.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  17.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  18.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  19.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  20.                       [1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  21.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  22.                       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
  23.                      ]
  24.         }
  25.     }
  26. }
  27.  
  28. // You may not post this on any other site than: http://www.emanueleferonato.com or http://www.frozenhaddock.com. You may not claim that you wrote this code. I'm not responsible for any nuclear activity that may be caused by this script.

While the solve_all function contained in the collision_manager.as solves all collisions in the forecast position of the player

ACTIONSCRIPT:
  1. package{
  2.    
  3.     public class collision_manager{
  4.         private var Tile_size:int;          //containing the size of the tiles
  5.         private var level;                  //level data container
  6.         private var forecast_x:int;         //where the player will be at the end of the frame
  7.         private var forecast_y:int;         //"                                               "
  8.         public var can_jump:Boolean;        //same as in Emanuele's tutorial
  9.         private var hero;                   //to store the Hero object in
  10.        
  11.         public function Setup(size,map,heroj){      //my standard setup function(init)
  12.             Tile_size = size;                       //initializing al vars
  13.             level = map;
  14.             hero = heroj;
  15.         }
  16.        
  17.         public function get_corners(point_x,point_y){              
  18.         //get the position of the four corners of the hero
  19.            
  20.             hero.downy = Math.round((point_y + 10 - Tile_size/2) / Tile_size);
  21.             hero.upy = Math.round((point_y - 10 - Tile_size/2) / Tile_size);
  22.             hero.rightx = Math.round((point_x + 5 - Tile_size/2) / Tile_size)
  23.             hero.leftx = Math.round((point_x - 5 - Tile_size/2) / Tile_size);
  24.             /*
  25.             Looks in wich tiles these four point are.
  26.             *Attention* TILES and not pixel!
  27.            
  28.             Will be used to get the position of the corners
  29.             and to get the end position of the hero.
  30.             */
  31.            
  32.             hero.downleft = level[hero.downy][hero.leftx];
  33.             hero.downright = level[hero.downy][hero.rightx];
  34.             hero.upright = level[hero.upy][hero.rightx];
  35.             hero.upleft = level[hero.upy][hero.leftx];
  36.            
  37.            
  38.             /*
  39.             Gets the sort tile the position of the corners has.
  40.            
  41.             One means there can be collision, zero is air.         
  42.             */
  43.         }
  44.        
  45.         public function check_ground(){
  46.             hero.downy = Math.round((hero.y + 11 - Tile_size/2) / Tile_size);
  47.             hero.rightx = Math.round((hero.x + 5 - Tile_size/2) / Tile_size)
  48.             hero.leftx = Math.round((hero.x - 5 - Tile_size/2) / Tile_size);
  49.             // Makes three points in tile-coordinates
  50.            
  51.             hero.downleft = level[hero.downy][hero.leftx];
  52.             hero.downright = level[hero.downy][hero.rightx];
  53.             //Checks the sort
  54.            
  55.             if(hero.downleft == 1 || hero.downright ==1){       //if there is any collision by the hero's feet
  56.                 can_jump = true;                                //than can jump
  57.             }
  58.             else{
  59.                 can_jump = false;                               //else not
  60.             }
  61.         }
  62.        
  63.         public function solve_all(forecastx, forecasty){
  64.         /*
  65.         This function looks hard... an it is...
  66.         I've been working on it for loads of hours, and this is the result.
  67.        
  68.         This is the best collision-test I've ever made, for sqaures.
  69.        
  70.         It's still readable, because I made it simple.
  71.        
  72.         It's four times almost the same. It checks for collision between the spots,
  73.         the four spots if there only were x_speeds, the four spots if there only was y_speed,
  74.         the four spots if there were both y- and x_speed.  
  75.         That are 3*4 = 12 spots.
  76.        
  77.        
  78.         //////////////////////////////////
  79.         Why's:
  80.        
  81.         question:
  82.         Why did I used forecast_x and forecast_y and not just hero.x and hero.y?
  83.        
  84.         answer:
  85.         Changing the hero over the screen will cost loads of CPU because an hero
  86.         exist out of loads of pixels. The forecast's are just simple variables
  87.        
  88.         question:
  89.         Is such a huge function not requiring a lot of CPU?
  90.        
  91.         answer:
  92.         It doesn't uses any while- or for loops, Math. functions and the most important of
  93.         all: no hitTestPoint()/hitTestObject(). So it's a lot faster.
  94.        
  95.         question:
  96.         Is there a better or faster collision test?
  97.        
  98.         answer:
  99.         Probaly, yes.
  100.         //////////////////////////////////
  101.        
  102.         var-explanation:
  103.        
  104.         downC   ->  is collision under the spot
  105.         upC     ->  is collision above the spot
  106.         rightC  ->  is collision right from the spot
  107.         leftC   ->  You probaly wouldn't expect this, but this is collision left from the spot
  108.        
  109.                 */
  110.             forecast_x = forecastx;
  111.             forecast_y = forecasty;
  112.            
  113.             get_corners(forecast_x,forecast_y);
  114.            
  115.             if(hero.downleft == 1){
  116.                 get_corners(hero.x,forecast_y);
  117.                     if(hero.downleft == 1){                
  118.                         hero.downC = true;
  119.                     }
  120.                     else{
  121.                         hero.downC = false;
  122.                     }
  123.                 get_corners(forecast_x,hero.y);
  124.                     if(hero.downleft == 1){                
  125.                         hero.leftC = true;
  126.                     }
  127.                     else{
  128.                         hero.leftC = false;
  129.                     }
  130.                     if(hero.leftC && hero.downC){
  131.                         forecast_x = (hero.leftx+1) * 25 + 5;
  132.                         forecast_y = (hero.downy+1) * 25 - 11;
  133.                         hero.y_speed = 0;
  134.                     }
  135.                     else if(hero.leftC){
  136.                         forecast_x = (hero.leftx+1) * 25 + 5;
  137.                     }
  138.                     else if(hero.downC){
  139.                         forecast_y = (hero.downy+1) * 25 - 11;
  140.                         hero.y_speed = 0;
  141.                     }
  142.             }
  143.            
  144.             get_corners(forecast_x,forecast_y);
  145.            
  146.             if(hero.downright == 1){
  147.                 get_corners(hero.x,forecast_y);
  148.                     if(hero.downright == 1){                   
  149.                         hero.downC = true;
  150.                     }
  151.                     else{
  152.                         hero.downC = false;
  153.                     }
  154.                 get_corners(forecast_x,hero.y);
  155.                     if(hero.downright == 1){                   
  156.                         hero.rightC = true;
  157.                     }
  158.                     else{
  159.                         hero.rightC = false;
  160.                     }
  161.                     if(hero.rightC && hero.downC){
  162.                         forecast_x = hero.rightx * 25 - 6;
  163.                         forecast_y = (hero.downy+1) * 25 - 11;
  164.                         hero.y_speed = 0;
  165.                     }
  166.                     else if(hero.rightC){
  167.                         forecast_x = hero.rightx * 25 - 6;
  168.                     }
  169.                     else if(hero.downC){
  170.                         forecast_y = (hero.downy+1) * 25 - 11;
  171.                         hero.y_speed = 0;
  172.                     }
  173.             }
  174.            
  175.             get_corners(forecast_x,forecast_y);
  176.            
  177.             if(hero.upleft == 1){
  178.                 get_corners(hero.x,forecast_y);
  179.                     if(hero.upleft == 1){                  
  180.                         hero.upC = true;
  181.                     }
  182.                     else{
  183.                         hero.upC = false;
  184.                     }
  185.                 get_corners(forecast_x,hero.y);
  186.                     if(hero.upleft == 1){                  
  187.                         hero.leftC = true;
  188.                     }
  189.                     else{
  190.                         hero.leftC = false;
  191.                     }
  192.                     if(hero.leftC && hero.upC){
  193.                         forecast_x = (hero.leftx+1) * 25 + 5;
  194.                         forecast_y = (hero.upy) * 25 + 10;
  195.                         hero.y_speed = 0;
  196.                     }
  197.                     else if(hero.leftC){
  198.                         forecast_x = (hero.leftx+1) * 25 + 5;
  199.                     }
  200.                     else if(hero.upC){
  201.                         forecast_y = (hero.upy) * 25 + 10;
  202.                         hero.y_speed  = 0;
  203.                     }
  204.             }
  205.            
  206.             get_corners(forecast_x,forecast_y);
  207.            
  208.             if(hero.upright == 1){
  209.                 get_corners(hero.x,forecast_y);
  210.                     if(hero.upright == 1){                 
  211.                         hero.upC = true;
  212.                     }
  213.                     else{
  214.                         hero.upC = false;
  215.                     }
  216.                 get_corners(forecast_x,hero.y);
  217.                     if(hero.upright == 1){                 
  218.                         hero.leftC = true;
  219.                     }
  220.                     else{
  221.                         hero.leftC = false;
  222.                     }
  223.                     if(hero.leftC && hero.upC){
  224.                         forecast_x = hero.rightx * 25 - 6;
  225.                         forecast_y = (hero.upy) * 25 + 10;
  226.                         hero.y_speed = 0;
  227.                     }
  228.                     else if(hero.leftC){
  229.                         forecast_x = hero.rightx * 25 - 6;
  230.                     }
  231.                     else if(hero.upC){
  232.                         forecast_y = (hero.upy) * 25 + 10;
  233.                         hero.y_speed  = 0;
  234.                     }
  235.             }
  236.            
  237.             hero.x = forecast_x;        //place the hero
  238.             hero.y = forecast_y;
  239.            
  240.             check_ground()      //runs the function to check for ground
  241.         }
  242.     }
  243. }
  244.  
  245. // You may not post this on any other site than: http://www.emanueleferonato.com or http://www.frozenhaddock.com. You may not claim that you wrote this code. I'm not responsible for any nuclear activity that may be caused by this script.

Now we have a working AS3 platform engine

Thanks to Bart de Boer for providing the source code of this prototype. Download it and start making your own AS3 platform game.

Rate this post: 1 Star2 Stars3 Stars4 Stars5 Stars (5 votes, average: 4.8 out of 5)
Loading ... Loading ...
If you found this post useful, please consider a small donation.
» 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.

10 Responses to “Step by step AS3 translation of Creation of a platform game with Flash – step 1.5”

  1. Frederik J on June 22nd, 2008 10:27 am

    I think that it’s in the place to mention that this engine, is based on Tony Pa’s tile tutorials…

  2. brart on June 22nd, 2008 11:38 am

    Only the getCorners function I used was the same as him… also I didn’t know it.

    I didn’t USED his one. I even didn’t read his one, know I read it because you mentioned it.

    Brart

  3. Andvari on June 23rd, 2008 8:44 pm

    yay!! Finally it works great :D

  4. elhector on July 9th, 2008 9:23 pm

    Hey Emanuele, I really really like your blog and have been following it for a while. But I notice you keep using AS2 in your examples: don’t get me wrong, you are awesome to share them either way!… What I am wondering is: is there an underlying reason why you haven’t make the switch to AS3 completely?… Any bugs you have bumped into or something?…

  5. lain on July 18th, 2008 12:38 pm

    How could i add a bigger charakter … size like Width 22, Height 56 ?
    I get always a bug when i try to change some of the
    “forecast_x = (hero.leftx+1) * 25 + 5;” values
    My Character is walking into the tiles… or the tile pulls him away…
    can somebody plz help me…

  6. XNA Monkey on August 18th, 2008 10:33 pm

    I can see that you wrote this from scratch great work. Tonys Get corners did the trick. I actually used the Flash Geom Rectangle Class to figure out the corners for me.

    DOnt worry Frederik J just wanted to hate and hijack you AS3 implementation at the same time LOL.

    Great work man.

  7. Nathan on August 26th, 2008 1:47 pm

    Can you make a tutorial on how to do slopes and ladders, I can’t translate from Tony Pa’s code.
    Is there a such thing as prototype in AS3?

    Please respond, it would be much obliged.

  8. rahul on September 2nd, 2008 12:40 pm

    hi
    i want to know more abt collsiosn…how to do the
    collsiosn of player with tiledMap(like 0 ,1)

  9. Rezki on April 22nd, 2009 10:07 am

    hi im newbie. wats the different between as2 and 3? thx

Leave a Reply




Trackbacks

  1. Adobe Flash CS3- AS3 and AS2 game tutorials roundup | Lemlinh.com on August 28th, 2008 1:57 am

    [...] Step 1.5 [...]

Posts