Create a flash draw game like Line Rider or others – part 3

Read all posts about "" game

March 31st update: part 5 released
March 4th update: part 4 released

In the 3rd part I am going to make the ball bounce.

Read lessons 1 and 2 if you haven’t done it already.

Trigonomerty Basics

Let’s introduce trigonometry basics and how flash manages trigonometry. I suggest you to give a look at wikipedia, where I found some information I am reporting here.

The shape of a right triangle is completely determined, up to similarity, by the value of either of the other two angles. This means that once one of the other angles is known, the ratios of the various sides are always the same regardless of the size of the triangle. These ratios are traditionally described by the following trigonometric functions of the known angle:

The sine function (sin), defined as the ratio of the leg opposite the angle to the hypotenuse.
The cosine function (cos), defined as the ratio of the adjacent leg to the hypotenuse.
The tangent function (tan), defined as the ratio of the opposite leg to the adjacent leg.
The adjacent leg is the side of the angle that is not the hypotenuse. The hypotenuse is the side opposite to the 90 degree angle in a right triangle; it is the longest side of the triangle.

The reciprocals of these functions are named the cosecant (csc), secant (sec) and cotangent (cot), respectively. The inverse functions are called the arcsine, arccosine, and arctangent, respectively

Trigonomerty

That’s all you need to know about trigonometry…

Trigonometry and Flash

Flash determines angles in radians, but we need degrees… so we need to know how to convert degrees to randians and radians to degrees.

angle_degrees = angle_radians * 180/Math.PI;
angle_radians = angle_degrees * Math.PI/180;

These are the formulas to convert between degrees and randias. The Math.PI is a constant with the value of pi (3.14…)

Direction theory

The first thing we need to know is the direction of the ball of whatever other thing.
To introduce these concepts, I am showing you a movie where there is a flat ground and an arrow that points from the mouse position to the center of the ground.

Move the mouse over the movie, and you’ll see the arrow to rotate keeping the direction from the mouse pointer to the center.

How can we do that? Using trigonometry previously explained.

_root.attachMovie("arrow", "arrow", 10001);
arrow._x = 150;
arrow._y = 150;
arrow.onEnterFrame = function() {
	mousex = _xmouse-150;
	mousey = (_ymouse-150)*-1;
	angle = Math.atan(mousey/mousex)/(Math.PI/180);
	if (mousex<0) {
		angle += 180;
	}
	if (mousex>=0 && mousey<0) {
		angle += 360;
	}
	_root.angletext.text = "Angle: "+angle;
	this._rotation = angle*-1;
};

Lines 1-3: the "arrow" movie is attached to the stage and placed at 150,150 (the absolute center of the stage).

Lines 5-6: determining the position of the mouse pointer relatively to the center of the stage.

Now, it's obvious that mousex and mousey values represent respectively the adjacent and the opposite values. We need to determine the angle.

Line 7 Applies a formula based on trigonometry explained above and converts the radians to degrees.

Lines 8-13 Transform angle value from flash angle system to "our" angle system. When I say "our" angle system I mean that 0 degrees is where the clock says "3", 90 degrees where the clock says "12", 180 degrees where the clock says "9" and 270 degrees where the clock says "6".

With this actionscript we determined the angle where the ball comes from.

Now, let's make it bounce.

Bouncing theory

In a real world, bounce is determined from various variables, such as terrain hardness, ball hardness, friction and so on. At the moment, we only need to know that the bouncing ball acts like a ray of light casted on a mirror. The ground is the mirror, and the incoming ball is the ray of light.

Look at this movie: you move the blue arrow (ball) with the mouse while the red arrow is the bouncing direction

The actionscript is very similar to the previous one:

_root.attachMovie("arrow", "arrow", 10001);
_root.attachMovie("bounce", "bounce", 1000);
arrow._x = 150;
arrow._y = 150;
bounce._x = 150;
bounce._y = 150;
arrow.onEnterFrame = function() {
	mousex = _xmouse-150;
	mousey = (_ymouse-150)*-1;
	angle = Math.atan(mousey/mousex)/(Math.PI/180);
	if (mousex<0) {
		angle += 180;
	}
	if (mousex>=0 && mousey<0) {
		angle += 360;
	}
	bounce_angle = 180-angle;
	if (bounce_angle<0) {
		bounce_angle += 360;
	}
	_root.angletext.text = "Angle: "+angle;
	_root.bouncetext.text = "Angle: "+bounce_angle;
	this._rotation = angle*-1;
	bounce._rotation = -bounce_angle;
};

The only important lines here are lines 17-20 where I get the bounce angle starting from the incoming angle and convert the value to the "clock" values explained before.

Now we know almost all about bouncing... I say "almost" because we assumed the ground to be plain. What if the ground itself should have an angle?

Bouncing on angled ground

In next example, you move the ball angle with the mouse and the ground with left and right arrow keys

Look: even if the ground has its angle, the bounce still works.

_root.attachMovie("arrow", "arrow", 10001);
_root.attachMovie("bounce", "bounce", 1000);
arrow._x = 150;
arrow._y = 150;
bounce._x = 150;
bounce._y = 150;
arrow.onEnterFrame = function() {
	if (Key.isDown(Key.LEFT)) {
		ground._rotation--;
	}
	if (Key.isDown(Key.RIGHT)) {
		ground._rotation++;
	}
	mousex = _xmouse-150;
	mousey = (_ymouse-150)*-1;
	angle = Math.atan(mousey/mousex)/(Math.PI/180);
	if (mousex<0) {
		angle += 180;
	}
	if (mousex>=0 && mousey<0) {
		angle += 360;
	}
	bounce_angle = 180-angle-2*(ground._rotation);
	if (bounce_angle<0) {
		bounce_angle += 360;
	}
	_root.angletext.text = "Angle: "+angle;
	_root.bouncetext.text = "Angle: "+bounce_angle;
	_root.groundtext.text = "Angle: "+ground._rotation;
	this._rotation = angle*-1;
	bounce._rotation = -bounce_angle;
};

Lines 8-13 manage the routine to pan the ground according to left and right arrow keys

Line 23 determines the bounce angle almost the same way as before but I considered the ground rotation too. The 2* multiplier is there because in this examples ground rotation does not go from 0 to 359 but from -179 to 180.

Now we know how to determine the angle of impact, the ground rotation and the ball bounce... time to do something serious.

Putting all together

Time to pick the last example we left in part 2 and add all these little tricks

onClipEvent (load) {
	yspeed = 0;
	xspeed = 0;
	gravity = 0.2;
	radius = 25;
	friction = 0.90;
	precision = 360;
	bounces = 0;
}
onClipEvent (enterFrame) {
	if (_root.go == true) {
		collisions = 0;
		sum_x = 0;
		sum_y = 0;
		yspeed = yspeed+gravity;
		for (x=1; x0) {
			bounces++;
			_root.collisions.text = "Bounces: "+bounces;
			ball_dir = Math.atan(yspeed/(xspeed*-1))/(Math.PI/180);
			if ((xspeed*-1)<0) {
				ball_dir += 180;
			}
			if ((xspeed*-1)>=0 && yspeed<0) {
				ball_dir += 360;
			}
			spot_x = sum_x/collisions;
			spot_y = sum_y/collisions;
			x_cat = spot_x-_x;
			y_cat = spot_y-_y;
			ball_coll = Math.atan(y_cat/x_cat)/(Math.PI/180);
			if (x_cat<0) {
				ball_coll += 180;
			}
			if (x_cat>=0 && y_cat<0) {
				ball_coll += 360;
			}
			ground_rotation = ball_coll-90;
			if (ground_rotation<0) {
				ground_rotation += 180;
			}
			bounce_angle = 180-ball_dir-2*(ground_rotation);
			if (bounce_angle<0) {
				bounce_angle += 360;
			}
			speed = Math.sqrt((yspeed*yspeed)+(xspeed*xspeed));
			xspeed = speed*Math.cos(bounce_angle*Math.PI/180)*friction;
			yspeed = (speed*Math.sin(bounce_angle*Math.PI/180))*-1*friction;
		}
		_y = _y+yspeed;
		_x = _x+xspeed;
	}
}

Let's examine the lines not previously explained:

Line 6: introducing the friction... to know how to apply friction to a ball, refer to flash game creation tutorial part 1

Line 8: I set a bounce counter to zero. This will become useful later.

Line 26: If a collision is detected, then increase the bounce counter.

Lines 28-34: Determining ball direction angle starting from its xspeed and yspeed (opposite and adjacent). The xspeed is multiplied by -1 because, unlike previous examples, when xspeed is greater than zero means I am moving from left to right, and when xspeed is less than zero means I am moving from right to left.

Lines 37-38: Once I determined the average spot of collision as explained in step 2, now I calculate its x and y position relatively to the ball center. These are the opposite and adjacent needed to determine ball angle of impact.

Lines 39-45: Determining ball angle of collision

Lines 46-49: From the angle of collision, I am determining the ground angle

Lines 50-53: Now that I have ball direction and ground angle, with the same formula explained before I determine the bounce angle.

Line 54: With the Pythagorean theorem I calculate the ball speed starting from xspeed and yspeed

Lines 55-56: Now that I have the speed (hypotenuse) and the angle (A), with the trigonometry formulas I calculate new xspeed (adjacent) and yspeed (opposite)

Test the movie and you will see a pretty accurate bouncing, with only two issues:

1) Sometimes the ball seems to bounce "twice" as necessary

2) The ball never stops

We will fix these issues later on this tutorial, that is way to be finished, but you should be able to create your own raw draw game. If you create something playable sent it to me and I will publish it, meanwhile download the full sources of these examples and give me feedback.

Then, proceed to part 4

Get the most popular Phaser 3 book

Through 202 pages, 32 source code examples and an Android Studio project you will learn how to build cross platform HTML5 games and create a complete game along the way.

Get the book

215 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 1+2=3
// 100 rounds
// 10000000
// 2 Cars
// 2048
// A Blocky Christmas
// A Jumping Block
// A Life of Logic
// Angry Birds
// Angry Birds Space
// Artillery
// Astro-PANIC!
// Avoider
// Back to Square One
// Ball Game
// Ball vs Ball
// Ball: Revamped
// Balloon Invasion
// BallPusher
// Ballz
// Bar Balance
// Bejeweled
// Biggification
// Block it
// Blockage
// Bloons
// Boids
// Bombuzal
// Boom Dots
// Bouncing Ball
// Bouncing Ball 2
// Bouncy Light
// BoxHead
// Breakout
// Bricks
// Bubble Chaos
// Bubbles 2
// Card Game
// Castle Ramble
// Chronotron
// Circle Chain
// Circle Path
// Circle Race
// Circular endless runner
// Cirplosion
// CLOCKS - The Game
// Color Hit
// Color Jump
// ColorFill
// Columns
// Concentration
// Crossy Road
// Crush the Castle
// Cube Jump
// CubesOut
// Dash N Blast
// Dashy Panda
// Deflection
// Diamond Digger Saga
// Don't touch the spikes
// Dots
// Down The Mountain
// Drag and Match
// Draw Game
// Drop Wizard
// DROP'd
// Dudeski
// Dungeon Raid
// Educational Game
// Elasticity
// Endless Runner
// Erase Box
// Eskiv
// Farm Heroes Saga
// Filler
// Flappy Bird
// Fling
// Flipping Legend
// Floaty Light
// Fuse Ballz
// GearTaker
// Gem Sweeper
// Globe
// Goat Rider
// Gold Miner
// Grindstone
// GuessNext
// Helicopter
// Hero Emblems
// Hero Slide
// Hexagonal Tiles
// HookPod
// Hop Hop Hop Underwater
// Horizontal Endless Runner
// Hundreds
// Hungry Hero
// Hurry it's Christmas
// InkTd
// Iromeku
// Jet Set Willy
// Jigsaw Game
// Knife Hit
// Knightfall
// Legends of Runeterra
// Lep's World
// Line Rider
// Lumines
// Magick
// MagOrMin
// Mass Attack
// Math Game
// Maze
// Meeblings
// Memdot
// Metro Siberia Underground
// Mike Dangers
// Mikey Hooks
// Nano War
// Nodes
// o:anquan
// One Button Game
// One Tap RPG
// Ononmin
// Pacco
// Perfect Square!
// Perfectionism
// Phyballs
// Pixel Purge
// PixelField
// Planet Revenge
// Plants Vs Zombies
// Platform
// Platform game
// Plus+Plus
// Pocket Snap
// Poker
// Pool
// Pop the Lock
// Pop to Save
// Poux
// Pudi
// Pumpkin Story
// Puppet Bird
// Pyramids of Ra
// qomp
// Quick Switch
// Racing
// Radical
// Rebuild Chile
// Renju
// Rise Above
// Risky Road
// Roguelike
// Roly Poly
// Run Around
// Rush Hour
// SameGame
// SamePhysics
// Save the Totem
// Security
// Serious Scramblers
// Shrink it
// Sling
// Slingy
// Snowflakes
// Sokoban
// Space Checkers
// Space is Key
// Spellfall
// Spinny Gun
// Splitter
// Spring Ninja
// Sproing
// Stabilize!
// Stack
// Stairs
// Stick Hero
// String Avoider
// Stringy
// Sudoku
// Super Mario Bros
// Surfingers
// Survival Horror
// Talesworth Adventure
// Tetris
// The Impossible Line
// The Moops - Combos of Joy
// The Next Arrow
// Threes
// Tic Tac Toe
// Timberman
// Tiny Wings
// Tipsy Tower
// Toony
// Totem Destroyer
// Tower Defense
// Trick Shot
// Tunnelball
// Turn
// Turnellio
// TwinSpin
// vvvvvv
// Warp Shift
// Way of an Idea
// Whack a Creep
// Wheel of Fortune
// Where's my Water
// Wish Upon a Star
// Word Game
// Wordle
// Worms
// Yanga
// Yeah Bunny
// Zhed
// zNumbers