Step by step AS3 translation of Creation of a platform game with Flash – step 1.5

Read all posts about "" game

According to Bart de Boer, this is the step 1.5 of the Step by step AS3 translation of Creation of a platform game with Flash.

He fixed the jump issue and improved the collision engine.

As in the previous example, the file Script.as is the main class:

/*____________________________________________________
|______________	register of functions _______________|
|____________________________________________________|

- main()			only calling to update_hero() (every frame)

- create_hero()		creates hero as the var "Hero"

- update_hero()		check collision an move

- BuildMap()		load and create the level


extern

Data.as
- Setup()			create levels 

collision_manager.as
- Setup(size,map,hero)		setup the map

- Solve_all(forecastx,forecasty)		solves the collsions and checks for a jump
*/


package{												//The begin of an .as file
	import flash.display.MovieClip;						//import some libraries
	import flash.events.Event;
	import flash.events.KeyboardEvent;

	public class Script extends MovieClip{				// start the script
	
	private const gravity:int = 1;
	private const max_speed:int = 8;
	
	private const walkspeed:int = 4;
	private const jumpspeed:int = 10;
	
	private var forecast_x:int;
	private var forecast_y:int;
	
	private const start_x:int = 50;
	private const start_y:int = 50;
	
	private var left:Boolean;
	private var up:Boolean;
	private var right:Boolean;
	private var space:Boolean;
		
	private var level:Array = new Array();
	private var tiles:Array = new Array();
	
	private var Map_data:Data = new Data;				// create a version of the Data.as
	private var Hero_col:collision_manager = new collision_manager;
	
	private var Hero:hero = new hero;
	
		public function Script(){						// the init (will only be runned once)
			BuildMap();
			create_hero();
			addEventListener(Event.ENTER_FRAME, main);
			stage.addEventListener(KeyboardEvent.KEY_DOWN, key_down);
			stage.addEventListener(KeyboardEvent.KEY_UP, key_up);
			
			Hero_col.Setup(25,level,Hero);
		}
		
		private function main(event:Event){
			update_hero();
		}
		
		private function key_down(event:KeyboardEvent){
			if(event.keyCode == 37){
				left = true;
			}
			if(event.keyCode == 38){
				up = true;
			}
			if(event.keyCode == 39){
				right = true;
			}
		}
		
		private function key_up(event:KeyboardEvent){
			if(event.keyCode == 37){
				left = false;
			}
			if(event.keyCode == 38){
				up = false;
			}
			if(event.keyCode == 39){
				right = false;
			}
		}
								
			
		
/*
///    ///		/////////	///////////		///////////
///    ///		///			////    ///		///		///
///    ///		///			////    ///		///		///
//////////		/////////	//////////		///		///
//////////		/////////	////	///		///		///
///    ///		///			////	///		///		///
///    ///		///			////	///		///		///
///    ///		/////////	////	///		///////////
*/
		private function create_hero(){
			addChild(Hero);
			Hero.x = start_x;
			Hero.y = start_y;
			Hero.x_speed = 0;
			Hero.y_speed = 0;
		}
		
		private function update_hero(){
			Hero.y_speed += gravity;
			if(left){
				Hero.x_speed = -walkspeed;
			}
			if(right){
				Hero.x_speed = walkspeed;
			}
			if(up && Hero_col.can_jump){
				Hero.y_speed = -jumpspeed;
			}
			
			if(Hero.y_speed > max_speed){
				Hero.y_speed = max_speed;
			}
			
			forecast_y = Hero.y + Hero.y_speed;
			forecast_x = Hero.x + Hero.x_speed;
			
			Hero_col.solve_all(forecast_x, forecast_y);
			
			
			Hero.x_speed = 0;
		}
	
	
/*
|||||||||||		 |||||||||||	  ||||||||||	||||||||||
||||||||||||	||||||||||||	 ||||	 ||||	||||	|||
||||	||||| |||||		||||	 ||||||||||||	||||||||||
||||	  |||||||		||||	 ||||	 ||||	||||
||||	    |||			||||	||||	  ||||	||||
||||					||||	||||      ||||	||||
*/
				
		private function BuildMap(){
			Map_data.Setup();												// setup data from extern file
			
			level = Map_data.level1;										// get data from extern file
			
			for(var t = 0; t < level.length; t++){
				for(var u = 0; u < level[t].length; u++){
					if(level[t][u] != 0){									//if the data is not null
						var new_tile:platform_tile = new platform_tile;		//than build a tile
						
						addChild(new_tile);									//put it on the screen
						
						new_tile.gotoAndStop(1);
						new_tile.x = u * 25;
						new_tile.y = t * 25;
						
						tiles.push(new_tile);								//put it in an array
					}
				}
			}
		}
	}
}

// You may not post this on any other site than: http://www.emanueleferonato.com or http://www.frozenhaddock.com. You may not claim that you wrote this code. I'm not responsible for any nuclear activity that may be caused by this script.

The level is stored in the Data.as

package{
	
	public class Data{
		
	public var level1:Array = new Array();
		public function Setup(){
			level1 = [
					  [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
					  [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
					  [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
					  [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
					  [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
					  [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1],
					  [1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
					  [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
					  [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
					  [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
					  [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
					  [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
					  [1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
					  [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
					  [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
					 ]
		}
	}
}

// You may not post this on any other site than: http://www.emanueleferonato.com or http://www.frozenhaddock.com. You may not claim that you wrote this code. I'm not responsible for any nuclear activity that may be caused by this script.

While the solve_all function contained in the collision_manager.as solves all collisions in the forecast position of the player

package{
	
	public class collision_manager{
		private var Tile_size:int;			//containing the size of the tiles
		private var level;					//level data container
		private var forecast_x:int;			//where the player will be at the end of the frame
		private var forecast_y:int;			//"												  "
		public var can_jump:Boolean;		//same as in Emanuele's tutorial
		private var hero;					//to store the Hero object in
		
		public function Setup(size,map,heroj){		//my standard setup function(init)
			Tile_size = size;						//initializing al vars
			level = map;
			hero = heroj;
		}
		
		public function get_corners(point_x,point_y){				
		//get the position of the four corners of the hero
			
			hero.downy = Math.round((point_y + 10 - Tile_size/2) / Tile_size);
			hero.upy = Math.round((point_y - 10 - Tile_size/2) / Tile_size);
			hero.rightx = Math.round((point_x + 5 - Tile_size/2) / Tile_size)
			hero.leftx = Math.round((point_x - 5 - Tile_size/2) / Tile_size);
			/*
			Looks in wich tiles these four point are.
			*Attention* TILES and not pixel!
			
			Will be used to get the position of the corners 
			and to get the end position of the hero.
			*/
			
			hero.downleft = level[hero.downy][hero.leftx];
			hero.downright = level[hero.downy][hero.rightx];
			hero.upright = level[hero.upy][hero.rightx];
			hero.upleft = level[hero.upy][hero.leftx];
			
			
			/*
			Gets the sort tile the position of the corners has.
			
			One means there can be collision, zero is air.			
			*/
		}
		
		public function check_ground(){
			hero.downy = Math.round((hero.y + 11 - Tile_size/2) / Tile_size);
			hero.rightx = Math.round((hero.x + 5 - Tile_size/2) / Tile_size)
			hero.leftx = Math.round((hero.x - 5 - Tile_size/2) / Tile_size);
			// Makes three points in tile-coordinates
			
			hero.downleft = level[hero.downy][hero.leftx];
			hero.downright = level[hero.downy][hero.rightx];
			//Checks the sort
			
			if(hero.downleft == 1 || hero.downright ==1){		//if there is any collision by the hero's feet
				can_jump = true;								//than can jump
			}
			else{
				can_jump = false;								//else not
			}
		}
		
		public function solve_all(forecastx, forecasty){
		/*
		This function looks hard... an it is...
		I've been working on it for loads of hours, and this is the result.
		
		This is the best collision-test I've ever made, for sqaures.
		
		It's still readable, because I made it simple.
		
		It's four times almost the same. It checks for collision between the spots, 
		the four spots if there only were x_speeds, the four spots if there only was y_speed, 
		the four spots if there were both y- and x_speed.	
		That are 3*4 = 12 spots.
		
		
		//////////////////////////////////
		Why's:
		
		question:
		Why did I used forecast_x and forecast_y and not just hero.x and hero.y?
		
		answer:
		Changing the hero over the screen will cost loads of CPU because an hero 
		exist out of loads of pixels. The forecast's are just simple variables
		
		question:
		Is such a huge function not requiring a lot of CPU?
		
		answer:
		It doesn't uses any while- or for loops, Math. functions and the most important of 
		all: no hitTestPoint()/hitTestObject(). So it's a lot faster.
		
		question:
		Is there a better or faster collision test?
		
		answer:
		Probaly, yes.
		//////////////////////////////////
		
		var-explanation:
		
		downC 	-> 	is collision under the spot
		upC		->	is collision above the spot
		rightC	->	is collision right from the spot
		leftC	->	You probaly wouldn't expect this, but this is collision left from the spot
		
				*/
			forecast_x = forecastx;
			forecast_y = forecasty;
			
			get_corners(forecast_x,forecast_y);
			
			if(hero.downleft == 1){
				get_corners(hero.x,forecast_y);
					if(hero.downleft == 1){					
						hero.downC = true;
					}
					else{
						hero.downC = false;
					}
				get_corners(forecast_x,hero.y);
					if(hero.downleft == 1){					
						hero.leftC = true;
					}
					else{
						hero.leftC = false;
					}
					if(hero.leftC && hero.downC){
						forecast_x = (hero.leftx+1) * 25 + 5;
						forecast_y = (hero.downy+1) * 25 - 11;
						hero.y_speed = 0;
					}
					else if(hero.leftC){
						forecast_x = (hero.leftx+1) * 25 + 5;
					}
					else if(hero.downC){
						forecast_y = (hero.downy+1) * 25 - 11;
						hero.y_speed = 0;
					}
			}
			
			get_corners(forecast_x,forecast_y);
			
			if(hero.downright == 1){
				get_corners(hero.x,forecast_y);
					if(hero.downright == 1){					
						hero.downC = true;
					}
					else{
						hero.downC = false;
					}
				get_corners(forecast_x,hero.y);
					if(hero.downright == 1){					
						hero.rightC = true;
					}
					else{
						hero.rightC = false;
					}
					if(hero.rightC && hero.downC){
						forecast_x = hero.rightx * 25 - 6;
						forecast_y = (hero.downy+1) * 25 - 11;
						hero.y_speed = 0;
					}
					else if(hero.rightC){
						forecast_x = hero.rightx * 25 - 6;
					}
					else if(hero.downC){
						forecast_y = (hero.downy+1) * 25 - 11;
						hero.y_speed = 0;
					}
			}
			
			get_corners(forecast_x,forecast_y);
			
			if(hero.upleft == 1){
				get_corners(hero.x,forecast_y);
					if(hero.upleft == 1){					
						hero.upC = true;
					}
					else{
						hero.upC = false;
					}
				get_corners(forecast_x,hero.y);
					if(hero.upleft == 1){					
						hero.leftC = true;
					}
					else{
						hero.leftC = false;
					}
					if(hero.leftC && hero.upC){
						forecast_x = (hero.leftx+1) * 25 + 5;
						forecast_y = (hero.upy) * 25 + 10;
						hero.y_speed = 0;
					}
					else if(hero.leftC){
						forecast_x = (hero.leftx+1) * 25 + 5;
					}
					else if(hero.upC){
						forecast_y = (hero.upy) * 25 + 10;
						hero.y_speed  = 0;
					}
			}
			
			get_corners(forecast_x,forecast_y);
			
			if(hero.upright == 1){
				get_corners(hero.x,forecast_y);
					if(hero.upright == 1){					
						hero.upC = true;
					}
					else{
						hero.upC = false;
					}
				get_corners(forecast_x,hero.y);
					if(hero.upright == 1){					
						hero.leftC = true;
					}
					else{
						hero.leftC = false;
					}
					if(hero.leftC && hero.upC){
						forecast_x = hero.rightx * 25 - 6;
						forecast_y = (hero.upy) * 25 + 10;
						hero.y_speed = 0;
					}
					else if(hero.leftC){
						forecast_x = hero.rightx * 25 - 6;
					}
					else if(hero.upC){
						forecast_y = (hero.upy) * 25 + 10;
						hero.y_speed  = 0;
					}
			}
			
			hero.x = forecast_x;		//place the hero
			hero.y = forecast_y;
			
			check_ground()		//runs the function to check for ground
		}
	}
}

// You may not post this on any other site than: http://www.emanueleferonato.com or http://www.frozenhaddock.com. You may not claim that you wrote this code. I'm not responsible for any nuclear activity that may be caused by this script.

Now we have a working AS3 platform engine

Thanks to Bart de Boer for providing the source code of this prototype. Download it and start making your own AS3 platform game.

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