Flash game creation tutorial – part 4

Read all posts about "" game

March 14th update: part 5.3 released.
March 3rd update: part 5.2 released.
February 9th update: part 5.1 released.
December 31st update: 5th part released.

Welcome to the 4th step of this flash game creation tutorial.

Read steps 1, 2 and 3 if you’re new to this tutorial, then follow this one.

The direction

Knowing the direction of the player may be very useful if we decide to add some special features to our game.
Always remember that it’s useless to make a simple clone of a game. If you decide to inspire yourself to an existing game, add some new features, or people will ignore your work.

I’ll explain you later in this tutorial how many pretty things you can do if you know the direction your player is moving.

Look at this actionscript

onClipEvent (load) {
	yspeed = 0;
	xspeed = 0;
	wind = 0.00;
	power = 0.65;
	gravity = 0.1;
	upconstant = 0.75;
	friction = 0.99;
}
onClipEvent (enterFrame) {
	if (Key.isDown(Key.LEFT)) {
		xspeed = xspeed-power;
	}
	if (Key.isDown(Key.RIGHT)) {
		xspeed = xspeed+power;
	}
	if (Key.isDown(Key.UP)) {
		yspeed = yspeed-power*upconstant;
	}
	if (Key.isDown(Key.DOWN)) {
		yspeed = yspeed+power*upconstant;
	}
	xspeed = (xspeed+wind)*friction;
	yspeed = yspeed+gravity;
	_y = _y+yspeed;
	_x = _x+xspeed;
	_rotation = _rotation+xspeed;
	angle = Math.atan(yspeed/xspeed)/(Math.PI/180);
	if (xspeed<0) {
		angle += 180;
	}
	if (xspeed>=0 && yspeed<0) {
		angle += 360;
	}
	this.hero_dir._rotation = angle-_rotation;
	if (_root.wall.hitTest(_x, _y, true)) {
		xspeed = 0;
		yspeed = 0;
		_x = 120;
		_y = 120;
	}
}

the formula at line 28 allows us to know the angle (direction) the player is moving, starting from its x and y speed.
Of course, you have to know the bare bones of trigonometry, but it's very easy.
Lines 29-34 simply transofrm trigonometry angles into flash angles. This is due because of differences between flash axis system and trigonometry axis system.
Line 35 rotates a movieclip instanced as hero_dir of angles degrees minus the _rotation value, since the hero_dir movieclip is attached to the hero so it rotates with this one. So, if the hero has an rotation of 5 degrees and is moving in a direction of 85 degrees, the line of rotation should have a rotation angle of 85-5 = 80 degrees. Watch the movieclip to see how does it work.

Good. Now you can determine the direction your hero is moving in.
How can you use it?

One-direction walls

One-direction walls are walls that your player can pass through without crashing into them, for example, from left to right, while they still remain deadly if passed from right to left.

So I created a movieclip instanced as "oneway". Look at the actionscript:

onClipEvent (load) {
	yspeed = 0;
	xspeed = 0;
	wind = 0.00;
	power = 0.65;
	gravity = 0.1;
	upconstant = 0.75;
	friction = 0.99;
}
onClipEvent (enterFrame) {
	if (Key.isDown(Key.LEFT)) {
		xspeed = xspeed-power;
	}
	if (Key.isDown(Key.RIGHT)) {
		xspeed = xspeed+power;
	}
	if (Key.isDown(Key.UP)) {
		yspeed = yspeed-power*upconstant;
	}
	if (Key.isDown(Key.DOWN)) {
		yspeed = yspeed+power*upconstant;
	}
	xspeed = (xspeed+wind)*friction;
	yspeed = yspeed+gravity;
	_y = _y+yspeed;
	_x = _x+xspeed;
	_rotation = _rotation+xspeed;
	angle = Math.atan(yspeed/xspeed)/(Math.PI/180);
	if (xspeed<0) {
		angle += 180;
	}
	if (xspeed>=0 && yspeed<0) {
		angle += 360;
	}
	this.hero_dir._rotation = angle-_rotation;
	if (_root.wall.hitTest(_x, _y, true)) {
		xspeed = 0;
		yspeed = 0;
		_x = 120;
		_y = 120;
	}
	if ((_root.oneway.hitTest(_x, _y, true)) and ((angle>90) and (angle<270))) {
		xspeed = 0;
		yspeed = 0;
		_x = 120;
		_y = 120;
	}
}

Line 42 Checks if the player hitted the oneway movieclip and if it has a direction angle from 90 to 270.
In this case, and only in this case, we know the hero is trying to pass the wall from right to left (remember that 0 degrees: right, 90 degrees: down, 180 degrees: left, 270 degrees, up), so the player dies.
The result of this actionscript is: if the wall can be passed from left to right, but it's deadly from right to left.

You may say: there's no need to play with trigonometry to do that: you can simply remember the old x position and verify that x position is increasing (moving to the right) or decreasing (moving to le left). That means I wasted a tutorial.

Or maybe not.

One-direction walls 2

Sometimes walls may not be just horizontal or vertical, and sometimes one-direction walls may allow to be passed only if the player has a given range of direction angle.

Now the oneway movieclip is rotated by 30° counter-clockwise

onClipEvent (load) {
	yspeed = 0;
	xspeed = 0;
	wind = 0.00;
	power = 0.65;
	gravity = 0.1;
	upconstant = 0.75;
	friction = 0.99;
}
onClipEvent (enterFrame) {
	if (Key.isDown(Key.LEFT)) {
		xspeed = xspeed-power;
	}
	if (Key.isDown(Key.RIGHT)) {
		xspeed = xspeed+power;
	}
	if (Key.isDown(Key.UP)) {
		yspeed = yspeed-power*upconstant;
	}
	if (Key.isDown(Key.DOWN)) {
		yspeed = yspeed+power*upconstant;
	}
	xspeed = (xspeed+wind)*friction;
	yspeed = yspeed+gravity;
	_y = _y+yspeed;
	_x = _x+xspeed;
	_rotation = _rotation+xspeed;
	angle = Math.atan(yspeed/xspeed)/(Math.PI/180);
	if (xspeed<0) {
		angle += 180;
	}
	if (xspeed>=0 && yspeed<0) {
		angle += 360;
	}
	this.hero_dir._rotation = angle-_rotation;
	if (_root.wall.hitTest(_x, _y, true)) {
		xspeed = 0;
		yspeed = 0;
		_x = 120;
		_y = 120;
	}
	
	if ((_root.oneway.hitTest(_x, _y, true)) and (angle<300)) {
		
		xspeed = 0;
		yspeed = 0;
		_x = 120;
		_y = 120;
	}
}

Line 43 now kills the player if it touchs the walls in a direction that is less of 300 degrees (or: in a range from 300 and 360 degrees). This means you have to pass the wall paying a lot of attention to your direction: the range of angles allowed are only 30 clockwise and 30 counter-clockwise, so the direction of the player must be very similar to the direction of the wall.

This can only easily be done if you know the direction of the player.

Later in this tutorial you will find another amazing way to have a special feature knowing player direction.

Now it's time for player's speed.

The speed

Sometimes it's important to know the player speed.
Time to unveil the Pythagorean theorem:

In any right triangle, the area of the square whose side is the hypotenuse (the side of a right triangle opposite the right angle) is equal to the sum of areas of the squares whose sides are the two legs (i.e. the two sides other than the hypotenuse). (from Wikipedia)

Well, it's rather obvious that the hypotenuse is the absolute speed and the two other sides are xspeed and yspeed values.

onClipEvent (load) {
	yspeed = 0;
	xspeed = 0;
	wind = 0.00;
	power = 0.65;
	gravity = 0.1;
	upconstant = 0.75;
	friction = 0.99;
}
onClipEvent (enterFrame) {
	if (Key.isDown(Key.LEFT)) {
		xspeed = xspeed-power;
	}
	if (Key.isDown(Key.RIGHT)) {
		xspeed = xspeed+power;
	}
	if (Key.isDown(Key.UP)) {
		yspeed = yspeed-power*upconstant;
	}
	if (Key.isDown(Key.DOWN)) {
		yspeed = yspeed+power*upconstant;
	}
	xspeed = (xspeed+wind)*friction;
	yspeed = yspeed+gravity;
	_y = _y+yspeed;
	_x = _x+xspeed;
	speed = Math.sqrt((yspeed*yspeed)+(xspeed*xspeed));
	_root.speed.text = "speed: "+speed;
	_rotation = _rotation+xspeed;
	angle = Math.atan(yspeed/xspeed)/(Math.PI/180);
	if (xspeed<0) {
		angle += 180;
	}
	if (xspeed>=0 && yspeed<0) {
		angle += 360;
	}
	this.hero_dir._rotation = angle-_rotation;
	if (_root.wall.hitTest(_x, _y, true)) {
		xspeed = 0;
		yspeed = 0;
		_x = 120;
		_y = 120;
	}
}

Line 27 applies the Pythagorean Theorem as explained above
Line 28 simply writes the speed in a text object.

How is the speed measured? It's measured in pixels/frame

How can we use the speed?

Speed walls

Sometimes you may decide to place a wall the player can pass through only if he has a speed greater than... something.
The new movieclip instanced as speed_wall is our new obstacle

onClipEvent (load) {
	yspeed = 0;
	xspeed = 0;
	wind = 0.00;
	power = 0.65;
	gravity = 0.1;
	upconstant = 0.75;
	friction = 0.99;
}
onClipEvent (enterFrame) {
	if (Key.isDown(Key.LEFT)) {
		xspeed = xspeed-power;
	}
	if (Key.isDown(Key.RIGHT)) {
		xspeed = xspeed+power;
	}
	if (Key.isDown(Key.UP)) {
		yspeed = yspeed-power*upconstant;
	}
	if (Key.isDown(Key.DOWN)) {
		yspeed = yspeed+power*upconstant;
	}
	xspeed = (xspeed+wind)*friction;
	yspeed = yspeed+gravity;
	_y = _y+yspeed;
	_x = _x+xspeed;
	speed = Math.sqrt((yspeed*yspeed)+(xspeed*xspeed));
	_root.speed.text = "speed: "+speed;
	_rotation = _rotation+xspeed;
	angle = Math.atan(yspeed/xspeed)/(Math.PI/180);
	if (xspeed<0) {
		angle += 180;
	}
	if (xspeed>=0 && yspeed<0) {
		angle += 360;
	}
	this.hero_dir._rotation = angle-_rotation;
	if (_root.wall.hitTest(_x, _y, true)) {
		xspeed = 0;
		yspeed = 0;
		_x = 120;
		_y = 120;
	}
	if (_root.speed_wall.hitTest(_x, _y, true) and (speed<5)) {
		xspeed = 0;
		yspeed = 0;
		_x = 120;
		_y = 120;
	}
}

Line 44 makes the player die if he hits the wall with a speed slower than 5 pixels/frame.
Of course you can combine speed walls with one-way walls and normal walls... if you play well with those kind of walls you can create amazing mazes in minutes.

Time to introduce a new element now...

The dark

Since I hate the player (it's obvious, isn't it?) I want him to play in dark areas with only a spotlight around him.
The new movieclip I created is instanced as "dark" and consists in a big black rectangle with a hole in its center filled with a semi-transpared gradient.

onClipEvent (load) {
	yspeed = 0;
	xspeed = 0;
	wind = 0.00;
	power = 0.65;
	gravity = 0.1;
	upconstant = 0.75;
	friction = 0.99;
}
onClipEvent (enterFrame) {
	if (Key.isDown(Key.LEFT)) {
		xspeed = xspeed-power;
	}
	if (Key.isDown(Key.RIGHT)) {
		xspeed = xspeed+power;
	}
	if (Key.isDown(Key.UP)) {
		yspeed = yspeed-power*upconstant;
	}
	if (Key.isDown(Key.DOWN)) {
		yspeed = yspeed+power*upconstant;
	}
	xspeed = (xspeed+wind)*friction;
	yspeed = yspeed+gravity;
	_y = _y+yspeed;
	_x = _x+xspeed;
	_root.dark._x = _x;
	_root.dark._y = _y;
	_rotation = _rotation+xspeed;
	angle = Math.atan(yspeed/xspeed)/(Math.PI/180);
	if (xspeed<0) {
		angle += 180;
	}
	if (xspeed>=0 && yspeed<0) {
		angle += 360;
	}
	this.hero_dir._rotation = angle-_rotation;
	if (_root.wall.hitTest(_x, _y, true)) {
		xspeed = 0;
		yspeed = 0;
		_x = 36;
		_y = 40;
	}
	if (_root.environment.hitTest(_x, _y, true)) {
		xspeed = 0;
		yspeed = 0;
		_x = 36;
		_y = 40;
	}
}

Then with only two lines (line 27 and line 28) we move the dark in the same way we move the player.
The result is simple but very amazing. The player has to move carefully through dark areas trying to spot walls before he hits them.

The last feature for this tutorial is a combination of dark and direction

The directional light

It works basically as the example covered before, but this time the dark movieclip does not have a spotlight but a directional light, so it will rotate in the angle the player moves. I told you knowing the player angle is useful...

onClipEvent (load) {
	yspeed = 0;
	xspeed = 0;
	wind = 0.00;
	power = 0.65;
	gravity = 0.1;
	upconstant = 0.75;
	friction = 0.99;
}
onClipEvent (enterFrame) {
	if (Key.isDown(Key.LEFT)) {
		xspeed = xspeed-power;
	}
	if (Key.isDown(Key.RIGHT)) {
		xspeed = xspeed+power;
	}
	if (Key.isDown(Key.UP)) {
		yspeed = yspeed-power*upconstant;
	}
	if (Key.isDown(Key.DOWN)) {
		yspeed = yspeed+power*upconstant;
	}
	xspeed = (xspeed+wind)*friction;
	yspeed = yspeed+gravity;
	_y = _y+yspeed;
	_x = _x+xspeed;
	_root.dark._x = _x;
	_root.dark._y = _y;
	_rotation = _rotation+xspeed;
	angle = Math.atan(yspeed/xspeed)/(Math.PI/180);
	if (xspeed<0) {
		angle += 180;
	}
	if (xspeed>=0 && yspeed<0) {
		angle += 360;
	}
	_root.dark._rotation = angle;
	this.hero_dir._rotation = angle-_rotation;
	if (_root.wall.hitTest(_x, _y, true)) {
		xspeed = 0;
		yspeed = 0;
		_x = 36;
		_y = 40;
	}
	if (_root.environment.hitTest(_x, _y, true)) {
		xspeed = 0;
		yspeed = 0;
		_x = 36;
		_y = 40;
	}
}

While lines 27 and 28 moves the dark movieclip according to player movements, line 37 provides the directional light rotation.

Well, that's enough at the moment. This tutorial is over but the game is way to be completed. You will learn how to manage lives, energy, enemies, room exits, code-cleaning and some other useful things.

Meanwhile, download the source of the examples covered in this tutorial and give me feedback.
At this time, you should be able to code a little game like Collectabubble or something more complex.
If you make a game following one mf my tutorials, or want to draw some graphics for walls or backgrounds for the final game, please give me your works and I will put them on this site with a credit to you and a link to your website, if any.

Continue to part 5

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