Source/GameObject.c

//¥ ------------------------------------------------------------------------------------------  ¥
//¥
//¥ Copyright © 1996 Apple Computer, Inc., All Rights Reserved
//¥
//¥
//¥     You may incorporate this sample code into your applications without
//¥     restriction, though the sample code has been provided "AS IS" and the
//¥     responsibility for its operation is 100% yours.  However, what you are
//¥     not permitted to do is to redistribute the source as "DSC Sample Code"
//¥     after having made changes. If you're going to re-distribute the source,
//¥     we require that you make it clear in the source that the code was
//¥     descended from Apple Sample Code, but that you've made changes.
//¥
//¥     Authors:
//¥         Chris De Salvo
//¥
//¥ ------------------------------------------------------------------------------------------  ¥
 
//¥ ------------------------------  Includes
 
#include "GameObject.h"
#include "Graphics.h"
#include "MemoryHandler.h"
#include "ObjectActions.h"
 
//¥ ------------------------------  Private Definitions
//¥ ------------------------------  Private Types
//¥ ------------------------------  Private Variables
 
static UInt32   gNumGameObjectsEver = 0;
 
//¥ ------------------------------  Private Functions
//¥ ------------------------------  Public Variables
 
UInt32  gNumGameObjects = 0;
 
//¥ --------------------    GameObjectAllocate
 
GameObjectPtr
GameObjectAllocate(void)
{
GameObjectPtr   go;
 
    //¥ Allocate memory for this object
    go = (GameObjectPtr) NewTaggedPtrClear(sizeof (GameObject), 'GObj', gNumGameObjectsEver++);
    if (! go)
        return (nil);
 
    gNumGameObjects++;
 
    go->action = ObjectIdle;
    SetRect(&go->screenRect, 0, 0, 0, 0);
    SetRect(&go->oldScreenRect, 0, 0, 0, 0);
 
    return (go);
}
 
//¥ --------------------    GameObjectDispose
 
void
GameObjectDispose(GameObjectPtr go)
{
    if (! go)
        return;
 
    switch (go->kind)
    {
        case objectEnemyParticles:
        case objectPlayerParticles:
        case objectPlasmaParticles:
        case objectMissileParticles:
            ParticlesDispose(&go->objectData.particles);
            break;
    }
    
    DisposeTaggedPtrZ((Ptr *) &go);
    gNumGameObjects--;
}
 
//¥ --------------------    GameObjectAddToList
 
void
GameObjectAddToList(GameObjectPtr *list, GameObjectPtr go)
{
    if (! go)
        return;
 
    //¥ Handle the case of this being the only item
    if (*list == nil)
    {
        *list = go;
        go->next = nil;
        go->prev = nil;
        
        return;
    }
 
    //¥ Otherwise, just add it to the top
    go->next = *list;           //¥ Have the new object point down to the old front
    go->prev = nil;             //¥ Point up to nothing
    go->next->prev = go;        //¥ Have the next item point back up to the new object
 
    *list = go;                 //¥ Update the global list head pointer
}
 
//¥ --------------------    GameObjectRemoveFromList
 
void
GameObjectRemoveFromList(GameObjectPtr *list, GameObjectPtr go)
{
    if (! go)
        return;
 
    if (! *list)
        return;
 
    //¥ Adjust the back link
    if (go->prev)
        go->prev->next = go->next;
 
    //¥ Adjust the forward link
    if (go->next)
        go->next->prev = go->prev;
 
    //¥ Handle the case of it being the first item
    if (go == *list)
    {
        if (go->next)
            *list = go->next;
        else
            *list = nil;
    }
}
 
//¥ --------------------    GameObjectDisposeList
 
void
GameObjectDisposeList(GameObjectPtr *list)
{
GameObjectPtr   next;
GameObjectPtr   current;
 
    if (! *list)
        return;
        
    current = *list;
    
    do
    {
        next = current->next;
        GameObjectDispose(current);
        current = next;
    } while (next);
 
    *list = nil;
}
 
//¥ --------------------    GameObjectSetSprite
 
void
GameObjectSetSprite(GameObjectPtr go, SpritePtr sprite)
{
    if (go && sprite)
        go->objectData.sprite = sprite;
}
 
//¥ --------------------    GameObjectGetSprite
 
SpritePtr
GameObjectGetSprite(GameObjectPtr go)
{
    if (! go)
        return (nil);
        
    return (go->objectData.sprite);
}
 
//¥ --------------------    GameObjectSetParticles
 
void
GameObjectSetParticles(GameObjectPtr go, ParticlesPtr particles)
{
    if (go && particles)
    {
        go->objectData.particles = particles;
        go->objectData.particles->bounds = go->bounds;
    }
}
 
//¥ --------------------    GameObjectGetParticles
 
ParticlesPtr
GameObjectGetParticles(GameObjectPtr go)
{
    if (! go)
        return (nil);
        
    return (go->objectData.particles);
}
 
//¥ --------------------    GameObjectSetBounds
 
void
GameObjectSetBounds(GameObjectPtr go, RectPtr r)
{
    if (go && r)
        go->bounds = *r;
}
 
//¥ --------------------    GameObjectGetBounds
 
RectPtr
GameObjectGetBounds(GameObjectPtr go)
{
    if (! go)
        return (nil);
 
    return (&go->bounds);
}
 
//¥ --------------------    GameObjectListAdvance
 
void
GameObjectListAdvance(GameObjectPtr list)
{
GameObjectPtr   next;
GameObjectPtr   current;
 
    if (! list)
        return;
 
    current = list;
 
    //¥ We need to iterate over the list in this manner because
    //¥ objects might remove themselves from the list as part of their action
    do
    {
        next = current->next;
        current->action(current);
        current = next;
    } while (next);
}
 
//¥ --------------------    GameObjectListDraw
 
void
GameObjectListDraw(GameObjectPtr list, CGrafPtr dest)
{
GameObjectPtr   index;
 
    for (index = list; index; index = index->next)
    {
        switch (index->kind)
        {
            case objectEnemy:
            case objectEnemyShot:
            case objectGreenPlayer:
            case objectGreenPlayerShot:
            case objectRedPlayer:
            case objectRedPlayerShot:
                index->screenRect = SpriteDraw(index->objectData.sprite, index->frame, dest, index->screenX, index->screenY);
                break;
                
            case objectEnemyParticles:
            case objectPlayerParticles:
            case objectPlasmaParticles:
            case objectMissileParticles:
                index->screenRect = ParticlesDraw(index->objectData.particles, dest);
                break;
        }
 
        if (! EmptyRect(&index->screenRect))
            GraphicsSetRectDirty(&index->screenRect);
            
        index->oldScreenRect = index->screenRect;
    }
}
 
//¥ --------------------    GameObjectListCount
 
UInt32
GameObjectListCount(GameObjectPtr list)
{
GameObjectPtr   index;
UInt32      count = 0;
 
    for (index = list; index; index = index->next)
        count++;
 
    return (count);
}