Learning 20: Lines and paths

This page describes the commands for creating and using lines and paths.

 

PS.line ( x1, y1, x2, y2 )

The most common animation task is moving beads or sprites from one place on the grid to another. Doing this requires a path defining each consecutive x/y coordinate from the starting position to the end.

Such paths are easy to calculate when all positions lie on a horizontal or vertical line, or on a perfect diagonal. But what if the path isn't perfectly straight?

The PS.line() function makes it easy to obtain a direct path between any two points on a 2-dimensional grid. Pass it the start and end points, and it returns an array of coordinates (each represented by a separate [ x, y ] array ) representing the shortest path between them.

The x1 and y1 parameters indicate the starting coordinates of the line, and x2 and y2 indicate the ending coordinates. All four integers are required. Non-integral values are floored.

// EXAMPLE
// Calc a path between 2, 3 and 7, 10

var path;

path = PS.line( 2, 3, 7, 10 );

// The path variable now contains
// the following array of coordinates:

path = [
 [ 3, 4 ], // first step after start point
 [ 3, 5 ],
 [ 4, 6 ],
 [ 5, 7 ],
 [ 6, 8 ],
 [ 6, 9 ],
 [ 7, 10 ] // destination point
];

// The number of steps in the path is path.length

If x1, y1 and x2, y2 specify the same coordinate, the array returned by PS.line() will be empty (length = 0).

Usage notes

1. PS.line() operates in an arbitrary coordinate space of almost limitless extent. It has no idea how a line it has calculated will be used in your game. It's your responsibility to interpret the data returned by PS.line() in the context of your application, and to deal with boundary conditions that might cause errors if violated.

Demonstration

This demo creates a 15x15 grid of random gray beads, and places a 1x1 solid green sprite at the center of the grid, on plane 1.

When you touch a bead, PS.line() calculates a path between the sprite's current location and the touched bead. The returned array is stored in the path variable.

A timer function, tick(), is constantly watching to see if the path variable contains data. When it does, it automatically moves the sprite along the path, one step at a time, deleting the path when the destination point is reached.

[Run Demo]

var G; // establish global namespace

( function () {
 var id; // sprite identifier
 var xpos = 7; // x-pos of sprite
 var ypos = 7; // y-pos of sprite

 var floorPlane = 0;
 var actorPlane = 1;

 var path = null; // path to follow, null if none
 var step = 0; // current step on path

 // Timer function, called every 1/10th sec

 function tick () {
 var p, nx, ny;

 if ( path ) { // path ready (not null)?
 // Get next point on path

 p = path[ step ];
 nx = p[ 0 ]; // next x-pos
 ny = p[ 1 ]; // next y-pos

 // If actor already at next pos,
 // path is exhausted, so nuke it

 if ( ( xpos === nx ) && ( ypos === ny ) ) {
 path = null;
 return;
 }

 // Move sprite to next position

 PS.spriteMove( id, nx, ny );
 xpos = nx; // update xpos
 ypos = ny; // and ypos

 step += 1; // point to next step

 // If no more steps, nuke path

 if ( step >= path.length ) {
 path = null;
 }
 }
 }

 G = {
 width : 15, // width of grid
 height : 15, // height of grid

 // Draw floor and initialize sprite

 drawMap : function () {
 var x, y, val;

 // Create random gray floor

 PS.gridPlane( floorPlane );
 for ( y = 0; y < G.height; y += 1 ) {
 for ( x = 0; x < G.width; x += 1 ) {
 val = ( PS.random( 32 ) - 1 ) + 128;
 PS.color( x, y, val, val, val );
 }
 }

 // Create 1x1 solid green sprite
 // Place on plane 1 in center of grid

 id = PS.spriteSolid( 1, 1 );
 PS.spriteSolidColor( id, PS.COLOR_GREEN );
 PS.spritePlane( id, actorPlane );
 PS.spriteMove( id, xpos, ypos );

 // Start the timer function
 // Run at 10 frames/sec (every 6 ticks)

 PS.timerStart( 6, tick );
 },

 // move( x, y )
 // Set up new path

 move : function ( x, y ) {
 var line;

 // Calc a line from current position
 // to touched position

 line = PS.line( xpos, ypos, x, y );

 // If line is not empty,
 // make it the new path

 if ( line.length > 0 ) {
 path = line;
 step = 0; // start at beginning
 }

 PS.audioPlay( "fx_click" );
 }
 };
}() );

PS.init = function( system, options ) {
 PS.gridSize( G.width, G.height ); // init grid
 PS.border( PS.ALL, PS.ALL, 0 ); // no borders
 G.drawMap(); // init walls & sprite
 PS.audioLoad( "fx_click" ); // preload sound
 PS.statusText( "Touch grid to move" );
};

// Respond to click/touch

PS.touch = function( x, y, data, options ) {
 "use strict";

 G.move( x, y );
};

Return value

PS.line() returns an array of sub-arrays, each with the following structure:

Each sub-array represents a single point in a straight line from x1, y1 to x2, y2, beginning with the first step away from x1, y1. Points are presented in sequence, starting with element zero (0) of the returned array. The final point is always x2, y2.

If x1, y1 and x2, y2 specify the same coordinate, the array returned by PS.line() will be empty (length = 0).

PS.ERROR is returned if an error occurs.

 

PS.pathMap ( image )

PS.line() works fine for calculating paths in open spaces. But what if a space contains walls or other obstacles?

The PS.pathMap() function provides a way to define a 2-dimensional space containing obstacles. This definition, an object called a pathmap, can then be passed to the PS.pathFind() function (described below) to calculate paths in the space that intelligently avoid the obstacles, using the classic A* pathfinding algorithm.

The required image parameter must be a reference to a valid imageMap object with the following characteristics:

The imageMap must be in format 1. This means that its image.data array must contain exactly (image.width * image.height) integers in the range 0 to 0xFFFFFF inclusive, and its image.pixelSize property must be set to 1.

∎ Each integer in the image.data array indicates whether or not the corresponding map location is "walkable."

∎ A non-zero value in the image.data array indicates that the corresponding coordinate should be considered by PS.pathFind() as a possible candidate for a path point.

∎ A value of zero (0) in the image.data array means that PS.pathFind() should never consider that coordinate for a path point.

// EXAMPLE
// A handmade 5x5 imageMap object
// containing two vertical "walls"
// All properties are REQUIRED

var myMap = {
 width : 5,
 height : 5,
 pixelSize : 1, // format 1
 data : [
 1, 1, 1, 1, 1, // 1 = walkable
 1, 0, 1, 0, 1, // 0 = obstacle
 1, 0, 1, 0, 1,
 1, 0, 1, 0, 1,
 1, 1, 1, 1, 1
 ]
};

// Pass the walkmap into PS.pathMap()
// Save the returned pathmap identifier

var mapID = PS.pathMap ( myMap );

// mapID can now be used with PS.pathFind()
// to calculate paths around the walls

The above example uses a small imageMap object explicitly defined in code. However, you can also use imageMap objects returned by PS.imageLoad() or PS.imageCapture(), as long as the imageMap is in format 1.

Usage notes

1. A convenient image.data value for a "walkable" coordinate is one (1). However, any integer greater than zero is acceptable. The values are interpreted as the relative "cost" of moving into that coordinate. You can use this feature to simulate different types of terrain. For example, flat terrain could be represented by the value 1, and steep terrain by the value 2. This would cause PS.pathFind() to prefer flat terrain when calculating paths, using steep terrain only if there is no other way to complete the path.

Return value

PS.pathMap() returns a string that uniquely identifies the newly created pathmap object.

A new identifier is generated by each call to PS.pathMap()). If you call it with same image more than once for some reason, each instance will be assigned a different identifier.

PS.ERROR is returned if an error occurs.

 

PS.pathFind ( pathmap, x1, y1, x2, y2, options )

The PS.pathFind() function calculates the shortest possible path between two coordinates in a pathmap object created by PS.pathMap().

The required pathmap parameter must be string uniquely identifying a pathmap object, of the type returned by PS.pathMap().

The x1 and y1 parameters indicate the starting coordinates of the path, and x2 and y2 indicate the ending coordinates. All four integers are required. Non-integral values are floored.

The x1 and x2 coordinates should be between 0 and (pathmap.width - 1) inclusive.

The y1 and y2 coordinates should be between 0 and (pathmap.height - 1) inclusive.

Usage notes

1. PS.pathFind() uses a modified A* pathfinding algorithm. The data you supply in the image used to create the pathmap can be used to influence the behavior of the algorithm. See PS.pathMap() above for details.

2. The pathmap locations at x1, y1 and x2, y2 must be "walkable;" that is, the corresponding data in the imageMap object passed to PS.pathMap() to create the pathmap must be non-zero. If either location is not walkable, an empty path (length = 0) is returned.

The optional options parameter provides additional capabilities described in the API documentation. If options is PS.DEFAULT or not supplied, all default settings are used.

// EXAMPLE
// A handmade 5x5 imageMap object
// containing two vertical "walls"
// All properties are REQUIRED

var myMap = {
 width : 5,
 height : 5,
 pixelSize : 1, // format 1
 data : [
 1, 1, 1, 1, 1, // 1 = walkable
 1, 0, 1, 0, 1, // 0 = obstacle
 1, 0, 1, 0, 1,
 1, 0, 1, 0, 1,
 1, 1, 1, 1, 1
 ]
};

// Pass the walkmap into PS.pathMap()
// Save the returned pathmap identifier

var mapID = PS.pathMap ( myMap );

// Call PS.pathFind() with mapID to calc a path
// between 0, 2 and 2, 2

var path = PS.pathFind( mapID, 0, 2, 2, 2 );

// The path variable now contains
// the following array of coordinates:

path = [
 [ 0, 1 ], // first step after start point
 [ 0, 0 ],
 [ 1, 0 ],
 [ 2, 0 ],
 [ 2, 1 ],
 [ 2, 2 ] // destination point
];

// The number of steps in the path is path.length

Demonstration

This demo creates a 15x15 grid of random gray beads, containing a pattern of black walls. A 1x1 solid green sprite is placed in the center, on plane 1.

The myMap variable contains an explicitly defined imageMap object. The .data property is a 15x15 array, with 1s representing walkable floor and 0s for walls. The drawMap() function uses this data to draw the map, and then passes it to PS.pathMap(), saving the returned pathmap ID in mapID for PS.pathFind() to use.

When you touch a bead, PS.pathFind() calculates the shortest legal path between the sprite's current location and the touched bead. The returned array is stored in the path variable.

A timer function, tick(), is constantly watching to see if the path variable contains data. When it does, it automatically moves the sprite along the path, one step at a time, deleting the path when the destination point is reached.

If you touch the grid while the sprite is moving, it will immediately begin to follow the new path.

If you click on a wall, PS.pathFind() will fail to calculate a path. The tick() function will detect this and honk at you.

[Run Demo]

var G; // establish global namespace

( function () {
 var id; // sprite identifier
 var xpos = 7; // x-pos of sprite
 var ypos = 7; // y-pos of sprite

 var floorPlane = 0;
 var actorPlane = 1;

 var mapID; // pathmap ID for pathfinder

 // Handmade imageMap for drawing and pathfinder
 // All properties MUST be present!
 // 0 = wall, 1 = floor

 var myMap = {
 width : 15,
 height : 15,
 pixelSize : 1,
 data : [
 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, 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, 1, 0, 0, 0, 0, 1, 1, 1,
 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1,
 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1,
 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1,
 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1,
 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1,
 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
 1, 1, 1, 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, 1, 1, 1, 1, 1, 1, 1,
 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
 ]
 };

 var path = null; // path to follow, null if none
 var step = 0; // current step on path

 // Timer function, called every 1/10th sec

 function tick () {
 var p, nx, ny;

 if ( !path ) { // path invalid (null)?
 return; // just exit
 }

 // Get next point on path

 p = path[ step ];
 nx = p[ 0 ]; // next x-pos
 ny = p[ 1 ]; // next y-pos

 // If actor already at next pos,
 // path is exhausted, so nuke it

 if ( ( xpos === nx ) && ( ypos === ny ) ) {
 path = null;
 return;
 }

 // Move sprite to next position

 PS.spriteMove( id, nx, ny );
 xpos = nx; // update xpos
 ypos = ny; // and ypos

 step += 1; // point to next step

 // If no more steps, nuke path

 if ( step >= path.length ) {
 path = null;
 }
 }

 G = {
 width : 15, // width of grid
 height : 15, // height of grid

 // Draw floor and initialize sprite

 drawMap : function () {
 var ptr, x, y, val;

 // Read map data to draw floor/walls

 PS.gridPlane( floorPlane );
 ptr = 0; // init data pointer
 for ( y = 0; y < G.height; y += 1 ) {
 for ( x = 0; x < G.width; x += 1 ) {
 val = myMap.data[ ptr ];
 if ( val === 0 ) { // wall
 PS.color( x, y, PS.COLOR_BLACK );
 }
 else { // random gray floor
 val = ( PS.random( 32 ) - 1 ) + 128;
 PS.color( x, y, val, val, val );
 }
 ptr += 1;
 }
 }

 // Create 1x1 solid green sprite
 // Place on plane 1 in center of grid

 id = PS.spriteSolid( 1, 1 );
 PS.spriteSolidColor( id, PS.COLOR_GREEN );
 PS.spritePlane( id, actorPlane );
 PS.spriteMove( id, xpos, ypos );

 // Create pathmap from our imageMap
 // for use by pathfinder

 mapID = PS.pathMap( myMap );

 // Start the timer function
 // Run at 10 frames/sec (every 6 ticks)

 PS.timerStart( 6, tick );
 },

 // move( x, y )
 // Set up new path

 move : function ( x, y ) {
 var line;

 // Calc a line from current position
 // to touched position

 line = PS.pathFind( mapID, xpos, ypos, x, y );

 // If line is not empty, it's valid,
 // so make it the new path
 // Otherwise hoot at player

 if ( line.length > 0 ) {
 path = line;
 step = 0; // start at beginning
 PS.audioPlay( "fx_click" );
 }
 else {
 PS.audioPlay( "fx_hoot" );
 }
 }
 };
}() );

PS.init = function( system, options ) {
 PS.gridSize( G.width, G.height ); // init grid
 PS.border( PS.ALL, PS.ALL, 0 ); // no borders
 G.drawMap(); // init walls & sprite
 PS.audioLoad( "fx_click" ); // preload sounds
 PS.audioLoad( "fx_hoot" );
 PS.statusText( "Touch grid to move" );
};

// Respond to click/touch

PS.touch = function( x, y, data, options ) {
 "use strict";

 G.move( x, y );
};

Return value

PS.pathFind() returns an array of sub-arrays, each with the following structure:

Each sub-array represents a single point in a path from x1, y1 to x2, y2, beginning with the first step away from x1, y1. Points are presented in sequence, starting with element zero (0) of the returned array. The final point is always x2, y2.

All coordinates are zero-based, relative to the top-left corner of the associated pathmap.

If x1, y1 and x2, y2 specify the same coordinate, or if the coordinate at either x1, y1 or x2, y2 is defined as non-walkable (data = 0), the array returned by PS.pathFind() will be empty (length = 0).

PS.ERROR is returned if an error occurs.

 

PS.pathData ( pathmap, left, top, width, height, data )

The PS.pathData() command lets you examine and modify the data in a pathmap object created by PS.pathMap().

The required pathmap parameter must be string uniquely identifying a pathmap object, of the type returned by PS.pathMap().

The required left, top, width and height parameters specify a zero-based rectangular region, relative to the top-left corner of the pathmap. Non-integral values are floored.

The left and top integers indicate the top-left coordinates of the region. The left coordinate should be between 0 and (pathmap.width - 1) inclusive. The top coordinate should be between 0 and (pathmap.height - 1) inclusive. Values outside these limits will cause an error.

The width and height integers indicate the dimensions of the region. The width parameter should be between 1 and (pathmap.width - left) inclusive. The height parameter should be between 1 and (pathmap.height - top) inclusive. Values outside these limits are clamped.

If width or height are PS.DEFAULT, the value one (1) is used.

The optional data parameter indicates the data that will replace the current values in the pathmap. It can be any positive integer. Non-integral values are floored.

If data is PS.DEFAULT, the data in the pathmap at the specified coordinates is restored to the values in place when the pathmap was originally created by PS.pathMap().

If data is PS.CURRENT or not supplied, the data in the pathmap is not changed.

// EXAMPLE
// A handmade 5x5 imageMap object
// containing two vertical "walls"
// All properties are REQUIRED

var myMap = {
 width : 5,
 height : 5,
 pixelSize : 1, // format 1
 data : [
 1, 1, 1, 1, 1, // 1 = walkable
 1, 0, 1, 0, 1, // 0 = obstacle
 1, 0, 1, 0, 1,
 1, 0, 1, 0, 1,
 1, 1, 1, 1, 1
 ]
};

// Pass the walkmap into PS.pathMap()
// Save the returned pathmap identifier

var mapID = PS.pathMap ( myMap );

// Call PS.pathFind() with mapID to calc a path
// between 0, 2 and 2, 2

var path = PS.pathFind( mapID, 0, 2, 2, 2 );

// The path variable now contains
// the following array of coordinates:

path = [
 [ 0, 1 ], // first step after start point
 [ 0, 0 ],
 [ 1, 0 ],
 [ 2, 0 ],
 [ 2, 1 ],
 [ 2, 2 ] // destination point
];

// Change the pathmap to open a "door" at 1, 3

PS.pathData( mapID, 1, 3, 1, 1, 1 );

// Call PS.pathFind() again to get a new path
// between 0, 2 and 2, 2

var path = PS.pathFind( mapID, 0, 2, 2, 2 );

// The path variable now contains
// the following array of coordinates:

path = [
 [ 1, 2 ], // first step after start point
 [ 2, 2 ] // destination point
];

Demonstration

This demo adds a secret door to the previous layout, preventing the sprite from entering the inner sanctum.

The player's sprite and a gold key are placed on opposite corners of the map. Moving the sprite over the key opens the secret door.

A call to PS.pathData() is used to change the pathmap data at location 7, 9 from a wall space (0) to a floor space (1) when the key is taken. This allows PS.pathFind() to calculate a successful path into the sanctum. A matching call to PS.color() changes the wall in the grid to a floor space.

[Run Demo]

var G; // establish global namespace

( function () {
 var actorID; // actor sprite ID
 var xpos = 1; // x-pos of actor
 var ypos = 1; // y-pos of sprite

 var keyID; // key sprite ID
 var kx = 13; // key x-pos
 var ky = 13; // key y-pos
 var found = false; // true when key found

 var dx = 7; // door x-pos
 var dy = 9; // door y-pos

 var floorPlane = 0;
 var keyPlane = 1;
 var actorPlane = 2;

 var mapID; // pathmap ID for pathfinder

 // Handmade imageMap for drawing and pathfinder
 // All properties MUST be present!
 // 0 = wall, 1 = floor
 // Note that (7, 9) = 0 in this version
 // This makes the "secret door" unwalkable

 var myMap = {
 width : 15, height : 15,
 pixelSize : 1,
 data : [
 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, 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, 1, 0, 0, 0, 0, 1, 1, 1,
 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1,
 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1,
 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1,
 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1,
 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1,
 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
 1, 1, 1, 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, 1, 1, 1, 1, 1, 1, 1,
 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
 ]
 };

 var path = null; // path to follow, null if none
 var step = 0; // current step on path

 // Timer function, called every 1/10th sec

 function tick () {
 var p, nx, ny;

 if ( !path ) { // path invalid (null)?
 return; // just exit
 }

 // Get next point on path

 p = path[ step ];
 nx = p[ 0 ]; // next x-pos
 ny = p[ 1 ]; // next y-pos

 // If actor already at next pos,
 // path is exhausted, so nuke it

 if ( ( xpos === nx ) && ( ypos === ny ) ) {
 path = null;
 return;
 }

 // Move sprite to next position

 PS.spriteMove( actorID, nx, ny );
 xpos = nx; // update xpos
 ypos = ny; // and ypos

 // Landed on key?

 if ( !found && (xpos===kx) && (ypos===ky) ) {
 found = true;
 PS.spriteShow( keyID, false ); // hide key

 // Change wall on grid to floor color

 PS.gridPlane( floorPlane );
 PS.color( dx, dy, PS.COLOR_GRAY );

 // Change pathMap data to replace wall
 // at dx, dy with floor (1)
 // This lets pathfinder "see" the open door

 PS.pathData( mapID, dx, dy, 1, 1, 1 );
 PS.audioPlay( "fx_coin1" );
 }

 step += 1; // point to next step

 // If no more steps, nuke path

 if ( step >= path.length ) {
 path = null;
 }
 }

 G = {
 width : 15, // width of grid
 height : 15, // height of grid

 // Draw floor and initialize sprite

 drawMap : function () {
 var ptr, x, y, val;

 // Read map data to draw floor/walls

 PS.gridPlane( floorPlane );
 ptr = 0; // init data pointer
 for ( y = 0; y < G.height; y += 1 ) {
 for ( x = 0; x < G.width; x += 1 ) {
 val = myMap.data[ ptr ];
 if ( val === 0 ) { // wall
 PS.color( x, y, PS.COLOR_BLACK );
 }
 else { // random gray floor
 val = ( PS.random( 32 ) - 1 ) + 128;
 PS.color( x, y, val, val, val );
 }
 ptr += 1;
 }
 }

 // Create 1x1 solid green sprite for actor

 actorID = PS.spriteSolid( 1, 1 );
 PS.spriteSolidColor( actorID, PS.COLOR_GREEN );
 PS.spritePlane( actorID, actorPlane );
 PS.spriteMove( actorID, xpos, ypos );

 // Create 1x1 solid gold sprite for key
 // Place in opposite corner from sprite

 keyID = PS.spriteSolid( 1, 1 );
 PS.spriteSolidColor( keyID, PS.COLOR_YELLOW );
 PS.spritePlane( keyID, keyPlane );
 PS.spriteMove( keyID, kx, ky );

 // Create pathmap from our imageMap
 // for use by pathfinder

 mapID = PS.pathMap( myMap );

 // Start the timer function
 // Run at 10 frames/sec (every 6 ticks)

 PS.timerStart( 6, tick );
 },

 // move( x, y )
 // Set up new path

 move : function ( x, y ) {
 var line;

 // Calc a line from current position
 // to touched position

 line = PS.pathFind( mapID, xpos, ypos, x, y );

 // If line is not empty,
 // make it the new path
 // Otherwise hoot at player

 if ( line.length > 0 ) {
 path = line;
 step = 0; // start at beginning
 PS.audioPlay( "fx_click" );
 }
 else {
 PS.audioPlay( "fx_hoot" );
 }
 }
 };
}() );

// PS.init() and PS.touch() are unchanged; see above

Return value

PS.pathData() returns an array of integers indicating the current data in the specified region of the pathmap. The array contains (width * height) elements in ascending row order, beginning with the top-left corner of the region.

PS.ERROR is returned if an error occurs.

 

PS.pathDelete ( pathmap )

The PS.pathDelete() command lets you delete a pathmap object created by PS.pathMap().

The required pathmap parameter must be string uniquely identifying a pathmap object, of the type returned by PS.pathMap().

The specified pathmap is deleted from the engine, and its pathmap identifier becomes invalid. Subsequent use of the identifier with any pathmap command will cause an error.

// EXAMPLE
// Delete a previously created pathmap

PS.pathDelete( mapID );

Usage notes

1. The pathmaps created by PS.pathMap() require a surprising amount of memory. When you're done using a pathmap, call PS.pathDelete() to free resources.

Return value

PS.pathDelete() returns PS.DONE if the call succeeds, else PS.ERROR.

 

Terms to know

Next: Utilities