Create a Flash game like Deflection

Read all posts about "" game

Multipart tutorial: available parts 1, 2, 3

Today I spent some time with a game called Deflection.

Deflection

According to his author, it’s an addictive physics based game where the objective is to deflect the ball into the goal by creating deflection walls.

I bet I scared most of you with the word “physics”. This means a physics engine, massive AS3 coding, and so on.

Although I am seriously determined to start a tutorial series about latest physics engines, I played a bit with Deflection and I noticed the only physics involved in the game is used to determine the bounce of a regular shape (a circle – the ball) when collides with a line.

So I thought there was another way to create an engine like this one without using physics libraries.

The answer lies in an old vector tutorial made by Tony Pa called Ball in the corner.

I suggest you to read all Tony’s vector tutorials to understand the math behind the engine.

I made some changes to the tutorial in order to make it more “AS2 like” (it’s an old AS1 tutorial) and to manage an arbitrary number of lines.

In this step you will only see the engine working with 4 lines and no user interaction, but it’s really easy to add lines at runtime with the mouse (I’ll cover it in the next step).

Moreover, this is another good example about how to use a Flash game tutorial to make your own game.

Ok, now it’s time to show you the modified actionscript:

// create game object
game = {gravity:0, dragging:false, clip:_root.game_mc, stageW:500, stageH:400, maxV:20};
// create object
// point p0 is its starting point in the coordinates x/y
_root.attachMovie("ball", "ball", 1);
game.myOb = {clip:ball, airf:1, b:1, f:1, r:20, lastTime:getTimer()};
game.myOb.p0 = {x:150, y:80};
// vectors x/y components
game.myOb.vx = 8;
game.myOb.vy = 12;
// create first vector
// point p0 is its starting point in the coordinates x/y
// point p1 is its end point in the coordinates x/y
game.v = new Array();
game.v[0] = {p0:{x:50, y:40}, p1:{x:450, y:40}, b:1, f:1};
game.v[1] = {p0:{x:50, y:40}, p1:{x:50, y:360}, b:1, f:1};
game.v[2] = {p0:{x:50, y:360}, p1:{x:450, y:360}, b:1, f:1};
game.v[3] = {p0:{x:100, y:80}, p1:{x:400, y:320}, b:1, f:1};
_root.createEmptyMovieClip("lines", 2);
lines.lineStyle(1, 0xff0000);
// draw and calculate all parameters for the wall vectors
for (x=0; xgame.maxV) {
		ob.vx = game.maxV;
	} else if (ob.vx<-game.maxV) {
		ob.vx = -game.maxV;
	}
	if (ob.vy>game.maxV) {
		ob.vy = game.maxV;
	} else if (ob.vy<-game.maxV) {
		ob.vy = -game.maxV;
	}
	// update the vector parameters        
	updateObject(ob);
	// check the walls for collisions
	for (x=0; x=0) {
			// move object away from the wall
			ob.p1.x += v.dx*pen;
			ob.p1.y += v.dy*pen;
			// change movement, bounce off from the normal of v
			var vbounce = {dx:v.lx, dy:v.ly, lx:v.dx, ly:v.dy, b:1, f:1};
			var vb = bounce(ob, vbounce);
			ob.vx = vb.vx;
			ob.vy = vb.vy;
		}
	}
	// reset object to other side if gone out of stage
	if (ob.p1.x>game.stageW+ob.r) {
		ob.p1.x = -ob.r;
	} else if (ob.p1.x<-ob.r) {
		ob.p1.x = game.stageW+ob.r;
	}
	if (ob.p1.y>game.stageH+ob.r) {
		ob.p1.y = -ob.r;
	} else if (ob.p1.y<-ob.r) {
		ob.p1.y = game.stageH+ob.r;
	}
	// draw it        
	drawAll(ob);
	// make end point equal to starting point for next cycle
	ob.p0 = ob.p1;
	// save the movement without time
	ob.vx = ob.vx/ob.timeFrame;
	ob.vy = ob.vy/ob.timeFrame;
}
// function to find all parameters for the vector
function updateVector(v, frompoints) {
	// x and y components
	if (frompoints) {
		v.vx = v.p1.x-v.p0.x;
		v.vy = v.p1.y-v.p0.y;
	} else {
		v.p1.x = v.p0.x+v.vx;
		v.p1.y = v.p0.y+v.vy;
	}
	// length of vector
	v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
	// normalized unti-sized components
	if (v.len>0) {
		v.dx = v.vx/v.len;
		v.dy = v.vy/v.len;
	} else {
		v.dx = 0;
		v.dy = 0;
	}
	// right hand normal
	v.rx = -v.dy;
	v.ry = v.dx;
	// left hand normal
	v.lx = v.dy;
	v.ly = -v.dx;
	return v;
}
function updateObject(v) {
	// find time passed from last update
	var thisTime = getTimer();
	var time = (thisTime-v.lastTime)/100;
	// we use time, not frames to move so multiply movement vector with time passed
	v.vx *= time;
	v.vy *= time;
	// add gravity, also based on time
	v.vy = v.vy+time*game.gravity;
	v.p1 = {};
	// find end point coordinates
	v.p1.x = v.p0.x+v.vx;
	v.p1.y = v.p0.y+v.vy;
	// length of vector
	v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
	// normalized unti-sized components
	v.dx = v.vx/v.len;
	v.dy = v.vy/v.len;
	// right hand normal
	v.rx = -v.vy;
	v.ry = v.vx;
	// left hand normal
	v.lx = v.vy;
	v.ly = -v.vx;
	// save the current time
	v.lastTime = thisTime;
	// save time passed
	v.timeFrame = time;
}
// find intersection point of 2 vectors
function findIntersection(v1, v2) {
	// vector between center of ball and starting point of wall
	var v3 = {};
	v3.vx = v1.p1.x-v2.p0.x;
	v3.vy = v1.p1.y-v2.p0.y;
	// check if we have hit starting point
	var dp = v3.vx*v2.dx+v3.vy*v2.dy;
	if (dp<0) {
		// hits starting point
		var v = v3;
	} else {
		var v4 = {};
		v4.vx = v1.p1.x-v2.p1.x;
		v4.vy = v1.p1.y-v2.p1.y;
		// check if we have hit side or endpoint
		var dp = v4.vx*v2.dx+v4.vy*v2.dy;
		if (dp>0) {
			// hits ending point
			var v = v4;
		} else {
			// it hits the wall
			// project this vector on the normal of the wall
			var v = projectVector(v3, v2.lx, v2.ly);
		}
	}
	return v;
}
// find new vector bouncing from v2
function bounce(v1, v2) {
	// projection of v1 on v2
	var proj1 = projectVector(v1, v2.dx, v2.dy);
	// projection of v1 on v2 normal
	var proj2 = projectVector(v1, v2.lx, v2.ly);
	var proj = {};
	// reverse projection on v2 normal
	proj2.len = Math.sqrt(proj2.vx*proj2.vx+proj2.vy*proj2.vy);
	proj2.vx = v2.lx*proj2.len;
	proj2.vy = v2.ly*proj2.len;
	// add the projections
	proj.vx = v1.f*v2.f*proj1.vx+v1.b*v2.b*proj2.vx;
	proj.vy = v1.f*v2.f*proj1.vy+v1.b*v2.b*proj2.vy;
	return proj;
}
// project vector v1 on unit-sized vector dx/dy
function projectVector(v1, dx, dy) {
	// find dot product
	var dp = v1.vx*dx+v1.vy*dy;
	var proj = {};
	// projection components
	proj.vx = dp*dx;
	proj.vy = dp*dy;
	return proj;
}

and this is the result… your own AS2 deflection engine ready for you to create a game.

If you want to write the code for player interaction, I will be happy to publish it, otherwise wait for me to do it.

Download the source code and enjoy.
Multipart tutorial: available parts 1, 2, 3

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