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

📄 sprite.cpp

📁 这是一个屠宰场游戏,此游戏很休闲的请大家下载来看看.
💻 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结构,记录对应状态的数据信息
	
	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;                 //CSound 对象
	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) //碰撞检测:检测精灵是否碰上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);//有交集返回true
}
////////////////////////////////////////////////////////////////////////
// Move sprite to new location
////////////////////////////////////////////////////////////////////////
void CSprite::MoveTo(POINT ptNewLoc)//移动精灵到点坐标
{
	m_ptLocation = ptNewLoc;  //m_ptLocation 精灵左上角坐标
}

////////////////////////////////////////////////////////////////////
// helper function of STL find 
///////////////////////////////////////////////////////////////////
bool CSprite::SSTATE::operator==( const long& nState) //SSTATE结构操作符“==”的定义
{
	return m_nState == nState;  //如果相等返回true,否则false
}

//////////////////////////////////////////////////////////////////
// Set the state of the sprite
//////////////////////////////////////////////////////////////////
void CSprite::SetState(long nState, bool bForceState) //设置精灵状态为nState,比如原来是静止的变成向左走
{
	if (m_CurrState.m_nState == nState)//已经是该State
		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) //如果是门,过关,返回true为其它物品
			return;
	}
	//查找 nState
	list<SSTATE>::iterator iState = find(m_StateList.begin(), m_StateList.end(), nState);//使用到操作符等于的定义
	//迭代器 (iterators)。它是指针的概括
	assert(*iState == nState); // iState->m_nState==nState
	m_CurrState = *iState;     // 	m_CurrState 被设置为 状态为nState的结构
	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.
	
	//--- 计算路径
	// 注:m_Movement.m_pfnFindPath 是一个函数指针,如果精灵需要计算路径,必须使它指向一个具体可用的路径计算函数
	// 如果 m_Movement.m_pfnFindPath==NULL 不需要计算路径
    // m_nPathFindDelay,是两次计算路径之间的延时,计算完一次路径之后将沿着该路径走一段时间,直到改变路径
	if (m_Movement.m_pfnFindPath && m_Movement.m_nPathFindDelay != 0) {
		if (m_Movement.m_nCurrPathFindDelay) {
			--m_Movement.m_nCurrPathFindDelay;

		} else { // m_Movement.m_nCurrPathFindDelay==0 时间到,执行计算路径,并重新设定延时
			m_Movement.m_nCurrPathFindDelay = m_Movement.m_nPathFindDelay;
			(*m_Movement.m_pfnFindPath)(this); //计算路径函数
		}
	}


	if (m_CurrState.m_nState == ST_KILL) { //如果被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; //延时基数减少1
		else { //m_Movement.m_nCurrMoveDelay==0
			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);  //this 指代当前Sprite
				}
			} else { //如果没碰撞上迷宫壁
				m_ptLocation = pt;
			}
		}
		
	}

   // 帧延时:

	if (m_Anim.m_nCurrDelay) {  // 延时时间不够 返回
		--m_Anim.m_nCurrDelay;
		return;
	}
	// if (m_Anim.m_nCurrDelay==0) :延时时间到
	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;    //置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 };
	
	// 不死延时计数减1
	if (m_Movement.m_nInvulnerable)
		m_Movement.m_nInvulnerable--;

	if ((m_Movement.m_nInvulnerable % 2)==0) {//不死闪烁,同时等于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 ;
	
	//rcBound.right = ptLoc.x + m_CurrState.m_rcBounding.right;
	//rcBound.bottom= ptLoc.y + 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 + -