static Vector3 GetPlayerPosition() { CCopyEntity *pPlayer = GetPlayerEntity(); if( pPlayer ) return pPlayer->GetWorldPosition(); else return Vector3(0,0,0); }
void CBE_Enemy::SearchPlayer(CCopyEntity* pCopyEnt, short& rsMode, Vector3& rvDesiredDirection, float* pfSqDistToPlayer) { // ========= enable the following 2 lines to use enemy observation mode ========== // rsMode = CEnemyState::STATE_SEARCH; // return; Vector3 vStart, vMyselfToPlayer; CCopyEntity* pPlayer = SinglePlayerInfo().GetCurrentPlayerBaseEntity()->GetPlayerCopyEntity(); vStart = pCopyEnt->GetWorldPosition() + pCopyEnt->GetDirection() * 1.42f; vMyselfToPlayer = pPlayer->GetWorldPosition() - vStart; // chehck the distance to the player float fSqDist = Vec3LengthSq( vMyselfToPlayer ); if( pfSqDistToPlayer ) *pfSqDistToPlayer = fSqDist; if( 40000 < fSqDist ) { // too far from the player rsMode = CEnemyState::STATE_SEARCH; return; } if( !CheckRayToPlayer(pCopyEnt) ) { rsMode = CEnemyState::STATE_SEARCH; // there is an obstacle between the player return; } // set 'rvDesiredDirection' - unit vector pointing at the target(player) Vec3Normalize( vMyselfToPlayer, vMyselfToPlayer ); rvDesiredDirection = vMyselfToPlayer; float fDotProduct = Vec3Dot( pCopyEnt->GetDirection(), vMyselfToPlayer ); // 'fDotProduct' ranges from -1 through 1 if( 0 < fDotProduct ) { //the player is visible from this entity rsMode = CEnemyState::STATE_ATTACK; // move to attack mode } else { if( fSqDist < 400.0f ) rsMode = CEnemyState::STATE_ATTACK; // close enough to hear the player else rsMode = CEnemyState::STATE_SEARCH; } }
void CES_Search::Act( CCopyEntity& rEntity, CBE_Enemy& rBaseEntity, float dt ) { // first, get the extra data of 'pCopyEnt' SBE_EnemyExtraData* pExtraData = rBaseEntity.GetExtraData( rEntity.iExtraDataIndex ); short& rsCurrentState = rEntity.s1; float& rfSensoringInterval = rEntity.f1; Vector3& rvDesiredDirection = rEntity.v1; float fSqDistToPlayer; rfSensoringInterval += dt; if( 0.32f <= rfSensoringInterval ) { rfSensoringInterval = 0; // check if the player is in a visible position and update 'rvDesiredDirection' and 'rsMode' short sSearchResult = 0; rBaseEntity.SearchPlayer( &rEntity, sSearchResult, rvDesiredDirection, &fSqDistToPlayer ); if( sSearchResult == STATE_ATTACK ) { // the player is in sight - engage rsCurrentState = STATE_ATTACK; rBaseEntity.UpdateDesiredYawAndPitch( &rEntity, rvDesiredDirection ); pExtraData->vLastCheckedDirectionToPlayer = rvDesiredDirection; pExtraData->fLastCheckedSqDistToPlayer = fSqDistToPlayer; pExtraData->vLastCheckedPlayerPosition = rvDesiredDirection * (float)sqrt(fSqDistToPlayer); return; } else { // lost sight of the player if( pExtraData->vLastCheckedPlayerPosition != Vector3(0,0,0) ) { Vector3 vDir = pExtraData->vLastCheckedPlayerPosition - rEntity.GetWorldPosition(); Vec3Normalize( rvDesiredDirection, vDir ); } } } rBaseEntity.SearchManeuver(&rEntity,pExtraData); }
void EntityManager::InitEntity( boost::shared_ptr<CCopyEntity> pNewCopyEntPtr, CCopyEntity *pParent, BaseEntity *pBaseEntity, CActorDesc* pPhysActorDesc ) { CCopyEntity* pNewCopyEnt = pNewCopyEntPtr.get(); // Mark the entity as in use pNewCopyEnt->inuse = true; pNewCopyEnt->m_pSelf = pNewCopyEntPtr; pNewCopyEnt->pBaseEntity = pBaseEntity; BaseEntity& rBaseEntity = (*pBaseEntity); pNewCopyEnt->m_pStage = m_pStage; // set id and increment the counter pNewCopyEnt->m_ID = m_EntityIDConter++; // z-sort is disabled by default initialization // Entities that have translucent polygons have to turn on their copy entities' // 'BETYPE_USE_ZSORT' in InitCopyEntity() if( pNewCopyEnt->m_TypeID == CCopyEntityTypeID::ALPHA_ENTITY ) { // For alpha entity, always use the z-sorting pNewCopyEnt->RaiseEntityFlags( BETYPE_USE_ZSORT ); } else { // Otherwise, disable z-sorting by default pNewCopyEnt->ClearEntityFlags( BETYPE_USE_ZSORT ); } // set the glare type if( rBaseEntity.m_EntityFlag & BETYPE_GLARESOURCE ) { pNewCopyEnt->RaiseEntityFlags( BETYPE_GLARESOURCE ); } else if( rBaseEntity.m_EntityFlag & BETYPE_GLAREHINDER ) { pNewCopyEnt->RaiseEntityFlags( BETYPE_GLAREHINDER ); } // update world aabb pNewCopyEnt->world_aabb.TransformCoord( pNewCopyEnt->local_aabb, pNewCopyEnt->GetWorldPosition() ); // link the new copy-entity to the top of 'm_pEntityInUse' if( m_pEntityInUse ) pNewCopyEnt->SetNext( m_pEntityInUse ); else pNewCopyEnt->SetNextToNull(); // first entity in the link list m_pEntityInUse = pNewCopyEntPtr; // set the created time of the entity pNewCopyEnt->m_CreatedTime = m_pStage->GetElapsedTime(); // set parent entity pNewCopyEnt->m_pParent = pParent; if( pNewCopyEnt->m_pParent ) { // 'pNewCopyEnt' is being created as a child of another copy entity pNewCopyEnt->m_pParent->AddChild( pNewCopyEnt->m_pSelf ); // establish link from the parent to this entity } // LOG_PRINT( "linking a copy entity of " + rBaseEntity.GetNameString() + " to the tree" ); // link the new copy-entity to the entity-tree Link( pNewCopyEnt ); // update light information if( pNewCopyEnt->Lighting() ) { pNewCopyEnt->ClearLights(); // UpdateLightInfo( pNewCopyEnt ); pNewCopyEnt->sState |= CESTATE_LIGHT_INFORMATION_INVALID; } // create object for physics simulation if( pNewCopyEnt->GetEntityFlags() & BETYPE_RIGIDBODY ) { CActor *pPhysActor = NULL; if( pPhysActorDesc ) { pPhysActorDesc->WorldPose = pNewCopyEnt->GetWorldPose();// * pNewCopyEnt->GetActorLocalPose(); pPhysActorDesc->BodyDesc.LinearVelocity = pNewCopyEnt->Velocity(); // each entity has its own actor desc pPhysActor = m_pStage->GetPhysicsScene()->CreateActor( *pPhysActorDesc ); } else if( pBaseEntity->GetPhysicsActorDesc().IsValid() ) { // actor desc is defined by entity attributes CActorDesc actor_desc = pBaseEntity->GetPhysicsActorDesc(); actor_desc.WorldPose = pNewCopyEnt->GetWorldPose(); actor_desc.BodyDesc.LinearVelocity = pNewCopyEnt->Velocity(); // pNewCopyEnt->pPhysicsActor = m_pStage->GetPhysicsScene()->CreateActor( actor_desc ); pPhysActor = m_pStage->GetPhysicsScene()->CreateActor( actor_desc ); } if( pPhysActor ) { pNewCopyEnt->m_vecpPhysicsActor.resize( 1 ); pNewCopyEnt->m_vecpPhysicsActor[0] = pPhysActor; pPhysActor->m_pFrameworkData = pNewCopyEnt; } } // When all the basic properties are copied, InitCopyEntity() is called to // do additional initialization specific to each base entity. rBaseEntity.InitCopyEntity( pNewCopyEnt ); }
/** Update all the entities cerrently existing in the stage. This function must be called once per frame. - Basic steps - 1. Call BaseEntity::UpdateBaseEntity( dt ) for each base entity - 2. Save positions of copy entities - 3. Run physics simulator - 4. Remove terminated entities from the active list - 5. Call CCopyEntity::Act() for each copy entity except for child entities - 6. Update link to the entity tree node if an entity has changed its position in Act() TODO: Do 5 & 6 in a single loop to update link for each entity right after is Act(). Current code does this in separate loops. */ void EntityManager::UpdateAllEntities( float dt ) { CCopyEntity *pEntity = NULL; CCopyEntity *pPrevEntity = NULL; CCopyEntity *pTouchedEnt = NULL; ONCE( LOG_PRINT( " - updating base entities" ) ); size_t i, num_base_entities = m_vecpBaseEntity.size(); for( i=0; i<num_base_entities; i++ ) { m_vecpBaseEntity[i]->UpdateBaseEntity( dt ); } // save the current entity positions for( pEntity = m_pEntityInUse.get(); pEntity != NULL; pEntity = pEntity->m_pNextRawPtr ) { pEntity->PrevPosition() = pEntity->GetWorldPosition(); } // run physics simulator // entity position may be modified in this call UpdatePhysics( dt ); ONCE( LOG_PRINT( " - updated physics" ) ); // remove terminated entities from the active entity list ReleaseTerminatedEntities(); ONCE( LOG_PRINT( " - removed terminated entities from the active entity list" ) ); // update active entities for( pEntity = this->m_pEntityInUse.get(), pPrevEntity = NULL; pEntity != NULL; pPrevEntity = pEntity, pEntity = pEntity->m_pNextRawPtr ) { // before updating pEntity, check if it has been terminated. if( !pEntity->inuse ) continue; // set the results of physics simulation to // pose, velocity and angular velocity of the entity // if( pEntity->pPhysicsActor && pEntity->GetEntityFlags() & BETYPE_USE_PHYSSIM_RESULTS ) if( 0 < pEntity->m_vecpPhysicsActor.size() && pEntity->GetEntityFlags() & BETYPE_USE_PHYSSIM_RESULTS ) pEntity->UpdatePhysics(); if( pEntity->sState & CESTATE_ATREST ) continue; if( !pEntity->m_pParent || !pEntity->m_pParent->inuse ) { // 'pEntity' has no parent or its parent is already terminated pEntity->pBaseEntity->Act( pEntity ); } if( !pEntity->inuse ) continue; // terminated in its own update routine UpdateEntityAfterMoving( pEntity ); // deal with entities touched during this frame for(int i=0; i<pEntity->vecpTouchedEntity.size(); i++) { pTouchedEnt = pEntity->vecpTouchedEntity[i]; pEntity->pBaseEntity->Touch( pEntity, pTouchedEnt ); if( pTouchedEnt ) pTouchedEnt->pBaseEntity->Touch( pTouchedEnt, pEntity ); } // clear touched entities for the next frame pEntity->vecpTouchedEntity.clear(); } ONCE( LOG_PRINT( " - updated active entities" ) ); // unlink and link the entity in the entity tree if it changed its position /* for( pEntity = m_pEntityInUse.get(); pEntity != NULL; pPrevEntity = pEntity, pEntity = pEntity->m_pNextRawPtr ) { if( !pEntity->inuse ) continue; UpdateEntityAfterMoving(); } */ }
bool CBE_Enemy::CheckRayToPlayer( CCopyEntity* pCopyEnt ) { CCopyEntity* pPlayer = SinglePlayerInfo().GetCurrentPlayerBaseEntity()->GetPlayerCopyEntity(); /// CCopyEntity* pPlayer = PlayerShip.GetPlayerCopyEntity(); STrace tr; Vector3 vCurrentPos = pCopyEnt->GetWorldPosition(); Vector3 vGoal = pPlayer->GetWorldPosition(); tr.vStart = vCurrentPos; tr.vGoal = vGoal; tr.bvType = BVTYPE_DOT; tr.fRadius = 0; tr.pSourceEntity = pCopyEnt; tr.sTraceType = TRACETYPE_IGNORE_NOCLIP_ENTITIES; Vector3 vDirToPlayer = vGoal - vCurrentPos; Vec3Normalize( vDirToPlayer, vDirToPlayer ); // normalization short sRadarPenetrationCount = 2; short sRadarState = ERS_NOT_IN_SOLID; while( 0 <= sRadarPenetrationCount ) { if( sRadarState == ERS_NOT_IN_SOLID ) { // check trace to the player // tr.vStart = vCurrentPos; // vGoal = &pPlayer->GetWorldPosition(); tr.in_solid = false; tr.fFraction = 1.0f; this->m_pStage->ClipTrace( tr ); vCurrentPos = tr.vEnd; if( tr.fFraction < 1.0f ) // hit something { if( tr.pTouchedEntity == pPlayer ) return true; // player is in a visible position else { // hit static geometry or another entity sRadarState = ERS_IN_SOLID; vCurrentPos += vDirToPlayer * 0.01f; // put 'vCurrentPos' in solid region sRadarPenetrationCount--; continue; } } else // i.e. tr.fFraction == 1.0f { // no hit - an exception. trace should at least hit the player return false; } } else // i.e. sRadarState == ERS_IN_SOLID { vCurrentPos += vDirToPlayer * CBE_ENEMY_RADAR_PENETRATION_CALC_STEP; tr.vEnd = vCurrentPos; tr.fFraction = 1.0f; tr.in_solid = false; m_pStage->CheckPosition( tr ); if( tr.in_solid ) { // proceeding inside the material sRadarPenetrationCount--; continue; } else { // penetrated through the material // move a little forward so that 'vCurrentPos' can safely get out of the wall vCurrentPos += vDirToPlayer * 0.05f; sRadarState = ERS_NOT_IN_SOLID; continue; } } } // player is not visible to this enemy entity return false; }
void GravityGun::Update( float dt ) { if( !IsWeaponSelected() ) return; // Vector3 vOwnerMuzzlePos = rWeaponSystem.m_vMuzzlePosition + rWeaponSystem.m_vMuzzleDirection * 0.25f // + rWeaponSystem.m_vMuzzleDir_Up * 0.90f; Vector3 vOwnerMuzzlePos = m_MuzzleEndWorldPose.vPosition; CCopyEntity *pTarget = m_Target.GetRawPtr(); if( pTarget ) { // calc the translation from the center of the target to the muzzle position Vector3 vDist = vOwnerMuzzlePos - pTarget->GetWorldPosition(); float fDistSq = Vec3LengthSq(vDist); if( m_fMaxRange * m_fMaxRange < fDistSq ) { m_iHoldingTargetToggle = 0; // m_pTarget->pPhysicsActor->SetAllowFreezing( true ); m_Target.Reset(); return; } STrace tr; tr.bvType = BVTYPE_DOT; tr.vStart = vOwnerMuzzlePos; Vector3 vGoal = pTarget->GetWorldPosition(); tr.vGoal = vGoal; tr.sTraceType = TRACETYPE_IGNORE_NOCLIP_ENTITIES; /* CTrace tr; tr.BVType = BVTYPE_DOT; tr.vStart = &vOwnerMuzzlePos; tr.vGoal = &pTarget->GetWorldPosition(); tr.TypeFlags = CTrace::FLAG_IGNORE_NOCLIP_ENTITIES;//TRACETYPE_IGNORE_NOCLIP_ENTITIES; */ // check trace CStageSharedPtr pStage = m_pStage.lock(); if( pStage ) pStage->ClipTrace( tr ); if( tr.pTouchedEntity != pTarget ) { // found an obstacle between the player and the target object // - unable to hold the target any more m_iHoldingTargetToggle = 0; // m_pTarget->pPhysicsActor->SetAllowFreezing( true ); m_Target.Reset(); return; } if( fDistSq < m_fGraspRange * m_fGraspRange || m_aTriggerState[1] == 1 ) { // the gravity gun is holding the target object // account for the target object's size so that it does not bump into the shooter float fDist = sqrtf(fDistSq); Vector3 vDir = vDist / fDist; // normalization fDist -= ( pTarget->fRadius + 0.2f ); vDist = vDir * fDist; // calc relative velocity Vector3 vRVel = pTarget->Velocity() - m_vMuzzleEndVelocity; Vector3 vForce; // vForce = m_fPosGain * vDist - m_fSpeedGain * vRVel; // m_pTarget->ApplyWorldImpulse( vForce, m_pTarget->GetWorldPosition()); if( 6.0f < fDist ) vForce = vDir * 6.0f * 2.5f; else if( fDist < 0.6f ) vForce = vDir * fDist * 8.0f; else // vForce = vDir * fDist * 2.5f; vForce = vDir * ( fDist * 2.0f + 3.0f ); vForce += m_vMuzzleEndVelocity; physics::CActor *pPhysicsActor = pTarget->GetPrimaryPhysicsActor(); if( pPhysicsActor ) pPhysicsActor->SetLinearVelocity( vForce ); /* Vector3 vPos = m_pTarget->pPhysicsActor->GetPosition(); Vector3 vVel = m_pTarget->pPhysicsActor->GetVelocity(); SmoothCD( vPos, vPos + vDist, vVel, 0.25f, dt ); if( 12.0f * 12.0f < Vec3LengthSq(vVel) ) { Vec3Normalize( vVel, vVel ); vVel *= 12.0f; } m_pTarget->pPhysicsActor->SetVelocity( vVel ); */ return; } else { // lost control of the target m_iHoldingTargetToggle = 0; ReleaseObject(); return; } } }
bool GravityGun::HandleInput( int input_code, int input_type, float fParam ) { Vector3 vOwnerMuzzlePos = m_MuzzleEndWorldPose.vPosition; switch( input_code ) { case ACTION_ATK_FIRE: if( input_type == ITYPE_KEY_PRESSED ) { m_aTriggerState[0] = 1; CCopyEntity *pTarget = m_Target.GetRawPtr(); if( pTarget ) { physics::CActor *pPhysicsActor = pTarget->GetPrimaryPhysicsActor(); Vector3 vDist = vOwnerMuzzlePos - pTarget->GetWorldPosition(); float fDistSq = Vec3LengthSq(vDist); if( fDistSq < m_fGraspRange * m_fGraspRange ) { Vector3 vImpulse = m_MuzzleEndLocalPose.matOrient.GetColumn(2) * m_fPower; // shoot object // pTarget->ApplyWorldImpulse( vImpulse, m_pTarget->GetWorldPosition() ); pPhysicsActor->SetLinearVelocity( vImpulse ); // release object // m_pTarget->pPhysicsActor->SetAllowFreezing( true ); m_Target.Reset(); m_iHoldingTargetToggle = 0; return true; } } } else if( input_type == ITYPE_KEY_RELEASED ) { m_aTriggerState[0] = 0; return true; } break; case ACTION_ATK_RAISEWEAPON: case ACTION_ATK_UNLOCK_TRIGGER_SAFETY: if( input_type == ITYPE_KEY_PRESSED ) { m_aTriggerState[1] = 1; // the owner pulled the second trigger m_iHoldingTargetToggle = ~m_iHoldingTargetToggle; CCopyEntity *pTarget = m_Target.GetRawPtr(); if( !pTarget ) { // trigger is pulled and the gravity gun is not holding any object right now // - check if there is an object in the aim direction return GraspObjectInAimDirection(); } else { // trigger is pulled when the gun is holding an object // - release the object ReleaseObject(); return true; } } else if( input_type == ITYPE_KEY_RELEASED ) { m_aTriggerState[1] = 0; return true; } break; default: break; } return false; }