windows-nt/Source/XPSP1/NT/multimedia/dshow/streams/foxbear/sprite.c

793 lines
16 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*==========================================================================
*
* 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 */