Get the full commented source code of

HTML5 Suika Watermelon Game

Talking about Ball Game game, Flash and Game development.

January 16th update: 4th part released

In the third part of this tutorial I am going to fix a minor bug and introduce three new tiles:

info tile (displays a message when the ball rolls over it)
reverse control tile (reverses the controls of the ball)
checkpoint tile (makes you respawn at the checkpoint tile if you die)

Before continuing, I suggest you to read tutorials 1 and 2.

The actionscript of the last example has changed to:

_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});
ball.texture.setMask(ball.ball_itself);
yspeed = 0;
xspeed = 0;
checkpoint_passed = false;
lev = 1;
draw_level(lev);
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;
	}
	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;
	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 = 0;
		_root.ball_start_y = 0;
		if (checkpoint_passed) {
			_root.ball_start_x = save_x;
			_root.ball_start_y = save_y;
		}
		level[0] = new Array(12001, 11, 11, 11, 11);
		level[1] = new Array(0, 0, 0, 0, 1);
		level[2] = new Array(1, 1, 10, 0, 1);
		level[3] = new Array(1, 0, 0, 0, 1);
		level[4] = new Array(12003, 1, 1, 13, 12002);
		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>12000) {
					frame_to_stop = 12;
				}
				place_brick.gotoAndStop(frame_to_stop);
			}
		}
	}
}

Let’s comment the new lines:

Line 3: Attaching the info_panel object (the panel that will show the messages when the ball rolls over it) and making it invisible

Line 7: Creating a new variable to know if the player passed a checkpoint or not, and setting it to false by default

Line 11: Making the info panel object invisible. This may seems redundant since I alredy set it as invisible at line 3, but consider that this line is inserted into a routine to be executed at every time (so it’s redundant line 3…)

Lines 17-20: To understand this code, you must know how did I manage message tiles. Message tiles are tiles at number 12, but in the level array I assign a value of 12000+x where x is the id of the message. As an example, if a value in the level array is 12045, it meas that it’s a tile of type 12 (info tile) with the message 45. That’s what is done with this set of lines: if a value is greater than 12000, then assign 12 to type_of_tile value and type_of_tile%12000 (even if type_of_tile-12000 would be better) to the message_to_show variable

Lines 73-76: Code for the reverse controls tile (tile 11): simply multiplies power by -1

Lines 77-81: Code for the info panel tile (tile 12). Setting the info panel to visibile and assigning the dynamic text

Lines 82-87: Code for the checkpoint tile (tile 13): setting the checkpoint_passed variable to true and saving the current x and y tile position in save_x and save_y variables.

Lines 140-141: Reset the speed when a level is initialized. This will prevent the ball to mantain its speed when the player passes the level

Lines 157-159: Messages to display

Lines 225-227: If the tile number is greater than 12000, then setting the frame to stop in the tiles movieclip to 12

And that’s it: the first level has the new features while the others are the same of part 2

I am about to publish a complete game with a lot of more tiles, obviously I am releasing a full tutorial.

Meanwhile, download the source of this one

Read 4th part released

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.