Create a Flash ball game with visual from above tutorial part 4
In the 4th part I am going to explain a feature that a race game must have: the laps
Read steps 1, 2 and 3 before continuing
Having laps in a track will result in a longer race.
The bad thing is that if you don’t design laps with some more actionscript than normally required, your players will cheat.
Look at the picture:

We have our track with 12 tiles with a clockwise direction. Assuming that you will start from 1, you should race through 1-2-3-4-5-6-7-8-9-A-B-C then 1 again in order to make a lap.
So when the ball rolls over C, it’s a new lap.
Wrong.
A cheater could move this way: 1-C-1-C-1 and he already completed 2 laps.
At this point, you would put an intermediate lap, let’s say at tile 7, and check that the intermediate lap has been passed before rolling over C. Now the player will have to drive through 1-2-3-4-5-6-7 but… let’s say the second part of the track is hardest than the first… he could make 1-2-3-4-5-6-7-6-5-4-3-2-1-C completing a lap without passing over 8-9-10-A-B, the hard part of the track.
To prevent this, you can put some “one way” tiles… if the tile 1 can be passed only from left to right, there is no way for the player to make 1-C because the game won’t allow it… but in some cases I would need to make 1-C, maybe he needs more speed to pass a certain tile (let’s say 3) and he founds himself at 2 without speed. He would need to make 2-1-C-B-C-1-2-3…
If you try to solve the lap problem this way, the player won’t be able to do 1-C to gain speed
Well, what about placing another intermediate lap, let’s say at A, so the player must pass over 7, then A and then C?
This may work, unless the path from A to C is harder than A to 1… so you may place an intermediate lap on B… and you end with an intermediate lap at every tile.
My solution allows to manage laps with only three tiles, one next to another. Let’s say C-1-2
The player will pass a lap when he rolls over C-1-2 but only if he never passed over tile 1 more than once. This means that a 1-C-1-2 does not count as a lap because he passed over the 1 twice.
Let’s see some actionscript: basically it’s the same as Create a Flash ball game with visual from above tutorial part 3 so I will comment only the new lines
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 | _root.attachMovie("starz", "starz", 1, {_x:-20, _y:-20});
_root.attachMovie("ball", "ball", 3, {_x:240, _y:220});
_root.attachMovie("info_panel", "info_panel", 4, {_y:410, _alpha:50, _visible:false});
_root.attachMovie("lap", "lap", 5);
ball.texture.setMask(ball.ball_itself);
yspeed = 0;
xspeed = 0;
checkpoint_passed = false;
lev = 1;
draw_level(lev);
laps = 0;
ball.onEnterFrame = function() {
info_panel._visible = false;
friction = 0.99;
power = 0.4;
brick_x = Math.floor((bricks._x-200)/80)*-1;
brick_y = Math.floor((bricks._y-180)/80)*-1;
type_of_tile = level[brick_y][brick_x];
if (type_of_tile>12000) {
message_to_show = messages[type_of_tile%12000];
type_of_tile = 12;
}
if (type_of_tile>10000) {
lap_sequence = type_of_tile-10000;
if ((lap_sequence == lap_to_go) and (lap_sequence == 1)) {
laps++;
lap.laptext.text = laps;
}
lap_to_go = lap_sequence%3+1;
type_of_tile = 1;
}
switch (type_of_tile) {
case 1 :
// normal tile
break;
case 2 :
// down spin tile
yspeed += 0.2;
break;
case 3 :
// up spin tile
yspeed -= 0.2;
break;
case 4 :
// left spin tile
xspeed -= 0.2;
break;
case 5 :
// right spin tile
xspeed += 0.2;
break;
case 6 :
// glass tile
depth = brick_y*12+brick_x;
bricks["brick_"+depth]._alpha--;
if (bricks["brick_"+depth]._alpha<1) {
level[brick_y][brick_x] = 0;
}
break;
case 7 :
// spin tile
xspeed *= 1.05;
yspeed *= 1.05;
break;
case 8 :
// slip tile
friction = 1;
power = 0;
break;
case 9 :
// beam
depth = brick_y*12+brick_x;
if (bricks["brick_"+depth].lava._currentframe>90) {
ball_die();
}
break;
case 10 :
// exit
checkpoint_passed = false;
lev++;
_root.removeMovieClip("bricks");
draw_level(lev);
break;
case 11 :
// reverse
power *= -1;
break;
case 12 :
// info
info_panel._visible = true;
info_panel.message_text.text = message_to_show;
break;
case 13 :
//checkpoint
checkpoint_passed = true;
save_x = brick_x;
save_y = brick_y;
break;
default :
// hole
ball_die();
break;
}
if (Key.isDown(Key.LEFT)) {
xspeed -= power;
}
if (Key.isDown(Key.RIGHT)) {
xspeed += power;
}
if (Key.isDown(Key.UP)) {
yspeed -= power;
}
if (Key.isDown(Key.DOWN)) {
yspeed += power;
}
xspeed *= friction;
yspeed *= friction;
if ((xspeed<0.1) and (xspeed>-0.1)) {
xspeed = 0;
}
if ((yspeed<0.1) and (yspeed>-0.1)) {
yspeed = 0;
}
bricks._y -= yspeed;
bricks._x -= xspeed;
starz._x = -20+((bricks._x-240)/10);
starz._y = -20+((bricks._y-220)/10);
this.texture._y += yspeed;
this.texture._x += xspeed;
if (this.texture._x>53) {
this.texture._x -= 63;
}
if (this.texture._x<-53) {
this.texture._x += 63;
}
if (this.texture._y>53) {
this.texture._y -= 63;
}
if (this.texture._y<-53) {
this.texture._y += 63;
}
};
function ball_die() {
bricks._x = 240-(80*_root.ball_start_x);
bricks._y = 220-(80*_root.ball_start_y);
xspeed = 0;
yspeed = 0;
lap_to_go = 2;
draw_level(lev);
}
function draw_level(number) {
yspeed = 0;
xspeed = 0;
level = new Array();
messages = new Array();
switch (number) {
case 1 :
_root.ball_start_x = 1;
_root.ball_start_y = 0;
if (checkpoint_passed) {
_root.ball_start_x = save_x;
_root.ball_start_y = save_y;
}
level[0] = new Array(1, 10001, 10002, 10003, 1);
level[1] = new Array(1, 0, 0, 0, 1);
level[2] = new Array(1, 0, 0, 0, 1);
level[3] = new Array(1, 0, 0, 0, 1);
level[4] = new Array(1, 1, 1, 1, 1);
messages[1] = "Welcome to the game";
messages[2] = "You are about to cross a checkpoint";
messages[3] = "Ok. Now suicide! You'll respawn on the checkpoint";
break;
case 2 :
_root.ball_start_x = 0;
_root.ball_start_y = 0;
level[0] = new Array(1, 4, 4, 5, 0);
level[1] = new Array(0, 0, 0, 1, 0);
level[2] = new Array(0, 0, 0, 1, 0);
level[3] = new Array(0, 0, 0, 10, 0);
level[4] = new Array(0, 0, 0, 0, 0);
break;
case 3 :
_root.ball_start_x = 0;
_root.ball_start_y = 0;
level[0] = new Array(1, 6, 6, 4, 0);
level[1] = new Array(0, 0, 0, 6, 0);
level[2] = new Array(6, 5, 5, 6, 0);
level[3] = new Array(6, 0, 0, 0, 0);
level[4] = new Array(1, 1, 10, 0, 0);
break;
case 4 :
_root.ball_start_x = 0;
_root.ball_start_y = 0;
level[0] = new Array(1, 7, 0, 0, 0);
level[1] = new Array(0, 7, 0, 7, 10);
level[2] = new Array(1, 3, 0, 1, 0);
level[3] = new Array(1, 0, 0, 1, 0);
level[4] = new Array(1, 1, 1, 7, 0);
break;
case 5 :
_root.ball_start_x = 4;
_root.ball_start_y = 2;
level[0] = new Array(7, 8, 8, 8, 10);
level[1] = new Array(1, 0, 0, 0, 0);
level[2] = new Array(1, 8, 8, 3, 1);
level[3] = new Array(0, 0, 0, 0, 0);
level[4] = new Array(0, 0, 0, 0, 0);
break;
case 6 :
_root.ball_start_x = 2;
_root.ball_start_y = 2;
level[0] = new Array(2, 8, 9, 8, 9);
level[1] = new Array(9, 0, 0, 0, 1);
level[2] = new Array(2, 8, 1, 0, 3);
level[3] = new Array(0, 0, 0, 0, 4);
level[4] = new Array(10, 9, 9, 8, 6);
break;
case 7 :
_root.ball_start_x = 2;
_root.ball_start_y = 2;
level[0] = new Array(0, 0, 0, 0, 0);
level[1] = new Array(0, 0, 0, 0, 0);
level[2] = new Array(0, 0, 1, 0, 0);
level[3] = new Array(0, 0, 0, 0, 0);
level[4] = new Array(0, 0, 0, 0, 0);
break;
}
_root.createEmptyMovieClip("bricks", 2);
bricks._x = 240-(80*ball_start_x);
bricks._y = 220-(80*ball_start_y);
for (y=0; y<=4; y++) {
for (x=0; x<=4; x++) {
if (level[y][x]>0) {
depth = y*12+x;
place_brick = bricks.attachMovie("brick", "brick_"+depth, bricks.getNextHighestDepth(), {_x:x*80, _y:y*80});
frame_to_stop = level[y][x];
if (frame_to_stop>10000) {
frame_to_stop = 1;
}
if (frame_to_stop>12000) {
frame_to_stop = 12;
}
place_brick.gotoAndStop(frame_to_stop);
}
}
}
} |
Line 4: Attaching a movieclip to display laps
Line 11: Variable counting the number of laps
Line 23: Checking if the type of tile is greater than 10000. In my game, lap tiles are 10001, 10002 and 10003
Line 24: Obtaining the lap sequence: 1, 2 or 3, according on which tile the ball is rolling on
Line 25: If the lap sequence is equal to a variable called lap_to_go (it stores the next lap sequence to go in order to complete the lap as you will see later) and its value is 1 (the 10001 tile, the one that represents the start)
Line 26: Increase the number of laps
Line 27: Display the number of laps
Line 29: Calculating the value of the next tile in order to make a correct lap
Line 30: Defining the type of tile (a normal one)
Line 164: Level design of lap tiles
Lines 237-239: Showing the default tile if its number is greater than 10000
As you can see, now you have laps!
Now you have a lot more gamplay options with this engine… download the source code and create the ultimate game!
They can be easily customized to meet the unique requirements of your project.
13 Responses to “Create a Flash ball game with visual from above tutorial part 4”
Leave a Reply
Trackbacks
-
Create a Flash ball game with visual from above tutorial part 3 : Emanuele Feronato - italian geek and PROgrammer on
January 16th, 2008 11:11 pm
[...] 16th update: 4th part [...]
- Get up to $100,000 for your next Flash game with Mochi GAME Developer Fund
- Create a dynamic content animated footer ad for your site in just 9 jQuery lines – 17 lines version
- Sell sitelocked version of your Flash games and even .fla sources to Free Online Games
- Protect your work from ActionScript code theft with SWF Protector
- Create a dynamic content animated footer ad for your site in just 9 jQuery lines
- Understanding Box2D’s one-way platforms, aka CLOUDS
- Triqui MochiAds Arcade plugin for WordPress upgraded to 1.2
- Box2D Flash game creation tutorial – part 2
- 11 Flash isometric engines you can use in your games
- Monetize your Flash games with GamesChart
- Create a Lightbox effect only with CSS - no javascript needed
- Flash game creation tutorial - part 1
- Create a Flash Racing Game Tutorial
- Flash game creation tutorial - part 2
- Make a Flash game like Flash Element Tower Defense - Part 2
- Flash game creation tutorial - part 3
- Make a Flash game like Flash Element Tower Defense - Part 1
- Create a flash draw game like Line Rider or others - part 1
- Triqui MochiAds Arcade plugin for WordPress official page
- Create a flash artillery game - step 1
- Flash game creation tutorial – part 5.2 (4.88/5)
- Create a flash artillery game – step 1 (4.79/5)
- Create a Flash Racing Game Tutorial (4.76/5)
- Create a flash artillery game – step 2 (4.74/5)
- Create a survival horror game in Flash tutorial – part 1 (4.73/5)
- Creation of a Flash arcade site using WordPress – step 2 (4.73/5)
- Flash game creation tutorial – part 2 (4.71/5)
- Flash game creation tutorial – part 1 (4.70/5)
- Create a flash draw game like Line Rider or others – part 1 (4.69/5)
- Creation of a platform game with Flash – step 2 (4.68/5)







very smart!
can u make a car racing game based on the same anti-cheat lap setup?
i wanted to make a space fighter racing game where u can shoot the cpu’s.
GReat EManuele!
Well done!
xavi,
if you want to make it, why do you ask him for it? try it yourself first:S. and if you succeed to make it without help you’ll be the only one with that code. which makes your game a lot more original (not like all the ball-game clones on the web)
very good!
hey emanuel is thier any way to make a tile that is smaller like in widtt so that peolpe could take short cuts?????????
first, i have tryed and tryed and tryed all freakin week to try to get a hit collison right. the thing wrong is that i cant get the too get my two marble rollers, when they run into each other, they they go back at first half the speed of the 1st guy, and some and half of the speed of the second guy,times -1.
can u please help
Ok im trying to add more levels and more tiles so it will be 10 levels high and 10 tiles long. But when ever i do this i can’t see the tiles past the 5th one. Why is this?
Art:
The last part of the code (lines 231 and 232), there are 2 cycles that “read” the arrays that determine the position of the tiles:
for (y=0; y<=4; y++) {
for (x=0; x0) {
depth = y*12+x;
if you want to have larger levels, you must modify the second part of both fors:
y<= 4 and x<=4. If you want levels with 10 tiles width and 10 tiles long, you should change these values to y<= 9 and x<= 9. But remember to set ALL your arrays with 10 numbers, otherwise youll get errors. If you want a specific level to be shorter, just fill the “empty” spaces with zeros.
So, your code should look like this:
for (y=0; y<=9; y++) {
for (x=0; x0) {
depth = y*12+x;
Wow this tutorial is great!!! Thanks a lot Emanuele for being so kind to share some of your knowledge with us!
I’m just itching to make a game for Bonus Level! I can’t wait for the level editor!
i played for hours and got 101 laps
This anti-cheat mechanism is flawed.
You said that perhaps the player needs to return a bit to gain speed. But what if he needs to return for gaining speed to the tile that you only allow “once”?
The correct anti-cheat procedure for any racing game is:
1. Whenever player passes through Tile N, store the time of passing (Time[N])
2. Whenever he passes some later tile O, again store the time (Time[O]).
3. Lap is only counted as correct if Time[O]>Time[N].
Even if player backtracks and returns to tile N, he then has to go through O again –> this check works.
i can’t put a gotoAndStop in this code help me pleas