Learning 19: Sprites

This page describes the commands used to create, display and manipulate sprites.

 

Solid and image sprites

A sprite is a rectangular array of color/alpha values, ranging in dimensions from 1x1 upward. Perlenspiel supports two classes of sprites, solid and image.

Solid sprites

In a solid sprite, all of the color/alpha values in the array are the same.

[1x1 solid sprite] 1x1 solid sprite, gray and opaque.

[3x2 solid sprite] 3x2 solid sprite, red with 50% opacity.

Image sprites

In an image sprite, each value in the rectangular array can have a different color/alpha value. Such sprites can be thought of as tiny images, and they can be created using data loaded or captured with Perlenspiel's Image commands.

[4x4 image sprite] 4x4 image sprite, various colors, opaque.

[5x3 image sprite] 5x3 image sprite, some transparency.

Once created, a sprite can be displayed and moved around the grid using a handful of simple commands. When used together with grid planes, sprites can greatly simplify many engineering tasks, especially animation.

 

PS.spriteSolid ( width, height )

The PS.spriteSolid() command creates a solid black sprite with no transparency.

The required width and height parameters specify the dimensions of the sprite. They can be any positive integers. Values less than one (1) are clamped to 1. Non-integral values are floored.

If either parameter is PS.DEFAULT, the value one (1) is used.

// EXAMPLE
// Create a 3x3 solid sprite
// Save sprite ID for later reference

var mySprite;

mySprite = PS.spriteSolid( 3, 3 );

See the Demonstrations section below for interactive sample code.

Usage notes

1. By default, solid sprites are PS.COLOR_BLACK and PS.ALPHA_OPAQUE. You can change a solid sprite's color with PS.spriteSolidColor(), and its alpha transparency with PS.spriteSolidAlpha().

2. Newly created sprites are not located anywhere. Call PS.spriteMove() to position a sprite on the current grid plane.

3. By default, the positional axis of a sprite created with PS.spriteSolid() is set to the top left corner of the sprite's rectangle (0, 0). You can change this with PS.spriteAxis().

Return value

PS.spriteSolid() returns a string that uniquely identifies the new solid sprite. It can be passed into any Perlenspiel command expecting a solid sprite identifier.

PS.ERROR is returned if an error occurs.

 

PS.spriteSolidColor ( sprite, color )

The PS.spriteSolidColor() command changes the color of a solid sprite previously created by PS.spriteSolid().

The required sprite parameter must be unique sprite identifier of the type returned by PS.spriteSolid().

The optional color parameter can be supplied in any of the four Perlenspiel color expression formats.

If color is PS.DEFAULT, the default color (PS.COLOR_BLACK) is applied. If color is PS.CURRENT or not supplied, the color is not changed.

// EXAMPLE
// Create a 2x4 solid sprite
// Save sprite ID for later reference

var mySprite;

mySprite = PS.spriteSolid( 2, 4 );

// Color the sprite green

PS.spriteSolidColor( mySprite, PS.COLOR_GREEN );

See the Demonstrations section below for interactive sample code.

Return value

PS.spriteSolidColor() returns a RGB triplet integer indicating the current color of the sprite.

PS.ERROR is returned if an error occurs.

 

PS.spriteSolidAlpha ( sprite, alpha )

The PS.spriteSolidAlpha() command changes the alpha transparency of a solid sprite previously created by PS.spriteSolid().

The required sprite parameter should be unique sprite identifier of the type returned by PS.spriteSolid().

The optional alpha parameter specifies the alpha transparency of the sprite. It should be an integer between 0 (completely transparent) and 255 (fully opaque) inclusive. Values outside this range are clamped. Non-integral values are floored.

If alpha is PS.DEFAULT, the default alpha (PS.ALPHA_OPAQUE) is applied. If alpha is PS.CURRENT or not supplied, the alpha is not changed.

// EXAMPLE
// Create a 3x2 solid sprite
// Save sprite ID for later reference

var mySprite;

mySprite = PS.spriteSolid( 3, 2 );

// Change sprite's opacity to 50%

PS.spriteSolidAlpha( mySprite, 127 );

See the Demonstrations section below for interactive sample code.

Return value

PS.spriteSolidAlpha() returns an integer in the range 0-255 inclusive indicating the current alpha transparency of the sprite.

PS.ERROR is returned if an error occurs.

 

PS.spriteImage ( image, region )

The PS.spriteImage() command creates an image sprite from a previously defined imageData object.

The required image parameter specifies the imageData object that will be used to initialize the sprite.

The optional region parameter specifies a zero-based rectangular region inside the image that will be included in the sprite. More information is available in the API documentation.

If region is PS.DEFAULT or not supplied, the entire image is used for the sprite.

// EXAMPLE
// Load an image to be used as a sprite

var myImage, mySprite;

PS.imageLoad( "images/sprite.bmp", function (data) {
 myImage = data; // save image ID

 // Create an image sprite from the loaded image
 // Save sprite ID for later reference

 mySprite = PS.spriteImage( myImage );
} );

See the Demonstrations section below for interactive sample code.

Usage notes

1. Any alpha information present in the image passed into PS.spriteImage() will be preserved in the new sprite.

2. Newly created sprites are not located anywhere. Call PS.spriteMove() to position a sprite on the current grid plane.

3. By default, the positional axis of a sprite created with PS.spriteImage() is set to the top left corner of the sprite (0, 0). You can change this with a call to PS.spriteAxis().

Return value

PS.spriteImage() returns a string that uniquely identifies the new image sprite. It can be passed into any Perlenspiel function expecting a sprite identifier except PS.spriteSolidColor() or PS.spriteSolidAlpha(), which can only be used with solid sprites.

PS.ERROR is returned if an error occurs.

 

PS.spritePlane ( sprite, plane )

The PS.spritePlane() command changes the grid plane assigned to a sprite.

The required sprite parameter should be unique sprite identifier of the type returned by PS.spriteSolid() or PS.spriteImage().

The optional plane parameter can be any positive integer. Values less than one (1) are clamped to zero. Non-integral values are floored.

If plane is PS.DEFAULT, the default plane (0) is used. If plane is PS.CURRENT or not supplied, the plane is not changed.

// EXAMPLE
// Create a 2x2 solid sprite
// Save sprite ID for later reference

var mySprite;

mySprite = PS.spriteSolid( 2, 2 );

// Change sprite's plane to 3

PS.spritePlane( mySprite, 3 );

See the Demonstrations section below for interactive sample code.

Usage notes

1. Calls to PS.spritePlane() do not trigger collision events.

2. If you change the plane of an invisible sprite, or a sprite that has never been placed on the grid with PS.spriteMove(), there is no visible effect.

Return value

PS.spritePlane() returns an integer indicating the current sprite plane.

PS.ERROR is returned if an error occurs.

 

PS.spriteShow( sprite, show )

The PS.spriteShow() command controls the visibility of a sprite.

The required sprite parameter should be unique sprite identifier of the type returned by PS.spriteSolid() or PS.spriteImage().

If the optional show parameter is false or the number zero (0), the specified sprite becomes invisible:

If show is true or any nonzero number, the sprite becomes visible again. If no visual attributes were changed while it was invisible, it assumes its previous state.

Calling PS.spriteShow( sprite, true ) on a visible sprite has no effect. Similarly, calling PS.spriteShow( sprite, false ) on an invisible sprite has no effect.

If show is PS.DEFAULT, the default visibility (true, visible) is assigned to the sprite. If show is PS.CURRENT or not supplied, the visibility is not changed.

// EXAMPLE
// Create a 5x5 solid sprite
// Save sprite ID for later reference

var mySprite;

mySprite = PS.spriteSolid( 5, 5 );

// Make sprite invisible

PS.spriteShow( mySprite, false );

See the Demonstrations section below for interactive sample code.

Usage notes

1. Calling PS.spriteShow() on an invisible sprite will trigger a collision event if that sprite is touching or overlapping any other visible sprite.

Return value

PS.spriteShow() returns true if the specified sprite is currently visible, else false.

PS.ERROR is returned if an error occurs.

 

PS.spriteAxis ( sprite, x, y )

By default, the positional axis of a sprite is its top left corner (0, 0). The PS.spriteAxis() command lets you change the axis to any location on (or off) the sprite.

The required sprite parameter should be unique sprite identifier of the type returned by PS.spriteSolid() or PS.spriteImage().

The optional x and y parameters specify the location of the sprite's positional axis relative to the top left corner of the sprite (0, 0). They can be any positive or negative integers. Non-integral values are floored.

If x or y are PS.DEFAULT, the default value zero (0) is used.

If x or y are PS.CURRENT or not supplied, the positional axis is not changed.

// EXAMPLE
// Create a 5x5 solid sprite
// Save sprite ID for later reference

var mySprite;

mySprite = PS.spriteSolid( 5, 5);

// Change positional axis to center of sprite

PS.spriteAxis( mySprite, 2, 2 );

See the Demonstrations section below for interactive sample code.

Usage notes

1. The axis of a sprite can placed anywhere, even outside the boundaries of the sprite. However, it's possible that some or all of the sprite may not be visible when the sprite is subsequently moved.

2. Changing the axis of a visible sprite will trigger a collision event if the repositioned sprite touches or overlaps any other visible sprite.

Return value

PS.spriteAxis() returns an object containing the following properties:

The .x and .y properties specify the location of the sprite's positional axis, relative to the top left corner of the sprite (0, 0).

PS.ERROR is returned if an error occurs.

 

PS.spriteMove ( sprite, x, y )

The PS.spriteMove() command lets you place or change the location of a sprite in its current grid plane.

The required sprite parameter should be unique sprite identifier of the type returned by PS.spriteSolid() or PS.spriteImage().

The optional x and y parameters specify the zero-based location of the sprite's positional axis on the current grid plane. They can be any positive or negative integers. Non-integral values are floored.

If x or y are PS.DEFAULT, the default value (0) is used for the corresponding coordinate.

If x or y are PS.CURRENT or not supplied, the corresponding coordinate is not changed.

// EXAMPLE
// Create a 1x1 solid sprite
// Save sprite ID for later reference

var mySprite;

mySprite = PS.spriteSolid( 1, 1 );

// Move sprite to 3, 3

PS.spriteMove( mySprite, 3, 3 );

See the Demonstrations section below for interactive sample code.

Usage notes

1. When a sprite is moved, the beads it previously occupied on the current grid plane become transparent (alpha = 0), and their color is set to PS.COLOR_WHITE.

2. The values of x and y can be set outside the boundaries of the grid if desired. However, it's possible that some or all of the sprite may not be visible.

3. Moving a visible sprite will cause a collision event if the moved sprite touches or overlaps any other visible sprite.

4. If an invisible sprite is moved, its coordinates are still updated, and it will appear at the new position when subsequently made visible.

Return value

PS.spriteMove() returns an object containing the following properties:

The .x and .y properties specify the current coordinates of the sprite's positional axis on the grid.

PS.ERROR is returned if an error occurs.

 

PS.spriteCollide ( sprite, exec )

The PS.spriteCollide() command lets you specify a function that will be called when a visible sprite touches or overlaps any other visible sprite.

The required sprite parameter should be unique sprite identifier of the type returned by PS.spriteSolid() or PS.spriteImage().

The optional exec parameter specifies a function that will be called when any call to PS.spriteMove(), PS.spriteShow() or PS.spriteAxis() causes the specified sprite to touch or collide with any other visible sprite, whether or not the sprites occupy the same grid plane.

The exec function should expect at least five arguments, as follows:

function collide( s1, p1, s2, p2, type ) {};

The first argument, s1, is set to sprite.

The second argument, p1, is set to the grid plane currently occupied by sprite.

The third argument, s2, is set to the unique identifier of the colliding sprite.

The fourth argument, p2, is set to the grid plane currently occupied by the colliding sprite.

The fifth argument, type, is set to the constant PS.SPRITE_TOUCH if any edge of the colliding sprite is immediately adjacent to any edge of sprite, or PS.SPRITE_OVERLAP if any region of the colliding sprite overlaps any region of sprite.

If exec is null or PS.DEFAULT, the default value (null, no collision function) is used.

If exec is PS.CURRENT or not supplied, the collision function is not changed.

// EXAMPLE
// Create a 1x1 solid sprite
// Save sprite ID for later reference

var mySprite;

mySprite = PS.spriteSolid( 1, 1 );

// Define a collision function

var myFunc = function ( s1, p1, s2, p2, type ) {
 PS.statusText( s1 + " collided with " + s2 + "!" );
};

// Assign collision function to sprite

PS.spriteCollide( mySprite, myFunc );

See the Demonstrations section below for interactive sample code.

Usage notes

1. If any call to PS.spriteMove(), PS.spriteShow() or PS.spriteAxis() results in a sprite collision, every sprite involved in the collision that has a collision function assigned to it will have that function called once for each colliding sprite.

2. When you change a visible sprite's collision function, that function is called immediately if the sprite is currently in a collision state with another visible sprite.

Return value

PS.spriteCollide() returns the collision function currently assigned to sprite, or null if no function is assigned.

PS.ERROR is returned if an error occurs.

 

PS.spriteDelete ( sprite )

The PS.spriteDelete() command deletes the data associates with a sprite, immediately removing that sprite from the grid if it is visible.

The required sprite parameter should be unique sprite identifier of the type returned by PS.spriteSolid() or PS.spriteImage().

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

// EXAMPLE
// Create a 2x2 solid sprite
// Save sprite ID for later reference

var mySprite;

mySprite = PS.spriteSolid( 1, 1 );

// Delete the sprite

PS.spriteDelete( mySprite );

Return value

PS.spriteDelete() returns PS.DONE on success, else PS.ERROR.

 

Demonstrations

The following series of demonstrations show how the sprite commands can be used to implement common animation effects.

Demonstration 1: Moving a solid sprite

This first demo creates a 15x15 floor of random gray beads, then creates a solid 3x3 red sprite in grid plane 1. Use the arrow/WASD keys to move the sprite around.

Notice that it's possible to move the sprite completely off the grid.

[Run Demo]

var G; // establish game namespace

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

 var floorPlane = 0;
 var spritePlane = 1;

 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 3x3 solid sprite, save its ID

 id = PS.spriteSolid( 3, 3 );

 // Set color to red

 PS.spriteSolidColor( id, PS.COLOR_RED );

 // Set plane to 1 (above floor)

 PS.spritePlane( id, spritePlane );

 // Position sprite at center of grid

 PS.spriteMove( id, xpos, ypos );
 },

 // move( x, y )
 // Move sprite relative to current position

 move : function ( x, y ) {
 xpos = xpos + x;
 ypos = ypos + y;
 PS.spriteMove( id, xpos, ypos );
 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(); // draws walls
 PS.audioLoad( "fx_click" ); // preload sound
 PS.statusText( "Use arrow/WASD keys to move" );
};

PS.keyDown = function( key, shift, ctrl, options ) {
 switch ( key ) {
 case PS.KEY_ARROW_UP:
 case 119: // lower-case w
 case 87: // upper-case W
 {
 G.move( 0, -1 );
 break;
 }
 case PS.KEY_ARROW_DOWN:
 case 115: // lower-case s
 case 83: // upper-case S
 {
 G.move( 0, 1 );
 break;
 }
 case PS.KEY_ARROW_LEFT:
 case 97: // lower-case a
 case 65: // upper-case A
 {
 G.move( -1, 0 );
 break;
 }
 case PS.KEY_ARROW_RIGHT:
 case 100: // lower-case d
 case 68: // upper-case D
 {
 G.move( 1, 0 );
 break;
 }
 }
};

Demonstration 2: Solid sprite with alpha

Here's the same demo with one line of code added, to show how alpha transparency works with solid sprites.

[Run Demo]

// Set color to red

PS.spriteSolidColor( id, PS.COLOR_RED );
PS.spriteSolidAlpha( id, 64 ); // 25% opacity

Demonstration 3: Creating an image sprite

[11x11 sprite] 3x3.bmp, magnified to 128 x 128 pixels.

Here's the same demo again, this time using an image sprite initialized from 3x3.bmp, a 3x3 image file.

[Run Demo]

var G; // establish game namespace
( function () {
 var id; // sprite identifier
 var xpos = 6; // x-pos of sprite
 var ypos = 6; // y-pos of sprite

 var floorPlane = 0;
 var spritePlane = 1;

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

 // Draw floor and initialize sprite

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

 // 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 );
 }
 }

 // Define a loader for the image file
 // It uses the loaded image data to
 // initialize an image sprite and move it
 // to the correct grid plane and location

 loader = function ( data ) {
 id = PS.spriteImage( data );
 PS.spritePlane( id, spritePlane );
 PS.spriteMove( id, xpos, ypos );
 };

 // Load the image

 PS.imageLoad( "images/3x3.bmp", loader );
 },

 // move( x, y )
 // Move sprite relative to current position

 move : function ( x, y ) {
 xpos = xpos + x;
 ypos = ypos + y;

 PS.spriteMove( id, xpos, ypos );
 PS.audioPlay( "fx_click" );
 }
 };
}() );

// PS.init() and PS.keyDown() are unchanged

Demonstration 4: Image sprite with alpha

[11x11 sprite] happy.png, magnified to 110 x 110 pixels.

Same demo, using an image sprite initialized from happy.png, an 11x11 image file containing alpha transparency. One way to create "shaped" sprites.

[Run Demo]

// Only the file being loaded and
// its initial position have changed

var xpos = 2; // x-pos of sprite
var ypos = 2; // y-pos of sprite


...

PS.imageLoad( "images/happy.png", loader );

Demonstration 5: Sprite collision

In this final demo, two solid sprites are created, a blue square on plane 1 and a semi-transparent green square on plane 2. Use the arrow/WASD keys to move the green sprite around and "over" the blue sprite. A collision function reports when the sprites touch or overlap.

[Run Demo]

var G; // establish game namespace

( function () {
 var id1; // sprite 1 identifier
 var id2; // sprite 2 identifier
 var xpos = 3; // x-pos of sprite 2
 var ypos = 6; // y-pos of sprite 2

 var floorPlane = 0;
 var s1Plane = 1;
 var s2Plane = 2;

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

 // Draw floor and initialize sprite

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

 // 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 3x3 solid blue sprite
 // Place on plane 1 at right side of grid

 id1 = PS.spriteSolid( 3, 3 );
 PS.spriteSolidColor( id1, PS.COLOR_BLUE );
 PS.spritePlane( id1, s1Plane );
 PS.spriteMove( id1, 9, 6 );

 // Create 3x3 solid green sprite
 // with 50% alpha transparency
 // Place on plane 2 at left side of grid

 id2 = PS.spriteSolid( 3, 3 );
 PS.spriteSolidColor( id2, PS.COLOR_GREEN );
 PS.spriteSolidAlpha( id2, 127 );
 PS.spritePlane( id2, s2Plane );
 PS.spriteMove( id2, xpos, ypos );

 // Assign collision function to sprite 2

 reporter = function ( s1, p1, s2, p2, type ) {
 if ( type === PS.SPRITE_TOUCH ) {
 type = " touched "
 }
 else {
 type = " overlapped ";
 }
 PS.statusText( s1 + type + s2 );
 }
 PS.spriteCollide( id2, reporter );
 },

 // move( x, y )
 // Move sprite relative to current position

 move : function ( x, y ) {
 PS.statusText( "" ); // clear
 xpos = xpos + x;
 ypos = ypos + y;
 PS.spriteMove( id2, xpos, ypos );
 PS.audioPlay( "fx_click" );
 }
 };
}() );

// PS.init() and PS.keyDown are unchanged

 

Terms to know

Next: Lines and paths