📄 game.cpp
字号:
}
else
{//向左移动,则X值越大越近
Compare.XLarge=true;
}
std::priority_queue<BLOCKINFO,std::vector<BLOCKINFO>,BLOCKINFOCompare> BlockList(Compare);//在运动路径内的所有阻挡物
int start,end;
if(Vert<0)
{//向上移动,只可能是本对象的顶线与阻挡物的底线相碰
start=Obj->YPos;
end=start+Vert;
//判断有无物体在移动路径之内
std::set<CObject*>::const_iterator it;
for(it=m_Object.begin();it!=m_Object.end();it++)
{
if(*it==Obj)continue;//是自己
int ypos=(*it)->YPos+(*it)->Height;
if(ypos>end&&ypos<=start)
{//底线在运动范围之内
//看阻挡物的横坐标是否在运动范围内
int x1=Obj->XPos+Horz*(ypos-start)/Vert;
int x2=x1+Obj->Width;
if(!((*it)->XPos>=x2||(*it)->XPos+(*it)->Width<=x1))
{//横坐标也在运动范围内,则受到阻挡
bi.Blocker=(*it);
bi.BlockMode=2;
bi.BumpMode=2;
bi.MayBe=false;
bi.x=x1;
bi.y=ypos;
BlockList.push(bi);
}
else if( (Horz>0&&(*it)->XPos==x2) || (Horz<0&&(*it)->XPos+(*it)->Width==x1) )
{//在水平方向上有速度,而阻挡物正好在运动区域的左或右边界上,则可能阻挡,也可能不阻挡
bi.Blocker=(*it);
bi.MayBe=true;
bi.x=x1;
bi.y=ypos;
BlockList.push(bi);
}
}
}
}
else if(Vert>0)
{//向下移动,只可能是本对象的底线与阻挡物的顶线相碰
start=Obj->YPos+Obj->Height;
end=start+Vert;
//判断有无物体在移动路径之内
std::set<CObject*>::const_iterator it;
for(it=m_Object.begin();it!=m_Object.end();it++)
{
if(*it==Obj)continue;//是自己
int ypos=(*it)->YPos;
if(ypos>=start&&ypos<end)
{//顶线在运动范围之内
//看阻挡物的横坐标是否在运动范围内
int x1=Obj->XPos+Horz*(ypos-start)/Vert;
int x2=x1+Obj->Width;
if(!((*it)->XPos>=x2||(*it)->XPos+(*it)->Width<=x1))
{//横坐标也在运动范围内,则受到阻挡
bi.Blocker=(*it);
bi.BlockMode=2;
bi.BumpMode=1;
bi.MayBe=false;
bi.x=x1;
bi.y=ypos-Obj->Height;
BlockList.push(bi);
}
else if( (Horz>0&&(*it)->XPos==x2) || (Horz<0&&(*it)->XPos+(*it)->Width==x1) )
{//在水平方向上有速度,而阻挡物正好在运动区域的左或右边界上,则可能阻挡,也可能不阻挡
bi.Blocker=(*it);
bi.MayBe=true;
bi.x=x1;
bi.y=ypos-Obj->Height;
BlockList.push(bi);
}
}
}
}
if(Horz<0)
{//向左移动,只可能是本对象的左边线与阻挡物的右边线相碰
start=Obj->XPos;
end=start+Horz;
//判断有无物体在移动路径之内
std::set<CObject*>::const_iterator it;
for(it=m_Object.begin();it!=m_Object.end();it++)
{
if(*it==Obj)continue;//是自己
int xpos=(*it)->XPos+(*it)->Width;
if(xpos>end&&xpos<=start)
{//右边线在运动范围之内
//看阻挡物的纵坐标是否在运动范围内
int y1=Obj->YPos+Vert*(xpos-start)/Horz;
int y2=y1+Obj->Height;
if(!((*it)->YPos>=y2||(*it)->YPos+(*it)->Height<=y1))
{//纵坐标也在运动范围内,则受到阻挡
bi.Blocker=(*it);
bi.BlockMode=1;
bi.BumpMode=3;
bi.MayBe=false;
bi.x=xpos;
bi.y=y1;
BlockList.push(bi);
}
else if( (Vert>0&&(*it)->YPos==y2) || (Vert<0&&(*it)->YPos+(*it)->Height==y1) )
{//在竖直方向上有速度,而阻挡物正好在运动区域的左或右边界上,则可能阻挡,也可能不阻挡
bi.Blocker=(*it);
bi.MayBe=false;
bi.x=xpos;
bi.y=y1;
BlockList.push(bi);
}
}
}
if(end<0)
{//左边线超出左边界
bi.Blocker=NULL;
bi.BlockMode=1;
bi.MayBe=false;
bi.x=0;
bi.y=Obj->YPos+Vert*(0-start)/Horz;
BlockList.push(bi);
}
}
else if(Horz>0)
{//向右移动,只可能是本对象的右边线与阻挡物的左边线相碰
start=Obj->XPos+Obj->Width;
end=start+Horz;
//判断有无物体在移动路径之内
std::set<CObject*>::const_iterator it;
for(it=m_Object.begin();it!=m_Object.end();it++)
{
if(*it==Obj)continue;//是自己
int xpos=(*it)->XPos;
if(xpos>=start&&xpos<end)
{//左边线在运动范围之内
//看阻挡物的纵坐标是否在运动范围内
int y1=Obj->YPos+Vert*(xpos-start)/Horz;
int y2=y1+Obj->Height;
if(!((*it)->YPos>=y2||(*it)->YPos+(*it)->Height<=y1))
{//纵坐标也在运动范围内,则受到阻挡
bi.Blocker=(*it);
bi.BlockMode=1;
bi.BumpMode=3;
bi.MayBe=false;
bi.x=xpos-Obj->Width;
bi.y=y1;
BlockList.push(bi);
}
else if( (Vert>0&&(*it)->YPos==y2) || (Vert<0&&(*it)->YPos+(*it)->Height==y1) )
{//在水平方向上有速度,而阻挡物正好在运动区域的左或右边界上,则可能阻挡,也可能不阻挡
bi.Blocker=(*it);
bi.MayBe=true;
bi.x=xpos-Obj->Width;
bi.y=y1;
BlockList.push(bi);
}
}
}
if(end+Obj->Width>288)
{//右边线超出左边界
bi.Blocker=NULL;
bi.BlockMode=1;
bi.MayBe=false;
bi.x=288-Obj->Width;
bi.y=Obj->YPos+Vert*(288-start)/Horz;
BlockList.push(bi);
}
}
//若没有阻挡,则运动到指定的位置
Obj->XPos=OrDestX;
Obj->YPos=OrDestY;
std::set<CObject*> Has;
for(;!BlockList.empty();BlockList.pop())
{
if(Has.find(BlockList.top().Blocker)!=Has.end())continue;//可能会有重复项
Has.insert(BlockList.top().Blocker);
int BumpMode;
if(BlockList.top().MayBe)
{//是一个刚好在边界上的阻挡物
if(Obj==m_Mario)
{//玛莉遇到这种情况,视为竖直方向遇到阻挡,仍可水平行走
retval=2;
BumpMode=Vert>0?1:2;
}
else
{//妖怪遇到这种情况,视为水平方向遇到阻挡,使其掉下去
retval=1;
BumpMode=3;
}
Obj->Bump(BlockList.top().Blocker,BumpMode,true);
//自己碰对方和对方碰自己的方式正好上下相反
if(1==BumpMode)
BumpMode=2;
else if(2==BumpMode)
BumpMode=1;
BlockList.top().Blocker->Bump(Obj,BumpMode,false);
if(!Obj->Block(BlockList.top().Blocker))continue;//不受阻挡,则继续看更远的阻挡物
Obj->XPos=BlockList.top().x;
Obj->YPos=BlockList.top().y;
break;
}
else
{
if(BlockList.top().Blocker)
{
Obj->Bump(BlockList.top().Blocker,BlockList.top().BumpMode,true);
//自己碰对方和对方碰自己的方式正好上下相反
if(1==BlockList.top().BumpMode)
BumpMode=2;
else if(2==BlockList.top().BumpMode)
BumpMode=1;
else
BumpMode=3;
BlockList.top().Blocker->Bump(Obj,BumpMode,false);
}
if(!Obj->Block(BlockList.top().Blocker))continue;//不受阻挡,则继续看更远的阻挡物
Obj->XPos=BlockList.top().x;
Obj->YPos=BlockList.top().y;
retval=BlockList.top().BlockMode;
BlockList.pop();
//同一距离可能有多个阻挡物,与它们都相碰
while(!BlockList.empty())
{
if(BlockList.top().MayBe)break;
if(BlockList.top().x!=Obj->XPos||BlockList.top().y!=Obj->YPos)break;
if(BlockList.top().Blocker)
{
Obj->Bump(BlockList.top().Blocker,BlockList.top().BumpMode,true);
//自己碰对方和对方碰自己的方式正好上下相反
if(1==BlockList.top().BumpMode)
BumpMode=2;
else if(2==BlockList.top().BumpMode)
BumpMode=1;
BlockList.top().Blocker->Bump(Obj,BumpMode,false);
}
BlockList.pop();
}
break;
}
}
if(1==retval)
{
if(Obj->YPos!=OrDestY)
{//水平方向有阻挡,且未达到指定的纵坐标,则要在竖直方向上走完该距离
retval|=Move(Obj,0,OrDestY-Obj->YPos);
}
}
else if(2==retval||4==retval)
{
if(Obj->XPos!=OrDestX)
{//竖直方向有阻挡,且未达到指定的横坐标,则要在水平方向上走完该距离
retval|=Move(Obj,OrDestX-Obj->XPos,0);
}
}
return retval;
}
void CGame::LoadMapData()
{
m_SoundMan->PlayBackMusic(1);
//将玛莉重置到这一关的起始位置
m_Mario->ResetPos(m_MapData[0]*16,m_MapData[1]*16);
//加载地图最前面16*20格的数据
int x,y;
const int (*pMap)[16];
pMap=reinterpret_cast<const int(*)[16]>(m_MapData+3);
for(x=0;x<20;x++)
{
for(y=0;y<16;y++)
{
if(pMap[x][y])InsertObject(x*16,y*16,pMap[x][y]);
}
}
m_MapPos=0;
m_NextMap=20;
}
void CGame::MoveMap(int Offset)
{
/*
将地图向左移动,读取右边的新数据。
参数:
[i]Offset 要移动的像素。
*/
int NewPos=m_MapPos+Offset;
if(NewPos>m_MapData[2]*16-288)NewPos=m_MapData[2]*16-288;//已到达最右边
Offset=NewPos-m_MapPos;
if(!Offset)return;//没有移动
m_MapPos=NewPos;
//所有的角色和物体都向左移动
std::set<CObject*>::iterator it;
for(it=m_Object.begin();it!=m_Object.end();it++)
{
(*it)->XPos-=Offset;
}
//读取右边的新数据
int end=(m_MapPos+288+(16-1))/16+1;//读到右边界外的一格
if(end>m_MapData[2])end=m_MapData[2];//右边界外已经没有了,则只读到右边界处
int x;
int y;
const int (*pMap)[16];
pMap=reinterpret_cast<const int(*)[16]>(m_MapData+3);
for(x=m_NextMap;x<end;x++)
{
for(y=0;y<16;y++)
{
if(pMap[x][y])InsertObject(x*16-m_MapPos,y*16,pMap[x][y]);
}
}
m_NextMap=end;
}
void CGame::AddObj(CObject * Obj)
{
/*
新增一个角色或物体。
参数:
[i]Obj 要增加的对象。
*/
m_Object.insert(Obj);
}
void CGame::SetSound(CSoundMan * Obj)
{
/*
设置声音处理对象。
参数:
[i]Obj 要使用的CSoundMan对象。在游戏中,CGame将通过该对象控制声音。
*/
m_SoundMan=Obj;
}
void CGame::PlaySound(CSoundMan::SOUNDNUM Num)
{
m_SoundMan->PlaySound(Num);
}
void CGame::PlayBackMusic(int Num)
{
m_SoundMan->PlayBackMusic(Num);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -