Chronotron Flash game prototype

Read all posts about "" game

Do you remember Chronotron?

It’s a puzzle platform which wants you to interact with past versions of yourself to solve levels. It’s a very original game, higly recommended

chronotron

Luis Fernando Silva, author of a Box2D platform engine alternative published on the blog some time ago, created a prototype of this game

« I really liked how this prototype turned out and I hope it might help someone out. Maybe a more creative coder might even improve it!

Anyways, for the past few days, I’ve been wondering how to achieve the cool time-warped NPC that repeats all you did on a past run of a level, like on Chronotron and Mouse 10*, I was shooting some thoughts on FGL chat and the idea of using arrays to store player input in an Array and make the NPC replay it came to mind. I started discussing the idea and it gained shape as I and the chat folks talked about the possibilities.

I decided I already had a good base to start coding on, and I promotly started scripting down in Flash. At the beggining, it was hard to code this, there was some issues with the way the input was ordered on the replay array, so I had to create a function to place it in the correct order, along with an issue the way the NPC interpreted it. But after many issues, troubles, crashes and bug testing, the thing is here! And it works (almost) flawlessly! »

The main file is on the timeline and it’s fully commented:

// Keyboard:
var inp:Input2 = new Input2(stage);

// List of NPCs:
var NPCs:Array = new Array();

// The array we'll store the run, with key presses and their respective intervals:
var Run:Array = new Array();

// The current level run time:
var Interval:int = 0;

// The interval limit (in frames):
var IntervalLimit:int = 300; // 300 frames = 10 seconds on 30fps

// This array stores the start time in which a key was pressed:
var KeyPress:Array = new Array(inp.Keys.length);

// Initialize it:
for(var i:int = 0; i < inp.Keys.length; i++){
	KeyPress[i] = 0;
}

// Loop event attachment:
stage.addEventListener('enterFrame', loop);

// The first element of the replay array is always the player
// position at the time the run was started being recording:
Run.push([player.x, player.y]);

// Loop event listener:
function loop(e:Event) : void {
	// Span the interval up:
	Interval ++;
	
	var ev:Boolean = false;
	
	// You could trim bit this later so it only captures
	// used key codes (like arrow keys, WASD, etc)
	for(var i:int = 0; i < inp.Keys.length; i++){
		// If a key is starting to be pressed now:
		if(inp.KeysInterval[i] == 1){
			// Change this key statement as being held down:
			if(KeyPress[i] == 0){
				// Start a 'key down' timer:
				KeyPress[i] = Interval;
			}
		}
		// If a key is NOT being pressed now:
		else if(inp.KeysInterval[i] == 0){
			// Checks if this key was being held down:
			if(KeyPress[i] > 0) {
				// Pushes the key, start time and interval:
				storeKeyEvent(i, KeyPress[i], Interval - KeyPress[i]);
				KeyPress[i] = 0;
				
				ev = true;
			}
		}
	}
	
	// Key event, show the array, please (remove the '&& false' to show):
	if(ev && false)
		trace(Run);
	
	// Interval over? Start over and place an NPC
	if(Interval > IntervalLimit){
		// Little trick to jump the current key state
		// to the next NPC:
		for(i = 0; i < inp.Keys.length; i++){
			if(KeyPress[i] > 0){
				storeKeyEvent(i, KeyPress[i], Interval - KeyPress[i]);
				KeyPress[i] -= Interval - 1;
			}
		}
		
		// Reset the interval:
		Interval = 0;
		
		var npc:Mc_NPC = new Mc_NPC();
		
		// Copy the run over to the NPC and init it:
		npc.Run = Run.slice();
		npc.init();
		
		// Set the label:
		npc.label.text = "NPC " + NPCs.length;
		
		// Add the NPC:
		addChild(npc);
		
		// pushes the NPC to the NPCs array:
		NPCs.push(npc);
		
		// Reset the run over:
		Run = new Array();
		Run.push([player.x, player.y]);
		
		// Reset the NPCs run, as well:
		for(i = 0; i < NPCs.length; i++){
			NPCs[i].Runtime = 0;
			NPCs[i].init();
		}
	}
	
	// Run the player:
	player.stepPlayer();
	
	// Run the NPCs:
	for(i = 0; i < NPCs.length; i++){
		NPCs[i].stepNPC();
	}
}

// Stores a key event on the 'time-warp' array. I use a function for this
// in order to achieve a correct ordering on the events order:
function storeKeyEvent(key:uint, start:uint, interval:uint) : void {
	// If there are no elements on the array, just push it already:
	if(Run.length == 1) {
		Run.push([key, KeyPress[key], Interval - KeyPress[key]]);
		
		return;
	}
	
	// Run the loop backwards, assuming the nearest position is at the end
	// of the array:
	for(var i:int = Run.length - 1; i >= 0; i--){
		// Checks to see the event order:
		if(i == 0 || (Run[i][1] < start)){
			// If this event happened before the event on [i], insert this event
			// after it:
			Run.splice(i+1, 0, [key, KeyPress[key], Interval - KeyPress[key]]);
			
			break;
		}
	}
}

And this is the result:

Move the main rectangle with left and right arrow keys, and when the upper timeline is over, watch for you chrono clone.

Download the source code and let me know if you improve it somehow

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

214 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
// 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