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

📄 m_entity.cpp

📁 C++课程大学作业的一次任务
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	//0-Present Direction, 1-Opposit Direction, 2-Other Dir 1, 3-Other Dir 2
	float fChance[4]={0,0,0,0};
	float tmpChance = 0;
	int deltaX=0, deltaY=0, accessible=0, accessList=0, nCnt=0;


//STEP 1. If present direction is STEADY, all possible direction go equal chance
	if(thisEnt->nDirection==DIR_STEADY)
	{//this should only happens when it respawn
		mb[0] = thisMap->GetMapBlockInfo(thisEnt->nPosX,thisEnt->nPosY-1);
		mb[1] = thisMap->GetMapBlockInfo(thisEnt->nPosX,thisEnt->nPosY+1);
		mb[2] = thisMap->GetMapBlockInfo(thisEnt->nPosX-1,thisEnt->nPosY);
		mb[3] = thisMap->GetMapBlockInfo(thisEnt->nPosX+1,thisEnt->nPosY);
		//check all accessible direction
		for(nCnt=0; nCnt<4; nCnt++)
		{
			if(mb[nCnt]->nBlockType!=B_WALL)
			{
				dir[nCnt] = nCnt+1;//zero fix, as c++ starts from 0 not 1
				accessible++;
				accessList+=(1<<nCnt);//0001 0010 0100 1000
			}
		}

		//calculate equal chances. Sorry, some complicated gramma... @_@
		for(nCnt=0; nCnt<4; nCnt++)
		{//that means:
		//(chance of this direction) = (1/total num of accessible direction) *
		//(is this direction accessible? 1-yes, 0-no)
			fChance[nCnt] = (1/float(accessible)) * (((accessList^(1<<nCnt))&(1<<nCnt))?0:1);
		}

		if(fChance[0]==fChance[1] && fChance[1]==fChance[2]
			&& fChance[2]==fChance[3] && fChance[3]==0)
		{//if all direction access denied
			return DIR_STEADY;
		}

		//go test
		srand((unsigned)clockticks);
		tmpChance = float(rand()%100)/100;

		if(tmpChance<fChance[0])
			return((curNextDir = nNextMovDir = thisEnt->nDirection = dir[0]));

		if(tmpChance>=fChance[0] && tmpChance<fChance[0]+fChance[1])
			return((curNextDir = nNextMovDir = thisEnt->nDirection = dir[1]));

		if(tmpChance>=fChance[0]+fChance[1] && tmpChance<fChance[0]+fChance[1]+fChance[2])
			return((curNextDir = nNextMovDir = thisEnt->nDirection = dir[2]));

		if(tmpChance>=fChance[0]+fChance[1]+fChance[2] && tmpChance<fChance[0]+fChance[1]+fChance[2]+fChance[3])
			return((curNextDir = nNextMovDir = thisEnt->nDirection = dir[3]));
	}
//STEP 2. If not respawn
	else
	{
		dir[0] = thisEnt->nDirection;
		switch(dir[0])
		{
			case DIR_UP:	dir[1] = DIR_DOWN;
							dir[2] = DIR_LEFT;
							dir[3] = DIR_RIGHT;
							break;

			case DIR_DOWN:	dir[1] = DIR_UP;
							dir[2] = DIR_LEFT;
							dir[3] = DIR_RIGHT;
							break;

			case DIR_LEFT:	dir[1] = DIR_RIGHT;
							dir[2] = DIR_UP;
							dir[3] = DIR_DOWN;
							break;

			case DIR_RIGHT:	dir[1] = DIR_LEFT;
							dir[2] = DIR_UP;
							dir[3] = DIR_DOWN;
							break;
		}

//STEP 3. Check access
		switch(thisEnt->nDirection)
		{//calculate delta moves
			case DIR_UP:     deltaX=0;  deltaY=-1; break;
			case DIR_DOWN:   deltaX=0;  deltaY=1;  break;
			case DIR_LEFT:   deltaX=-1; deltaY=0;  break;
			case DIR_RIGHT:  deltaX=1;  deltaY=0;  break;
			case DIR_STEADY: deltaX=0;  deltaY=0;  break;
		}
		//get next block info <0-UP,1-DOWN,2-LEFT,3-RIGHT>
		mb[0] = thisMap->GetMapBlockInfo(thisEnt->nPosX+deltaX,thisEnt->nPosY+deltaY-1);
		mb[1] = thisMap->GetMapBlockInfo(thisEnt->nPosX+deltaX,thisEnt->nPosY+deltaY+1);
		mb[2] = thisMap->GetMapBlockInfo(thisEnt->nPosX+deltaX-1,thisEnt->nPosY+deltaY);
		mb[3] = thisMap->GetMapBlockInfo(thisEnt->nPosX+deltaX+1,thisEnt->nPosY+deltaY);

		//check access for 4 dir
		for(int dirCnt=0; dirCnt<4; dirCnt++)
		{
		 for(nCnt=0; nCnt<4; nCnt++)
		 {
			if(dir[dirCnt]==(nCnt+1) && mb[nCnt]->nBlockType!=B_WALL)
			{
				accessible++;
				accessList+=(1<<dirCnt);
			}
		 }
		}

		if(((accessList^4)&4) && ((accessList^8)&8) && !((accessList^1)&1))
		{//if both OTHER DIRECTIONs access denied,
		 //and PRESENT DIRECTION accessible
			return((nNextMovDir=curNextDir=thisEnt->nDirection));
		}//return PRESENT direction

		if(((accessList^4)&4) && ((accessList^8)&8) && ((accessList^1)&1))
		{//if neither OTHER DIRECTIONs nor PRESENT DIRECTION is accessible
			return((nNextMovDir=curNextDir=dir[1]));
		}//return OPPOSIT direction

		if(!((accessList^4)&4) || !((accessList^8)&8))
		{//if either OTHER DIRECTION is accessible
		 //set chances
			if(!((accessList^4)&4) && !((accessList^8)&8))
			{//if both OTHER DIRECTION are accessible
				fChance[2]=fChance[3]=0.4;
			}
			else
			{//if only one of the OTHER DIRECTIONs is accessible
				if(!((accessList^4)&4))//if OTHER DIRECTION 1 accessible
					fChance[2] = 0.8;
				else//if OTHER DIRECTION 2 accessible
					fChance[3] = 0.8;
			}

			if(!((accessList^1)&1) && !((accessList^2)&2))
			{//if both PRESENT and OPPOSIT DIRECTIONs are accessible
				fChance[0] = 0.15;
				fChance[1] = 0.05;
			}
			else
			{//if only one of them is accessible
				if(!((accessList^1)&1))//if PRESENT DIRECTION accessible
					fChance[0] = 0.2;
				else
					fChance[1] = 0.2;//if OPPOSIT DIRECTION accessible
			}
		}



//STEP 4. Calculate the final random next direction
		srand((unsigned)clockticks);//use MILLISECOND RESOLUTION TIMER as seed
		tmpChance = float(rand()%100)/100;//get a random 0.x number

		if(tmpChance<fChance[0])
			return((curNextDir = nNextMovDir = dir[0]));

		if(tmpChance>=fChance[0] && tmpChance<fChance[0]+fChance[1])
			return((curNextDir = nNextMovDir = dir[1]));

		if(tmpChance>=fChance[0]+fChance[1] && tmpChance<fChance[0]+fChance[1]+fChance[2])
			return((curNextDir = nNextMovDir = dir[2]));

		if(tmpChance>=fChance[0]+fChance[1]+fChance[2] && tmpChance<fChance[0]+fChance[1]+fChance[2]+fChance[3])
			return((curNextDir = nNextMovDir = dir[3]));
	}
 }
 return M_ERR_UNKNOWN;//should never reach this line
}

void M_Monster::AIChangeNextMove(int nextMove)
{
	nNextMovDir = nextMove;
	curNextDir = nextMove;
}

//////////////////////
//    M_ITEM CLASS
//////////////////////
M_Item::M_Item()
{
	nScore = DEFAULT_ADDITION_SCORE;
}

bool M_Item::bDisable = M_FALSE;//static member

//////////////////////
// M_POWERDOT CLASS
//////////////////////

M_PowerDot::M_PowerDot(int x, int y)
{
	thisEnt->nPosX = x;
	thisEnt->nPosY = y;
	thisEnt->fSpeed = 0;
	thisEnt->nDirection = DIR_STEADY;
	thisEnt->nTexture = T_POWER_DOT;
	thisEnt->isLiving = M_FALSE;

	nScore = -(DEFAULT_MONSTER_SCORE);//equals one monster's score
	isActivated = M_FALSE;
	nextThinkTime = -1;
}

bool M_PowerDot::Respawn()
{//if not activated and is not living
 if(isActivated==M_FALSE && thisEnt->isLiving==M_FALSE)
 {
	thisRenderer->AddEC(thisEnt->nPosX, thisEnt->nPosY, thisEnt->nTexture);
	thisEnt->isLiving = M_TRUE;
 }
 else
 {
	if(thisEnt->isLiving == M_TRUE)
		return M_ERR_ALREADY_LIVING;
	if(isActivated == M_TRUE)
		return M_ERR_ITEM_ALREADY_USED;
 }

 return M_ERR_UNKNOWN;
}

bool M_PowerDot::Think(M_Sprite* sprite, MonsterNode* monsters)
{
 if(thisEnt->isLiving == M_TRUE)//only when living
 {
  if(bDisable!=M_TRUE && nextThinkTime == -1)//not activating
  {
	if(sprite->Report()->nPosX == thisEnt->nPosX &&
		sprite->Report()->nPosY == thisEnt->nPosY)
	{
		sprite->MoverState(S_POWER);//set Sprite to be POWERed
		sprite->AddScore(nScore);
		MonsterNode* ThisNode = monsters;

		while(ThisNode!=NULL)
		{
			ThisNode->thisMonster->MoverState(S_WEAK);
			ThisNode = ThisNode->nextMonster;
		}

		nextThinkTime = clockticks + 10000;
		thisRenderer->AddMBC(thisEnt->nPosX, thisEnt->nPosY, T_SPACE);
		isActivated = M_TRUE;
		bDisable = M_TRUE;
	 return M_NORMAL;
	}
	else
	{
		thisRenderer->AddEC(thisEnt->nPosX, thisEnt->nPosY, thisEnt->nTexture);
	 return M_NORMAL;
	}
  }
  else
  {
   if(nextThinkTime!=-1)
   {
	if(clockticks<nextThinkTime)
	{
		return M_NORMAL;
	}
	else
	{
		sprite->MoverState(S_NORMAL);

		MonsterNode* ThisNode = monsters;

		while(ThisNode!=NULL)
		{
			if(ThisNode->thisMonster->MoverState()!=S_NORMAL)
			ThisNode->thisMonster->MoverState(S_NORMAL);

			ThisNode = ThisNode->nextMonster;
		}

		nextThinkTime = -1;
		bDisable = M_FALSE;
		Kill();
	  return M_NORMAL;
	}
   }
   else if(bDisable==M_TRUE) thisRenderer->AddMBC(thisEnt->nPosX,thisEnt->nPosY,T_SPACE);
  }
 }
 return M_ERR_NOTLIVING;
}

bool M_PowerDot::Kill()
{
	if(thisEnt->isLiving == M_TRUE)
	{
		thisEnt->isLiving = M_FALSE;
	 return M_NORMAL;
	}
 return M_ERR_NOTLIVING;
}

//////////////////////
// M_SPEEDDOT CLASS
//////////////////////

M_SpeedDot::M_SpeedDot(int x, int y)
{
	thisEnt->nPosX = x;
	thisEnt->nPosY = y;
	thisEnt->fSpeed = 0;
	thisEnt->nDirection = DIR_STEADY;
	thisEnt->nTexture = T_SPEED_DOT;
	thisEnt->isLiving = M_FALSE;

	respawnTime = clockticks+50000;
	nScore = 0;
	isActivated = M_FALSE;
	nextThinkTime = -1;

}

bool M_SpeedDot::Respawn()
{//if not activated and is not living
 if(thisEnt->isLiving==M_FALSE && clockticks>respawnTime)
 {
	thisRenderer->AddEC(thisEnt->nPosX, thisEnt->nPosY, thisEnt->nTexture);
	thisEnt->isLiving = M_TRUE;
 }
 else
 {
	if(thisEnt->isLiving == M_TRUE)
		return M_ERR_ALREADY_LIVING;
	if(clockticks<respawnTime)
		return M_ERR_ITEM_NOT_READY;
 }

 return M_ERR_UNKNOWN;
}

bool M_SpeedDot::Think(M_Sprite* sprite, MonsterNode* monsters)
{
 if(thisEnt->isLiving == M_TRUE)//only when living
 {
  if(bDisable!=M_TRUE && nextThinkTime == -1)
  {
	if(sprite->Report()->nPosX == thisEnt->nPosX &&
		sprite->Report()->nPosY == thisEnt->nPosY)
	{
		sprite->MoverState(S_SPEED);//set Sprite to be SPEEDed
		sprite->AddScore(nScore);
		MonsterNode* ThisNode = monsters;

		while(ThisNode!=NULL)
		{
			ThisNode->thisMonster->MoverState(S_WEAK);
			ThisNode = ThisNode->nextMonster;
		}

		nextThinkTime = clockticks + 20000;
		thisRenderer->AddMBC(thisEnt->nPosX, thisEnt->nPosY, T_SPACE);
		bDisable = M_TRUE;
		isActivated = M_TRUE;

	 return M_NORMAL;
	}
	else
	{
		if(clockticks>respawnTime) thisRenderer->AddEC(thisEnt->nPosX, thisEnt->nPosY, thisEnt->nTexture);
	 return M_NORMAL;
	}
  }
  else
  {
   if(nextThinkTime!=-1)
   {
	if(clockticks<nextThinkTime)
	{
		return M_NORMAL;
	}
	else
	{
		sprite->MoverState(S_NORMAL);

		MonsterNode* ThisNode = monsters;

		while(ThisNode!=NULL)
		{
			if(ThisNode->thisMonster->MoverState()!=S_NORMAL)
				ThisNode->thisMonster->MoverState(S_NORMAL);

			ThisNode = ThisNode->nextMonster;
		}
		isActivated = M_FALSE;
		bDisable = M_FALSE;
		nextThinkTime = -1;
		Kill();
	return M_NORMAL;
	}
   }
   else if(bDisable==M_TRUE) thisRenderer->AddMBC(thisEnt->nPosX,thisEnt->nPosY,T_SPACE);
  }
 }
 return M_ERR_NOTLIVING;
}

bool M_SpeedDot::Kill()
{
	if(thisEnt->isLiving == M_TRUE)
	{
		thisEnt->isLiving = M_FALSE;
		respawnTime = clockticks+SPEEDDOT_RESPAWN_PERIOD;
	 return M_NORMAL;
	}
 return M_ERR_NOTLIVING;
}

⌨️ 快捷键说明

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