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:

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
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;
gravity = 0.5;
jump_speed = 6;
climbing = false;
climb_speed = 0.8;
level = new Array();
enemy = new Array();
coin = 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, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 1];
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];
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];
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];
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];
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];
player = [5, 8];
enemy[0] = [10, 3, -2];
enemy[1] = [3, 3, -2];
coin[0] = [2, 2];
coin[1] = [23, 4];
coin;
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<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();
		}
	}
}
function check_collisions() {
	y_pos += yspeed;
	get_edges();
	// collision to the bottom 
	if (yspeed>0) {
		if ((bottom_right != 0 and bottom_right != 6) or (bottom_left != 0 and bottom_left != 6)) {
			// 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 ((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)) {
			x_pos = (left+1)*tile_size+6;
			xspeed = 0;
		}
	}
	// collision to the right                                                                                
	if (xspeed>0) {
		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)) {
			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});
}

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 (15 votes, average: 5.00 out of 5)
Loading ... Loading ...
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.
Be my fan on Facebook and follow me on Twitter! Exclusive content for my Facebook fans and Twitter followers

This post has 23 comments

  1. Andrius

    on October 7, 2008 at 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 7, 2008 at 2:01 pm

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

  3. Gabriel Bianconi

    on October 7, 2008 at 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 7, 2008 at 4:33 pm

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

  5. Christo

    on October 7, 2008 at 4:42 pm

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

  6. Josh

    on October 7, 2008 at 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 7, 2008 at 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 7, 2008 at 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 7, 2008 at 6:30 pm

    Not boxhead tut. Nano wars :)

  10. Superdean

    on October 8, 2008 at 12:02 am

    aww…so i was WRONG???

    i knew i forgot something…

  11. Brad

    on October 8, 2008 at 3:26 am

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

  12. Emanuele Feronato

    on October 8, 2008 at 10:29 am

    christo: info[at]emanueleferonato.com

  13. Basic level editor for a tile based game : Emanuele Feronato

    on October 8, 2008 at 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 [...]

  14. JDog053

    on October 8, 2008 at 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 !

  15. Christo

    on October 9, 2008 at 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 :)

  16. Jerry

    on October 9, 2008 at 4:52 pm

    Great work as always.

  17. FrozenHaddock

    on October 10, 2008 at 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/

  18. Daniel Rodriguez

    on October 11, 2008 at 3:37 am

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

  19. Michael Brandse

    on October 12, 2008 at 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…

  20. oventoaster

    on October 13, 2008 at 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.

  21. New tile based platform engine - part 10 - optimization, doors n’ keys : Emanuele Feronato

    on October 13, 2008 at 3:48 pm

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

  22. Gatzä02

    on November 29, 2008 at 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.

  23. DannyDaNinja

    on January 27, 2010 at 11:41 am

    Cool.