793 lines
16 KiB
C
793 lines
16 KiB
C
/*==========================================================================
|
|
*
|
|
* Copyright (c) 1995 - 1997 Microsoft Corporation. All Rights Reserved.
|
|
* Copyright (C) 1994-1995 ATI Technologies Inc. All Rights Reserved.
|
|
*
|
|
* File: sprite.c
|
|
* Content: sprite manipulation functions
|
|
*
|
|
***************************************************************************/
|
|
#include "foxbear.h"
|
|
|
|
/*
|
|
* CreateSprite
|
|
*/
|
|
HSPRITE *CreateSprite (
|
|
USHORT bitmapCount,
|
|
LONG x,
|
|
LONG y,
|
|
USHORT width,
|
|
USHORT height,
|
|
USHORT xmax,
|
|
USHORT ymax,
|
|
SHORT as,
|
|
BOOL active )
|
|
{
|
|
HSPRITE *hSprite;
|
|
USHORT i;
|
|
|
|
hSprite = MemAlloc( sizeof (HSPRITE) );
|
|
if( hSprite == NULL )
|
|
{
|
|
ErrorMessage( "hSprite in CreateSprite" );
|
|
}
|
|
|
|
hSprite->hSBM = CMemAlloc( bitmapCount, sizeof (HSPRITE_BM) );
|
|
if( hSprite->hSBM == NULL )
|
|
{
|
|
MemFree( hSprite );
|
|
ErrorMessage( "hSprite->hSBM in CreateSprite" );
|
|
}
|
|
|
|
hSprite->active = active;
|
|
hSprite->bitmapCount = bitmapCount;
|
|
hSprite->x = x;
|
|
hSprite->y = y;
|
|
hSprite->width = width;
|
|
hSprite->height = height;
|
|
hSprite->xv = 0;
|
|
hSprite->yv = 0;
|
|
hSprite->xa = 0;
|
|
hSprite->ya = 0;
|
|
hSprite->xmax = xmax;
|
|
hSprite->ymax = ymax;
|
|
hSprite->absSwitch = as;
|
|
hSprite->relSwitch = 0;
|
|
hSprite->switchType = HOR;
|
|
hSprite->switchForward = TRUE;
|
|
hSprite->switchDone = FALSE;
|
|
|
|
for( i = 0; i < bitmapCount; ++i )
|
|
{
|
|
hSprite->hSBM[i].hBM = NULL;
|
|
}
|
|
|
|
return hSprite;
|
|
|
|
} /* CreateSprite */
|
|
|
|
/*
|
|
* BitBltSprite
|
|
*/
|
|
BOOL BitBltSprite (
|
|
HSPRITE *hSprite,
|
|
GFX_HBM hBM,
|
|
ACTION action,
|
|
DIRECTION direction,
|
|
SHORT x,
|
|
SHORT y,
|
|
USHORT w,
|
|
USHORT h )
|
|
{
|
|
USHORT count;
|
|
|
|
if( hSprite == NULL )
|
|
{
|
|
ErrorMessage( "hSprite in BitBltSprite" );
|
|
}
|
|
|
|
if( hBM == NULL )
|
|
{
|
|
ErrorMessage( "hBM in BitBltSprite" );
|
|
}
|
|
|
|
if( (x >= hSprite->width) || (y >= hSprite->height) )
|
|
{
|
|
ErrorMessage( "x or y in BitBltSprite" );
|
|
}
|
|
|
|
count = 0;
|
|
while( hSprite->hSBM[count].hBM != NULL )
|
|
{
|
|
count++;
|
|
if( count >= hSprite->bitmapCount )
|
|
{
|
|
ErrorMessage( "Bitmap overflow in BitBltSprite" );
|
|
}
|
|
}
|
|
|
|
hSprite->hSBM[count].hBM = hBM;
|
|
hSprite->hSBM[count].action = action;
|
|
hSprite->hSBM[count].direction = direction;
|
|
hSprite->hSBM[count].x = x;
|
|
hSprite->hSBM[count].y = y;
|
|
hSprite->hSBM[count].width = w;
|
|
hSprite->hSBM[count].height = h;
|
|
|
|
return TRUE;
|
|
|
|
} /* BitBltSprite */
|
|
|
|
/*
|
|
* SetSpriteAction
|
|
*/
|
|
BOOL SetSpriteAction ( HSPRITE *hSprite, ACTION action, DIRECTION direction )
|
|
{
|
|
USHORT c;
|
|
|
|
c = 0;
|
|
|
|
if( direction == SAME )
|
|
{
|
|
direction = hSprite->currentDirection;
|
|
}
|
|
|
|
while( (hSprite->hSBM[c].action != action) || (hSprite->hSBM[c].direction != direction) )
|
|
{
|
|
++c;
|
|
}
|
|
|
|
hSprite->currentAction = action;
|
|
hSprite->currentDirection = direction;
|
|
hSprite->currentBitmap = c;
|
|
hSprite->relSwitch = 0;
|
|
|
|
return TRUE;
|
|
|
|
} /* SetSpriteAction */
|
|
|
|
/*
|
|
* ChangeSpriteDirection
|
|
*/
|
|
BOOL ChangeSpriteDirection( HSPRITE *hSprite )
|
|
{
|
|
DIRECTION direction;
|
|
|
|
if( hSprite->currentDirection == RIGHT )
|
|
{
|
|
direction = LEFT;
|
|
}
|
|
else
|
|
{
|
|
direction = RIGHT;
|
|
}
|
|
|
|
SetSpriteAction( hSprite, hSprite->currentAction, direction );
|
|
|
|
return TRUE;
|
|
|
|
} /* ChangeSpriteDirection */
|
|
|
|
/*
|
|
* GetSpriteAction
|
|
*/
|
|
ACTION GetSpriteAction( HSPRITE *hSprite )
|
|
{
|
|
return hSprite->currentAction;
|
|
|
|
} /* GetSpriteAction */
|
|
|
|
|
|
/*
|
|
* GetSpriteDirection
|
|
*/
|
|
DIRECTION GetSpriteDirection( HSPRITE *hSprite )
|
|
{
|
|
return hSprite->currentDirection;
|
|
|
|
} /* GetSpriteDirection */
|
|
|
|
/*
|
|
* SetSpriteActive
|
|
*/
|
|
BOOL SetSpriteActive( HSPRITE *hSprite, BOOL active )
|
|
{
|
|
hSprite->active = active;
|
|
|
|
if( active == FALSE )
|
|
{
|
|
hSprite->xv = 0;
|
|
hSprite->yv = 0;
|
|
hSprite->xa = 0;
|
|
hSprite->ya = 0;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} /* SetSpriteActive */
|
|
|
|
/*
|
|
* GetSpriteActive
|
|
*/
|
|
BOOL GetSpriteActive( HSPRITE *hSprite )
|
|
{
|
|
return hSprite->active;
|
|
|
|
} /* GetSpriteActive */
|
|
|
|
/*
|
|
* SetSpriteVelX
|
|
*/
|
|
BOOL SetSpriteVelX( HSPRITE *hSprite, LONG xv, POSITION position )
|
|
{
|
|
if( hSprite->active == FALSE )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if( position == P_ABSOLUTE )
|
|
{
|
|
hSprite->xv = xv;
|
|
}
|
|
else if( position == P_RELATIVE )
|
|
{
|
|
hSprite->xv += xv;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} /* SetSpriteVelX */
|
|
|
|
/*
|
|
* GetSpriteVelX
|
|
*/
|
|
LONG GetSpriteVelX( HSPRITE *hSprite )
|
|
{
|
|
return hSprite->xv;
|
|
|
|
} /* GetSpriteVelX */
|
|
|
|
/*
|
|
* SetSpriteVelY
|
|
*/
|
|
BOOL SetSpriteVelY( HSPRITE *hSprite, LONG yv, POSITION position )
|
|
{
|
|
if( hSprite->active == FALSE )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if( position == P_ABSOLUTE )
|
|
{
|
|
hSprite->yv = yv;
|
|
}
|
|
else if( position == P_RELATIVE )
|
|
{
|
|
hSprite->yv += yv;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} /* SetSpriteVelY */
|
|
|
|
/*
|
|
* GetSpriteVelY
|
|
*/
|
|
LONG GetSpriteVelY( HSPRITE *hSprite )
|
|
{
|
|
return hSprite->yv;
|
|
|
|
} /* GetSpriteVelY */
|
|
|
|
/*
|
|
* SetSpriteAccX
|
|
*/
|
|
BOOL SetSpriteAccX ( HSPRITE *hSprite, LONG xa, POSITION position )
|
|
{
|
|
if( position == P_ABSOLUTE )
|
|
{
|
|
hSprite->xa = xa;
|
|
}
|
|
else if( position == P_RELATIVE )
|
|
{
|
|
hSprite->xa += xa;
|
|
}
|
|
return TRUE;
|
|
|
|
} /* SetSpriteAccX */
|
|
|
|
/*
|
|
* GetSpriteAccX
|
|
*/
|
|
LONG GetSpriteAccX( HSPRITE *hSprite )
|
|
{
|
|
return hSprite->xa;
|
|
|
|
} /* GetSpriteAccX */
|
|
|
|
/*
|
|
* SetSpriteAccY
|
|
*/
|
|
BOOL SetSpriteAccY ( HSPRITE *hSprite, LONG ya, POSITION position )
|
|
{
|
|
if( position == P_ABSOLUTE )
|
|
{
|
|
hSprite->ya = ya;
|
|
}
|
|
else if( position == P_RELATIVE )
|
|
{
|
|
hSprite->ya += ya;
|
|
}
|
|
return TRUE;
|
|
|
|
} /* SetSpriteAccY */
|
|
|
|
/*
|
|
* GetSpriteAccY
|
|
*/
|
|
LONG GetSpriteAccY( HSPRITE *hSprite )
|
|
{
|
|
return hSprite->ya;
|
|
|
|
} /* GetSpriteAccY */
|
|
|
|
/*
|
|
* SetSpriteX
|
|
*/
|
|
BOOL SetSpriteX( HSPRITE *hSprite, LONG x, POSITION position )
|
|
{
|
|
if( hSprite->active == FALSE )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if( position == P_AUTOMATIC )
|
|
{
|
|
hSprite->xv += hSprite->xa;
|
|
hSprite->x += hSprite->xv;
|
|
}
|
|
else if( position == P_ABSOLUTE )
|
|
{
|
|
hSprite->x = x;
|
|
}
|
|
else if( position == P_RELATIVE )
|
|
{
|
|
hSprite->x += x;
|
|
}
|
|
|
|
if( hSprite->x < 0 )
|
|
{
|
|
hSprite->x += hSprite->xmax << 16;
|
|
}
|
|
else if( hSprite->x >= hSprite->xmax << 16 )
|
|
{
|
|
hSprite->x -= hSprite->xmax << 16;
|
|
}
|
|
return TRUE;
|
|
|
|
} /* SetSpriteX */
|
|
|
|
/*
|
|
* GetSpriteX
|
|
*/
|
|
LONG GetSpriteX( HSPRITE *hSprite )
|
|
{
|
|
return hSprite->x;
|
|
|
|
} /* GetSpriteX */
|
|
|
|
/*
|
|
* SetSpriteY
|
|
*/
|
|
BOOL SetSpriteY ( HSPRITE *hSprite, LONG y, POSITION position )
|
|
{
|
|
if( hSprite->active == FALSE )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if( position == P_AUTOMATIC )
|
|
{
|
|
hSprite->yv += hSprite->ya;
|
|
hSprite->y += hSprite->yv;
|
|
}
|
|
else if( position == P_ABSOLUTE )
|
|
{
|
|
hSprite->y = y;
|
|
}
|
|
else if( position == P_RELATIVE )
|
|
{
|
|
hSprite->y += y;
|
|
}
|
|
|
|
if( hSprite->y < 0 )
|
|
{
|
|
hSprite->y += hSprite->ymax << 16;
|
|
}
|
|
else if( hSprite->y >= hSprite->ymax << 16 )
|
|
{
|
|
hSprite->y -= hSprite->ymax << 16;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} /* SetSpriteY */
|
|
|
|
/*
|
|
* GetSpriteY
|
|
*/
|
|
LONG GetSpriteY( HSPRITE *hSprite )
|
|
{
|
|
return hSprite->y;
|
|
|
|
} /* GetSpriteY */
|
|
|
|
/*
|
|
* SetSpriteSwitch
|
|
*/
|
|
BOOL SetSpriteSwitch ( HSPRITE *hSprite, LONG absSwitch, POSITION position )
|
|
{
|
|
if( position == P_ABSOLUTE )
|
|
{
|
|
hSprite->absSwitch = absSwitch;
|
|
}
|
|
else if( position == P_RELATIVE )
|
|
{
|
|
hSprite->absSwitch += absSwitch;
|
|
}
|
|
return TRUE;
|
|
|
|
} /* SetSpriteSwitch */
|
|
|
|
|
|
/*
|
|
* IncrementSpriteSwitch
|
|
*/
|
|
BOOL IncrementSpriteSwitch ( HSPRITE *hSprite, LONG n )
|
|
{
|
|
hSprite->relSwitch += n;
|
|
return TRUE;
|
|
|
|
} /* IncrementSpriteSwitch */
|
|
|
|
/*
|
|
* SetSpriteSwitchType
|
|
*/
|
|
BOOL SetSpriteSwitchType( HSPRITE *hSprite, SWITCHING switchType )
|
|
{
|
|
hSprite->switchType = switchType;
|
|
hSprite->relSwitch = 0;
|
|
return TRUE;
|
|
|
|
} /* SetSpriteSwitchType */
|
|
|
|
|
|
/*
|
|
* GetSpriteSwitchType
|
|
*/
|
|
SWITCHING GetSpriteSwitchType ( HSPRITE *hSprite )
|
|
{
|
|
return hSprite->switchType;
|
|
|
|
} /* GetSpriteSwitchType */
|
|
|
|
/*
|
|
* SetSpriteSwitchForward
|
|
*/
|
|
BOOL SetSpriteSwitchForward( HSPRITE *hSprite, BOOL switchForward )
|
|
{
|
|
hSprite->switchForward = switchForward;
|
|
|
|
return TRUE;
|
|
|
|
} /* SetSpriteSwitchForward */
|
|
|
|
/*
|
|
* GetSpriteSwitchForward
|
|
*/
|
|
BOOL GetSpriteSwitchForward( HSPRITE *hSprite )
|
|
{
|
|
return hSprite->switchForward;
|
|
|
|
} /* GetSpriteSwitchForward */
|
|
|
|
/*
|
|
* SetSpriteSwitchDone
|
|
*/
|
|
BOOL SetSpriteSwitchDone( HSPRITE *hSprite, BOOL switchDone )
|
|
{
|
|
hSprite->switchDone = switchDone;
|
|
return TRUE;
|
|
|
|
} /* SetSpriteSwitchDone */
|
|
|
|
|
|
/*
|
|
* GetSpriteSwitchDone
|
|
*/
|
|
BOOL GetSpriteSwitchDone( HSPRITE *hSprite )
|
|
{
|
|
return hSprite->switchDone;
|
|
|
|
} /* GetSpriteSwitchDone */
|
|
|
|
/*
|
|
* SetSpriteBitmap
|
|
*/
|
|
BOOL SetSpriteBitmap ( HSPRITE *hSprite, USHORT currentBitmap )
|
|
{
|
|
USHORT c;
|
|
|
|
c = 0;
|
|
while( (hSprite->currentAction != hSprite->hSBM[c].action) ||
|
|
(hSprite->currentDirection != hSprite->hSBM[c].direction) )
|
|
{
|
|
++c;
|
|
}
|
|
hSprite->currentBitmap = c + currentBitmap;
|
|
return TRUE;
|
|
|
|
} /* SetSpriteBitmap */
|
|
|
|
/*
|
|
* GetSpriteBitmap
|
|
*/
|
|
USHORT GetSpriteBitmap( HSPRITE *hSprite )
|
|
{
|
|
USHORT count;
|
|
|
|
count = 0;
|
|
while( (hSprite->currentAction != hSprite->hSBM[count].action) ||
|
|
(hSprite->currentDirection != hSprite->hSBM[count].direction) )
|
|
{
|
|
++count;
|
|
}
|
|
return hSprite->currentBitmap - count;
|
|
|
|
} /* GetSpriteBitmap */
|
|
|
|
/*
|
|
* advanceSpriteBitmap
|
|
*/
|
|
static BOOL advanceSpriteBitmap( HSPRITE *hSprite )
|
|
{
|
|
SHORT c;
|
|
SHORT n;
|
|
ACTION curAct;
|
|
ACTION act;
|
|
DIRECTION curDir;
|
|
DIRECTION dir;
|
|
|
|
curAct = hSprite->currentAction;
|
|
curDir = hSprite->currentDirection;
|
|
|
|
//
|
|
// See if we're cycling forward or backward though the images.
|
|
//
|
|
if( hSprite->switchForward ) // Are we cycling forward?
|
|
{
|
|
c = hSprite->currentBitmap + 1;
|
|
|
|
// Does the next image exceed the number of images we have?
|
|
if( c >= hSprite->bitmapCount )
|
|
{
|
|
// if the next image is past the end of the list,
|
|
// we need to set it to the start of the series.
|
|
SetSpriteBitmap( hSprite, 0 );
|
|
c = hSprite->currentBitmap;
|
|
}
|
|
else
|
|
{
|
|
act = hSprite->hSBM[c].action;
|
|
dir = hSprite->hSBM[c].direction;
|
|
|
|
// By examining the action and direction fields we can tell
|
|
// if we've past the current series of images and entered
|
|
// another series.
|
|
if( (curAct != act) || (curDir != dir) )
|
|
{
|
|
SetSpriteBitmap( hSprite, 0 );
|
|
}
|
|
else // We're still in the series, use the next image.
|
|
{
|
|
hSprite->currentBitmap = c;
|
|
}
|
|
}
|
|
}
|
|
else //cycling backwards
|
|
{
|
|
c = hSprite->currentBitmap - 1;
|
|
|
|
if( c < 0 ) // Is the next image past the beginning of the list?
|
|
{
|
|
n = 0;
|
|
|
|
// Find the last bitmap in the series
|
|
while( (n <= hSprite->bitmapCount) &&
|
|
(curAct == hSprite->hSBM[n].action) &&
|
|
(curDir == hSprite->hSBM[n].direction) )
|
|
{
|
|
++n;
|
|
}
|
|
|
|
hSprite->currentBitmap = n - 1;
|
|
}
|
|
|
|
else
|
|
{
|
|
act = hSprite->hSBM[c].action;
|
|
dir = hSprite->hSBM[c].direction;
|
|
// Is the next image past the of the series
|
|
if( (curAct != act) || (curDir != dir) )
|
|
{
|
|
n = c + 1;
|
|
while( (n <= hSprite->bitmapCount) &&
|
|
(curAct == hSprite->hSBM[n].action) &&
|
|
(curDir == hSprite->hSBM[n].direction) )
|
|
{
|
|
++n;
|
|
}
|
|
|
|
hSprite->currentBitmap = n - 1;
|
|
}
|
|
else // The next image is fine, use it.
|
|
{
|
|
hSprite->currentBitmap = c;
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
|
|
} /* advanceSpriteBitmap */
|
|
|
|
/*
|
|
* DisplaySprite
|
|
*/
|
|
BOOL DisplaySprite ( GFX_HBM hBuffer, HSPRITE *hSprite, LONG xPlane )
|
|
{
|
|
USHORT count;
|
|
SHORT left;
|
|
SHORT right;
|
|
SHORT shortx;
|
|
SHORT shorty;
|
|
SHORT planex;
|
|
POINT src;
|
|
RECT dst;
|
|
|
|
if( hSprite->active == FALSE )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
count = hSprite->currentBitmap;
|
|
shortx = (SHORT) (hSprite->x >> 16);
|
|
shorty = (SHORT) (hSprite->y >> 16);
|
|
planex = (SHORT) (xPlane >> 16);
|
|
src.x = 0;
|
|
src.y = 0;
|
|
|
|
if( shortx < planex - C_SCREEN_W )
|
|
{
|
|
shortx += hSprite->xmax;
|
|
}
|
|
else if( shortx >= planex + C_SCREEN_W )
|
|
{
|
|
shortx -= hSprite->xmax;
|
|
}
|
|
|
|
left = shortx - planex;
|
|
|
|
if( hSprite->currentDirection == RIGHT )
|
|
{
|
|
left += hSprite->hSBM[count].x;
|
|
}
|
|
else
|
|
{
|
|
left += hSprite->width - hSprite->hSBM[count].x - hSprite->hSBM[count].width;
|
|
}
|
|
|
|
right = left + hSprite->hSBM[count].width;
|
|
|
|
if( left > C_SCREEN_W )
|
|
{
|
|
left = C_SCREEN_W;
|
|
}
|
|
else if( left < 0 )
|
|
{
|
|
src.x = -left;
|
|
left = 0;
|
|
}
|
|
|
|
if( right > C_SCREEN_W )
|
|
{
|
|
right = C_SCREEN_W;
|
|
}
|
|
else if( right < 0 )
|
|
{
|
|
right = 0;
|
|
}
|
|
|
|
dst.left = left;
|
|
dst.right = right;
|
|
dst.top = shorty + hSprite->hSBM[count].y;
|
|
dst.bottom = dst.top + hSprite->hSBM[count].height;
|
|
|
|
gfxBlt(&dst,hSprite->hSBM[count].hBM,&src);
|
|
|
|
if( hSprite->switchType == HOR )
|
|
{
|
|
hSprite->relSwitch += abs(hSprite->xv);
|
|
|
|
if( hSprite->relSwitch >= hSprite->absSwitch )
|
|
{
|
|
hSprite->relSwitch = 0;
|
|
advanceSpriteBitmap( hSprite );
|
|
}
|
|
}
|
|
else if( hSprite->switchType == VER )
|
|
{
|
|
hSprite->relSwitch += abs(hSprite->yv);
|
|
|
|
if( hSprite->relSwitch >= hSprite->absSwitch )
|
|
{
|
|
hSprite->relSwitch = 0;
|
|
advanceSpriteBitmap( hSprite );
|
|
|
|
if( GetSpriteBitmap( hSprite ) == 0 )
|
|
{
|
|
SetSpriteSwitchDone( hSprite, TRUE );
|
|
}
|
|
}
|
|
}
|
|
else if( hSprite->switchType == TIMESWITCH )
|
|
{
|
|
hSprite->relSwitch += C_UNIT;
|
|
|
|
if( hSprite->relSwitch >= hSprite->absSwitch )
|
|
{
|
|
hSprite->relSwitch = 0;
|
|
advanceSpriteBitmap( hSprite );
|
|
|
|
if( GetSpriteBitmap( hSprite ) == 0 )
|
|
{
|
|
SetSpriteSwitchDone( hSprite, TRUE );
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} /* DisplaySprite */
|
|
|
|
/*
|
|
* DestroySprite
|
|
*/
|
|
BOOL DestroySprite ( HSPRITE *hSprite )
|
|
{
|
|
USHORT i;
|
|
|
|
if( hSprite == NULL )
|
|
{
|
|
ErrorMessage( "hSprite in DestroySprite" );
|
|
}
|
|
|
|
if( hSprite->hSBM == NULL )
|
|
{
|
|
ErrorMessage( "hSprite->hSBM in DestroySprite" );
|
|
}
|
|
|
|
for( i = 0; i < hSprite->bitmapCount; ++i )
|
|
{
|
|
if( !gfxDestroyBitmap( hSprite->hSBM[i].hBM ) )
|
|
{
|
|
ErrorMessage( "gfxDestroyBitmap (hBM) in DestroySprite" );
|
|
}
|
|
}
|
|
|
|
MemFree( hSprite->hSBM );
|
|
MemFree( hSprite );
|
|
|
|
return TRUE;
|
|
|
|
} /* DestroySprite */
|