New tile based platform engine – part 11 – slopes part b
As said in New tile based platform engine – part 11 – slopes part a, the game needed a fix for the jump from/on slope bug.
In part b the bug becomes a glitch… now you can jump from/on the slope but sometimes there is a “rebounce” glitch.
It’s very easy to determine why it’s happening and fix it… I am just leaving the explication for next time because I just got my computer repaired and need to do a lot of things.
I just wanted to answer a question about senseless slopes and N game mechanics.
There is a lot of difference between my tile based engine and a raycasting one.
Maybe I’ll cover it in next future.
Meanwhile, you are invited to take a look at the source code and fix the glitch at line 338
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 |
walkable_tiles = Array(0, 5, 6, 7, 10, 11); tile_size = 20; ground_acceleration = 1; ground_friction = 0.8; air_acceleration = 0.5; air_friction = 0.7; ice_acceleration = 0.15; ice_friction = 0.95; treadmill_speed = 2; max_speed = 3; xspeed = 0; yspeed = 0; falling = false; jumping = false; on_slope = false; gravity = 0.5; jump_speed = 6; climbing = false; climb_speed = 0.8; level = new Array(); enemy = new Array(); coin = new Array(); key = new Array(); 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]; 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]; 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]; 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]; level[4] = [1, 0, 1, 2, 2, 1, 0, 4, 4, 8, 3, 3, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 1]; level[5] = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0, 0, 1]; level[6] = [1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 1, 0, 0, 0, 0, 0, 1]; level[7] = [1, 1, 1, 0, 0, 1, 0, 0, 0, 10, 1, 11, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 1]; level[8] = [1, 1, 1, 1, 0, 9, 0, 0, 10, 1, 1, 1, 11, 0, 7, 0, 0, 6, 0, 0, 0, 0, 7, 0, 1]; level[9] = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 4, 4, 1, 8, 1, 8, 1]; player = [10, 6]; enemy[0] = [10, 3, -2]; enemy[1] = [3, 3, -2]; coin[0] = [2, 2]; coin[1] = [23, 4]; key[0] = [1, 5, 5, 8]; function create_level(l) { _root.createEmptyMovieClip("level_container",1); level_height = l.length; level_width = l[0].length; for (y=0; y<level_height; y++) { for (x=0; x<level_width; x++) { if (l[y][x] != 0) { t = level_container.attachMovie("tile", "t"+y+"_"+x, _root.level_container.getNextHighestDepth(), {_x:x*tile_size, _y:y*tile_size}); t.gotoAndStop(l[y][x]); } } } place_player(); for (x=0; x<coin.length; x++) { 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}); coin_mc.onEnterFrame = function() { if (this.hitTest(level_container.hero._x, level_container.hero._y, true)) { this.removeMovieClip(); } }; } for (x=0; x<key.length; x++) { key_mc = level_container.attachMovie("key", "key"+_root.level_container.getNextHighestDepth(), _root.level_container.getNextHighestDepth(), {_x:key[x][0]*tile_size+tile_size/2, _y:key[x][1]*tile_size+tile_size/2+1}); key_mc.ind = x; key_mc.onEnterFrame = function() { if (this.hitTest(level_container.hero._x, level_container.hero._y, true)) { open_x = [key[this.ind][2]]; open_y = [key[this.ind][3]]; level[open_y][open_x] = 0; _root.level_container["t"+open_y+"_"+open_x].removeMovieClip(); this.removeMovieClip(); } }; } for (x=0; x<enemy.length; x++) { 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}); foe.speed = enemy[x][2]; foe.onEnterFrame = function() { this.x_pos = this._x; this.y_pos = this._y; this.x_pos += this.speed; this.left_foot_x = Math.floor((this.x_pos-6)/tile_size); this.right_foot_x = Math.floor((this.x_pos+5)/tile_size); this.foot_y = Math.floor((this.y_pos+9)/tile_size); this.bottom = Math.floor((this.y_pos+8)/tile_size); this.left_foot = level[this.foot_y][this.left_foot_x]; this.right_foot = level[this.foot_y][this.right_foot_x]; this.left = level[this.bottom][this.left_foot_x]; this.right = level[this.bottom][this.right_foot_x]; if (this.left_foot != 0 and this.right_foot != 0 and this.left == 0 and this.right == 0) { this._x = this.x_pos; } else { this.speed *= -1; } }; } } create_level(level); _root.onEnterFrame = function() { ground_under_feet(); walking = false; climbing = false; if (Key.isDown(Key.LEFT)) { xspeed -= speed; walking = true; } if (Key.isDown(Key.RIGHT)) { xspeed += speed; walking = true; } if (Key.isDown(Key.UP)) { get_edges(); if (top_right == 6 or bottom_right == 6 or top_left == 6 or bottom_left == 6) { jumping = false; falling = false; climbing = true; climbdir = -1; } } if (Key.isDown(Key.DOWN)) { get_edges(); if ((over == "ladder") or (top_right == 6 or bottom_right == 6 or top_left == 6 or bottom_left == 6)) { jumping = false; falling = false; climbing = true; climbdir = 1; } } if (Key.isDown(Key.SPACE)) { //get_edges(); if (!falling and !jumping) { jumping = true; yspeed = -jump_speed; } } if (!walking) { xspeed *= friction; if (Math.abs(xspeed)<0.5) { xspeed = 0; } } if (xspeed>max_speed) { xspeed = max_speed; } if (xspeed<max_speed*-1) { xspeed = max_speed*-1; } if (falling or jumping) { yspeed += gravity; } if (climbing) { yspeed = climb_speed*climbdir; } if (!falling and !jumping and !climbing) { yspeed = 0; } xspeed += bonus_speed; check_collisions(); level_container.hero._x = x_pos; level_container.hero._y = y_pos; xspeed -= bonus_speed; }; function ground_under_feet() { bonus_speed = 0; left_foot_x = Math.floor((x_pos-6)/tile_size); right_foot_x = Math.floor((x_pos+5)/tile_size); foot_y = Math.floor((y_pos+9)/tile_size); left_foot = level[foot_y][left_foot_x]; right_foot = level[foot_y][right_foot_x]; if (left_foot != 0) { current_tile = left_foot; } else { current_tile = right_foot; } switch (current_tile) { case 0 : over = "air"; speed = air_acceleration; friction = air_friction; falling = true; break; case 1 : over = "ground"; speed = ground_acceleration; friction = ground_friction; break; case 2 : over = "ice"; speed = ice_acceleration; friction = ice_friction; break; case 3 : over = "treadmill"; speed = ground_acceleration; friction = ground_friction; bonus_speed = -treadmill_speed; break; case 4 : over = "treadmill"; speed = ground_acceleration; friction = ground_friction; bonus_speed = treadmill_speed; break; case 5 : over = "cloud"; speed = ground_acceleration; friction = ground_friction; break; case 6 : over = "ladder"; speed = ground_acceleration; friction = ground_friction; break; case 7 : over = "trampoline"; speed = ground_acceleration; friction = ground_friction; break; case 8 : over = "spikes"; if (left_foot == 8 and right_foot == 8) { place_player(); } default : over = "ground"; speed = ground_acceleration; friction = ground_friction; break; } } function check_collisions() { get_edges(); is_on_slope(); y_pos += yspeed; get_edges(); // collision to the bottom if (yspeed>0 and !on_slope) { if ((bottom_right != 0 and bottom_right != 6 and bottom_right != 10 and bottom_right != 11) or (bottom_left != 0 and bottom_left != 6 and bottom_left != 10 and bottom_left != 11)) { // not a cloud... if (bottom_right != 5 and bottom_left != 5) { // a trampoline if ((bottom_right == 7 or bottom_left == 7) and (Math.abs(yspeed)>1)) { yspeed = yspeed*-1; jumping = true; falling = true; } else { y_pos = bottom*tile_size-9; yspeed = 0; falling = false; jumping = false; } } else { //cloud if (prev_bottom<bottom) { y_pos = bottom*tile_size-9; yspeed = 0; falling = false; jumping = false; } } } } // collision to the top if (yspeed<0) { if ((top_right != 0 and top_right != 5 and top_right != 6) or (top_left != 0 and top_left != 5 and top_left != 6)) { y_pos = bottom*tile_size+1+8; yspeed = 0; falling = false; jumping = false; } } x_pos += xspeed; get_edges(); // collision to the left if (xspeed<0) { if (!is_walkable(top_left) or !is_walkable(bottom_left)) { x_pos = (left+1)*tile_size+6; xspeed = 0; } } // collision to the right if (xspeed>0) { if (!is_walkable(top_right) or !is_walkable(bottom_right)) { x_pos = right*tile_size-6; xspeed = 0; } } prev_bottom = bottom; } function get_edges() { // right edge right = Math.floor((x_pos+5)/tile_size); // left edge left = Math.floor((x_pos-6)/tile_size); // bottom edge bottom = Math.floor((y_pos+8)/tile_size); // top edge top = Math.floor((y_pos-9)/tile_size); // adjacent tiles top_right = level[top][right]; top_left = level[top][left]; bottom_left = level[bottom][left]; bottom_right = level[bottom][right]; } function place_player() { level_container.hero.removeMovieClip(); x_pos = player[0]*tile_size+tile_size/2; y_pos = player[1]*tile_size+tile_size/2+1; level_container.attachMovie("hero","hero",_root.level_container.getNextHighestDepth(),{_x:x_pos, _y:y_pos}); } function is_walkable(tile) { walkable = false; if (!on_slope) { for (x=0; x<walkable_tiles.length; x++) { if (tile == walkable_tiles[x]) { walkable = true; break; } } } else { walkable = true; } return (walkable); } function is_on_slope() { on_slope = false; x_slope_detector = Math.floor(x_pos/tile_size); y_slope_detector = Math.floor(y_pos/tile_size); if (jumping or falling) { if (level[y_slope_detector][x_slope_detector] == 10 or level[y_slope_detector][x_slope_detector] == 11) { if (level[y_slope_detector][x_slope_detector] == 10) { x_offset = tile_size-x_pos%tile_size; } // could be an "else"... if (level[y_slope_detector][x_slope_detector] == 11) { x_offset = x_pos%tile_size; } if (y_pos>Math.floor(y_pos/tile_size)*tile_size-9+x_offset) { // rebounce fix here } } } // could NOT be an else if (!jumping and !falling) { if (level[y_slope_detector+1][x_slope_detector] == 10 or level[y_slope_detector+1][x_slope_detector] == 11) { y_pos = (y_slope_detector+1)*tile_size+tile_size/2+1; y_slope_detector += 1; } if (level[y_slope_detector][x_slope_detector] == 10 or level[y_slope_detector][x_slope_detector] == 11) { if (level[y_slope_detector][x_slope_detector] == 10) { x_offset = tile_size-x_pos%tile_size; } // could be an "else"... if (level[y_slope_detector][x_slope_detector] == 11) { x_offset = x_pos%tile_size; } y_pos = Math.floor(y_pos/tile_size)*tile_size-9+x_offset; on_slope = true; } } if (!jumping and !falling and !on_slope and over != "ladder") { y_pos = (y_slope_detector)*tile_size+tile_size/2+1; } } |
Enjoy the result
Download the source code and have fun
They can be easily customized to meet the unique requirements of your project.





(27 votes, average: 4.78 out of 5)






This post has 28 comments
Pedro
I’ve found a small glitch about treadmills. When hero is on a last right treadmill, it’s totally moved to next tile, but, when it’s on a last left treadmill, only a pixel of the clip finishes above the next tile.
Your platform engine it’s great, thanks!!
Dude
Well done…looks like the glitch only apears when landing in the middle of the slope an not on the cornerns…
Anyways I was wondering if you could enhance the enemies in the next part so they kill you and you can kill them (maybe by jumping on them)?
Joel Parkey
Thats pretty darned aweome.
Jeremi
Nice work, dude you really help making flash games easy, thanks for helping all of us. I like all of your tutorials they are very helpful.
AS3 Gamer
Are you seriously coding in AS2 in 2008?
miff
This is a good slope now
Next part – scrolling level maybe?
EagleVision
@AS3 Gamer
Yes, and along with thousands of people who still don’t have enough money to buy CS3/CS4, unlike you rich guy.
Just don’t assume things, and make a firm statement. Think. ^^
Anyways, enough flaming. :P Nice tutorial, I won’t download it yet, since I like to see how it goes first, and if I work on the first the next version comes out with something I don’t want to work on…And that just gets very messy.
Good job, keep going.
Samuel
jacko123
Hey…
nice tutorial!
By The Way: Your feed is broken!
Josh of Cubicle Ninjas
I love guys like AS3 Gamer.
They still haven’t figured out the difference between tools and content. You just hand built a clean and efficient platforming engine and he is worried that it isn’t “new” enough. Does it work any worse? Nope. And yet he bitches on.
The good news is that people like him are so busy chasing technology they never make anything useful. Give me Flash 5, Photoshop 3, and some free time and I will blow your mind…
As always amazing work Emanuele!
(BTW anyone else find the RSS on this site broken? I rarely get new updates through the feed.)
Anonymous
I once jumped on the first red block, and fell through and didn’t see the character again.
Anonymous
im trying to make a platformer/rpg game and i want to make a slope without code being in the frame, i want it to be on a mc. Do you know how?
woody harris
how did you learn as2/3 so well? i understand most of the code youve done like in that ball revamped clone but when you start to have to use math, tiles, shooting, etc i dont really know what to do and therefore cant make so many genres of games because of these limitations. my expertise is in java and though the language is nearly identical i cant grasp the game programmers mentality. any recommendations.
Quarky Quantum
Great work on the tutorials,
by the way I too have noticed your broken rss feed.
Jon W
I’m a long fan of yours and have seen this platformer engine. Its brilliant! And I’ve seen a lot of people asking for a level editor, so, I made one! Download it here:
http://www.uploading.com/files/BGQFI3EC/editor.zip.html
Hope you like it and happy building!
Jon
askovitch
hi whens the next part coming out?? could you make exits and more levels prehaps?
Goodbye AS2… : Emanuele Feronato
[...] you noticed, my last post about AS2 coding is New tile based platform engine – part 11 – slopes part b, almost a month [...]
caboose
what program are you using to make the scripts and tower deffence games?
Chris
for killing your guy on contact with enemy just paste this code under the enemy stuff (after: “else{ this.speed *= -1; }”:
if (this.hitTest(level_container.hero._x, level_container.hero._y, true)) {
place_player();
}
Chris
For Scrolling use this code:
if (Key.isDown(Key.LEFT)) {
//scrolls screen
_x += -xspeed*.6;
xspeed -= speed;
walking = true;
}
if (Key.isDown(Key.RIGHT)) {
//scrolls screen
_x -= xspeed*.6;
xspeed += speed;
walking = true;
}
Chris
Also you shoud add “_x = 0†under the place player
Agadoijo
Great work on the tutorial!
Do you plan to load levels from files? That would be great!
Thanks for your help.
Gravyerd
please, next you need say:
Lava + Scroll + Enemy Killer
i find how to create coins :D and a number of coins xp
Gravyerd
and a question…
how to use teleport?
onClipEvent (enterFrame) {
if (this.hitTest(_root.level_container.hero)) {
// if this hits the char (_root.char)
level_container.hero._y += 20;
// _root.score goes up 1
unloadMovie(this);
// this movie clip is unloaded
}
}
this is my try script (but don’t work)
i put it in a mc already created… why don’t work?
i make the code to coins and work
onClipEvent (enterFrame) {
if (this.hitTest(_root.level_container.hero)) {
// This is the hit, and it work
_root.score.text++;
// to work
unloadMovie(this);
// anything work, but the teleport not work…
}
}
but teleport not… please help me
Gravyerd
Only 1 problem why your game:
You can’t put a preloader or anything before, is the code in first frame or is the code in first frame, if not in frame 1, do not work
need a preloader, in the start the game start LOOOOOOW and stoping every 2 seconds… slow download, need download the game + images in the same time that the player are playing… please, need free the frame number, i can make 10 level, but is 1 over other and other, please fix this
FatJoe
Gravyerd – put the preloader in a new scene, make sure the preloader scene is moved above the game scene ( shift + F2 ) should work..
michael
if i want to refer to the tiles or enemies at a different point in the code, say, a hittest, how would i do that?
something like _root.blah.tile
Luis
Does anyone knows how to make the enemies fall from where they are? I mean if the moving enemies detect a 0 in the array they fall until they touch ground? any helP?
Eric
Any one know how to kill the enemy? I need help with this.. but I can figure it out myself with my poor programing skill..