示例#1
0
void EntityManager::update(float dt) {
    CCArray *keys = m_pIDToEntitiesMap->allKeys();
    if (keys) {     // if the dictionary has no objects, keys will be NULL
        for (int i=0; i<keys->count(); i++) {
            CCInteger *integer = (CCInteger *)keys->objectAtIndex(i);
            int key = integer->getValue();
            
            BaseGameEntity *entity = (BaseGameEntity *)m_pIDToEntitiesMap->objectForKey(key);
            if (entity->getIsActive()) {    // Only update the entity if it's active.
                entity->update(dt);
            }
        }
    }
    
    /*
    // Add new entities.
    for (int i=0; i<m_pEntitiesToAdd->count(); i++) {
        BaseGameEntity *newEntity = (BaseGameEntity *)m_pEntitiesToAdd->objectAtIndex(i);
        m_pIDToEntitiesMap->setObject(newEntity, newEntity->getID());
    }
    m_pEntitiesToAdd->removeAllObjects();
    */
    
    // Remove old entities.
    for (int i=0; i<m_pEntitiesToRemove->count(); i++) {
        BaseGameEntity *oldEntity = (BaseGameEntity *)m_pEntitiesToRemove->objectAtIndex(i);
        m_pIDToEntitiesMap->removeObjectForKey(oldEntity->getID());
    }
    m_pEntitiesToRemove->removeAllObjects();
}
//---------------------- DispatchDelayedMessages -------------------------
//
//  This function dispatches any telegrams with a timestamp that has
//  expired. Any dispatched telegrams are removed from the queue
//------------------------------------------------------------------------
void MessageDispatcher::DispatchDelayedMessages()
{ 
  //first get current time
  double CurrentTime = TickCounter->GetCurrentFrame(); 

  //now peek at the queue to see if any telegrams need dispatching.
  //remove all telegrams from the front of the queue that have gone
  //past their sell by date
  while( !PriorityQ.empty() &&
	     (PriorityQ.begin()->DispatchTime < CurrentTime) && 
         (PriorityQ.begin()->DispatchTime > 0) )
  {
    //read the telegram from the front of the queue
    const Telegram& telegram = *PriorityQ.begin();

    //find the recipient
    BaseGameEntity* pReceiver = EntityMgr->GetEntityFromID(telegram.Receiver);

    #ifdef SHOW_MESSAGING_INFO
    debug_con << "\nQueued telegram ready for dispatch: Sent to " 
         << pReceiver->ID() << ". Msg is "<< telegram.Msg << "";
    #endif

    //send the telegram to the recipient
    Discharge(pReceiver, telegram);

	//remove it from the queue
    PriorityQ.erase(PriorityQ.begin());
  }
}
示例#3
0
//---------------------- DispatchDelayedMessages -------------------------
//
//  This function dispatches any telegrams with a timestamp that has
//  expired. Any dispatched telegrams are removed from the queue
//------------------------------------------------------------------------
void MessageDispatcher::DispatchDelayedMessages()
{ 
    
   // cout << "\nDispatch Delayed Message";
    //first get current time
    double CurrentTime = Clock->GetCurrentTime(); 
     //cout << "\nCurrent time" << CurrentTime;
    //now peek at the queue to see if any telegrams need dispatching.
    //remove all telegrams from the front of the queue that have gone
    //past their sell by date
    /*if(!PriorityQ.empty()){
        cout << "\nDispatch time" << PriorityQ.begin()->DispatchTime;
    }*/
    
    
    while( !PriorityQ.empty() &&
          (PriorityQ.begin()->DispatchTime < CurrentTime) && 
          (PriorityQ.begin()->DispatchTime > 0) )
    {
        //read the telegram from the front of the queue
        const Telegram& telegram = *PriorityQ.begin();
        
        //find the recipient
        BaseGameEntity* pReceiver = EntityMgr->GetEntityFromID(telegram.Receiver);
        
        cout << "\nQueued telegram ready for dispatch: Sent to " 
        << GetNameOfEntity(pReceiver->ID()) << ". Msg is " << MsgToStr(telegram.Msg);
        
        //send the telegram to the recipient
        Discharge(pReceiver, telegram);
        
        //remove it from the queue
        PriorityQ.erase(PriorityQ.begin());
    }
}
示例#4
0
void
StateZombieChase::Execute(Zombie* pZombie, u32 elapsedTime)
{
    Animate(pZombie, elapsedTime);
    //--------------------------------------------
    //
    // use physics model for executing
    //
    //--------------------------------------------
    // find target object
    ZombiePhysics* pPhysicsModel = pZombie->GetPhysicsModel();

    pPhysicsModel->ResetTarget();

    vector2df me(pZombie->Pos().X,pZombie->Pos().Y);
    std::vector<BaseGameEntity*> enties = EntityMgr.GetEntityListFromGroupID(ENTITY_TYPE_HUMAN);

    bool isTarget = false;
    for (std::vector<BaseGameEntity*>::iterator iter = enties.begin(); iter != enties.end(); iter++)
    {
        // find out close human, but now just get first human....
        BaseGameEntity* pEntity = *iter;
        f32 collisiondistance = me.getDistanceFrom(vector2df(pEntity->Pos().X, pEntity->Pos().Y));
        if(RANGE_ZOMBIE_TARGET_RECOGNITION >= collisiondistance)//ÀÎ½Ä ¹üÀ§ ¾È¿¡¼­ ÀÖ´ÂÁö?
        {
            if(RANGE_ZOMBIE_ATTACKMEELE_RECOGNITION >= collisiondistance)//¸Â ´ê¾Æ¼­ attack mode·Î º¯°æ
            {
                pZombie->GetFSM()->ChangeState(StateZombieAttackBite::Instance());
                isTarget = true;
                break;
            }
            else//¾ÆÁ÷ Á»ºñ°¡ °ø°ÝÇÒ Á¤µµ·Î °¡±õÁö ¾ÊÀ½
            {
                pPhysicsModel->SetTarget(b2Vec2(pEntity->Pos().X, pEntity->Pos().Y));
                isTarget = true;
                break;
            }
        }
    }
    if(!isTarget)//Ÿ°ÙÀ» †õÄ¡¸é ´Ù½Ã roam »óÅ·Î
    {
        //°Ë»ö µÇ¸é ÃßÀû ½ºÅ×ÀÌÆ®·Î º¯½Å
        pZombie->GetPhysicsModel()->GetBody()->m_maxForwardSpeed = ZOMBIE_ROAMSTATE_PHYSICS_MAX_FORWARDSPEED;
        pZombie->GetPhysicsModel()->GetBody()->m_maxDriveForce = ZOMBIE_ROAMSTATE_PHYSICS_MAX_FRONTFORCE;
        //RAN_LOG("Zombie[chase] changestate - Roam");
        pZombie->GetFSM()->ChangeState(StateZombieRoam::Instance());
    }

    pPhysicsModel->Update(elapsedTime);

    //--------------------------------------------
    //
    // apply executed result to object property
    //
    //--------------------------------------------
    b2Vec2 vec = pZombie->GetPhysicsModel()->GetPosition();
    f32 angle = pZombie->GetPhysicsModel()->GetAngle();
    pZombie->SetPos(vector3df(vec.x, vec.y, 0));
    pZombie->SetRotation(vector3df(0.f, 0.f, ANGLE_TO_RADIAN(angle)));
}
//-------------------------------- Cohesion ------------------------------
//
//  returns a steering force that attempts to move the agent towards the
//  center of mass of the agents in its immediate area
//
//  USES SPACIAL PARTITIONING
//------------------------------------------------------------------------
Vector2D SteeringBehavior::CohesionPlus(const vector<Vehicle*> &neighbors)
{
	//first find the center of mass of all the agents
	Vector2D CenterOfMass, SteeringForce;

	int NeighborCount = 0;

	//iterate through the neighbors and sum up all the position vectors
	for (BaseGameEntity* pV = m_pVehicle->World()->CellSpace()->begin();
		!m_pVehicle->World()->CellSpace()->end();
		pV = m_pVehicle->World()->CellSpace()->next())
	{
		//make sure *this* agent isn't included in the calculations and that
		//the agent being examined is close enough
		if (pV != m_pVehicle)
		{
			CenterOfMass += pV->Pos();

			++NeighborCount;
		}
	}

	if (NeighborCount > 0)
	{
		//the center of mass is the average of the sum of positions
		CenterOfMass /= (double)NeighborCount;

		//now seek towards that position
		SteeringForce = Seek(CenterOfMass);
	}

	//the magnitude of cohesion is usually much larger than separation or
	//allignment so it usually helps to normalize it.
	return Vec2DNormalize(SteeringForce);
}
示例#6
0
void HeroHurt::enter(Hero *object)
{
	// 面向对你造成伤害者
	int entity_id = object->getStateMachine()->userdata().hurt_source;
	BaseGameEntity *entity = object->getEntityManger()->getEntityByID(entity_id);
	if (entity != nullptr)
	{
		if (entity->getPositionX() < object->getPositionX())
		{
			object->setDirection(BaseGameEntity::kLeftDirection);
		}
		else
		{
			object->setDirection(BaseGameEntity::kRightDirection);
		}
	}

	system_clock::time_point current_time = system_clock::now();
	system_clock::time_point last_hurt_time = object->getStateMachine()->userdata().was_hit_time;
	system_clock::duration duration = current_time - last_hurt_time;
	if (duration_cast<milliseconds>(duration).count() < 1000)
	{
		++object->getStateMachine()->userdata().was_hit_count;
	}
	else
	{
		object->getStateMachine()->userdata().was_hit_count = 1;
	}

	if (object->getStateMachine()->userdata().was_hit_count < 3)
	{
		Animation *animation = AnimationManger::instance()->getAnimation("hero_hurt");
		Animate *animate = Animate::create(animation);
		animate->setTag(ActionTags::kHeroHurt);
		object->runAction(animate);
		object->getStateMachine()->userdata().was_hit_time = system_clock::now();
	}
	else
	{
		object->getStateMachine()->change_state(HeroKnockout::instance());
	}

	if (object->hasWeapon())
	{
		auto current_level = object->getEntityManger()->getCurrentLevel();
		current_level->dropWeapon(object);
	}
}
示例#7
0
void RabbitWanderingState::Execute(Rabbit* rabbit)
{
	Node* current = rabbit->GetPosition();
	Node* next = current->GetEdges()[Random::Next(0, current->GetEdges().size() - 1)]->child;

	if (next->ContainsEntity("Pill")) {
		BaseGameEntity *pill = next->ContainsEntity("Pill");
		next->RemoveEntity(pill);

		Node *random = rabbit->GetGraph()->GetRandomNode(next);
		random->AddEntity(pill);
		pill->SetPosition(random);

		rabbit->GetFSM()->ChangeState(RabbitSleepingState::Instance());
	}

	rabbit->MoveTo(next);
}
示例#8
0
void RabbitSearchPillState::Execute(Rabbit* rabbit)
{
	Node* current = rabbit->GetPosition();
	Node* next = current->GetEdges()[Random::Next(0, current->GetEdges().size() - 1)]->child;

	if (next->ContainsEntity("Pill")) {
		BaseGameEntity *pill = next->ContainsEntity("Pill");
		next->RemoveEntity(pill);
		pill->SetPosition(nullptr);

		rabbit->Pickup(static_cast<GameItem*>(pill));

		printf("Rabbit: picked up pill\n");

		rabbit->GetFSM()->ChangeState(RabbitWanderingState::Instance());
	}
	rabbit->MoveTo(next);
}
示例#9
0
void 
ChaseGroupState::Execute(ChaserPlayer* pPlayer, u32 elapsedTime)
{
	//sk

	//충돌 처리를 여기 넣는게 맞나?? - 현재 정의된 어떤 상태이든 총알에 영향을 받기 때문에
	//충돌 테스트 - 나중에 독립된 함수로 분리
	std::vector<BaseGameEntity*> vec = EntityMgr.GetCollidedEntites(pPlayer);
	if(vec.size() > 0)
	{
		//if there is bullet, chaser state should be changed.
		std::vector<BaseGameEntity*>::iterator iter;
		for (iter = vec.begin(); iter != vec.end(); iter++)
		{
			BaseGameEntity* pEntity = *iter;
			if(pEntity->Name() == "Bullet")
			{  
				pPlayer->GetFSM()->ChangeState(ChaseDeadState::Instance());
				return;
			}
		}
	}
	Animate(pPlayer, elapsedTime);

	//플레이어를 향해 가도록 설정 
	//*/
	//BaseGameEntity* pTargetEntity = EntityMgr.GetEntityFromID(12); 
	//주인공 케릭터를 얻어오는 방식이 수정되어야 함. 현재 id로 얻어 오는 방식은 ID가 계속 변하기 때문에 의미가 없음.
	std::vector<BaseGameEntity*>  fugivevec = EntityMgr.GetEntityListFromGroupID(100);
	BaseGameEntity* pTargetEntity = fugivevec[0];// 

	vector3df forwardobject = pTargetEntity->Pos()-pPlayer->Pos();
	pPlayer->SetPos(pPlayer->m_myAI.ObjectFlokcing(pPlayer->Pos(),pPlayer->Velocity(), pPlayer->MaxSpeed() ,
		elapsedTime,forwardobject.normalize(),pPlayer->m_uGroupID,pPlayer));
	/*/테스트용 patrol
	pPlayer->SetPos(pPlayer->m_myAI.ObjectFlokcing(pPlayer->Pos(),pPlayer->Velocity(), pPlayer->MaxSpeed() ,
		elapsedTime,pPlayer->Heading(),pPlayer->m_uGroupID,pPlayer));
	//*/
	//end sk  
	
}
示例#10
0
void
StateZombieAttackBite::Execute(Zombie* pZombie, u32 elapsedTime)
{

    Animate(pZombie, elapsedTime);

    //--------------------------------------------
    //
    // use physics model for executing
    //
    //--------------------------------------------
    // find target object
    ZombiePhysics* pPhysicsModel = pZombie->GetPhysicsModel();

    pPhysicsModel->ResetTarget();

    vector2df me(pZombie->Pos().X,pZombie->Pos().Y);
    std::vector<BaseGameEntity*> enties = EntityMgr.GetEntityListFromGroupID(ENTITY_TYPE_HUMAN);

    bool isTarget = false;
    for (std::vector<BaseGameEntity*>::iterator iter = enties.begin(); iter != enties.end(); iter++)
    {
        // find out close human,
        BaseGameEntity* pEntity = *iter;
        f32 collisiondistance = me.getDistanceFrom(vector2df(pEntity->Pos().X, pEntity->Pos().Y));
        if(RANGE_ZOMBIE_ATTACKMEELE_RECOGNITION >= collisiondistance)//±ÙÁ¢ °ø°Ý ¹üÀ§ ¾È¿¡¼­ ÀÖ´ÂÁö?
        {
            pPhysicsModel->SetTarget(b2Vec2(pEntity->Pos().X, pEntity->Pos().Y));
            isTarget = true;
#ifdef ZOBIE_AILEVEL_INFECTION_SYSTEM
            int idAttacked = pEntity->ID();
            //sendmessage: human À» °¨¿°»óÅ·Π...
            Dispatcher->DispatchMsg(SEND_MSG_IMMEDIATELY, // time delay
                                    pZombie->ID(),        // ID of sender
                                    idAttacked,	  // ID of recipient
                                    MSG_TYPE_HUMAN_INFECTION,	  // the message
                                    NO_ADDITIONAL_INFO);
#endif
            break;
        }
    }
    if(!isTarget)//Ÿ°ÙÀ» ³õÄ¡¸é ´Ù½Ã roam »óÅ·Î
    {
        pZombie->GetPhysicsModel()->GetBody()->m_maxForwardSpeed = ZOMBIE_ROAMSTATE_PHYSICS_MAX_FORWARDSPEED;
        pZombie->GetPhysicsModel()->GetBody()->m_maxDriveForce = ZOMBIE_ROAMSTATE_PHYSICS_MAX_FRONTFORCE;
        pZombie->GetFSM()->ChangeState(StateZombieRoam::Instance());
    }

    pPhysicsModel->Update(elapsedTime);

    //--------------------------------------------
    //
    // apply executed result to object property
    //
    //--------------------------------------------
    b2Vec2 vec = pZombie->GetPhysicsModel()->GetPosition();
    f32 angle = pZombie->GetPhysicsModel()->GetAngle();
    pZombie->SetPos(vector3df(vec.x, vec.y, 0));
    pZombie->SetRotation(vector3df(0.f, 0.f, ANGLE_TO_RADIAN(angle)));
}
示例#11
0
//--------------------- GetPosOfClosestSwitch -----------------------------
//
//  returns the position of the closest visible switch that triggers the
//  door of the specified ID
//-----------------------------------------------------------------------------
Vector2D 
Raven_Game::GetPosOfClosestSwitch(Vector2D botPos, unsigned int doorID)const
{
  std::vector<unsigned int> SwitchIDs;
  
  //first we need to get the ids of the switches attached to this door
  std::vector<Raven_Door*>::const_iterator curDoor;
  for (curDoor = m_pMap->GetDoors().begin();
       curDoor != m_pMap->GetDoors().end();
       ++curDoor)
  {
    if ((*curDoor)->ID() == doorID)
    {
       SwitchIDs = (*curDoor)->GetSwitchIDs(); break;
    }
  }

  Vector2D closest;
  double ClosestDist = MaxDouble;
  
  //now test to see which one is closest and visible
  std::vector<unsigned int>::iterator it;
  for (it = SwitchIDs.begin(); it != SwitchIDs.end(); ++it)
  {
    BaseGameEntity* trig = EntityMgr->GetEntityFromID(*it);

    if (isLOSOkay(botPos, trig->Pos()))
    {
      double dist = Vec2DDistanceSq(botPos, trig->Pos());

      if ( dist < ClosestDist)
      {
        ClosestDist = dist;
        closest = trig->Pos();
      }
    }
  }

  return closest;
}
示例#12
0
bool Projectile::handleMessage(const Telegram *telegram) {
    switch (telegram->message) {
        case kMessageReachPosition:
            reset();
            return true;
            
        case kMessageCollide:
            BaseGameEntity *entity = GameModel::instance()->getEntityForID(telegram->sender);
            
            if (arc4random()%10 > 3) {
                return false;
            }
            
            if (entity->getEntityType() == kFighter && entity->getController() != m_eController) {
                MessageDispatcher::instance()->dispatchMessage(0, m_uID, entity->getID(), kMessageHit, (void *)&m_iDamage);
                reset();
                return true;
            }
            return false;
    }
    return false;
}
void 
IdleCamera::Execute(BaseCamera* pCamera, u32 elapsedTime)
{
	// follow target
	int id = pCamera->GetTargetEntityID();
	if (id < 0)
	{
		return;
	}

	BaseGameEntity* pTargetEntity = EntityMgr.GetEntityFromID(id);
	vector3df targetPos = pTargetEntity->Pos();	

	vector3df newPos = vector3df(targetPos.X, targetPos.Y, pCamera->Pos().Z);
	static EventReceiver* pEventReceiver = &(EventRcv);
	/*if (pEventReceiver->IsKeyDown(KEY_KEY_W))
	{
		pEventReceiver->SetKeyDown(KEY_KEY_W, false);

		newPos.Z += 10.0f;
		if (0 <= newPos.Z)
		{
			newPos.Z = -10.f;
		}
	}
	else if (pEventReceiver->IsKeyDown(KEY_KEY_S))
	{
		pEventReceiver->SetKeyDown(KEY_KEY_S, false);

		newPos.Z -= 10.0f;		
	}*/
		
	//pCamera->SetDestPos(newPos, true);
	pCamera->SetPos(newPos);
	pCamera->SetLookAt(vector3df(newPos.X, newPos.Y, targetPos.Z));
}
//---------------------------- Separation --------------------------------
//
// this calculates a force repelling from the other neighbors
//
//  USES SPACIAL PARTITIONING
//------------------------------------------------------------------------
Vector2D SteeringBehavior::SeparationPlus(const vector<Vehicle*> &neighbors)
{
	Vector2D SteeringForce;

	//iterate through the neighbors and sum up all the position vectors
	for (BaseGameEntity* pV = m_pVehicle->World()->CellSpace()->begin();
		!m_pVehicle->World()->CellSpace()->end();
		pV = m_pVehicle->World()->CellSpace()->next())
	{
		//make sure this agent isn't included in the calculations and that
		//the agent being examined is close enough
		if (pV != m_pVehicle)
		{
			Vector2D ToAgent = m_pVehicle->Pos() - pV->Pos();

			//scale the force inversely proportional to the agents distance  
			//from its neighbor.
			SteeringForce += Vec2DNormalize(ToAgent) / ToAgent.Length();
		}

	}

	return SteeringForce;
}
//---------------------------- DispatchMessage ---------------------------
//
//  given a message, a receiver, a sender and any time delay , this function
//  routes the message to the correct agent (if no delay) or stores
//  in the message queue to be dispatched at the correct time
//------------------------------------------------------------------------
void MessageDispatcher::DispatchMessage(double  delay,
                                        int    sender,
                                        int    receiver,
                                        int    msg,
                                        void*  ExtraInfo)
{
  SetTextColor(BACKGROUND_RED|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);

  //get pointers to the sender and receiver
  BaseGameEntity* pSender   = EntityMgr->GetEntityFromID(sender);
  BaseGameEntity* pReceiver = EntityMgr->GetEntityFromID(receiver);

  //make sure the receiver is valid
  if (pReceiver == NULL)
  {
    cout << "\nWarning! No Receiver with ID of " << receiver << " found";

    return;
  }
  
  //create the telegram
  Telegram telegram(0, sender, receiver, msg, ExtraInfo);
  
  //if there is no delay, route telegram immediately                       
  if (delay <= 0.0f)                                                        
  {
    SetTextColor(BACKGROUND_RED|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);
    cout << "\nInstant telegram dispatched at time: " << Clock->GetCurrentTime()
         << " by " << GetNameOfEntity(pSender->ID()) << " for " << GetNameOfEntity(pReceiver->ID()) 
         << ". Msg is "<< MsgToStr(msg);

    //send the telegram to the recipient
    Discharge(pReceiver, telegram);
  }

  //else calculate the time when the telegram should be dispatched
  else
  {
    double CurrentTime = Clock->GetCurrentTime(); 

    telegram.DispatchTime = CurrentTime + delay;

    //and put it in the queue
    PriorityQ.insert(telegram);   

	SetTextColor(BACKGROUND_RED|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);
    cout << "\nDelayed telegram from " << GetNameOfEntity(pSender->ID()) << " recorded at time " 
            << Clock->GetCurrentTime() << " for " << GetNameOfEntity(pReceiver->ID())
            << ". Msg is "<< MsgToStr(msg);
            
  }
}
示例#16
0
bool
Human::Update(u32 elapsedTime)
{
	//--------------------------------------------
	//
	// update entity 
	//
	//--------------------------------------------
	MovingEntity::Update(elapsedTime);

#ifdef HUMAN_AILEVEL_STARVATION_SYSTEM
	//effect which are applied independently of state
	if(m_fCurrentLifeEnergy>0)
		m_fCurrentLifeEnergy-= (elapsedTime * HUMAN_ENERGYDECREASE_PER_MILLISECOND);
	else
		m_fCurrentLifeEnergy=0;
	if(m_fCurrentLifeEnergy < HUMAN_THRESHOLD_TO_STARVATION &&
		this-> m_State != HUMAN_STATE_STARVATION &&
		this-> m_State != HUMAN_STATE_DEATH){
		m_State = HUMAN_STATE_STARVATION;
		GetFSM()->ChangeState(StateHumanStarvation::Instance());
	}
#endif
#ifdef HUMAN_AILEVEL_EAT_SYSTEM
	vector2df me(this->Pos().X,this->Pos().Y);
	std::vector<BaseGameEntity*> enties = EntityMgr.GetEntityListFromGroupID(ENTITY_TYPE_ITEM_FOOD);
	
	//bool isTarget = false;
	for (std::vector<BaseGameEntity*>::iterator iter = enties.begin(); iter != enties.end(); iter++)
	{
		// find out close human, but now just get first human....
		BaseGameEntity* pEntity = *iter;
		f32 collisiondistance = me.getDistanceFrom(vector2df(pEntity->Pos().X, pEntity->Pos().Y));
		if(RANGE_HUMAN_EAT_RECOGNITION >= collisiondistance)
		{
			//식량 섭취
			m_fCurrentLifeEnergy = HUMAN_MAX_LIFE_ENERGY_DEFAULT;
			HumanPhysics* pPhysicsModel = this->GetPhysicsModel();
			pPhysicsModel->ResetTarget();
			GetFSM()->ChangeState(StateHumanHide::Instance());	
			//해당 아이템에 소멸 메세지 전달
			int idfood = pEntity->ID();
			Dispatcher->DispatchMsg(SEND_MSG_IMMEDIATELY, // time delay
								ID(),        // ID of sender
								idfood,	  // ID of recipient
								MSG_TYPE_FOOD_DISAPPEAR,	  // the message
								NO_ADDITIONAL_INFO); 

			//((BaseItem*)pEntity)->GetFSM()->ChangeState(StateBaseItemDisappear::Instance());
			break;
		}
	}	
#endif


	if (m_pStateMachine)
	{
		m_pStateMachine->Update(elapsedTime);
	}

	//이전 프레임의 위치가 필요하므로 저장한다.(업데이트 되기전의 이전 좌표)
	m_VecTemporayPos.X = Pos().X;
	m_VecTemporayPos.Y = Pos().Y;

	//--------------------------------------------
	//
	// sync property with scene node
	//
	//--------------------------------------------
	if (m_p2DSprite)
	{
		m_p2DSprite->setPosition(Pos());
	}

	return this->IsAlived();
}
示例#17
0
void
StateZombieRoam::Execute(Zombie* pZombie, u32 elapsedTime)
{
    Animate(pZombie, elapsedTime);

    //--------------------------------------------
    //
    // use physics model for executing
    //
    //--------------------------------------------
    // find target object
    ZombiePhysics* pPhysicsModel = pZombie->GetPhysicsModel();

    vector2df me(pZombie->Pos().X,pZombie->Pos().Y);
    vector2df roamdest(pZombie->m_VecRoamDest.X,pZombie->m_VecRoamDest.Y);
    //pZombie->CountTimeSamePos(vector2df(pZombie->Pos().X,pZombie->Pos().Y),elapsedTime);
    pZombie->m_AIAgent.CountTimeSamePos(me,
                                        pZombie->m_VecTemporayPos,elapsedTime,pZombie->m_uLockPosTime,TOLERANCE_ZOMBIE_MOVOMENT);

    if(pZombie->m_AIAgent.IsArriveRoamDest(me,roamdest,TOLERANCE_ZOMBIE_ROAMARRIVE) )
    {
        //¹æÇâ Àç ¼³Á¤
        pZombie->m_AIAgent.SetRandDestforRoam(me,pZombie->m_VecRoamDest,RANGE_ZOMBIE_ROAM);

        pPhysicsModel->ResetTarget();
        pPhysicsModel->SetTarget(b2Vec2(pZombie->m_VecRoamDest.X,
                                        pZombie->m_VecRoamDest.Y));
        pZombie->m_uLockPosTime = 0;
        //RAN_LOG("dest point %d, %f, %f", (int)pZombie, pZombie->m_VecRoamDest.X, pZombie->m_VecRoamDest.Y);
    }
    else if(pZombie->m_AIAgent.IsSamePosLongtime(pZombie->m_uLockPosTime,TIME_ZOMBIE_ROCKPOS))//º®¸é¿¡ ºÎµúÈù °æ¿ì ´Ù½Ã ¼³Á¤ or ÀÏÁ¤ ½Ã°£ ÀÌ»ó ÇÑ ÁÂÇ¥¿¡ ¸Ó¹° °æ¿ì
    {
        //¹æÇâ Àç ¼³Á¤
        pZombie->m_AIAgent.SetRandDestforRoam(me,pZombie->m_VecRoamDest,RANGE_ZOMBIE_ROAM);

        pPhysicsModel->ResetTarget();
        pPhysicsModel->SetTarget(b2Vec2(pZombie->m_VecRoamDest.X,
                                        pZombie->m_VecRoamDest.Y));
        pZombie->m_uLockPosTime = 0;
    }
    else
    {
        std::vector<BaseGameEntity*> enties = EntityMgr.GetEntityListFromGroupID(ENTITY_TYPE_HUMAN);
        for (std::vector<BaseGameEntity*>::iterator iter = enties.begin(); iter != enties.end(); iter++)
        {
            // find out close human
            BaseGameEntity* pEntity = *iter;
            if(RANGE_ZOMBIE_RECOGNITION >= me.getDistanceFrom(vector2df(pEntity->Pos().X, pEntity->Pos().Y)))//ÀÎ½Ä ¹üÀ§ ¾È¿¡¼­ ÀÖ´ÂÁö?
            {
                pPhysicsModel->SetTarget(b2Vec2(pEntity->Pos().X, pEntity->Pos().Y));
                //°Ë»ö µÇ¸é ÃßÀû ½ºÅ×ÀÌÆ®·Î º¯½Å
                pZombie->GetPhysicsModel()->GetBody()->m_maxForwardSpeed = ZOMBIE_CHASESTATE_PHYSICS_MAX_FORWARDSPEED;
                pZombie->GetPhysicsModel()->GetBody()->m_maxDriveForce = ZOMBIE_CHASESTATE_PHYSICS_MAX_FRONTFORCE;
                pZombie->GetPhysicsModel()->ApplyLinearImpulse(ZOMBIE_CHASESTATE_PHYSICS_MAX_FORWARDSPEED);
                pZombie->GetFSM()->ChangeState(StateZombieChase::Instance());
                break;
            }
        }
    }
    //ÀÌÀü ÇÁ·¹ÀÓÀÇ À§Ä¡°¡ ÇÊ¿äÇϹǷΠÀúÀåÇÑ´Ù.(¾÷µ¥ÀÌÆ® µÇ±âÀüÀÇ ÀÌÀü ÁÂÇ¥)
    pZombie->m_VecTemporayPos.X = pZombie->Pos().X;
    pZombie->m_VecTemporayPos.Y = pZombie->Pos().Y;

    pPhysicsModel->Update(elapsedTime);

    //--------------------------------------------
    //
    // apply executed result to object property
    //
    //--------------------------------------------
    b2Vec2 vec = pZombie->GetPhysicsModel()->GetPosition();
    f32 angle = pZombie->GetPhysicsModel()->GetAngle();
    pZombie->SetPos(vector3df(vec.x, vec.y, 0));
    pZombie->SetRotation(vector3df(0.f, 0.f, ANGLE_TO_RADIAN(angle)));
}
示例#18
0
//------------------------------ Render ----------------------------------
//------------------------------------------------------------------------
void GameWorld::Render()
{
	gdi->TransparentText();

	//render any walls
	gdi->BlackPen();
	for (unsigned int w = 0; w < m_Walls.size(); ++w)
	{
		m_Walls[w].Render(true);  //true flag shows normals
	}

	//render any obstacles
	gdi->BlackPen();

	for (unsigned int ob = 0; ob < m_Obstacles.size(); ++ob)
	{
		gdi->Circle(m_Obstacles[ob]->Pos(), m_Obstacles[ob]->BRadius());
	}

	//render the agents
	for (unsigned int a = 0; a < m_Vehicles.size(); ++a)
	{
		m_Vehicles[a]->Render();

		//render cell partitioning stuff
		if (m_bShowCellSpaceInfo && a == 0)
		{
			gdi->HollowBrush();
			InvertedAABBox2D box(m_Vehicles[a]->Pos() - Vector2D(Prm.ViewDistance, Prm.ViewDistance),
				m_Vehicles[a]->Pos() + Vector2D(Prm.ViewDistance, Prm.ViewDistance));
			box.Render();

			gdi->RedPen();
			CellSpace()->CalculateNeighbors(m_Vehicles[a]->Pos(), Prm.ViewDistance);
			for (BaseGameEntity* pV = CellSpace()->begin(); !CellSpace()->end(); pV = CellSpace()->next())
			{
				gdi->Circle(pV->Pos(), pV->BRadius());
			}

			gdi->GreenPen();
			gdi->Circle(m_Vehicles[a]->Pos(), Prm.ViewDistance);
		}
	}

	//#define CROSSHAIR
#ifdef CROSSHAIR
	//and finally the crosshair
	gdi->RedPen();
	gdi->Circle(m_vCrosshair, 4);
	gdi->Line(m_vCrosshair.x - 8, m_vCrosshair.y, m_vCrosshair.x + 8, m_vCrosshair.y);
	gdi->Line(m_vCrosshair.x, m_vCrosshair.y - 8, m_vCrosshair.x, m_vCrosshair.y + 8);
	gdi->TextAtPos(5, cyClient() - 20, "Click to move crosshair");
#endif


	//gdi->TextAtPos(cxClient() -120, cyClient() - 20, "Press R to reset");

	gdi->TextColor(Cgdi::grey);
	if (RenderPath())
	{
		gdi->TextAtPos((int)(cxClient() / 2.0f - 80), cyClient() - 20, "Press 'U' for random path");

		m_pPath->Render();
	}

	if (RenderFPS())
	{
		gdi->TextColor(Cgdi::grey);
		gdi->TextAtPos(5, cyClient() - 20, ttos(1.0 / m_dAvFrameTime));
	}

	if (m_bShowCellSpaceInfo)
	{
		m_pCellSpace->RenderCells();
	}

}
示例#19
0
//---------------------- ObstacleAvoidance -------------------------------
//
//  Given a vector of CObstacles, this method returns a steering force
//  that will prevent the agent colliding with the closest obstacle
//------------------------------------------------------------------------
Vector2D SteeringBehavior::ObstacleAvoidance()
{
	//the detection box length is proportional to the agent's velocity
	float realBoxLength = m_dDBoxLength /* + 
										(m_pMovingEntity->Speed()) * m_dDBoxLength */;

	//this will keep track of the closest intersecting obstacle (CIB)
	BaseGameEntity* ClosestIntersectingObstacle = NULL;

	//this will be used to track the distance to the CIB
	double DistToClosestIP = MaxDouble;

	//this will record the transformed local coordinates of the CIB
	Vector2D LocalPosOfClosestObstacle;

	std::set<Obstacle*>::const_iterator curOb = Obstacle::getAll().begin(),
		endOb = Obstacle::getAll().end();

	while(curOb != endOb)
	{

		Obstacle* obst = (*curOb);

		Vector2D to = obst->Pos() - m_pMovingEntity->Pos();

		//the bounding radius of the other is taken into account by adding it 
		//to the range
		double range = realBoxLength + obst->BRadius();

		//if entity within range, tag for further consideration. (working in
		//distance-squared space to avoid sqrts)
		if ((to.LengthSq() < range*range))
		{

			//calculate this obstacle's position in local space
			Vector2D LocalPos = PointToLocalSpace(obst->Pos(),
				m_pMovingEntity->Heading(),
				m_pMovingEntity->Pos());

			//if the local position has a negative x value then it must lay
			//behind the agent. (in which case it can be ignored)
			if (LocalPos.x >= 0)
			{
				//if the distance from the x axis to the object's position is less
				//than its radius + half the width of the detection box then there
				//is a potential intersection.
				double ExpandedRadius = obst->BRadius() + m_pMovingEntity->BRadius();

				/*if (fabs(LocalPos.y) < ExpandedRadius)
				{*/
				//now to do a line/circle intersection test. The center of the 
				//circle is represented by (cX, cY). The intersection points are 
				//given by the formula x = cX +/-sqrt(r^2-cY^2) for y=0. 
				//We only need to look at the smallest positive value of x because
				//that will be the closest point of intersection.
				double cX = LocalPos.x;
				double cY = LocalPos.y;

				//we only need to calculate the sqrt part of the above equation once
				double SqrtPart = sqrt(ExpandedRadius*ExpandedRadius - cY*cY);

				double ip = cX - SqrtPart;

				if (ip <= 0.0)
				{
					ip = cX + SqrtPart;
				}

				//test to see if this is the closest so far. If it is keep a
				//record of the obstacle and its local coordinates
				if (ip < DistToClosestIP)
				{
					DistToClosestIP = ip;

					ClosestIntersectingObstacle = obst;

					LocalPosOfClosestObstacle = LocalPos;
				}         
			}
			//}
		}

		++curOb;
	}

	//if we have found an intersecting obstacle, calculate a steering 
	//force away from it
	Vector2D SteeringForce;

	if (ClosestIntersectingObstacle)
	{
		//the closer the agent is to an object, the stronger the 
		//steering force should be
		float multiplier = 1.0 + (m_dDBoxLength - LocalPosOfClosestObstacle.x) /
			m_dDBoxLength;

		//calculate the lateral force
		SteeringForce.y = (ClosestIntersectingObstacle->BRadius()-
			LocalPosOfClosestObstacle.y)  * multiplier;   

		//apply a braking force proportional to the obstacles distance from
		//the MovingEntity. 
		const float BrakingWeight = 0.2f;

		SteeringForce.x = (ClosestIntersectingObstacle->BRadius() - 
			LocalPosOfClosestObstacle.x) * 
			BrakingWeight;
	}

	//finally, convert the steering vector from local to world space
	return VectorToWorldSpace(SteeringForce,
		m_pMovingEntity->Heading());
}
Vec2 SteeringForce::ObstacleAvoidance(const std::vector<BaseGameEntity *> obstacles)
{
    m_dDBoxLength = m_pVehicle->getVeloctity().length()/m_pVehicle->getMaxSpeed()*40+40;
    
    //标记范围内的所有障碍物
    GameData::Instance()->tagObstaclesWithinViewRange(m_pVehicle, m_dDBoxLength);
    
    
    //追踪最近相交的障碍物
    BaseGameEntity *ClosestIntersectingObstacle = nullptr;
    
    //追踪到CIB的距离
    double DistToClosestIP =  MAXFLOAT;
    
    //记录CIB被转化的局部坐标
    Vec2 LocalPosOfClosestObstacle;
    
    std::vector<BaseGameEntity*>::const_iterator curOb = obstacles.begin();
    while (curOb!= obstacles.end()) {
        if ((*curOb)->isTagged()) {
            Vec2 LocalPos =  m_pVehicle->convertToNodeSpaceAR((*curOb)->getPosition());
            
            //如果举办空间位置有个负的x值,那么它肯定在智能体后面
            if (LocalPos.x >=0) {
                //如果物体到x轴的距离小于它的半径+检查盒宽度的一半
                //那么可能相交
                double ExpandeRadius = (*curOb)->getContentSize().height/2*(*curOb)->getScale()+m_pVehicle->getContentSize().height/2;
                
                if (fabs(LocalPos.y)<ExpandeRadius) {
                    //现在做线/圆周相交厕所吗 圆周圆心是(cx,cy);
                
                    //相交点的公式是x = cx +(-sqrt(  r*r - cY*cY));
                    //我们只需看x的最小值,因为那是最近的相交点
                    
                    double cX = LocalPos.x;
                    double cY = LocalPos.y;
                    //我们只需一次计算上面等式的开方
                    
                    double SqrtPart = sqrt(ExpandeRadius*ExpandeRadius-cY*cY);
                    
                    double ip = SqrtPart;
                    if (ip<=0) {
                        ip = cX+SqrtPart;
                    }
                    if (ip<DistToClosestIP) {
                        DistToClosestIP = ip;
                        
                        ClosestIntersectingObstacle = *curOb;
                        LocalPosOfClosestObstacle = LocalPos;
                    }
                }
            }
        }
        ++curOb;
    }
    
    
    Vec2 SteeringForce;
    
    if (ClosestIntersectingObstacle) {
        
        //智能体越近,操控力越强
        double muliplier =1 + (m_dDBoxLength-LocalPosOfClosestObstacle.x)/m_dDBoxLength;
        
        
        //计算侧向力
        SteeringForce.y = (ClosestIntersectingObstacle->getContentSize().height/2*ClosestIntersectingObstacle->getScale()-LocalPosOfClosestObstacle.y)*muliplier;
        
        
        if (LocalPosOfClosestObstacle.y>0&&LocalPosOfClosestObstacle.y<ClosestIntersectingObstacle->getContentSize().height/2*ClosestIntersectingObstacle->getScale()) {
            SteeringForce.y = -SteeringForce.y;
            }
        
       
        //施加一个制动力,它正比于障碍物到交通工具的距离
        const double BrakingWeight = 0.3;
        SteeringForce.x = (ClosestIntersectingObstacle->getContentSize().height/2*ClosestIntersectingObstacle->getScale()-LocalPosOfClosestObstacle.x)*BrakingWeight;
    }
    
    //最后,把操控向量换成世界坐标
//    log("********SteeringForce:%f,%f*********",( m_pVehicle->convertToWorldSpaceAR(SteeringForce)-m_pVehicle->getPosition()).x,( m_pVehicle->convertToWorldSpaceAR(SteeringForce)-m_pVehicle->getPosition()).y);
    
    return m_pVehicle->convertToWorldSpaceAR(SteeringForce)-m_pVehicle->getPosition();
    
}
//---------------------- ObstacleAvoidance -------------------------------
//
//  Given a vector of CObstacles, this method returns a steering force
//  that will prevent the agent colliding with the closest obstacle
//------------------------------------------------------------------------
Vector2D SteeringBehavior::ObstacleAvoidance(const std::vector<BaseGameEntity*>& obstacles)
{
	//the detection box length is proportional to the agent's velocity
	m_dDBoxLength = Prm.MinDetectionBoxLength +
		(m_pVehicle->Speed() / m_pVehicle->MaxSpeed()) *
		Prm.MinDetectionBoxLength;

	//tag all obstacles within range of the box for processing
	m_pVehicle->World()->TagObstaclesWithinViewRange(m_pVehicle, m_dDBoxLength);

	//this will keep track of the closest intersecting obstacle (CIB)
	BaseGameEntity* ClosestIntersectingObstacle = NULL;

	//this will be used to track the distance to the CIB
	double DistToClosestIP = MaxDouble;

	//this will record the transformed local coordinates of the CIB
	Vector2D LocalPosOfClosestObstacle;

	std::vector<BaseGameEntity*>::const_iterator curOb = obstacles.begin();

	while (curOb != obstacles.end())
	{
		//if the obstacle has been tagged within range proceed
		if ((*curOb)->IsTagged())
		{
			//calculate this obstacle's position in local space
			Vector2D LocalPos = PointToLocalSpace((*curOb)->Pos(),
				m_pVehicle->Heading(),
				m_pVehicle->Side(),
				m_pVehicle->Pos());

			//if the local position has a negative x value then it must lay
			//behind the agent. (in which case it can be ignored)
			if (LocalPos.x >= 0)
			{
				//if the distance from the x axis to the object's position is less
				//than its radius + half the width of the detection box then there
				//is a potential intersection.
				double ExpandedRadius = (*curOb)->BRadius() + m_pVehicle->BRadius();

				if (fabs(LocalPos.y) < ExpandedRadius)
				{
					//now to do a line/circle intersection test. The center of the 
					//circle is represented by (cX, cY). The intersection points are 
					//given by the formula x = cX +/-sqrt(r^2-cY^2) for y=0. 
					//We only need to look at the smallest positive value of x because
					//that will be the closest point of intersection.
					double cX = LocalPos.x;
					double cY = LocalPos.y;

					//we only need to calculate the sqrt part of the above equation once
					double SqrtPart = sqrt(ExpandedRadius*ExpandedRadius - cY*cY);

					double ip = cX - SqrtPart;

					if (ip <= 0.0)
					{
						ip = cX + SqrtPart;
					}

					//test to see if this is the closest so far. If it is keep a
					//record of the obstacle and its local coordinates
					if (ip < DistToClosestIP)
					{
						DistToClosestIP = ip;

						ClosestIntersectingObstacle = *curOb;

						LocalPosOfClosestObstacle = LocalPos;
					}
				}
			}
		}

		++curOb;
	}

	//if we have found an intersecting obstacle, calculate a steering 
	//force away from it
	Vector2D SteeringForce;

	if (ClosestIntersectingObstacle)
	{
		//the closer the agent is to an object, the stronger the 
		//steering force should be
		double multiplier = 1.0 + (m_dDBoxLength - LocalPosOfClosestObstacle.x) /
			m_dDBoxLength;

		//calculate the lateral force
		SteeringForce.y = (ClosestIntersectingObstacle->BRadius() -
			LocalPosOfClosestObstacle.y)  * multiplier;

		//apply a braking force proportional to the obstacles distance from
		//the vehicle. 
		const double BrakingWeight = 0.2;

		SteeringForce.x = (ClosestIntersectingObstacle->BRadius() -
			LocalPosOfClosestObstacle.x) *
			BrakingWeight;
	}

	//finally, convert the steering vector from local to world space
	return VectorToWorldSpace(SteeringForce,
		m_pVehicle->Heading(),
		m_pVehicle->Side());
}
示例#22
0
void
Human::DrawExtraInfo()
{
#ifdef AI_TEST_DISPLAY_HUMAN_STATE
//---------
	//sk test
		
	/*/ //좌표 보정전
	gui::IGUIFont* font2 = IrrDvc.GetDevice()->getGUIEnvironment()->getBuiltInFont();
    u32 time = IrrDvc.GetDevice()->getTimer()->getTime();

    core::stringw temp;
    temp = core::stringw(time).c_str(); //숫자를 stringw로 변환하는 루틴

	u32 coordposX = Pos().X;
	u32 coordposY = Pos().Y;

    if (font2)
		font2->draw(temp,core::rect<s32>(coordposX,coordposY,coordposX+50,coordposY+60), video::SColor(255,time % 255,time % 255,255));
		
	/*/ //좌표 보정 후 
	std::vector<BaseGameEntity*> enties = EntityMgr.GetEntityListFromGroupID(ENTITY_TYPE_VEHICLE);
	std::vector<BaseGameEntity*>::iterator iter = enties.begin();
	// find out close vehicle, but now just get first vehicle....
	BaseGameEntity* pTargetEntity = *iter;

	
	m_uDifferenceXOrgFugtivePlayer = m_uScreenHalfWidth - pTargetEntity->Pos().X * LOCALCOORD_SCREENCOORD_RATIO;//need optimization. change to once call.
	m_uDifferenceYOrgFugtivePlayer = m_uScreenHalfHeight + pTargetEntity->Pos().Y * LOCALCOORD_SCREENCOORD_RATIO;//need optimization. change to once call.

	/*
		m_uDifferenceXOrgFugtivePlayer = m_uScreenHalfWidth - Pos().X * LOCALCOORD_SCREENCOORD_RATIO;//need optimization. change to once call.
	m_uDifferenceYOrgFugtivePlayer = m_uScreenHalfHeight + Pos().Y * LOCALCOORD_SCREENCOORD_RATIO;//need optimization. change to once call.
*/
	gui::IGUIFont* font2 = IrrDvc.GetDevice()->getGUIEnvironment()->getBuiltInFont();
    u32 time = IrrDvc.GetDevice()->getTimer()->getTime();
	core::stringw temp;

	u32 coordposX = m_uDifferenceXOrgFugtivePlayer + Pos().X * LOCALCOORD_SCREENCOORD_RATIO;
	u32 coordposY = m_uDifferenceYOrgFugtivePlayer - Pos().Y * LOCALCOORD_SCREENCOORD_RATIO;

	
	core::stringw prefix;
    if (font2)
	{
		temp = core::stringw(time).c_str(); //숫자를 stringw로 변환하는 루틴
		font2->draw(temp,core::rect<s32>(coordposX,coordposY,coordposX+50,coordposY+60), video::SColor(255,time % 255,time % 255,255));

		temp = GetStateName();
		prefix = "state:";
		font2->draw(prefix+temp,core::rect<s32>(coordposX,coordposY+10,coordposX+50,coordposY+60), video::SColor(255,time % 255,time % 255,255));

		temp = core::stringw(m_fCurrentLifeEnergy).c_str(); //숫자를 stringw로 변환하는 루틴
		prefix = "E:";
		font2->draw(prefix+temp,core::rect<s32>(coordposX,coordposY+20,coordposX+50,coordposY+60), video::SColor(255,time % 255,time % 255,255));
	}
#endif //AI_TEST_DISPLAY_HUMAN_STATE
	
	//*/
//--------
}