AS3 version of Nodes engine: full playable game with infinite solvable levels

Read all posts about "" game

Today I want to point you on a very interesting prototype I made more than four years ago… Creation of the engine behind “Nodes” game with Flash.

It’s a basic prototype of Nodes, a puzzle game which got some success years ago.

Why am I publishing this prototype today? First, because I improved and now it’s a “complete” game, which means you can play for real, trying to beat infinite random-generated solvable levels.

Second, and probably most important reason, is the gameplay is perfect for a mobile porting, which I am currently making.

Anyway, this is the game:

Drag the red nodes to highlight all blue targets with the laser. Once a level is completed, you will face another random generated level.

And this is the short source code I used to make it:

package {
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	public class Main extends Sprite {
		private const DRAGGABLES:Number=4;
		private const TARGETS:Number=5;
		private var draggableNode:DraggableNode;
		private var target:Target;
		private var laserCanvas:Sprite=new Sprite();
		private var draggableVector:Vector.=new Vector.();
		private var targetVector:Vector.=new Vector.();
		private var isDragging:Boolean=false;
		public function Main() {
			addChild(laserCanvas);
			placeDraggables(false);
			placeTargets(false);
			shuffleDraggables();
			drawLaser();
			stage.addEventListener(MouseEvent.MOUSE_MOVE,moving);
		}
		private function placeDraggables(justMove:Boolean):void {
			for (var i:Number=0; i=0; j--) {
						if (getDistance(draggableVector[j],draggableVector[i])<150) {
							wellPlaced=false;
						}
					}
				} while (!wellPlaced);
			}
		}
		private function placeTargets(justMove:Boolean):void {
			for (var i:Number=0; i=0; j--) {
						if (getDistance(targetVector[j],targetVector[i])<50) {
							wellPlaced=false;
						}
					}
					for (j=0; j

Let's see the most interesting lines:

private const DRAGGABLES:Number=4;
private const TARGETS:Number=5;
private var draggableNode:DraggableNode;
private var target:Target;
private var laserCanvas:Sprite=new Sprite();
private var draggableVector:Vector.=new Vector.();
private var targetVector:Vector.=new Vector.();
private var isDragging:Boolean=false;

DRAGGABLES and TARGETS are respectively the amounts of red draggable nodes and blue targets.

draggableNode and target are variables to instantiate respectively DraggableNode and Target sprites, in the library

laserCanvas is the sprite we will use to draw the laser

draggableVector and targetVector are vectors we will fill respectively with draggable nodes and targets

isDragging is a Boolean variable to help us know whether the player is dragging a node.

addChild(laserCanvas);
placeDraggables(false);
placeTargets(false);
shuffleDraggables();
drawLaser();
stage.addEventListener(MouseEvent.MOUSE_MOVE,moving);

This is the game itself, which works this way: first, draggable nodes are randomly placed on the stage, then target are randomly placed over lasers, generating a solvable levels, then draggable nodes are shuffled and finally the laser is shown.

A listener is added to trigger mouse movements.

And this is how we place draggable nodes:

private function placeDraggables(justMove:Boolean):void {
	for (var i:Number=0; i=0; j--) {
				if (getDistance(draggableVector[j],draggableVector[i])<150) {
					wellPlaced=false;
				}
			}
		} while (!wellPlaced);
	}
}

The Boolean argument is used to let us know whether we just have to adjust nodes or we also have to physically add them to stage and fill draggableVector vector. When the game is run, we have to physically add the nodes, but when the player completes a level we just have to arrange nodes in different positions.

Look at the listeners attached to each node, and also look how we are ensuring there are at least 150 pixels of empty space around nodes.

private function placeTargets(justMove:Boolean):void {
	for (var i:Number=0; i=0; j--) {
				if (getDistance(targetVector[j],targetVector[i])<50) {
					wellPlaced=false;
				}
			}
			for (j=0; j

Targets are placed/moved in the same way, just keeping at least 50 pixels of empty space before we find another target or a draggable node.

The interesting part starts at line 52 where I choose a random laser segment where to place the target.

Lines 53-54: Given the segment, I determine the nodes which delimit such segment

Line 55: Finding the angle of the segment

Line 56: Finding segment length

Lines 57-58: Once I know the start and end points of the segment, as well as its length and angle, it's easy to place the target in a random point of the segment using trigonometry.

private function shuffleDraggables():void {
	for (var i:Number=0; i

This is how draggable nodes are shuffled... just placing them in a random position.

private function drawLaser():void {
	laserCanvas.graphics.clear();
	laserCanvas.graphics.lineStyle(5,0xff0000);
	laserCanvas.graphics.moveTo(draggableVector[0].x,draggableVector[0].y);
	for (var i:Number=1; i

And this is how the laser is placed on the stage, it's just a line connecting all nodes in sequence, also connecting the latest node with the first node.

private function moving(e:MouseEvent):void {
	var connected:Number=0;
	if (isDragging) {
		drawLaser();
		for (var i:Number=0; i

The last interesting function is the one which handles nodes movement. In this case, I just perform an hit test between nodes registration point and the laser line, so the strongest the line, the easier the game. Once all targets are touched by laser simultaneously, a new level starts.

And that's all, download the source code, hope you enjoyed this prototype and you will enjoy the mobile porting too.

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