New tile based platform engine – part 8 – patrols

Every platform game should have enemies.

Every enemy has an artificial intelligence that makes it act in a smart or dumb way… and the patrol is the dumbest enemy.

The patrol walk in a direction until he has ground under his feet and does not hit a wall.

In this first version, the patrol does not kill the player (player’s death will be covered later) and stops when he find anything different than the open area marked by 0 in level array.

As for the player, the patrol has an array determining the y and x starting position.

Moreover, the third element in the array determines his initial speed

Now take some actionscript

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
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();
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, 0, 0, 1];
level[9] = [1, 1, 1, 1, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 1, 1];
player = [5, 8];
enemy[0] = [10, 3, -2];
enemy[1] = [3, 3, -2];
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]);
			}
		}
	}
	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});
	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") {
			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 :
			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;
	}
}
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];
}

And enjoy the result

Next steps will cover the theory behind these 267 lines, so you will soon be able to design your own engine.

Download the source code.

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

19 Responses to “New tile based platform engine – part 8 – patrols”

  1. Chris on October 1st, 2008 11:27 pm

    Great Game Idea, haven’t been on this site for a long time.

  2. Gabriel Bianconi on October 1st, 2008 11:28 pm

    This is a great tutorial. Please do a AS3 version too…

    Thanks!

  3. zennext on October 2nd, 2008 1:05 am

    Do something with enemies hurting you and with something that can kill you like spikes.

  4. Daniel on October 2nd, 2008 6:47 am

    Really love the tutorials, but I have question, its better to do the engine with tiles, or make the level with movieclips that represent the ladder and the ground, etc…
    I believe its better to the level design make it with graphcs. Hope you understand my english :P and answer the question.

  5. Andrius on October 2nd, 2008 1:35 pm

    Hello,

    Could you make after other parts how to make levels using http://www.emanueleferonato.com/2008/01/10/flash-game-level-editor/ this level editor and then by copying generated code, paste into game to load level?

    Thx!

  6. Gecko on October 2nd, 2008 6:08 pm

    Yes! I really want to know how to make a level editor!

  7. Prankard on October 2nd, 2008 7:26 pm

    Looking forward to reading what you have to say about the theory. One day I intend to make a decent platform engine and you’ve managed to split this up nicely into easy “bite-sized” sections.

    Just wanted to post a glitch about the ladders. I’m pretty sure you’d want to disable jumping while climbing a ladder (which you can do at the moment).

    Again, looking really nice. I hope you can incorporate this with some great level design and make a fantastic game.

  8. souled on October 2nd, 2008 8:41 pm

    Very nice. Enemies work quite well too.

  9. Javier Lázaro on October 3rd, 2008 1:24 am

    I agree with the level editor suggestion. Could be very handy.

    Apart from that, kudos for this tutorial. 8 parts so far, the longest I have seen!

  10. Arxanas on October 3rd, 2008 2:26 am

    AWESOME!!!
    I never would have been able to make that patrol ActionScript! But wouldn’t it be a little easier to make movieclips and just place them wherever? Then you could define the exact movement, instead of just putting a patrol thing.

  11. Andrius on October 3rd, 2008 10:22 am

    Arxanas – most of tuts here use ActionScript (on frames only) so making movieclips and placing em won’t be such same as otehr tuts and some codes won’t work.

    Still waiting for level editor, full patrols and some kind of score thing.

  12. Robert on October 3rd, 2008 1:09 pm

    I love that your still doing the tuts in as2 cuz i cant afford as3 compatable programs

  13. Josh on October 3rd, 2008 7:35 pm

    i have a question completely off topic but i’m creating a shooting game and when you get 2 a new level all my actionscrip is stayin in use on different frames how do i cancel or stop this?Such as i dont want the player to be able to shoot in one frame but he shoots anyway becuase last frame i used action script to allow him to fire. Another probleme i have iwth this is when i attach a death scene to the nmes unless i make it go away after a while it stays there when i move to another lvl (annother frame)?

  14. Andrius on October 4th, 2008 9:16 am

    @Josh – I don’t understand 2nd part (please fix) and on other frames just unload movieclips used in levels. I did so on my pool game so all balls and stick won’t appear. Try something like:
    removeMovieClip(“player”)
    And next time post this in forums.

  15. robert on October 4th, 2008 3:10 pm

    hey I was wondering how would you make a loops of zen type game

  16. Superdean on October 5th, 2008 3:53 am
  17. robert on October 7th, 2008 11:42 am

    hey emanuele can you make disapearing blocks like in the old tutorial because ive tried and it just freezez

  18. Ben on October 10th, 2008 5:07 pm

    This tutorial is one of your best to date – nice one!

    I don’t like how you fall down a ladder if you jump on to it from above, but otherwise the collision seems quite solid. I’d like to see what happens if the character is larger than a tile, I guess I should try it for myself :)

    I’d be interested to learn how you would approach sloped tiles. I’d love to be able to add hills to my game to make more organic levels.

  19. jake on November 10th, 2008 10:14 am

    great tutorial! but ive been trying to make a base for the patrols, where they would spawn out of every second, but i cant seem to get it. please help :D

Leave a Reply




flash games company