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

📄 m_entity.cpp

📁 C++课程大学作业的一次任务
💻 CPP
📖 第 1 页 / 共 3 页
字号:

	//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 + -