home *** CD-ROM | disk | FTP | other *** search
- /*===========================================================================*\
- |
- | File: cgsprite.cpp
- |
- | Description:
- |
- |-----------------------------------------------------------------------------
- |
- | Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved.
- |
- | Written by Moss Bay Engineering, Inc. under contract to Microsoft Corporation
- |
- \*===========================================================================*/
-
- /**************************************************************************
-
- (C) Copyright 1995-1996 Microsoft Corp. All rights reserved.
-
- You have a royalty-free right to use, modify, reproduce and
- distribute the Sample Files (and/or any modified version) in
- any way you find useful, provided that you agree that
- Microsoft has no warranty obligations or liability for any
- Sample Application Files which are modified.
-
- we do not recomend you base your game on IKlowns, start with one of
- the other simpler sample apps in the GDK
-
- **************************************************************************/
-
- #include <windows.h>
- #include "cgdebug.h"
- #include "cgglobl.h"
- #include "cgtimer.h"
- #include "cgscreen.h"
- #include "cgsprite.h"
- #include "cgupdate.h"
-
- extern CGameTimer* Timer;
-
- char seqSection[] = "Sequences";
- char seqKey[] = "Sequence";
- char spriteKey[] = "Sprite";
- char sprExtension[] = "spr";
- char bmpExtension[] = "bmp";
-
- /*---------------------------------------------------------------------------*\
- |
- | Class CGameSprite
- |
- | DESCRIPTION:
- |
- |
- |
- \*---------------------------------------------------------------------------*/
- CGameSprite::CGameSprite(
- char* pFileName,
- char* pSpriteName,
- CGameBitBuffer* pBits,
- BOOL needHorzMirror,
- BOOL needVertMirror
- )
- {
- // grab this sprite's parameters from the .spr file
- // and put into mInfo[0]
- mInfo[SRI_NORMAL].mSrcX = (int) GetPrivateProfileInt(
- pSpriteName,
- "X",
- 0, // default to 0
- pFileName
- );
-
- mInfo[SRI_NORMAL].mSrcY = (int) GetPrivateProfileInt(
- pSpriteName,
- "Y",
- 0, // default to 0
- pFileName
- );
-
- mInfo[SRI_NORMAL].mpBits = pBits;
- mInfo[SRI_NORMAL].mNewBits = FALSE;
-
- mInfo[SRI_NORMAL].mWidth = (int) GetPrivateProfileInt(
- pSpriteName,
- "Width",
- 0, // default to 0
- pFileName
- );
-
- mInfo[SRI_NORMAL].mHeight = (int) GetPrivateProfileInt(
- pSpriteName,
- "Height",
- 0, // default to 0
- pFileName
- );
-
- // create mirrored images if necessary
- if (needHorzMirror)
- {
- if (gUse_DDraw)
- {
- mInfo[SRI_HORZMIRROR].mpBits = new CGameDDrawBitBuffer(
- mInfo[SRI_NORMAL].mWidth,
- mInfo[SRI_NORMAL].mHeight,
- pBits->GetHPalette(),
- pBits->GetTransColor()
- );
- }
- else
- {
- mInfo[SRI_HORZMIRROR].mpBits = new CGameDSBitBuffer(
- mInfo[SRI_NORMAL].mWidth,
- mInfo[SRI_NORMAL].mHeight,
- pBits->GetHPalette(),
- pBits->GetTransColor()
- );
- }
-
- mInfo[SRI_HORZMIRROR].mNewBits = TRUE;
- mInfo[SRI_HORZMIRROR].mWidth = mInfo[SRI_NORMAL].mWidth;
- mInfo[SRI_HORZMIRROR].mHeight = mInfo[SRI_NORMAL].mHeight;
- mInfo[SRI_HORZMIRROR].mSrcX = 0;
- mInfo[SRI_HORZMIRROR].mSrcY = 0;
-
- mInfo[SRI_HORZMIRROR].mpBits->Blt(
- mInfo[SRI_HORZMIRROR].mWidth-1,
- 0,
- -mInfo[SRI_HORZMIRROR].mWidth, // create mirror image
- mInfo[SRI_HORZMIRROR].mHeight,
- pBits,
- mInfo[SRI_NORMAL].mSrcX,
- mInfo[SRI_NORMAL].mSrcY,
- SRCCOPY
- );
- }
- else
- {
- // just make a copy of normal image
- mInfo[SRI_HORZMIRROR] = mInfo[SRI_NORMAL];
-
- // negate the width to force a mirrored blt
- mInfo[SRI_HORZMIRROR].mWidth = -mInfo[SRI_NORMAL].mWidth;
-
- // make sure we don't delete it
- mInfo[SRI_HORZMIRROR].mNewBits = FALSE;
- }
-
- if (needVertMirror)
- {
- if (gUse_DDraw)
- {
- mInfo[SRI_VERTMIRROR].mpBits = new CGameDDrawBitBuffer(
- mInfo[SRI_NORMAL].mWidth,
- mInfo[SRI_NORMAL].mHeight,
- pBits->GetHPalette(),
- pBits->GetTransColor()
- );
-
- }
- else
- {
- mInfo[SRI_VERTMIRROR].mpBits = new CGameDSBitBuffer(
- mInfo[SRI_NORMAL].mWidth,
- mInfo[SRI_NORMAL].mHeight,
- pBits->GetHPalette(),
- pBits->GetTransColor()
- );
- }
-
- mInfo[SRI_VERTMIRROR].mNewBits = TRUE;
- mInfo[SRI_VERTMIRROR].mWidth = mInfo[SRI_NORMAL].mWidth;
- mInfo[SRI_VERTMIRROR].mHeight = mInfo[SRI_NORMAL].mHeight;
- mInfo[SRI_VERTMIRROR].mSrcX = 0;
- mInfo[SRI_VERTMIRROR].mSrcY = 0;
-
- mInfo[SRI_VERTMIRROR].mpBits->Blt(
- 0,
- mInfo[SRI_VERTMIRROR].mHeight-1,
- mInfo[SRI_VERTMIRROR].mWidth,
- -mInfo[SRI_VERTMIRROR].mHeight, // create mirror image
- pBits,
- mInfo[SRI_NORMAL].mSrcX,
- mInfo[SRI_NORMAL].mSrcY,
- SRCCOPY
- );
- }
- else
- {
- // just make a copy of normal image
- mInfo[SRI_VERTMIRROR] = mInfo[SRI_NORMAL];
-
- // negate the height to force a mirrored blt
- mInfo[SRI_VERTMIRROR].mHeight = -mInfo[SRI_NORMAL].mHeight;
-
- // make sure we don't delete it
- mInfo[SRI_VERTMIRROR].mNewBits = FALSE;
- }
-
- // do we need both horizontal and vertical?
- if (needHorzMirror && needVertMirror)
- {
- if (gUse_DDraw)
- {
- mInfo[SRI_BOTHMIRROR].mpBits = new CGameDDrawBitBuffer(
- mInfo[SRI_NORMAL].mWidth,
- mInfo[SRI_NORMAL].mHeight,
- pBits->GetHPalette(),
- pBits->GetTransColor()
- );
-
- }
- else
- {
- mInfo[SRI_BOTHMIRROR].mpBits = new CGameDSBitBuffer(
- mInfo[SRI_NORMAL].mWidth,
- mInfo[SRI_NORMAL].mHeight,
- pBits->GetHPalette(),
- pBits->GetTransColor()
- );
- }
-
- mInfo[SRI_BOTHMIRROR].mNewBits = TRUE;
- mInfo[SRI_BOTHMIRROR].mWidth = mInfo[SRI_NORMAL].mWidth;
- mInfo[SRI_BOTHMIRROR].mHeight = mInfo[SRI_NORMAL].mHeight;
- mInfo[SRI_BOTHMIRROR].mSrcX = 0;
- mInfo[SRI_BOTHMIRROR].mSrcY = 0;
-
-
- mInfo[SRI_BOTHMIRROR].mpBits->Blt(
- mInfo[SRI_BOTHMIRROR].mWidth-1,
- mInfo[SRI_NORMAL].mHeight-1,
- -mInfo[SRI_BOTHMIRROR].mWidth, // create mirror image
- -mInfo[SRI_BOTHMIRROR].mHeight,
- pBits,
- mInfo[SRI_NORMAL].mSrcX,
- mInfo[SRI_NORMAL].mSrcY,
- SRCCOPY
- );
- }
- else
- {
- // just make a copy of normal image
- mInfo[SRI_BOTHMIRROR] = mInfo[SRI_NORMAL];
-
- // negate the width and height to force a mirrored blt
- mInfo[SRI_BOTHMIRROR].mWidth = -mInfo[SRI_NORMAL].mHeight;
- mInfo[SRI_BOTHMIRROR].mHeight = -mInfo[SRI_NORMAL].mHeight;
-
- // make sure we don't delete it
- mInfo[SRI_BOTHMIRROR].mNewBits = FALSE;
- }
- }
-
- CGameSprite::~CGameSprite()
- {
- for (int i = SRI_INFOCOUNT; i>0; i--)
- {
- if (mInfo[i-1].mNewBits)
- {
- delete mInfo[i-1].mpBits;
- }
- }
- }
-
- /*---------------------------------------------------------------------------*\
- |
- | class CGameSpriteBuffer
- |
- | DESCRIPTION:
- |
- |
- |
- \*---------------------------------------------------------------------------*/
- CGameSpriteBuffer::CGameSpriteBuffer(
- char* pFileName
- ) : mpFileName( NULL ),
- mpBitBuffer( NULL ),
- mRefCount( 0 )
- {
- mpFileName = new char[lstrlen( pFileName ) +1];
- lstrcpy( mpFileName, pFileName );
-
- // open the set's DIB file
- char bmpName[256];
- SprToBmp( pFileName, bmpName, 256 );
-
- CGameDIB dib( bmpName );
-
- if (gUse_DDraw)
- {
- mpBitBuffer = new CGameDDrawBitBuffer( &dib );
- if (!mpBitBuffer->IsValid())
- {
- // we didn't get video memory, so delete that buffer
- delete mpBitBuffer;
- // & create a system memory one
- mpBitBuffer = new CGameDSBitBuffer( &dib );
- }
- }
- else
- {
- mpBitBuffer = new CGameDSBitBuffer( &dib );
- }
- ++mRefCount;
- }
-
- CGameSpriteBuffer::~CGameSpriteBuffer()
- {
- delete mpBitBuffer;
- delete[] mpFileName;
- }
-
- void
- CGameSpriteBuffer::SprToBmp(
- char* pSprName,
- char* pOutBuffer,
- int size
- )
- {
- lstrcpyn( pOutBuffer, pSprName, size );
-
- int dotPos = strcspn( pOutBuffer, "." );
-
- if (dotPos < lstrlen( pOutBuffer ))
- {
- pOutBuffer[dotPos] = '\0';
- lstrcat( pOutBuffer, "." );
- lstrcat( pOutBuffer, bmpExtension );
- }
- }
-
- /*---------------------------------------------------------------------------*\
- |
- | Class CGameSpriteSequence
- |
- | DESCRIPTION:
- |
- |
- |
- \*---------------------------------------------------------------------------*/
-
- LinkedList* CGameSpriteSequence::mpBufferList = NULL;
-
- CGameSpriteSequence::CGameSpriteSequence(
- char* pFileName,
- char* pSequenceName,
- int rate,
- BOOL mirrorHorz, // keep mirror images of sprites?
- BOOL mirrorVert
- ) : mpSpriteArray( NULL ),
- mNumSprites( 0 ),
- mCurSprite( 0 ),
- mpMyBuffer( NULL ),
- mLastTime( -1 )
- {
- char sprFile[MAX_PATH];
-
- lstrcpy(sprFile, gDataPath);
- lstrcat(sprFile, "\\");
- lstrcat(sprFile, pFileName);
-
- // get a ptr to this sequence's source bitmap
- mpMyBuffer = LoadSpriteBits( pFileName );
-
- // get the number of sprites
- mNumSprites = GetPrivateProfileInt(
- "Sequences",
- pSequenceName,
- 0,
- sprFile
- );
-
- mpSpriteArray = new CGameSprite*[mNumSprites];
-
- // get the sprite list
- char spriteBuf[256];
- char defSprite[] = ""; // no default sprite names
-
- GetPrivateProfileString(
- pSequenceName,
- NULL, // grab all the key names
- defSprite,
- spriteBuf,
- sizeof( spriteBuf ),
- sprFile
- );
-
- int i=0;
- for (char *pSprite = spriteBuf; *pSprite && (i<mNumSprites); pSprite++)
- {
- mpSpriteArray[i] = new CGameSprite( sprFile, pSprite, mpMyBuffer->mpBitBuffer, mirrorHorz, mirrorVert );
- pSprite += lstrlen( pSprite ); // move beyond terminator
- ++i;
- }
-
- mPeriod = 1000 / rate;
- }
-
- CGameSpriteSequence::~CGameSpriteSequence()
- {
- // !!! assumes that mpSpriteArray is valid if mNumSprites>0
- for (; mNumSprites>0; mNumSprites--)
- {
- delete mpSpriteArray[mNumSprites-1];
- }
-
- // remove our file from list
- UnloadSpriteBits();
-
- delete[] mpSpriteArray;
- }
-
- BOOL // return TRUE if the are more sprites in sequence
- CGameSpriteSequence::Frame()
- {
- return TRUE;
- }
-
- int // return mCurSprite .... is Zero if no more (i.e., wrapped)
- CGameSpriteSequence::NextSprite(
- int time, // current game time
- BOOL wrap // wrap around (i.e. loop) at end of sequence
- )
- {
- if (mLastTime == -1)
- mLastTime = time-mPeriod;
-
- int elapsed = time - mLastTime;
- if (elapsed >= mPeriod)
- {
- mLastTime = time;
- mCurSprite += elapsed / mPeriod;
- if (mCurSprite >= mNumSprites)
- {
- mCurSprite = wrap ? (mCurSprite % mNumSprites) : 0;
- }
- }
- return mCurSprite;
- }
-
- void
- CGameSpriteSequence::Render(
- CGameScreen* pScreen,
- int x,
- int y,
- BOOL revX, // reverse the image?
- BOOL revY, // reverse the image?
- LPRECT pDirty // invalid rectangle in screen coordinates
- )
- {
- int which = (int) revX + ((int) revY * 2);
- RECT update;
- int clipX = max(x, pDirty->left);
- int clipY = max(y, pDirty->top);
-
- int offsetX = max(pDirty->left - x, 0);
- int offsetY = max(pDirty->top - y, 0);
-
- update.left = mpSpriteArray[mCurSprite]->mInfo[which].mSrcX +
- offsetX;
-
- update.top = mpSpriteArray[mCurSprite]->mInfo[which].mSrcY +
- offsetY;
-
- // we're using right & bottom for width & height
- update.right = min( mpSpriteArray[mCurSprite]->mInfo[which].mWidth -
- offsetX, pDirty->right-clipX+1 );
-
- update.bottom = min( mpSpriteArray[mCurSprite]->mInfo[which].mHeight -
- offsetY, pDirty->bottom-clipY+1 );
-
- if ((update.right > 0) && (update.bottom > 0))
- pScreen->TransRender(
- clipX,
- clipY,
- update.right,
- update.bottom,
- mpSpriteArray[mCurSprite]->mInfo[which].mpBits,
- update.left,
- update.top
- );
- }
-
- // return a ptr to the sprite buffer corresponding to this .spr filename
- // keeps track of whether file is already loaded & maintains reference count
- CGameSpriteBuffer*
- CGameSpriteSequence::LoadSpriteBits( char* pFileName )
- {
- CGameSpriteBuffer* pResult = NULL;
- CGameSpriteBuffer* pCurBuffer = NULL;
-
- // initialize buffer list if necessary
- if (!mpBufferList)
- {
- mpBufferList = new LinkedList;
- }
- else
- {
- pCurBuffer = (CGameSpriteBuffer*) mpBufferList->GetFirst();
-
- while (pCurBuffer && !pResult)
- {
- if (lstrcmpi( pFileName, pCurBuffer->mpFileName ) == 0 )
- {
- pResult = pCurBuffer;
- pCurBuffer->mRefCount++;
- }
- else
- {
- pCurBuffer = (CGameSpriteBuffer*) mpBufferList->GetNext();
- }
- }
- }
-
- // if we didn't find it, we need to load it
- if (!pResult)
- {
- pResult = new CGameSpriteBuffer(pFileName); // increments ref count
-
- mpBufferList->Append( pResult );
- }
-
- return pResult;
- }
-
-
- // decrement the ref count for the given file & remove it if 0
- void
- CGameSpriteSequence::UnloadSpriteBits()
- {
- if (--mpMyBuffer->mRefCount == 0)
- {
- mpBufferList->Remove( mpMyBuffer );
- delete mpMyBuffer;
-
- // !!! should we delete the list if empty?
- }
- }
-