⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sprite.cpp

📁 Visual C++游戏开发技术与实例一书配套光盘。包含了冒险屠宰场、入侵者、赛车、网络五子棋、网络台球、对战坦克大战和面包圈7个游戏实例的完整源代码。
💻 CPP
字号:
// 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());
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -