Using the Sprite Toolbox to Create Sprite Animations

This chapter discusses the sprite toolbox and how you can use it to add sprite-based animation to an application. The chapter is aimed at developers who are using the low-level sprite toolbox APIs to create sprite animations in their applications–– not in a QuickTime movie.

The chapter is divided into these sections:

Overview of Sprite Toolbox

The sprite toolbox is a set of data types and functions you can use to add sprite-based animation to an application. The sprite toolbox handles the following:

If you’re authoring an animation outside of a movie, you use the sprite toolbox to create sprite worlds and sprite animations. For more information about the constants and data types available to your application in the sprite toolbox, refer to

To create a sprite track in a QuickTime movie, you create media samples used by the sprite media handler, which, in turn, makes use of the sprite toolbox. Chapter 3, Sprite Media Handler, provides information on how to use the sprite media handler.

How To Add Sprite-Based Animations to an Application

The following section discusses how you can use the sprite toolbox to create sprite worlds and sprite animations. It is divided into these topics:

Creating and Initializing a Sprite World

To create a sprite animation in an application, you first create a sprite world to contain your sprites. To do this, you perform the following steps:

  1. Allocate a sprite layer graphics world that corresponds to the size and bit depth of your destination graphics world.

  2. If you plan to have a background image behind your sprites that is static or that changes infrequently, create a background graphics world that is the same size and depth as the sprite layer graphics world. You do not need to do this if you plan to have a solid background color behind your sprites. Animations that use a solid background color require less memory and perform slightly better than animations that use a background image.

  3. Call LockPixels on the pixel maps of the sprite layer and background graphics worlds. These graphics worlds must remain valid for the lifetime of the sprite world.

  4. Call the NewSpriteWorld function to create the new sprite world.

The sample code function CreateSpriteStuff, shown in Listing 5-1, calculates the bounds of the destination window and calls NewGWorld to create a new sprite layer graphics world. It then calls LockPixels to lock the pixel map of the sprite layer graphics world.

Next, CreateSpriteStuff calls NewSpriteWorld to create a new sprite world, passing the destination graphics world (WindowPtr) and the sprite layer graphics world. CreateSpriteStuff passes a background color to NewSpriteWorld instead of specifying a background graphics world. The newly created sprite world is returned in the global variable gSpriteWorld.

Finally, CreateSpriteStuff calls the sample code function CreateSprites to populate the sprite world with sprites.

Listing 5-1  Creating a sprite world

// global variables
GWorldPtr spritePlane = nil;
SpriteWorld gSpriteWorld = nil;
Rect gBounceBox;
RGBColor gBackgroundColor;
 
void CreateSpriteStuff (Rect *windowBounds, CGrafPtr windowPtr)
{
    OSErr err;
    Rect bounds;
 
    // calculate the size of the destination
    bounds = *windowBounds;
    OffsetRect (&bounds, -bounds.left, -bounds.top);
    gBounceBox = bounds;
    InsetRect (&gBounceBox, 16, 16);
 
    // create a sprite layer graphics world with a bit depth of 16
    NewGWorld (&spritePlane, 16, &bounds, nil, nil, useTempMem);
    if (spritePlane == nil)
        NewGWorld (&spritePlane, 16, &bounds, nil, nil, 0);
 
    if (spritePlane)
    {
        LockPixels (spritePlane->portPixMap);
        gBackgroundColor.red = gBackgroundColor.green =
            gBackgroundColor.blue = 0;
 
        // create a sprite world
        err = NewSpriteWorld (&gSpriteWorld, (CGrafPtr)windowPtr,
                                spritePlane, &gBackgroundColor, nil);
 
        // create sprites
        CreateSprites ();
    }
}

Creating and Initializing Sprites

Once you have created a sprite world, you can create sprites within it. To do this, you must first obtain image descriptions and image data for your sprites. This image data may be any image data that has been compressed using QuickTime’s Image Compression Manager.

You create sprites and add them to your sprite world using the NewSprite function. If you want to create a sprite that is drawn to the background graphics world, you should specify the constant kBackgroundSpriteLayerNum for the layer parameter.

Creating Sprites for a Sample Application

The sample code function CreateSprites, shown in Listing 5-2, creates the sprites for the sample application shown in Listing 5-1.

First, the function initializes some global arrays with position and image information for the sprites. Next, CreateSprites iterates through all the sprite images, preparing each image for display. For each image, CreateSprites calls the sample code function MakePictTransparent function, which strips any surrounding background color from the image. MakePictTransparent does this by using the animation compressor to recompress the PICT images using a key color. Then, CreateSprites calls ExtractCompressData, which extracts the compressed data from the PICT image. This is one technique for creating compressed images; there are other, more optimized ways to store and retrieve sprite images.

Once the images have been prepared, CreateSprites calls NewSprite to create each sprite in the sprite world. CreateSprites creates each sprite in a different layer.

Listing 5-2  Creating sprites

// constants
#define kNumSprites 4
#define kNumSpaceShipImages 24
#define kBackgroundPictID 158
#define kFirstSpaceShipPictID (kBackgroundPictID + 1)
#define kSpaceShipWidth 106
#define kSpaceShipHeight 80
 
// global variables
SpriteWorld gSpriteWorld = nil;
Sprite gSprites[kNumSprites];
Rect gDestRects[kNumSprites];
Point gDeltas[kNumSprites];
short gCurrentImages[kNumSprites];
Handle gCompressedPictures[kNumSpaceShipImages];
ImageDescriptionHandle gImageDescriptions[kNumSpaceShipImages];
 
void CreateSprites (void)
{
    long i;
    Handle compressedData = nil;
    PicHandle picture;
    CGrafPtr savePort;
    GDHandle saveGD;
    OSErr err;
    RGBColor keyColor;
 
    SetRect (&gDestRects[0], 132, 132, 132 + kSpaceShipWidth,
        132 + kSpaceShipHeight);
    SetRect (&gDestRects[1], 50, 50, 50 + kSpaceShipWidth,
        50 + kSpaceShipHeight);
    SetRect (&gDestRects[2], 100, 100, 100 + kSpaceShipWidth,
        100 + kSpaceShipHeight);
    SetRect (&gDestRects[3], 130, 130, 130 + kSpaceShipWidth,
        130 + kSpaceShipHeight);
 
    gDeltas[0].h = -3;
    gDeltas[0].v = 0;
    gDeltas[1].h = -5;
    gDeltas[1].v = 3;
    gDeltas[2].h = 4;
    gDeltas[2].v = -6;
    gDeltas[3].h = 6;
    gDeltas[3].v = 4;
 
    gCurrentImages[0] = 0;
    gCurrentImages[1] = kNumSpaceShipImages / 4;
    gCurrentImages[2] = kNumSpaceShipImages / 2;
    gCurrentImages[3] = kNumSpaceShipImages * 4 / 3;
 
    keyColor.red = keyColor.green = keyColor.blue = 0xFFFF;
 
    // recompress PICT images to make them transparent
    for (i = 0; i < kNumSpaceShipImages; i++)
    {
        picture = (PicHandle) GetPicture (i + kFirstSpaceShipPictID);
        DetachResource ((Handle)picture);
 
        MakePictTransparent (picture, &keyColor);
        ExtractCompressData (picture, &gCompressedPictures[i],
            &gImageDescriptions[i]);
        HLock (gCompressedPictures[i]);
 
        KillPicture (picture);
    }
 
    // create the sprites for the sprite world
    for (i = 0; i < kNumSprites; i++)
    {
        MatrixRecord matrix;
 
        SetIdentityMatrix (&matrix);
 
        matrix.matrix[2][0] = ((long)gDestRects[i].left << 16);
        matrix.matrix[2][1] = ((long)gDestRects[i].top << 16);
 
        err = NewSprite (&(gSprites[i]), gSpriteWorld,
            gImageDescriptions[i],* gCompressedPictures[i],
            &matrix, true, i);
    }
}

Animating Sprites

To animate a sprite, you use the SetSpriteProperty function to change one or more of the sprite’s properties, such as its matrix, layer, or image data. In addition to modifying a property, SetSpriteProperty invalidates the appropriate areas of the sprite’s sprite world.

The SpriteWorldIdle function is responsible for redrawing a sprite world’s invalid regions. Your application should call this function after modifying sprite properties to give the sprite world the opportunity to redraw.

Listing 5-3 shows the sample application’s main function. It performs all of the application’s initialization tasks, including initializing the sprite world and its sprites. It displays the window and loops until the user clicks the button in the window. To perform the animation, main calls the sample code function MoveSprites each time through the loop, to modify the properties of the sprites, and then calls SpriteWorldIdle to give the sprite world the opportunity to redraw its invalid areas.

Listing 5-3  The main function

// global variables
SpriteWorld gSpriteWorld = nil;
 
void main (void)
{
 
    // ...
    // initialize everything and create a window
    // create a sprite world and the sprites in it
    // show the window
    // ...
    CreateSpriteStuff(...);
    while (!Button())
    {
        // animate the sprites
        MoveSprites ();
        SpriteWorldIdle (gSpriteWorld, 0, 0);
    }
 
    // ...
    // dispose of the sprite world and its sprites
    // shut down everything else
    // ...
    DisposeEverything();
}

The MoveSprites function, shown in Listing 5-4, is responsible for modifying the properties of the sprites. For each sprite, the function calls SetSpriteProperty twice, once to change the sprite’s matrix and once to change the sprite’s image data pointer.

Listing 5-4  Animating sprites

// constants
#define kNumSprites 4
#define kNumSpaceShipImages 24
 
// global variables
Rect gBounceBox;
Sprite gSprites[kNumSprites];
Rect gDestRects[kNumSprites];
Point gDeltas[kNumSprites];
short gCurrentImages[kNumSprites];
Handle gCompressedPictures[kNumSpaceShipImages];
 
void MoveSprites (void)
{
    short i;
    MatrixRecord matrix;
 
    SetIdentityMatrix (&matrix);
 
    // for each sprite
    for (i = 0; i < kNumSprites; i++)
    {
        // modify the sprite’s matrix
        OffsetRect (&gDestRects[i], gDeltas[i].h, gDeltas[i].v);
 
        if ( (gDestRects[i].right >= gBounceBox.right) ||
            (gDestRects[i].left <= gBounceBox.left) )
            gDeltas[i].h = -gDeltas[i].h;
 
        if ( (gDestRects[i].bottom >= gBounceBox.bottom) ||
            (gDestRects[i].top <= gBounceBox.top) )
            gDeltas[i].v = -gDeltas[i].v;
 
        matrix.matrix[2][0] = ((long)gDestRects[i].left << 16);
        matrix.matrix[2][1] = ((long)gDestRects[i].top << 16);
 
        SetSpriteProperty (gSprites[i], kSpritePropertyMatrix, &matrix);
 
        // change the sprite’s image
        gCurrentImages[i]++;
        if (gCurrentImages[i] >= (kNumSpaceShipImages * (i+1)))
            gCurrentImages[i] = 0;
        SetSpriteProperty (gSprites[i], kSpritePropertyImageDataPtr,
            *gCompressedPictures[gCurrentImages[i] / (i+1)] );
    }
}

Disposing of a Sprite Animation

When your application has finished displaying a sprite animation, you should do the following things in the order shown:

  1. Dispose of the sprite world associated with the animation. (You need to do this first.) Disposing of a sprite world automatically destroys the sprites in the sprite world.

  2. Dispose of the sprite image data.

  3. Dispose of graphics worlds associated with the sprite animation.

In the sample application, main calls the sample code function DisposeEverything to dispose of sprite-related structures. This function, shown in Listing 5-5, iterates through the sprites, disposing of each sprite’s image data. Then, DisposeEverything calls DisposeSpriteWorld to dispose of the sprite world and all of the sprites in it. Finally, the function calls DisposeGWorld to dispose of the graphics world associated with the sprite world.

Listing 5-5  Disposing of sprites and the sprite world

// constants
#define kNumSprites 4
#define kNumSpaceShipImages 24
 
// global variables
SpriteWorld gSpriteWorld = nil;
Sprite gSprites[kNumSprites];
Handle gCompressedPictures[kNumSpaceShipImages];
ImageDescriptionHandle gImageDescriptions[kNumSpaceShipImages];
 
void DisposeEverything (void)
{
    short i;
    // dispose of the sprite world and associated graphics world
    if (gSpriteWorld)
        DisposeSpriteWorld (gSpriteWorld);
 
    // dispose of each sprite’s image data
    for (i = 0; i < kNumSprites; i++)
    {
        if (gCompressedPictures[i])
            DisposeHandle (gCompressedPictures[i]);
        if (gImageDescriptions[i])
            DisposeHandle ((Handle)gImageDescriptions[i]);
    }
    DisposeGWorld (spritePlane);
}

Sprite Hit-Testing

The sprite toolbox provides two functions for performing hit-testing operations with sprites, SpriteWorldHitTest and SpriteHitTest.

The SpriteWorldHitTest function determines whether any sprites exist at a specified location in a sprite world’s display coordinate system. This function retrieves the frontmost sprite at the specified location.

The SpriteHitTest function determines whether a particular sprite exists at a specified location in the sprite’s display coordinate system. This function is useful for hit-testing a subset of the sprites in a sprite world and for detecting multiple sprites at a single location.

For either hit-test function, there are two flags, spriteHitTestBounds and spriteHitTestImage, that control the hit-test operation. For example, you set the spriteHitTestBounds flag to check if there has been a hit anywhere within the sprite’s bounding box, and you set the spriteHitTestImage flag to check if there has been a hit anywhere within the sprite image.

Hit-Testing Flags

The following hit-testing flags are used with both the sprite toolbox and the movie sprite track hit-testing routines:

  • spriteHitTestInvisibleSprites, which you set if you want invisible sprites to be hit-tested along with visible ones.

  • spriteHitTestLocInDisplayCoordinates, which you set if the hit-testing point is in display coordinates instead of local sprite track coordinates.

  • spriteHitTestIsClick, which you set if you want the hit-testing operation to pass a click on to the codec currently rendering the sprites image. For example, this can be used to make the Ripple Codec ripple.

Enhancing Sprite Animation Performance

To achieve the best performance for your sprite animation, you should observe the following guidelines when creating a sprite world:

  • When you create a graphics world to be used for your sprite world, you achieve the best performance if the graphics world’s dimensions are a multiple of 16 pixels.

  • Your sprite layer graphics world and background graphics world should both be the same size and depth as the destination of your sprite animation.

  • Use translation-only matrices for creating sprite worlds and sprites.

  • Do not set a clipping region for your sprite world.

  • Call the SpriteWorldIdle function frequently.

  • Avoid clipping sprites with the sprite world boundary.

  • Use the Animation compressor to create sprites with transparent areas.

Constants and Functions in the Sprite Toolbox

This section describes some of the constants and functions that are useful and available to your application in the sprite toolbox. It also describes functions provided by the Movie Toolbox for sprite support. The section is not all-inclusive. For a complete list of functions, refer to the QuickTime API Reference (see bibliography).

Constants

Background Sprites

You assign the following constant to a sprite’s kSpritePropertyLayer property to designate the sprite as a background sprite.

enum {
    kBackgroundSpriteLayerNum   = 32767
};

Flags for Sprite Hit-Testing

You can pass the following flags to control sprite hit-testing.

enum {
    spriteHitTestBounds                 = 1L << 0,
    spriteHitTestImage                  = 1L << 1
    spriteHitTestInvisibleSprites       = 1L << 2,
    spriteHitTestIsClick                = 1L << 3,
    spriteHitTestLocInDisplayCoordinates  = 1L << 4
};
spriteHitTestBounds

The specified location must be within the sprite’s bounding box.

spriteHitTestImage

If both this flag and spriteHitTestBounds are set, the specified location must be within the shape of the sprite’s image.

spriteHitTestInvisibleSprites

This flag enables invisible sprites to be hit-tested.

spriteHitTestIsClick

This flag is for codecs that want mouse events, such as the ripple codec.

spriteHitTestLocInDisplayCoordinates

You set this flag if you want to pass a display coordinate point to SpriteHitTest, such as returned by the Mac OS Toolbox routine getMouse.

Sprite Properties

The following constants represent the different properties of a sprite. When you call SetSpriteProperty to set a sprite property, you pass one of these constants to specify the property you wish to modify.

enum {
    kSpritePropertyMatrix                   = 1,
    kSpritePropertyImageDescription         = 2,
    kSpritePropertyImageDataPtr             = 3,
    kSpritePropertyVisible                  = 4,
    kSpritePropertyLayer                    = 5,
    kSpritePropertyGraphicsMode             = 6,
    kSpritePropertyImageIndex               = 100
};
kSpritePropertyMatrix

A matrix of type MatrixRecord that defines the sprite’s display coordinate system.

kSpritePropertyImageDescription

An image description handle that describes the sprite’s image data. This must be valid as long as the sprite uses it. The caller owns the storage. The sprite toolbox does not copy this data.

kSpritePropertyImageDataPtr

A pointer to the sprite’s image data. This must be valid as long as the sprite uses it. The caller owns the storage. The sprite toolbox does not copy this data.

kSpritePropertyVisible

A Boolean value that indicates whether the sprite is visible.

kSpritePropertyLayer

A short integer value that defines the sprite’s layer. You set this property to kBackgroundSpriteLayerNum to designate the sprite as a background sprite.

kSpritePropertyGraphicsMode

A ModifierTrackGraphicsModeRecord value that specifies the graphics mode to be used when drawing the sprite.

kSpritePropertyImageIndex

In a sprite track, the index of the sprite’s image in the pool of shared images.

Flags for SpriteWorldIdle

You can pass the following flags as input to SpriteWorldIdle to control drawing of the sprite world.

enum {
    kOnlyDrawToSpriteWorld  = 1L << 0,
    kSpriteWorldPreFlight   = 1L << 1
};
kOnlyDrawToSpriteWorld

You set this flag to indicate that drawing should take place in the sprite world only; drawing to the final destination should be suppressed.

kSpriteWorldPreFlight

You can set this flag to determine whether the sprite world has any invalid areas that need to be drawn. If so, the SpriteWorldIdle function returns the kSpriteWorldNeedsToDraw flag in the flagsOut parameter.

The following flags may be returned in the flagsOut parameter of SpriteWorldIdle.

enum {
    kSpriteWorldDidDraw         = 1L << 0,
    kSpriteWorldNeedsToDraw     = 1L << 1
};
kSpriteWorldDidDraw

If set, this flag indicates that SpriteWorldIdle updated the sprite world.

kSpriteWorldNeedsToDraw

If set, this flag indicates that the sprite world has invalid areas that need to be drawn.

Sprite and Sprite World Identifiers

The sprite world and sprite data structures are private data structures. You identify a sprite world or a sprite data structure to the sprite toolbox by means of a data type that is supplied by the sprite toolbox. The following data types are currently defined:

Sprite

Specifies the sprite for an operation. Your application obtains a sprite identifier when you create a new sprite by calling NewSprite.

SpriteWorld

Specifies the sprite world for an operation. Your application obtains a sprite world identifier when you create a sprite world by calling NewSpriteWorld .

Useful Sprite Toolbox Functions

This section describes the functions provided by the Movie Toolbox for sprite support. It also describes some of the functions that you can use to create and manipulate sprites and sprite worlds.

NewSpriteWorld

You call the NewSpriteWorld function to create a new sprite world with associated destination and sprite layer graphics worlds, and either a background color or a background graphics world. Once created, you can manipulate the sprite world and add sprites to it using other sprite toolbox functions. The sprite world created by this function has an identity matrix. The sprite world does not have a clip shape.

pascal OSErr NewSpriteWorld (SpriteWorld *newSpriteWorld,                             GWorldPtrdestination,                             GWorldPtr spriteLayer,
                            RGBColor *backgroundColor,
                            GWorldPtr background);

The newSpriteWorld, destination, and spriteLayer parameters are all required. You should specify a background color, a background graphics world, or both. You should not pass nil for both parameters. If you specify both a background graphics world and a background color, the sprite world is filled with the background color before the background sprites are drawn. If no background color is specified, black is the default. If you specify a background graphics world, it should have the same dimensions and depth as the graphics world specified by spriteLayer. If you draw to the graphics worlds associated with a sprite world using standard QuickDraw and QuickTime functions, your drawing is erased by the sprite world’s background color.

Before calling NewSpriteWorld, you should call LockPixels on the pixel maps of the sprite layer and background graphics worlds. These graphics worlds must remain valid and locked for the lifetime of the sprite world. The sprite world does not own the graphics worlds that are associated with it; it is the caller’s responsibility to dispose of the graphics worlds when they are no longer needed.

DisposeSpriteWorld

You call the DisposeSpriteWorld function to dispose of a sprite world created by the NewSpriteWorld function. This function also disposes of all of the sprites associated with the sprite world. This function does not dispose of the graphics worlds associated with the sprite world. It is safe to pass nil to this function.

pascal void DisposeSpriteWorld  (SpriteWorld theSpriteWorld);

SetSpriteWorldClip

You call the SetSpriteWorldClip function to change the clip shape of a sprite world. You may pass a value of nil for the clipRgn parameter to indicate that there is no longer a clip shape for the sprite world. This means that the whole area is drawn.

The clip shape should be specified in the sprite world’s source space, the coordinate system of the sprite layer’s graphics world before the sprite world’s matrix is applied to it. The specified region is owned by the caller and is not copied by this function.

pascal OSErr SetSpriteWorldClip (SpriteWorld theSpriteWorld, RgnHandle                                 clipRgn);

SetSpriteWorldMatrix

You call the SetSpriteWorldMatrix function function to change the matrix of a sprite world. You may pass a value of nil for the matrix parameter to set the sprite world’s matrix to an identity matrix. Transformations, including translation, scaling, rotation, skewing, and perspective, are all supported in QuickTime.

SpriteWorldIdle

You call the SpriteWorldIdle function function to allow a sprite world the opportunity to redraw its invalid areas. This is the only function that causes drawing to occur; you should call it as often as is necessary.

The flagsIn parameter contains flags that describe allowable actions during the idle period. For the default behavior, you should set the value of this parameter to 0. The flagsOut parameter is optional; if you do not need the information returned by this parameter, set the value of this parameter to nil.

Typically, you would make changes in perspective for a number of sprites and then call SpriteWorldIdle to redraw the changed sprites.

InvalidateSpriteWorld

Typically, your application calls the InvalidateSpriteWorld function function when the sprite world’s destination window receives an update event. Invalidating an area of the sprite world will cause the area to be redrawn the next time that SpriteWorldIdle is called.

The invalid rectangle pointed to by the invalidArea parameter should be specified in the sprite world’s source space, the coordinate system of the sprite layer’s graphics world before the sprite world’s matrix is applied to it. To invalidate the entire sprite world, pass nil for this parameter.

When you modify sprite properties, invalidation takes place automatically; you do not need to call InvalidateSpriteWorld.

SpriteWorldHitTest

You call the SpriteWorldHitTest function to determine whether any sprites exist at a specified location in a sprite world’s display coordinate system. If you are drawing the sprite world in a window, you should call GlobalToLocal to convert the location to your window’s local coordinate system before passing it to SpriteWorldHitTest.

You use the spriteHitTestBounds and spriteHitTestImage flags in the flags parameter to control the hit-test operation. Set the spriteHitTestBounds flag to check if there has been a hit anywhere within the sprite’s bounding box. Set the spriteHitTestImage flag to check if there has been a hit anywhere within the sprite image.

A hit-testing operation does not occur unless you pass one of the flags, either SpriteHitTestBound or SpriteHitTestImage. You can add other flags as needed.

DisposeAllSprites

The DisposeAllSprites function disposes all sprites associated with a sprite world.

NewSprite

You call the NewSprite function to create a new sprite associated with a sprite world. Once you have created the sprite, you can manipulate it using SetSpriteProperty.

The newSprite, itsSpriteWorld, visible, and layer parameters are required. Sprites with lower layer values appear in front of sprites with higher layer values. If you want to create a sprite that is drawn to the background graphics world, you should specify the constant kBackgroundSpriteLayerNum for the layer parameter.

You can defer assigning image data to the sprite by passing nil for both the idh and imageDataPtr parameters. If you choose to defer assigning image data, you must call SetSpriteProperty to assign the image description handle and image data to the sprite before the next call to SpriteWorldIdle. The caller owns the image description handle and the image data pointer; it is the caller’s responsibility to dispose of them after it disposes of a sprite.

DisposeSprite

You call the DisposeSprite function to dispose of a sprite created by the NewSprite function. The image description handle and image data pointer associated with the sprite are not disposed by this function.

InvalidateSprite

The InvalidateSprite function invalidates the portion of a sprite’s sprite world that is occupied by the sprite.

pascal void InvalidateSprite  (Sprite theSprite);

In most cases, you don’t need to call this function. When you call the SetSpriteProperty function to modify a sprite’s properties, SetSpriteProperty takes care of invalidating the appropriate regions of the sprite world. However, you might call this function if you change a sprite’s image data, but retain the same image data pointer.

SpriteHitTest

The SpriteHitTest function determines whether a location in a sprite’s display coordinate system intersects the sprite. You call this function to determine whether a sprite exists at a specified location in the sprite’s display coordinate system. This function is useful for hit-testing a subset of the sprites in a sprite world and for detecting multiple hits for a single location.

You should apply the sprite world’s matrix to the location before passing it to SpriteHitTest. To convert a location to local coordinates, you should use the GlobalToLocal function to convert the location to your window’s local coordinate system and then apply the inverse of the sprite world’s matrix to the location.

You use the spriteHitTestBounds and spriteHitTestImage flags in the flags parameter to control the hit-test operation. Set the spriteHitTestBounds flag to check if there has been a hit anywhere within the sprite’s bounding box. Set the spriteHitTestImage flag to check if there has been a hit anywhere within the sprite image.

GetSpriteProperty

The GetSpriteProperty function retrieves the value of the specified sprite property. You call this function to retrieve a value of a sprite property. You set the propertyType parameter to the property you want to retrieve. The following table lists the sprite properties and the data types of the corresponding property values.

Sprite Property

Data Type

kSpritePropertyMatrix

MatrixRecord

kSpritePropertyImageDescription

ImageDescriptionHandle

kSpritePropertyImageDataPtr

Ptr

kSpritePropertyVisible

Boolean

kSpritePropertyLayer

short

kSpritePropertyGraphicsMode

ModifierTrackGraphicsModeRecord

In the case of the kSpritePropertyImageDescription and kSpritePropertyImageDataPtr properties, this function does not return a copy of the data; rather, the pointers returned are references to the sprite’s data.

SetSpriteProperty

The SetSpriteProperty function sets the specified property of a sprite. You animate a sprite by modifying its properties. You call this function to modify a property of a sprite. This function invalidates the sprite’s sprite world as needed.

You set the propertyType parameter to the property you want to modify. Depending on the property type, you set the propertyValue parameter to either a pointer to the property value or the property value itself, cast as a void*.

The following table lists the sprite properties and the data types of the corresponding property values.

Sprite Property

Data Type

kSpritePropertyMatrix

MatrixRecord *

kSpritePropertyImageDescription

ImageDescriptionHandle

kSpritePropertyImageDataPtr

Ptr

kSpritePropertyVisible

Boolean

kSpritePropertyLayer

short

kSpritePropertyGraphicsMode

ModifierTrackGraphicsModeRecord *