New tile based platform engine – part 9 – coins n’ spikes

You asked for coins and spikes, and here they are...

As usual I had to define some rules... in this case spikes are deadly only when the player has both feet on it... later I will make a lava (or electric) tile that will kill the player even if he only has one foot on it.

At the moment the player just restarts when he dies, later I will manage real deaths.

Coins are... well... coins... just collect them.

Fix for the fix for infamous Ladder Bug in the Platform Tutorials

In New tile based platform engine - more theory I said superdean fixed the ladder bug... that's not completely true because with his code the player cannot climb down a ladder when he's walking over it.

So the correct if statement to perform when the player presses DOWN is neither mine

if (over == "ladder") {

nor superdean's one

if (top_right == 6 or bottom_right == 6 or top_left == 6 or bottom_left == 6){

but

if ((over == "ladder") or (top_right == 6 or bottom_right == 6 or top_left == 6 or bottom_left == 6)) {

Now grab the source code:

ACTIONSCRIPT:
  1. tile_size = 20;
  2. ground_acceleration = 1;
  3. ground_friction = 0.8;
  4. air_acceleration = 0.5;
  5. air_friction = 0.7;
  6. ice_acceleration = 0.15;
  7. ice_friction = 0.95;
  8. treadmill_speed = 2;
  9. max_speed = 3;
  10. xspeed = 0;
  11. yspeed = 0;
  12. falling = false;
  13. gravity = 0.5;
  14. jump_speed = 6;
  15. climbing = false;
  16. climb_speed = 0.8;
  17. level = new Array();
  18. enemy = new Array();
  19. coin = new Array();
  20. level[0] = [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];
  21. level[1] = [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. level[2] = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 1, 0, 0, 0, 0, 1];
  23. level[3] = [1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 1];
  24. level[4] = [1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 1];
  25. level[5] = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 1];
  26. level[6] = [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 1, 0, 0, 0, 0, 0, 1];
  27. level[7] = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 1];
  28. level[8] = [1, 1, 1, 1, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 7, 0, 0, 6, 0, 0, 0, 0, 7, 0, 1];
  29. level[9] = [1, 1, 1, 1, 1, 1, 1, 2, 2, 8, 8, 8, 8, 1, 1, 3, 3, 1, 4, 4, 1, 8, 1, 8, 1];
  30. player = [5, 8];
  31. enemy[0] = [10, 3, -2];
  32. enemy[1] = [3, 3, -2];
  33. coin[0] = [2, 2];
  34. coin[1] = [23, 4];
  35. coin;
  36. function create_level(l) {
  37.     _root.createEmptyMovieClip("level_container", 1);
  38.     level_height = l.length;
  39.     level_width = l[0].length;
  40.     for (y=0; y<level_height; y++) {
  41.         for (x=0; x<level_width; x++) {
  42.             if (l[y][x] != 0) {
  43.                 t = level_container.attachMovie("tile", "t"+y+"_"+x, _root.level_container.getNextHighestDepth(), {_x:x*tile_size, _y:y*tile_size});
  44.                 t.gotoAndStop(l[y][x]);
  45.             }
  46.         }
  47.     }
  48.     place_player();
  49.     for (x=0; x<coin.length; x++) {
  50.         coin_mc = level_container.attachMovie("coin", "coin_"+_root.level_container.getNextHighestDepth(), _root.level_container.getNextHighestDepth(), {_x:coin[x][0]*tile_size+tile_size/2, _y:coin[x][1]*tile_size+tile_size/2+1});
  51.         coin_mc.onEnterFrame = function() {
  52.             if (this.hitTest(level_container.hero._x, level_container.hero._y, true)) {
  53.                 this.removeMovieClip();
  54.             }
  55.         };
  56.     }
  57.     for (x=0; x<enemy.length; x++) {
  58.         foe = level_container.attachMovie("patrol", "patrol_"+_root.level_container.getNextHighestDepth(), _root.level_container.getNextHighestDepth(), {_x:enemy[x][0]*tile_size+tile_size/2, _y:enemy[x][1]*tile_size+tile_size/2+1});
  59.         foe.speed = enemy[x][2];
  60.         foe.onEnterFrame = function() {
  61.             this.x_pos = this._x;
  62.             this.y_pos = this._y;
  63.             this.x_pos += this.speed;
  64.             this.left_foot_x = Math.floor((this.x_pos-6)/tile_size);
  65.             this.right_foot_x = Math.floor((this.x_pos+5)/tile_size);
  66.             this.foot_y = Math.floor((this.y_pos+9)/tile_size);
  67.             this.bottom = Math.floor((this.y_pos+8)/tile_size);
  68.             this.left_foot = level[this.foot_y][this.left_foot_x];
  69.             this.right_foot = level[this.foot_y][this.right_foot_x];
  70.             this.left = level[this.bottom][this.left_foot_x];
  71.             this.right = level[this.bottom][this.right_foot_x];
  72.             if (this.left_foot != 0 and this.right_foot != 0 and this.left == 0 and this.right == 0) {
  73.                 this._x = this.x_pos;
  74.             } else {
  75.                 this.speed *= -1;
  76.             }
  77.         };
  78.     }
  79. }
  80. create_level(level);
  81. _root.onEnterFrame = function() {
  82.     ground_under_feet();
  83.     walking = false;
  84.     climbing = false;
  85.     if (Key.isDown(Key.LEFT)) {
  86.         xspeed -= speed;
  87.         walking = true;
  88.     }
  89.     if (Key.isDown(Key.RIGHT)) {
  90.         xspeed += speed;
  91.         walking = true;
  92.     }
  93.     if (Key.isDown(Key.UP)) {
  94.         get_edges();
  95.         if (top_right == 6 or bottom_right == 6 or top_left == 6 or bottom_left == 6) {
  96.             jumping = false;
  97.             falling = false;
  98.             climbing = true;
  99.             climbdir = -1;
  100.         }
  101.     }
  102.     if (Key.isDown(Key.DOWN)) {
  103.         get_edges();
  104.         if ((over == "ladder") or (top_right == 6 or bottom_right == 6 or top_left == 6 or bottom_left == 6)) {
  105.             jumping = false;
  106.             falling = false;
  107.             climbing = true;
  108.             climbdir = 1;
  109.         }
  110.     }
  111.     if (Key.isDown(Key.SPACE)) {
  112.         get_edges();
  113.         if (!falling and !jumping) {
  114.             jumping = true;
  115.             yspeed = -jump_speed;
  116.         }
  117.     }
  118.     if (!walking) {
  119.         xspeed *= friction;
  120.         if (Math.abs(xspeed)<0.5) {
  121.             xspeed = 0;
  122.         }
  123.     }
  124.     if (xspeed>max_speed) {
  125.         xspeed = max_speed;
  126.     }
  127.     if (xspeed<max_speed*-1) {
  128.         xspeed = max_speed*-1;
  129.     }
  130.     if (falling or jumping) {
  131.         yspeed += gravity;
  132.     }
  133.     if (climbing) {
  134.         yspeed = climb_speed*climbdir;
  135.     }
  136.     if (!falling and !jumping and !climbing) {
  137.         yspeed = 0;
  138.     }
  139.     xspeed += bonus_speed;
  140.     check_collisions();
  141.     level_container.hero._x = x_pos;
  142.     level_container.hero._y = y_pos;
  143.     xspeed -= bonus_speed;
  144. };
  145. function ground_under_feet() {
  146.     bonus_speed = 0;
  147.     left_foot_x = Math.floor((x_pos-6)/tile_size);
  148.     right_foot_x = Math.floor((x_pos+5)/tile_size);
  149.     foot_y = Math.floor((y_pos+9)/tile_size);
  150.     left_foot = level[foot_y][left_foot_x];
  151.     right_foot = level[foot_y][right_foot_x];
  152.     if (left_foot != 0) {
  153.         current_tile = left_foot;
  154.     } else {
  155.         current_tile = right_foot;
  156.     }
  157.     switch (current_tile) {
  158.     case 0 :
  159.         over = "air";
  160.         speed = air_acceleration;
  161.         friction = air_friction;
  162.         falling = true;
  163.         break;
  164.     case 1 :
  165.         over = "ground";
  166.         speed = ground_acceleration;
  167.         friction = ground_friction;
  168.         break;
  169.     case 2 :
  170.         over = "ice";
  171.         speed = ice_acceleration;
  172.         friction = ice_friction;
  173.         break;
  174.     case 3 :
  175.         over = "treadmill";
  176.         speed = ground_acceleration;
  177.         friction = ground_friction;
  178.         bonus_speed = -treadmill_speed;
  179.         break;
  180.     case 4 :
  181.         over = "treadmill";
  182.         speed = ground_acceleration;
  183.         friction = ground_friction;
  184.         bonus_speed = treadmill_speed;
  185.         break;
  186.     case 5 :
  187.         over = "cloud";
  188.         speed = ground_acceleration;
  189.         friction = ground_friction;
  190.         break;
  191.     case 6 :
  192.         over = "ladder";
  193.         speed = ground_acceleration;
  194.         friction = ground_friction;
  195.         break;
  196.     case 7 :
  197.         over = "trampoline";
  198.         speed = ground_acceleration;
  199.         friction = ground_friction;
  200.         break;
  201.     case 8 :
  202.         over = "spikes";
  203.         if (left_foot == 8 and right_foot == 8) {
  204.             place_player();
  205.         }
  206.     }
  207. }
  208. function check_collisions() {
  209.     y_pos += yspeed;
  210.     get_edges();
  211.     // collision to the bottom
  212.     if (yspeed>0) {
  213.         if ((bottom_right != 0 and bottom_right != 6) or (bottom_left != 0 and bottom_left != 6)) {
  214.             // not a cloud...
  215.             if (bottom_right != 5 and bottom_left != 5) {
  216.                 // a trampoline
  217.                 if ((bottom_right == 7 or bottom_left == 7) and (Math.abs(yspeed)>1)) {
  218.                     yspeed = yspeed*-1;
  219.                     jumping = true;
  220.                     falling = true;
  221.                 } else {
  222.                     y_pos = bottom*tile_size-9;
  223.                     yspeed = 0;
  224.                     falling = false;
  225.                     jumping = false;
  226.                 }
  227.             } else {
  228.                 //cloud
  229.                 if (prev_bottom<bottom) {
  230.                     y_pos = bottom*tile_size-9;
  231.                     yspeed = 0;
  232.                     falling = false;
  233.                     jumping = false;
  234.                 }
  235.             }
  236.         }
  237.     }
  238.     // collision to the top                                                        
  239.     if (yspeed<0) {
  240.         if ((top_right != 0 and top_right != 5 and top_right != 6) or (top_left != 0 and top_left != 5 and top_left != 6)) {
  241.             y_pos = bottom*tile_size+1+8;
  242.             yspeed = 0;
  243.             falling = false;
  244.             jumping = false;
  245.         }
  246.     }
  247.     x_pos += xspeed;
  248.     get_edges();
  249.     // collision to the left          
  250.     if (xspeed<0) {
  251.         if ((top_left != 0 and top_left != 5 and top_left != 6 and top_left != 7) or (bottom_left != 0 and bottom_left != 5 and bottom_left != 6 and bottom_left != 7)) {
  252.             x_pos = (left+1)*tile_size+6;
  253.             xspeed = 0;
  254.         }
  255.     }
  256.     // collision to the right                                                                                
  257.     if (xspeed>0) {
  258.         if ((top_right != 0 and top_right != 5 and top_right != 6 and top_right != 7) or (bottom_right != 0 and bottom_right != 5 and bottom_right != 6 and bottom_right != 7)) {
  259.             x_pos = right*tile_size-6;
  260.             xspeed = 0;
  261.         }
  262.     }
  263.     prev_bottom = bottom;
  264. }
  265. function get_edges() {
  266.     // right edge
  267.     right = Math.floor((x_pos+5)/tile_size);
  268.     // left edge  
  269.     left = Math.floor((x_pos-6)/tile_size);
  270.     // bottom edge
  271.     bottom = Math.floor((y_pos+8)/tile_size);
  272.     // top edge
  273.     top = Math.floor((y_pos-9)/tile_size);
  274.     // adjacent tiles
  275.     top_right = level[top][right];
  276.     top_left = level[top][left];
  277.     bottom_left = level[bottom][left];
  278.     bottom_right = level[bottom][right];
  279. }
  280. function place_player() {
  281.     level_container.hero.removeMovieClip();
  282.     x_pos = player[0]*tile_size+tile_size/2;
  283.     y_pos = player[1]*tile_size+tile_size/2+1;
  284.     level_container.attachMovie("hero", "hero", _root.level_container.getNextHighestDepth(), {_x:x_pos, _y:y_pos});
  285. }

and play the game.

Can you grab the rightmost coin? (the other is too easy because patrols can't kill the player)

Download the source code and enjoy.

Nest step... code optimization.

Rate this post: 1 Star2 Stars3 Stars4 Stars5 Stars (12 votes, average: 5 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.

22 Responses to “New tile based platform engine – part 9 – coins n’ spikes”

  1. Andrius on October 7th, 2008 1:48 pm

    Awesome. I allredy made spikes but these are good too. And after all stuff, can you make level editor/loader? Thanks!

  2. dix huit on October 7th, 2008 2:01 pm

    This is great and all but what’s happening with the WordPress arcade plugin?

  3. Gabriel Bianconi on October 7th, 2008 2:14 pm

    Nice tut… But where’s the WP Arcade?

    And BoxHead Tutorial?

    And AS3 Versions?

    Ok… I know I’m asking too much…

  4. MalQue on October 7th, 2008 4:33 pm

    Yeah, I think the Boxhead tutorial became vaporware. I was waiting on that one too.

  5. Christo on October 7th, 2008 4:42 pm

    How can I contact you, I dont think me email is going through ?

  6. Josh on October 7th, 2008 5:25 pm

    Tower defense tuts lol pls that would make my month
    and gh4 is gonna be awesome but tower defense tuts good i guess

  7. EagleVision on October 7th, 2008 5:58 pm

    Very nice.
    I might actually use this! =)
    Thank you!

    Boxhead tutorial became vaporware I suppose.
    But anyhow, keep it up, you’ve improved with the blog. =) …And me = Bad

  8. Javier Lázaro on October 7th, 2008 6:12 pm

    Code optimization! Cool! I always want to make my code as efficient as possible.

    BTW, I hope the Boxhead tutorial will not become vaporware…

  9. Andrius on October 7th, 2008 6:30 pm

    Not boxhead tut. Nano wars :)

  10. Superdean on October 8th, 2008 12:02 am

    aww…so i was WRONG???

    i knew i forgot something…

  11. Brad on October 8th, 2008 3:26 am

    Its okay superdean, who needs to climb down a ladder when they can jump down right. :)

  12. Emanuele Feronato on October 8th, 2008 10:29 am

    christo: info[at]emanueleferonato.com

  13. JDog053 on October 8th, 2008 8:29 pm

    Awesome stuff here Emanuele, I still check daily even if I don’t post a response. I’ve also got a good game idea that uses a tile engine I made before. It should be good, it also hlps that I love Pixel art too. I’d love to get as much money as Nitrome per game, they must get 5k per game atleast, they’re fantastic !

  14. Christo on October 9th, 2008 12:51 pm

    Ok I try again, allready sent you 3 or 4 emails, perhaps they are not going through, I really dont want too spam you, I’ll try again now.

    Thanks

    BTW awesome tutorials on your site :)

  15. Jerry on October 9th, 2008 4:52 pm

    Great work as always.

  16. FrozenHaddock on October 10th, 2008 12:22 am

    Excellent engine, definitely going to look into developing it further.

    Also, optimisation? What is this ‘optimisation’ you speak of?

    /Recently got shouted at for poor optimisation
    http://frozenhaddock.co.uk/2008/10/avoiding-game-pt-5b/

  17. Daniel Rodriguez on October 11th, 2008 3:37 am

    One interesting tile will be slopes, really dont have any idea to do it.

  18. Michael Brandse on October 12th, 2008 4:25 pm

    Just found your blog through google, as I am interested in getting some actionscript experience and want to do so while making a side scrolling action adventure. So, there are two particular things that have been on my mind as a completely inexperienced programmer:

    -How to implement doors? So that you can switch from the one levelsheet to the other? I have seen some tutorials with doors implemented, but the problem with those were that they relied on going to a different frame. What I am searching for is to replace the level while staying in the same frame; cleaning up one level and loading the other.

    -How to implement a scrolling feature, where the player walks to the middle of the screen and as long as the level is long enough the level starts scrolling at that point?

    Sorry for the questions already…

  19. oventoaster on October 13th, 2008 3:40 pm

    Ahm may i ask something sir? this question might have been ask by others on the comment but,

    is there a way where the players jump height can be determine on how long the player presses the jump key?

    i mean just like how super mario does but of course theres a limit to how high he jumps. i already got the idea but dont really know how to apply it, im thinking of a loop where it checks if the max height of a jump is reached.

  20. Gatzä02 on November 29th, 2008 9:17 pm

    hi,
    i have a question. Can you write me an e-mail? I wanna send you a try of my platform game…. but I still have two problems.

Leave a Reply




Trackbacks

  1. Basic level editor for a tile based game : Emanuele Feronato on October 8th, 2008 12:43 pm

    [...] am sharing with you a basic level editor made for the platform engine but easily adaptable to any tile based game made by Daniel Felipe Rodriguez Your recent set of [...]

  2. New tile based platform engine - part 10 - optimization, doors n’ keys : Emanuele Feronato on October 13th, 2008 3:48 pm

    [...] how does the script at step 9 determine if a tile is walkable (player can pass through [...]

Posts