📄 m_entity.cpp
字号:
//Add Entity to chgList
thisRenderer->AddEC(thisEnt->nPosX,thisEnt->nPosY,thisEnt->nTexture,fOffsetX,fOffsetY);
//refresh last mov direction
nLastMovDir = direction;
return M_NORMAL;
}
return M_ERR_NOTLIVING;
}
int M_Mover::MoverSpeed(int desiredSpeed)
{
if(desiredSpeed!=-1 && desiredSpeed>=0)
{
thisEnt->fSpeed = desiredSpeed;
}
return thisEnt->fSpeed;
}
bool M_Mover::HaveOffset()
{
if(fOffsetX==0 && fOffsetY==0)
{
return M_FALSE;
}
return M_TRUE;
}
int M_Mover::MoverState(int state)
{
if(state!=-1) nState = state;
return nState;
}
/////////////////////////////
// M_SPRITE CLASS
///////////////////////////
M_Sprite::M_Sprite()
{
thisEnt->fSpeed = DEFAULT_SPRITE_SPEED;
thisEnt->nTexture = T_NORMAL_SPRITE;
thisEnt->nPosX = -1;//Not Respawn yet
thisEnt->nPosY = -1;
thisEnt->nDirection = DIR_STEADY;
thisEnt->isLiving = M_FALSE;
isInit = M_TRUE;
nLives = DEFAULT_SPRITE_LIVES;
nNextMovDir = DIR_STEADY;
nLastMovDir = DIR_STEADY;
fOffsetX = 0;
fOffsetY = 0;
lTotalScore = 0;
bReadyToRespawn = M_FALSE;//don't respawn until user confirmed
lZombieTime = DEFAULT_ZOMBIE_TIME;
}
bool M_Sprite::Respawn()
{
if(nLives<=0) return M_ERR_NO_LIVES;//if no lives
if(thisEnt->isLiving == M_FALSE && bReadyToRespawn == M_TRUE)
{
//if it's first time called
if(isInit == M_TRUE )
{
if(thisMap->GetMapState() == M_TRUE)
{
//looks for map defined initial respawn point
thisEnt->nPosX = thisMap->GetMapInfo()->nInitialSRPointX;
thisEnt->nPosY = thisMap->GetMapInfo()->nInitialSRPointY;
nTotalSRP = thisMap->GetMapInfo()->nTotalSRPoints;
isInit = M_FALSE;
}
else
{
return M_ERR_MAP_NOT_READY;
}
}
else //still have lives
{
srand((unsigned)clockticks);
randomize();
const RespawnPoint* thisSRP = thisMap->SRPS()+(rand()%nTotalSRP);
thisEnt->nPosX = thisSRP->x;//get a random SRP to respawn
thisEnt->nPosY = thisSRP->y;
}
//reset directions
thisEnt->nDirection = DIR_STEADY;
nNextMovDir = DIR_STEADY;
nLastMovDir = DIR_STEADY;
thisEnt->isLiving = M_TRUE;
fOffsetX = 0;
fOffsetY = 0;
nState = S_NORMAL;
bReadyToRespawn = M_FALSE;
//fill changed list
thisRenderer->AddMBC(thisEnt->nPosX,thisEnt->nPosY,thisMap->GetMapBlockInfo(thisEnt->nPosX,thisEnt->nPosY)->nTexture);
thisRenderer->AddEC(thisEnt->nPosX,thisEnt->nPosY,thisEnt->nTexture);
return M_NORMAL;
}
else
{
return M_ERR_ALREADY_LIVING;
}
}
bool M_Sprite::Kill()
{
if(thisEnt->isLiving == M_TRUE)
{
thisEnt->isLiving = M_FALSE;
nLives--;
//fill changed list.//maybe need to add the offset??
thisRenderer->AddMBC(thisEnt->nPosX,thisEnt->nPosY,thisMap->GetMapBlockInfo(thisEnt->nPosX,thisEnt->nPosY)->nTexture);
if(nLastMovDir == DIR_UP || nLastMovDir == DIR_DOWN)
{//if offsets is presented, refresh the DOWN one
if(fOffsetX!=0 || fOffsetY!=0)
thisRenderer->AddMBC(thisEnt->nPosX,thisEnt->nPosY+1,thisMap->GetMapBlockInfo(thisEnt->nPosX,thisEnt->nPosY+1)->nTexture);
}
if(nLastMovDir == DIR_LEFT || nLastMovDir == DIR_RIGHT)
{//if offsets is presented, refresh the RIGHT one
if(fOffsetX!=0 || fOffsetY!=0)
thisRenderer->AddMBC(thisEnt->nPosX+1,thisEnt->nPosY,thisMap->GetMapBlockInfo(thisEnt->nPosX+1,thisEnt->nPosY)->nTexture);
}
bReadyToRespawn = M_FALSE;
lZombieTime = clockticks + DEFAULT_ZOMBIE_TIME;
return M_NORMAL;
}
return M_ERR_NOTLIVING;
}
bool M_Sprite::Think()
{
if(thisEnt->isLiving == M_FALSE)
{
//do not respawn until user confirmed
if(thisEvent->GetEvent() == M_KEY_PRESSED || clockticks>lZombieTime)
bReadyToRespawn = M_TRUE;
if(Respawn() == M_ERR_NO_LIVES)
return M_ERR_NO_LIVES;
else//if respawn is success
return M_NORMAL;
}
//State check
if(nState==S_POWER) thisEnt->nTexture=T_ALT_SPRITE;
if(nState==S_NORMAL)
{
thisEnt->nTexture = T_NORMAL_SPRITE;
thisEnt->fSpeed = DEFAULT_SPRITE_SPEED;
}
if(nState==S_SPEED)
{
thisEnt->nTexture=T_ALT_SPRITE;
thisEnt->fSpeed = DEFAULT_SPRITE_SPEED * SPEED_EFFECT;
}
//Event CHECK
if(thisEvent->GetEvent() == M_KEY_PRESSED)
{
DispatchEvent();
}
//take action
Move(thisEnt->nDirection);
return M_NORMAL;
}
void M_Sprite::DispatchEvent()
{
const MapBlock* mbUp = thisMap->GetMapBlockInfo(thisEnt->nPosX,thisEnt->nPosY-1);
const MapBlock* mbDn = thisMap->GetMapBlockInfo(thisEnt->nPosX,thisEnt->nPosY+1);
const MapBlock* mbLt = thisMap->GetMapBlockInfo(thisEnt->nPosX-1,thisEnt->nPosY);
const MapBlock* mbRt = thisMap->GetMapBlockInfo(thisEnt->nPosX+1,thisEnt->nPosY);
switch(thisEvent->keyCode)
{
case KP_UPARROW:
case K_UPARROW:{//We don't check if it's going into avoid!!! Be sure to build the map carefully!
if(mbUp->nBlockType!=B_WALL && fOffsetX==0 && fOffsetY==0)
{
thisEnt->nDirection = DIR_UP;
nNextMovDir = DIR_STEADY;
}
else
{
nNextMovDir = DIR_UP;
}
break;
}
case KP_DOWNARROW:
case K_DOWNARROW:{
if(mbDn->nBlockType!=B_WALL && fOffsetX==0 && fOffsetY==0)
{
thisEnt->nDirection = DIR_DOWN;
nNextMovDir = DIR_STEADY;
}
else
{
nNextMovDir = DIR_DOWN;
}
break;
}
case KP_LEFTARROW:
case K_LEFTARROW:{
if(mbLt->nBlockType!=B_WALL && fOffsetX==0 && fOffsetY==0)
{
thisEnt->nDirection = DIR_LEFT;
nNextMovDir = DIR_STEADY;
}
else
{
nNextMovDir = DIR_LEFT;
}
break;
}
case KP_RIGHTARROW:
case K_RIGHTARROW:{
if(mbRt->nBlockType!=B_WALL && fOffsetX==0 && fOffsetY==0)
{
thisEnt->nDirection = DIR_RIGHT;
nNextMovDir = DIR_STEADY;
}
else
{
nNextMovDir = DIR_RIGHT;
}
break;
}
case K_ESC:{
//KILL!
Kill();
break;
}
}
}
int M_Sprite::AddLives(int deltaLives)
{
if(deltaLives!=0)
{
nLives+=deltaLives;
}
return nLives;
}
long M_Sprite::AddScore(int score)
{
lTotalScore+=score;
return lTotalScore;
}
//////////////////////
// M_MONSTER CLASS
//////////////////////
int M_Monster::presentMRP = 0;//static variable
M_Monster::M_Monster()
{
srand((unsigned)clockticks);
thisEnt->fSpeed = DEFAULT_MONSTER_SPEED + float(rand()%100)/100;
thisEnt->nTexture = T_NORMAL_MONSTER;
thisEnt->nPosX = -1;//Not Respawn yet
thisEnt->nPosY = -1;
thisEnt->nDirection = DIR_STEADY;
thisEnt->isLiving = M_FALSE;
nNextMovDir = DIR_STEADY;
nLastMovDir = DIR_STEADY;
curNextDir = DIR_STEADY;
fOffsetX = 0;
fOffsetY = 0;
}
bool M_Monster::Respawn()
{
if(thisEnt->isLiving == M_FALSE)//only dead things can respawn
{
if(thisMap->GetMapState() == M_TRUE)
{
const RespawnPoint* thisMRP = thisMap->MRPS()+(presentMRP++);
if(presentMRP==thisMap->GetMapInfo()->nTotalMRPoints)
{
//srand((unsigned)clockticks);
presentMRP=0;//rand()%(thisMap->GetMapInfo()->nTotalMRPoints);
}
thisEnt->nPosX = thisMRP->x;//get a random MRP to respawn
thisEnt->nPosY = thisMRP->y;
}
else
{
return M_ERR_MAP_NOT_READY;
}
//reset directions
thisEnt->nDirection = DIR_STEADY;
nNextMovDir = DIR_STEADY;
nLastMovDir = DIR_STEADY;
thisEnt->isLiving = M_TRUE;
fOffsetX = 0;
fOffsetY = 0;
curNextDir = DIR_STEADY;
nState = S_NORMAL;
nAwareDistance = DEFAULT_AWARE_DISTANCE;
//fill changed list
thisRenderer->AddMBC(thisEnt->nPosX,thisEnt->nPosY,thisMap->GetMapBlockInfo(thisEnt->nPosX,thisEnt->nPosY)->nTexture);
thisRenderer->AddEC(thisEnt->nPosX,thisEnt->nPosY,thisEnt->nTexture);
return M_NORMAL;
}
else
{
return M_ERR_ALREADY_LIVING;
}
}
bool M_Monster::Kill()
{
if(thisEnt->isLiving == M_TRUE)//only living things can die...
{
thisEnt->isLiving = M_FALSE;
//fill changed list.
thisRenderer->AddMBC(thisEnt->nPosX,thisEnt->nPosY,thisMap->GetMapBlockInfo(thisEnt->nPosX,thisEnt->nPosY)->nTexture);
if(nLastMovDir == DIR_UP || nLastMovDir == DIR_DOWN)
{//if offsets is presented, refresh the DOWN one
if(fOffsetX!=0 || fOffsetY!=0)
thisRenderer->AddMBC(thisEnt->nPosX,thisEnt->nPosY+1,thisMap->GetMapBlockInfo(thisEnt->nPosX,thisEnt->nPosY+1)->nTexture);
}
if(nLastMovDir == DIR_LEFT || nLastMovDir == DIR_RIGHT)
{//if offsets is presented, refresh the RIGHT one
if(fOffsetX!=0 || fOffsetY!=0)
thisRenderer->AddMBC(thisEnt->nPosX+1,thisEnt->nPosY,thisMap->GetMapBlockInfo(thisEnt->nPosX+1,thisEnt->nPosY)->nTexture);
}
return M_NORMAL;
}
return M_ERR_NOTLIVING;
}
bool M_Monster::Think()
{
//A monster is immortal, respawns again and again...
if(thisEnt->isLiving == M_FALSE)
{
Respawn();
return M_NORMAL;
}
//State check
if(nState==S_WEAK)
{
thisEnt->nTexture=T_ALT_MONSTER;
thisEnt->fSpeed = DEFAULT_MONSTER_SPEED * SLOW_FACTOR;//slows down when weak
}
if(nState==S_NORMAL)
{
thisEnt->nTexture=T_NORMAL_MONSTER;
thisEnt->fSpeed = DEFAULT_MONSTER_SPEED;
}
//think about the path
RandomDir();
//take action
Move(thisEnt->nDirection);
return M_NORMAL;
}
int M_Monster::RandomDir()
{
//FIX ME!!! - when (especially when Extra AI changed the next direction)
// present direction == steady && nextmove!=steady, it stuck!
// this line intends to fix the bug
if(thisEnt->nDirection==DIR_STEADY && curNextDir!=DIR_STEADY)
curNextDir=DIR_STEADY;
//STEP 0. Only when present direction equals current next direction
if(curNextDir == thisEnt->nDirection)
{
const MapBlock *mb[4];//0-UP,1-DOWN,2-LEFT,3-RIGHT
int dir[4]={DIR_STEADY, DIR_STEADY, DIR_STEADY,DIR_STEADY};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -