Sprite.cpp
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:9k
- // Sprite.cpp: implementation of the CSprite class.
- //
- //////////////////////////////////////////////////////////////////////
- #include <list>
- #include <algorithm>
- #include <assert.h>
- #include "DSUtil.h"
- #include "ddutil.h"
- #include "Sprite.h"
- using namespace std;
- extern CSoundManager* g_pSoundManager;
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- CSprite::CSprite():m_pfnDead(0),m_pfnKill(0)
- {
- m_Anim.m_bIsAnimBiDir = true;
- ::ZeroMemory(&m_CurrState, sizeof(SSTATE));
- }
- CSprite::~CSprite()
- {
- Destroy();
- }
- ////////////////////////////////////////////////////////////////////////
- // Create the sprite by giving it the Surface containing all the sprite
- // images.
- // Type is for storing game specific information like, this sprite is an
- // enemy or friend or food, etc.
- // Set the dimensions of the sprite
- /////////////////////////////////////////////////////////////////////////
- void CSprite::CreateSprite(CSurface** ppSurface, long nType,long nHeight, long nWidth)
- {
- m_ppSurface = ppSurface;
- m_nType = nType;
- m_Anim.m_nHeight = nHeight;
- m_Anim.m_nWidth = nWidth;
- }
- ///////////////////////////////////////////////////////////////////////////
- // Add a new state for the sprite
- // State could be like WALKING_UP or WALKING_DOWN or SHOOTING
- // Since sprite will have different animation sequence based on there state
- // this function can be used to give all the different things a sprite can do.
- // Parameters:
- // nState is a user define value used to identify the state
- // ptFrame is the x,y for of the first frame in the surface.
- // Since the dimentions are fixed we don't need that info here
- // nNoOfFrames is the total animations frames this state has
- // nDelay is to control the animation speed.
- //////////////////////////////////////////////////////////////////////////////
- void CSprite::AddState(long nState, POINT ptFrame, long nNoOfFrames, long nDelay, RECT* prcBound, LPTSTR pszSound, bool bLoopSound)
- {
- SSTATE State;
- State.m_nState = nState;
- State.m_ptFirstFrame = ptFrame;
- State.m_nNoOfFrames = nNoOfFrames;
- State.m_nDelay = nDelay;
- State.m_bLoopSound = bLoopSound;
- State.m_pSound=NULL;
- if (prcBound == NULL) {
- State.m_rcBounding.top = State.m_rcBounding.left=0;
- State.m_rcBounding.bottom=m_Anim.m_nHeight ;
- State.m_rcBounding.right= m_Anim.m_nWidth ;
- } else {
- State.m_rcBounding =*prcBound;
- }
- if (pszSound) {
- // Load the wave file into a DirectSound buffer
- g_pSoundManager->Create( &State.m_pSound, pszSound, 0, GUID_NULL );
- }
- m_StateList.push_back(State);
- }
- /////////////////////////////////////////////////////////////////////////
- // Check if the give rectangle intersects with any part of the sprite
- // This is used for collusion detection.
- ////////////////////////////////////////////////////////////////////////
- bool CSprite::IsHit(RECT rcRect)
- {
- if (m_CurrState.m_nState == ST_DEAD || m_CurrState.m_nState == ST_KILL)
- return false;
- RECT rcIntersect;
- RECT rcSprite= GetBoundingRect(m_ptLocation);
-
- return (::IntersectRect(&rcIntersect, &rcSprite, &rcRect) != 0);
- }
- ////////////////////////////////////////////////////////////////////////
- // Move sprite to new location
- ////////////////////////////////////////////////////////////////////////
- void CSprite::MoveTo(POINT ptNewLoc)
- {
- m_ptLocation = ptNewLoc;
- }
- ////////////////////////////////////////////////////////////////////
- // helper function of STL find
- ///////////////////////////////////////////////////////////////////
- bool CSprite::SSTATE::operator==( const long& nState)
- {
- return m_nState == nState;
- }
- //////////////////////////////////////////////////////////////////
- // Set the state of the sprite
- //////////////////////////////////////////////////////////////////
- void CSprite::SetState(long nState, bool bForceState)
- {
- if (m_CurrState.m_nState == nState)
- return;
- if (m_CurrState.m_nState == ST_KILL && bForceState == false)
- return;
-
- if (m_CurrState.m_pSound) {
- m_CurrState.m_pSound->Stop();
- }
-
- if(nState == ST_KILL && m_pfnKill) {
- if (((*m_pfnKill)(this)) == false)
- return;
- }
- list<SSTATE>::iterator iState = find(m_StateList.begin(), m_StateList.end(), nState);
-
- assert(*iState == nState);
- m_CurrState = *iState;
- m_Anim.m_nCurrFrame = 0;
- m_Anim.m_nCurrDelay = m_CurrState.m_nDelay;
- m_Anim.m_bIsAnimForward = true;
- if (m_CurrState.m_pSound) {
- DWORD dwFlags = m_CurrState.m_bLoopSound ? DSBPLAY_LOOPING : 0L;
- m_CurrState.m_pSound->Play( 0, dwFlags ) ;
- }
- }
- void CSprite::Update()
- {
- if (m_CurrState.m_nState == ST_DEAD)
- return;
-
- // If m_Movement.m_nPathFindDelay = 0 then path is only updated
- // when a collision occurs.
- if (m_Movement.m_pfnFindPath && m_Movement.m_nPathFindDelay != 0) {
- if (m_Movement.m_nCurrPathFindDelay) {
- --m_Movement.m_nCurrPathFindDelay;
- } else {
- m_Movement.m_nCurrPathFindDelay = m_Movement.m_nPathFindDelay;
- (*m_Movement.m_pfnFindPath)(this);
- }
- }
- if (m_CurrState.m_nState == ST_KILL) {
- m_Movement.m_dx =0;
- m_Movement.m_dy =0;
- }
-
- if (m_Movement.m_pfnCollision) {
- if (m_Movement.m_nCurrMoveDelay)
- --m_Movement.m_nCurrMoveDelay;
- else {
- m_Movement.m_nCurrMoveDelay = m_Movement.m_nMoveDelay;
- POINT pt = m_ptLocation;
- pt.x += m_Movement.m_dx;
- pt.y += m_Movement.m_dy;
-
- // Check for collision at the new location
- // If is has collided call path find function
- // for new direction.
- if ((*m_Movement.m_pfnCollision)(GetBoundingRect(pt))) {
- if (m_Movement.m_pfnFindPath) {
- (*m_Movement.m_pfnFindPath)(this);
- }
- } else {
- m_ptLocation = pt;
- }
- }
-
- }
- if (m_Anim.m_nCurrDelay) {
- --m_Anim.m_nCurrDelay;
- return;
- }
- m_Anim.m_nCurrDelay = m_CurrState.m_nDelay;
- if (m_CurrState.m_nNoOfFrames == 1) {
- if (m_CurrState.m_nState == ST_KILL) {
- m_CurrState.m_nState = ST_DEAD;
- if (m_pfnDead)
- (*m_pfnDead)(this);
- }
- return;
- }
- if (m_Anim.m_bIsAnimBiDir) {
- if (m_Anim.m_bIsAnimForward) {
- if ( m_Anim.m_nCurrFrame == m_CurrState.m_nNoOfFrames - 1) {
- m_Anim.m_bIsAnimForward = false;
- if (m_CurrState.m_nState == ST_KILL) {
- m_CurrState.m_nState = ST_DEAD;
- if (m_pfnDead) {
- (*m_pfnDead)(this);
- return;
- }
- }
- --m_Anim.m_nCurrFrame;
- }
- else
- ++m_Anim.m_nCurrFrame; // Move to the last frame
- } else {
- if ( m_Anim.m_nCurrFrame == 0) {
- m_Anim.m_bIsAnimForward = true;
- ++m_Anim.m_nCurrFrame;
- }
- else
- --m_Anim.m_nCurrFrame;
-
- }
- } else {
- if ( ++m_Anim.m_nCurrFrame == m_CurrState.m_nNoOfFrames) {
- m_Anim.m_nCurrFrame = 0;
- if (m_CurrState.m_nState == ST_KILL) {
- m_CurrState.m_nState = ST_DEAD;
- if (m_pfnDead)
- (*m_pfnDead)(this);
- }
-
- }
- }
- }
- void CSprite::Draw(LPDIRECTDRAWSURFACE7 pdds)
- {
- if (m_CurrState.m_nState == ST_DEAD)
- return;
- RECT rcFrame = { m_CurrState.m_ptFirstFrame.x + (m_Anim.m_nCurrFrame * m_Anim.m_nWidth),
- m_CurrState.m_ptFirstFrame.y,
- m_CurrState.m_ptFirstFrame.x + (m_Anim.m_nCurrFrame * m_Anim.m_nWidth) + m_Anim.m_nWidth,
- m_CurrState.m_ptFirstFrame.y + m_Anim.m_nHeight };
-
- if (m_Movement.m_nInvulnerable)
- m_Movement.m_nInvulnerable--;
- if ((m_Movement.m_nInvulnerable % 2)==0) {
- pdds->BltFast(m_ptLocation.x, m_ptLocation.y, (*m_ppSurface)->GetDDrawSurface(), &rcFrame, DDBLTFAST_SRCCOLORKEY);
- }
-
- if (m_bDrawBorder) {
- CSurface Surface;
- rcFrame.left = m_ptLocation.x; rcFrame.top = m_ptLocation.y ;
- rcFrame.right= m_ptLocation.x + m_Anim.m_nWidth; rcFrame.bottom =m_ptLocation.y + m_Anim.m_nHeight;
- Surface.Create(pdds);
- Surface.DrawRect(rcFrame, RGB(0,255,0));
- Surface.DrawRect(GetBoundingRect(m_ptLocation), RGB(0,255,0));
- }
- }
- RECT CSprite::GetRect()
- {
- RECT rcRect = { m_ptLocation.x, m_ptLocation.y, m_ptLocation.x + m_Anim.m_nWidth, m_ptLocation.y + m_Anim.m_nHeight };
- return rcRect;
-
- }
- void CSprite::MoveTo(long nX, long nY)
- {
- m_ptLocation.x = nX;
- m_ptLocation.y = nY;
- }
- long& CSprite::GetState()
- {
- return m_CurrState.m_nState;
- }
- void CSprite::EnableBorder(bool bDraw)
- {
- m_bDrawBorder = bDraw;
- }
- void CSprite::SetAnimBiDir(bool bIsAnimBiDir)
- {
- m_Anim.m_bIsAnimBiDir = bIsAnimBiDir;
- }
- RECT CSprite::GetBoundingRect(POINT &ptLoc)
- {
- RECT rcBound;
- rcBound.left = ptLoc.x + m_CurrState.m_rcBounding.left;
- rcBound.top = ptLoc.y + m_CurrState.m_rcBounding.top;
- rcBound.right = rcBound.left + m_CurrState.m_rcBounding.right;
- rcBound.bottom= rcBound.top + m_CurrState.m_rcBounding.bottom ;
- return rcBound;
- }
- const long& CSprite::GetType()
- {
- return m_nType;
- }
- void CSprite::Destroy()
- {
- list<SSTATE>::iterator iState;
- for ( iState = m_StateList.begin(); iState != m_StateList.end(); iState++) {
- if (iState->m_pSound) {
- delete iState->m_pSound;
- iState->m_pSound = NULL;
- }
- }
- m_StateList.erase(m_StateList.begin(),m_StateList.end());
- }