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

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

26 Responses to “New tile based platform engine – part 11 – slopes part b”

  1. Pedro on October 24th, 2008 2:28 pm

    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!!

  2. Dude on October 24th, 2008 2:38 pm

    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)?

  3. Joel Parkey on October 24th, 2008 7:03 pm

    Thats pretty darned aweome.

  4. Jeremi on October 25th, 2008 3:37 am

    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.

  5. AS3 Gamer on October 25th, 2008 6:10 am

    Are you seriously coding in AS2 in 2008?

  6. miff on October 25th, 2008 1:20 pm

    This is a good slope now
    Next part – scrolling level maybe?

  7. EagleVision on October 25th, 2008 4:28 pm

    @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

  8. jacko123 on October 25th, 2008 4:52 pm

    Hey…
    nice tutorial!
    By The Way: Your feed is broken!

  9. Josh of Cubicle Ninjas on October 25th, 2008 8:25 pm

    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.)

  10. Anonymous on October 26th, 2008 8:18 pm

    I once jumped on the first red block, and fell through and didn’t see the character again.

  11. Anonymous on October 26th, 2008 8:20 pm

    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?

  12. woody harris on October 26th, 2008 8:59 pm

    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.

  13. Quarky Quantum on October 26th, 2008 9:05 pm

    Great work on the tutorials,
    by the way I too have noticed your broken rss feed.

  14. Jon W on October 28th, 2008 11:30 am

    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

  15. askovitch on November 3rd, 2008 11:57 am

    hi whens the next part coming out?? could you make exits and more levels prehaps?

  16. caboose on November 28th, 2008 6:18 am

    what program are you using to make the scripts and tower deffence games?

  17. Chris on December 12th, 2008 3:43 am

    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();
    }

  18. Chris on December 12th, 2008 9:20 am

    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;
    }

  19. Chris on December 12th, 2008 9:52 pm

    Also you shoud add “_x = 0” under the place player

  20. Agadoijo on December 31st, 2008 5:21 pm

    Great work on the tutorial!
    Do you plan to load levels from files? That would be great!
    Thanks for your help.

  21. Gravyerd on March 23rd, 2009 2:56 am

    please, next you need say:
    Lava + Scroll + Enemy Killer
    i find how to create coins :D and a number of coins xp

  22. Gravyerd on March 23rd, 2009 3:08 am

    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

  23. Gravyerd on March 25th, 2009 2:38 am

    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

  24. FatJoe on June 5th, 2009 4:09 pm

    Gravyerd – put the preloader in a new scene, make sure the preloader scene is moved above the game scene ( shift + F2 ) should work..

  25. michael on September 22nd, 2009 4:41 am

    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

Leave a Reply




Trackbacks

  1. Goodbye AS2… : Emanuele Feronato on November 26th, 2008 1:02 pm

    [...] you noticed, my last post about AS2 coding is New tile based platform engine – part 11 – slopes part b, almost a month [...]

flash games company