コード例 #1
0
void plDynamicWalkingStrategy::Apply(float delSecs)
{
    hsVector3 velocity = fController->GetLinearVelocity();
    hsVector3 achievedVelocity = fController->GetAchievedLinearVelocity();

    // Add in gravity if the avatar's z velocity isn't being set explicitly
    if (hsABS(velocity.fZ) < 0.001f)
    {
        // Get our previous z velocity.  If we're on the ground, clamp it to zero at
        // the largest, so we won't launch into the air if we're running uphill.
        float prevZVel = achievedVelocity.fZ;
        if (IsOnGround())
            prevZVel = hsMinimum(prevZVel, 0.f);

        velocity.fZ = prevZVel + (kGravity * delSecs);
    }

    if (velocity.fZ < kTerminalVelocity)
        velocity.fZ = kTerminalVelocity;

    fController->SetPushingPhysical(nil);
    fController->SetFacingPushingPhysical(false);
    fGroundHit = fFalseGround = false;

    float groundZVelocity;
    if (ICheckForGround(groundZVelocity))
        velocity.fZ += groundZVelocity;

    fController->SetLinearVelocitySim(velocity);
}
コード例 #2
0
ファイル: Monster.cpp プロジェクト: gjzskyland/cuberite
void cMonster::MoveToWayPoint(cChunk & a_Chunk)
{
	if ((m_NextWayPointPosition - GetPosition()).SqrLength() < WAYPOINT_RADIUS * WAYPOINT_RADIUS)
	{
		return;
	}


	if (m_JumpCoolDown == 0)
	{
		if (DoesPosYRequireJump(FloorC(m_NextWayPointPosition.y)))
		{
			if (((IsOnGround()) && (GetSpeed().SqrLength() == 0.0f)) ||
			(IsSwimming()))
			{
				m_bOnGround = false;
				m_JumpCoolDown = 20;
				// TODO: Change to AddSpeedY once collision detection is fixed - currently, mobs will go into blocks attempting to jump without a teleport
				AddPosY(1.6);  // Jump!!
				SetSpeedX(3.2 * (m_NextWayPointPosition.x - GetPosition().x));  // Move forward in a preset speed.
				SetSpeedZ(3.2 * (m_NextWayPointPosition.z - GetPosition().z));  // The numbers were picked based on trial and error and 1.6 and 3.2 are perfect.
			}
		}
	}
	else
	{
		--m_JumpCoolDown;
	}

	Vector3d Distance = m_NextWayPointPosition - GetPosition();
	if ((Distance.x != 0.0f) || (Distance.z != 0.0f))
	{
		Distance.y = 0;
		Distance.Normalize();

		if (m_bOnGround)
		{
			Distance *= 2.5f;
		}
		else if (IsSwimming())
		{
			Distance *= 1.3f;
		}
		else
		{
			// Don't let the mob move too much if he's falling.
			Distance *= 0.25f;
		}
		// Apply walk speed:
		Distance *= m_RelativeWalkSpeed;
		/* Reduced default speed.
		Close to Vanilla, easier for mobs to follow m_NextWayPointPositions, hence
		better pathfinding. */
		Distance *= 0.5;
		AddSpeedX(Distance.x);
		AddSpeedZ(Distance.z);
	}
}
コード例 #3
0
void plWalkingStrategy::Update(float delSecs)
{
    if (fGroundHit || fFalseGround)
        fTimeInAir = 0.0f;
    else
    {
        fTimeInAir += delSecs;
        if (fHeadHit)
        {
            // If we're airborne and hit our head, override achieved velocity to avoid being shoved sideways
            hsVector3 velocity = fController->GetLinearVelocity();
            hsVector3 achievedVelocity = fController->GetAchievedLinearVelocity();

            achievedVelocity.fX = velocity.fX;
            achievedVelocity.fY = velocity.fY;
            if (achievedVelocity.fZ > 0.0f)
                achievedVelocity.fZ = 0.0f;

            fController->OverrideAchievedLinearVelocity(achievedVelocity);
        }
    }

    hsVector3 zeroVelocity(0.f, 0.f, 0.f);
    fController->SetLinearVelocity(zeroVelocity);

    if (!fHitGroundInThisAge && IsOnGround())
        fHitGroundInThisAge = true;

    if (fClearImpact)
    {
        fImpactTime = 0.0f;
        fImpactVelocity.Set(0.0f, 0.0f, 0.0f);
    }

    if (IsOnGround())
        fClearImpact = true;
    else
    {
        fImpactTime = fTimeInAir;
        fImpactVelocity = fController->GetAchievedLinearVelocity();
        // convert orientation from subworld to avatar-local coordinates
        fImpactVelocity = (hsVector3)fController->GetLocalRotation().Rotate(&fImpactVelocity);
        fClearImpact = false;
    }
}
コード例 #4
0
ファイル: Player.cpp プロジェクト: cedeel/MCServer
void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos)
{
	StatValue Value = (StatValue)floor(a_DeltaPos.Length() * 100 + 0.5);

	if (m_AttachedTo == NULL)
	{
		if (IsClimbing())
		{
			if (a_DeltaPos.y > 0.0)  // Going up
			{
				m_Stats.AddValue(statDistClimbed, (StatValue)floor(a_DeltaPos.y * 100 + 0.5));
			}
		}
		else if (IsSubmerged())
		{
			m_Stats.AddValue(statDistDove, Value);
			AddFoodExhaustion(0.00015 * (double)Value);
		}
		else if (IsSwimming())
		{
			m_Stats.AddValue(statDistSwum, Value);
			AddFoodExhaustion(0.00015 * (double)Value);
		}
		else if (IsOnGround())
		{
			m_Stats.AddValue(statDistWalked, Value);
			AddFoodExhaustion((m_IsSprinting ? 0.001 : 0.0001) * (double)Value);
		}
		else
		{
			if (Value >= 25)  // Ignore small/slow movement
			{
				m_Stats.AddValue(statDistFlown, Value);
			}
		}
	}
	else
	{
		switch (m_AttachedTo->GetEntityType())
		{
			case cEntity::etMinecart: m_Stats.AddValue(statDistMinecart, Value); break;
			case cEntity::etBoat:     m_Stats.AddValue(statDistBoat,     Value); break;
			case cEntity::etMonster:
			{
				cMonster * Monster = (cMonster *)m_AttachedTo;
				switch (Monster->GetMobType())
				{
					case cMonster::mtPig:   m_Stats.AddValue(statDistPig,   Value); break;
					case cMonster::mtHorse: m_Stats.AddValue(statDistHorse, Value); break;
					default: break;
				}
				break;
			}
			default: break;
		}
	}
}
コード例 #5
0
ファイル: linmove.cpp プロジェクト: Chettie/Eulora-client
void psLinearMovement::GetDRData (bool& on_ground,
	csVector3& pos, float& yrot, iSector*& sector, csVector3& vel,
	csVector3& worldVel, float& ang_vel)
{
  on_ground = IsOnGround ();
  GetLastPosition (pos, yrot, sector);
  vel = velBody;
  ang_vel = angularVelocity.y;
  worldVel = this->velWorld;
}
コード例 #6
0
void plWalkingStrategy::RecalcVelocity(double timeNow, float elapsed, bool useAnim)
{
    if (fControlledFlight != 0)
    {
        if (IsOnGround())
            fControlledFlightTime = fTimeInAir;

        if (fControlledFlightTime > kControlledFlightThreshold)
            EnableControlledFlight(false);
    }

    plAnimatedMovementStrategy::RecalcVelocity(timeNow, elapsed, useAnim);
}
コード例 #7
0
ファイル: FlagObjects.cpp プロジェクト: Arc0re/lithtech
DDWORD FlagObject::EngineMessageFn(DDWORD messageID, void *pData, DFLOAT fData)
{
	// Handle the engine messages we're interested in...

	switch(messageID)
	{
		case MID_PRECREATE:
		{
			if (fData == PRECREATE_WORLDFILE || fData == PRECREATE_STRINGPROP)
			{
				ReadProp((ObjectCreateStruct*)pData);
			}

			PostPropRead((ObjectCreateStruct*)pData);

			break;
		}

		case MID_INITIALUPDATE:
		{
			OnInitialUpdate(pData, fData);
			break;
		}

		case MID_TOUCHNOTIFY:
		{
			if (!IsWithPlayer())
			{
				OnTouchNotify((HOBJECT)pData);
			}
			break;
		}

		case MID_UPDATE:
		{
			if (IsOnGround())
			{
				ReturnToFlagStand();
			}
			break;
		}
	}

	return B2BaseClass::EngineMessageFn(messageID, pData, fData);
}
コード例 #8
0
ファイル: linmove.cpp プロジェクト: Chettie/Eulora-client
// Do the actual move
int psLinearMovement::MoveV (float delta)
{
  if (velBody < SMALL_EPSILON && velWorld < SMALL_EPSILON && (!colldet || colldet->IsOnGround ()))
    return PS_MOVE_DONTMOVE;  // didn't move anywhere

  int ret = PS_MOVE_SUCCEED;
  iMovable* movable = mesh->GetMovable ();
  if (movable->GetSectors ()->GetCount () <= 0)
    return PS_MOVE_DONTMOVE;  // didn't move anywhere

  csMatrix3 mat;

  // To test collision detection we use absolute position and transformation
  // (this is relevant if we are anchored). Later on we will correct that.
  csReversibleTransform fulltransf = movable->GetFullTransform ();
  mat = fulltransf.GetT2O ();

  csVector3 worldVel (fulltransf.This2OtherRelative (velBody) + velWorld);
  csVector3 oldpos (fulltransf.GetOrigin ());
  csVector3 newpos (worldVel*delta + oldpos);
  csVector3 bufpos = newpos;
  float dist = (newpos - oldpos).Norm ();

  // @@@ Magodra: In some cases the newpos seams to be invalid. Not sure about
  //              the reason, but the FollowSegment function will not work later
  //              in this function. So check for that condidtion, give warning,
  //              and halt the movement.
  if (CS::IsNaN(newpos.x) || CS::IsNaN(newpos.y) || CS::IsNaN(newpos.z))
  {
      printf("From old position %s ",toString(oldpos,movable->GetSectors()->Get(0)).GetDataSafe());
      StackTrace("LinearMovement to a NAN position.");
      return PS_MOVE_DONTMOVE;  // didn't move anywhere
  }

  // Check for collisions and adjust position
  if (colldet)
  {
    if (!colldet->AdjustForCollisions (oldpos, newpos, worldVel,
    	delta, movable))
    {
      ret = PS_MOVE_FAIL;
      newpos = oldpos;
    }
    else
    {
      // check if we collided, did move less than 9/10 of the distance
      if ((newpos - bufpos).Norm () > dist/10.0)
      {
        ret = PS_MOVE_PARTIAL;
      }
    }
  }

  csVector3 origNewpos = newpos;
  bool mirror = false;

  // Update position to account for portals
  iSector* new_sector = movable->GetSectors ()->Get (0);
  iSector* old_sector = new_sector;

  // @@@ Jorrit: had to do this add!
  // We need to measure slightly above the position of the actor or else
  // we won't really cross a portal.
  float height5 = (bottomSize.y + topSize.y) / 10.0f;
  newpos.y += height5;
  csMatrix3 id;
  csOrthoTransform transform_oldpos (id, oldpos +
  	csVector3 (0.0f, height5, 0.0f));

  new_sector = new_sector->FollowSegment (transform_oldpos, newpos, mirror,
  	PS_LINMOVE_FOLLOW_ONLY_PORTALS);
  newpos.y -= height5;
  if (new_sector != old_sector)
    movable->SetSector (new_sector);

  portalDisplaced += newpos - origNewpos;
  if(!IsOnGround ())
  {
	  //printf("Applying gravity: velY: %g.\n", velWorld.y);
    // gravity! move down!
    velWorld.y  -= gravity * delta;
    /*
     * Terminal velocity
     *   ((120 miles/hour  / 3600 second/hour) * 5280 feet/mile)
     *   / 3.28 feet/meter = 53.65 m/s
     */
    // The body velocity is figured in here too.
    if (velWorld.y < 0)
    {

      if (fulltransf.This2OtherRelative (velBody).y
      	+ velWorld.y < -(ABS_MAX_FREEFALL_VELOCITY))
      	velWorld.y = -(ABS_MAX_FREEFALL_VELOCITY)
      	- fulltransf.This2OtherRelative (velBody).y;
      if (velWorld.y > 0)
      {
	      // printf("Reset other y %g\n", fulltransf.This2OtherRelative (velBody).y);
        velWorld.y = 0;
      }
    }  
  }
  else
  {
    if(velWorld.y < 0)
    {
      velWorld.y = 0;
    }

    if (hugGround)
      HugGround (newpos, new_sector);
  }

  // Move to the new position. If we have an anchor we have to convert
  // the new position from absolute to relative.
  movable->GetTransform ().SetOrigin (newpos);
  movable->GetTransform ().SetT2O(
  	movable->GetTransform ().GetT2O () * transform_oldpos.GetT2O ());

  if (colldet)
  {
    // Part 4: Add us to all nearby sectors.
    mesh->PlaceMesh ();
  }

  movable->UpdateMove ();

  return ret;
}
コード例 #9
0
ファイル: Monster.cpp プロジェクト: gjzskyland/cuberite
void cMonster::HandleFalling()
{
	m_bTouchGround = IsOnGround();
	super::HandleFalling();
}
コード例 #10
0
void CHostageImprov::MoveTowards(const Vector &pos, float deltaT)
{
	Vector move;
	float_precision accelRate;
	const float crouchWalkRate = 250.0f;

	// Jump up on ledges
	// Because we may not be able to get to our goal position and enter the next
	// area because our extent collides with a nearby vertical ledge, make sure
	// we look far enough ahead to avoid this situation.
	// Can't look too far ahead, or bots will try to jump up slopes.
	//
	// NOTE: We need to do this frequently to catch edges at the right time
	// TODO: Look ahead *along path* instead of straight line
	ClearPath();

	if ((m_lastKnownArea == NULL || !(m_lastKnownArea->GetAttributes() & NAV_NO_JUMP))
		&& !IsUsingLadder() && !IsJumping() && IsOnGround() && !IsCrouching())
	{
		float ground;
		Vector aheadRay(pos.x - GetFeet().x, pos.y - GetFeet().y, 0);
		aheadRay.NormalizeInPlace();

		bool jumped = false;
		if (IsRunning())
		{
			const float farLookAheadRange = 80.0f;
			Vector normal;
			Vector stepAhead = GetFeet() + farLookAheadRange * aheadRay;
			stepAhead.z += HumanHeight;

			if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground, &normal ))
			{
				if (normal.z > 0.9f)
					jumped = DiscontinuityJump(ground, HOSTAGE_ONLY_JUMP_DOWN);
			}
		}

		if (!jumped)
		{
			// close up jumping
			// cant be less or will miss jumps over low walls
			const float lookAheadRange = 30.0f;
			Vector stepAhead = GetFeet() + lookAheadRange * aheadRay;
			stepAhead.z += HumanHeight;

			if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground))
			{
				jumped = DiscontinuityJump(ground);
			}
		}

		if (!jumped)
		{
			// about to fall gap-jumping
			const float lookAheadRange = 10.0f;
			Vector stepAhead = GetFeet() + lookAheadRange * aheadRay;
			stepAhead.z += HumanHeight;

			if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground))
			{
				jumped = DiscontinuityJump(ground, HOSTAGE_ONLY_JUMP_DOWN, HOSTAGE_MUST_JUMP);
			}
		}
	}

	move = (pos - GetFeet());
	move.z = 0;

	if (!move.IsZero())
	{
		move.NormalizeInPlace();
	}

	switch (m_moveType)
	{
	case Stopped:
		accelRate = 0;
		break;
	case Walking:
		if (IsCrouching())
			accelRate = crouchWalkRate;
		else
			accelRate = 400;
		break;
	case Running:
		if (IsCrouching())
			accelRate = crouchWalkRate;
		else
			accelRate = 1000;
		break;
	}

	m_vel.x = move.x * accelRate * deltaT + m_vel.x;
	m_vel.y = move.y * accelRate * deltaT + m_vel.y;
}
コード例 #11
0
void CHostageImprov::__MAKE_VHOOK(OnUpdate)(float deltaT)
{
	if (!IsAlive() || cv_hostage_stop.value > 0.0f)
		return;

	if (m_blinkTimer.IsElapsed())
	{
		if (m_scaredTimer.IsElapsed() && m_animateState.GetPerformance() != HostageAnimateState::Afraid)
		{
			m_blinkTimer.Start(RANDOM_FLOAT(3, 10));
			m_blinkCounter = RANDOM_LONG(2, 4);
		}
		else
		{
			m_blinkTimer.Start(RANDOM_FLOAT(0.5f, 2.0f));
			m_blinkCounter = RANDOM_LONG(1, 2);

		}
	}

	if (m_blinkCounter)
	{
		m_hostage->pev->body = 1;
		--m_blinkCounter;
	}
	else
	{
		m_hostage->pev->body = 0;
	}

	UpdateGrenadeReactions();
	UpdateDelayedChatter();
	UpdateVision();

	m_behavior.Update();

	m_actualVel.x = m_hostage->pev->origin.x - m_lastPosition.x;
	m_actualVel.y = m_hostage->pev->origin.y - m_lastPosition.y;

	const float runSpeed = 289.0f;
	const float walkSpeed = 9.0f;
	const float fallVelocity = -1000.0f;
	const float safeTime = 0.4f;

	if (IsOnGround())
	{
		if (IsCrouching())
		{
			if (m_actualVel.LengthSquared() > 9.0f)
			{
				if (m_animateState.GetPerformance() != HostageAnimateState::CrouchWalk)
				{
					m_animateState.Reset();
					m_animateState.SetPerformance(HostageAnimateState::CrouchWalk);

					ClearLookAt();
					if (m_scaredTimer.IsElapsed() && m_animateState.GetPerformance() != HostageAnimateState::Afraid)
						m_animateState.AddSequence(this, ACT_CROUCH_WALK, 99.9, 2.0);
					else
						m_animateState.AddSequence(this, ACT_CROUCH_WALK_SCARED, 99.9, 2.0);
				}
			}
			else if (m_animateState.GetPerformance() != HostageAnimateState::Crouch)
			{
				m_animateState.Reset();
				m_animateState.SetPerformance(HostageAnimateState::Crouch);

				if (m_scaredTimer.IsElapsed())
					m_animateState.AddSequence(this, ACT_CROUCH_IDLE, 99.9);
				else
					m_animateState.AddSequence(this, ACT_CROUCH_IDLE_SCARED);
			}
		}
		else
		{
			UTIL_MakeVectors(m_hostage->pev->angles);

			float dot = DotProduct2D(gpGlobals->v_forward, m_actualVel);

			if (dot < -3.0f)
			{
				if (m_animateState.GetPerformance() != HostageAnimateState::Walk)
				{
					m_animateState.Reset();
					m_animateState.SetPerformance(HostageAnimateState::Walk);
					ClearLookAt();

					float speed;
					if (m_actualVel.LengthSquared() > runSpeed)
						speed = 2.0f;
					else
						speed = 1.0f;

					m_animateState.AddSequence(this, ACT_WALK_BACK, 99.9, speed);
				}
			}
			else
			{
				if (m_actualVel.LengthSquared() > runSpeed)
				{
					if (m_animateState.GetPerformance() != HostageAnimateState::Run)
					{
						m_animateState.Reset();
						m_animateState.SetPerformance(HostageAnimateState::Run);
						ClearLookAt();

						if (m_scaredTimer.IsElapsed() && m_animateState.GetPerformance() != HostageAnimateState::Afraid && !m_behavior.IsState(&m_escapeState))
							m_animateState.AddSequence(this, ACT_RUN, 99.9, 2.0);
						else
							m_animateState.AddSequence(this, ACT_RUN_SCARED, 99.9, 2.0);
					}
				}
				else if (m_actualVel.LengthSquared() > walkSpeed)
				{
					if (m_animateState.GetPerformance() != HostageAnimateState::Walk)
					{
						m_animateState.Reset();
						m_animateState.SetPerformance(HostageAnimateState::Walk);
						ClearLookAt();

						if (m_behavior.IsState(&m_escapeState))
						{
							m_animateState.AddSequence(this, ACT_WALK_SNEAKY, 99.9, 1.5);
						}
						else if (m_scaredTimer.IsElapsed() && m_animateState.GetPerformance() != HostageAnimateState::Afraid)
						{
							m_animateState.AddSequence(this, ACT_WALK, 99.9, 1.5);
						}
						else
							m_animateState.AddSequence(this, ACT_WALK_SCARED, 99.9, 1.5);
					}
				}
				else
				{
					if (m_animateState.GetPerformance() == HostageAnimateState::Walk || m_animateState.GetPerformance() == HostageAnimateState::Run)
						m_animateState.Reset();

					UpdateStationaryAnimation();
				}
			}
		}
	}
	else if (m_hostage->pev->velocity.z < fallVelocity && m_animateState.GetPerformance() != HostageAnimateState::Fall)
	{
		m_animateState.Reset();
		m_animateState.SetPerformance(HostageAnimateState::Fall);
		m_animateState.AddSequence(this, ACT_FALL, 99.9);
	}

	if (!m_collisionTimer.HasStarted() || m_collisionTimer.IsGreaterThen(safeTime))
		SetKnownGoodPosition(m_lastPosition);

	m_lastPosition = m_hostage->pev->origin;
	m_animateState.OnUpdate(this);
}
コード例 #12
0
void plRidingAnimatedPhysicalStrategy::Apply(float delSecs)
{
    hsVector3 LinearVelocity=fCore->GetLinearVelocity();
    hsVector3 AchievedLinearVelocity=fCore->GetAchievedLinearVelocity();
    if (fCore->IsKinematic())
    {   
        //want to make sure nothing funky happens in the sim
        IApplyKinematic();
        return;
    }
    if (!fCore->IsEnabled())
        return;

    //need to sweep ahead to see what we might hit. 
    // if we hit anything we should probably apply the force that would normally be applied in

    
    fCore->SetPushingPhysical(nil);
    fCore->SetFacingPushingPhysical( false);
    plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded());
    hsPoint3 startPos, desiredDestination, endPos;
    fCore->GetPositionSim(startPos);
    uint32_t collideFlags =
    1<<plSimDefs::kGroupStatic |
    1<<plSimDefs::kGroupAvatarBlocker |
    1<<plSimDefs::kGroupDynamic;
    std::multiset<plControllerSweepRecord> GroundHitRecords;
    int possiblePlatformCount =fCore->SweepControllerPath(startPos, startPos + hsPoint3(0.f,0.f, -0.002f), true, true, collideFlags, GroundHitRecords);
    float maxPlatformVel = - FLT_MAX;
    int platformCount=0;
    fGroundHit = false;
    if(possiblePlatformCount)
    {
        
        std::multiset<plControllerSweepRecord>::iterator curRecord; 

        for(curRecord = GroundHitRecords.begin(); curRecord != GroundHitRecords.end(); curRecord++)
        {
            hsBool groundlike=false;
            if((curRecord->locHit.fZ - startPos.fZ)<= .2) groundlike= true;
            if(groundlike)
            {
                if(curRecord->ObjHit !=nil)
                {
                    hsVector3 vel;
                    curRecord->ObjHit->GetLinearVelocitySim(vel);
                    if(vel.fZ > maxPlatformVel)
                    {
                        maxPlatformVel= vel.fZ;
                    }
                }
                platformCount ++;
                fGroundHit = true;
            }
        }
    }
    
    
    
    bool gotGroundHit = fGroundHit;
    if (so)
    {
        
        // If we've been moved since the last physics update (somebody warped us),
        // update the physics before we apply velocity.
        const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld();
        if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f))
            fCore->SetGlobalLoc(l2w);

        // Convert our avatar relative velocity to subworld relative
        if (!LinearVelocity.IsEmpty())
        {
            LinearVelocity = l2w * LinearVelocity;
            const plCoordinateInterface* subworldCI = fCore->GetSubworldCI();
            if (subworldCI)
                LinearVelocity = subworldCI->GetWorldToLocal() * LinearVelocity;
        }
        
        if(!IsOnGround())
        {
            if(!fNeedVelocityOverride)
            {
                LinearVelocity.fZ= AchievedLinearVelocity.fZ;
            }
            else
            {
                LinearVelocity = fOverrideVelocity;
            }
        }
        if(fStartJump)
        {
            LinearVelocity.fZ =12.0f;
        }
        if(platformCount)
        {
            LinearVelocity.fZ = LinearVelocity.fZ + maxPlatformVel;
        }

        //probably neeed to do something with contact normals in here
        //for false ground stuff
        
        fFalseGround = false;
        hsVector3 testLength = LinearVelocity * delSecs + hsVector3(0.0, 0.0, -0.00f);
    //
        hsPoint3 desiredDestination= startPos + testLength;
        if(!IsOnGround())
        {
            if(ICheckMove(startPos, desiredDestination))
            {//we can get there soley by the LinearVelocity
                
                fNeedVelocityOverride =false;
            }
            else
            {
                
                fNeedVelocityOverride =true;
                fOverrideVelocity = LinearVelocity;
                fOverrideVelocity.fZ -=  delSecs * 32.f;
            }
        }
        else
        {
            fNeedVelocityOverride =false;
        }

        fCore->SetLinearVelocity(LinearVelocity);
    
    }
}
コード例 #13
0
///////////////////////////
//Walking Strategy
void plWalkingStrategy::Apply(float delSecs)
{
    //Apply Should Only be Called from a PhysicalControllerCore
    hsAssert(fCore,"No Core shouldn't be Applying");
    uint32_t collideFlags =
        1<<plSimDefs::kGroupStatic |
        1<<plSimDefs::kGroupAvatarBlocker |
        1<<plSimDefs::kGroupDynamic;
    if(!fCore->IsSeeking())
    {
        collideFlags|=(1<<plSimDefs::kGroupExcludeRegion);
    }
    bool OnTopOfAnimatedPhys=false;
    hsVector3 LinearVelocity=fCore->GetLinearVelocity();
    hsVector3 AchievedLinearVelocity=fCore->GetAchievedLinearVelocity();
    hsPoint3 positionBegin;
    fCore->GetPositionSim(positionBegin);
    bool recovered=false;
    if (fCore->IsKinematic())
    {
            plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded());
            if (so)
            {
                // If we've been moved since the last physics update (somebody warped us),
                // update the physics before we apply velocity.
                const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld();
                if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f))
                {
                    fCore->SetKinematicLoc(l2w);
                    fCore->SetGlobalLoc(l2w);
                }
            }
        return;
    }

    if (!fCore->IsEnabled())
        return;

    bool gotGroundHit = fGroundHit;
    fGroundHit = false;
    
    fCore->SetPushingPhysical(nil);
    fCore->SetFacingPushingPhysical( false);
    plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded());
    if (so)
    {
        static const float kGravity = -32.f;
        // If we've been moved since the last physics update (somebody warped us),
        // update the physics before we apply velocity.
        const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld();
        if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f))
            fCore->SetGlobalLoc(l2w);

        // Convert our avatar relative velocity to subworld relative
        if (!LinearVelocity.IsEmpty())
        {
            LinearVelocity = l2w * LinearVelocity;
            const plCoordinateInterface* subworldCI = fCore->GetSubworldCI();
            if (subworldCI)
                LinearVelocity = subworldCI->GetWorldToLocal() * LinearVelocity;
        }

        // Add in gravity if the avatar's z velocity isn't being set explicitly
        // (Add in a little fudge factor, since the animations usually add a
        // tiny bit of z.)
        if (hsABS(LinearVelocity.fZ) < 0.001f)
        {
            // Get our previous z velocity.  If we're on the ground, clamp it to zero at
            // the largest, so we won't launch into the air if we're running uphill.
            float prevZVel = AchievedLinearVelocity.fZ;
            if (IsOnGround())
                prevZVel = hsMinimum(prevZVel, 0.f);
            float grav = kGravity * delSecs;
            // If our gravity contribution isn't high enough this frame, we won't
            // report a collision even when standing on solid ground.
            float maxGrav = -.001f / delSecs;
            if (grav > maxGrav)
                grav = maxGrav;
            LinearVelocity.fZ = prevZVel + grav;
        }

        // If we're airborne and the velocity isn't set, use the velocity from
        // the last frame so we maintain momentum.
        if (!IsOnGround() && LinearVelocity.fX == 0.f && LinearVelocity.fY == 0.f)
        {
            LinearVelocity.fX = AchievedLinearVelocity.fX;
            LinearVelocity.fY = AchievedLinearVelocity.fY;
        }

        //make terminal velocity equal to k. it is wrong but has been this way and
        //don't want to break any puzzles. on top of that it will reduce tunneling behavior
        if(LinearVelocity.fZ<kGravity)LinearVelocity.fZ=kGravity;
        
        

        
        fCore->SetLinearVelocity(LinearVelocity);
        // Scale the velocity to our actual step size (by default it's feet/sec)
        hsVector3 vel(LinearVelocity.fX * delSecs, LinearVelocity.fY * delSecs, LinearVelocity.fZ * delSecs);
        unsigned int colFlags = 0;
        fGroundHit = false;
        fFalseGround = false;
        fContactNormals.Swap(fPrevSlidingNormals);
        fContactNormals.SetCount(0);
        fCore->Move(vel, collideFlags,  colFlags);
        ICheckForFalseGround();
        //if(fReqMove2) fCore->Move2(vel);
        /*If the Physx controller  thinks we have a collision from below, need to make sure we
        have at least have false ground, otherwise Autostepping can send us into the air, and we will some times 
        float/panic link. For some reason the NxControllerHitReport does not always send messages
        regarding Controller contact with ground plane, but will (almost) always return NXCC_COLLISION_DOWN
        with the move method.
        */
        if((colFlags&kBottom ) &&(fGroundHit==false))
        {
            fFalseGround=true;
        }
        
        if(colFlags&kTop)
        {
            fHitHead=true;
            //Did you hit your head on a dynamic?
            //with Physx's wonderful controller hit report vs flags issues we need to actually sweep to see
            std::multiset< plControllerSweepRecord > HitsDynamic;
            uint32_t testFlag=1<<plSimDefs::kGroupDynamic;
            hsPoint3 startPos;
            hsPoint3 endPos;
            fCore->GetPositionSim(startPos);
            endPos= startPos + vel;
            int NumObjsHit=fCore->SweepControllerPath(startPos, endPos, true, false, testFlag, HitsDynamic);
            if(NumObjsHit>0)
            {
                for(std::multiset< plControllerSweepRecord >::iterator curObj= HitsDynamic.begin();
                    curObj!=HitsDynamic.end(); curObj++)
                {

                    hsAssert(curObj->ObjHit,"We allegedly hit something, but there is no plasma physical associated with it");
                    if(curObj->ObjHit)
                    {//really we shouldn't have to check hitObj should be nil only if we miss, or the physX object
                        //doesn't have a user data associated with this either way this just shouldn't happen
                        hsVector3 hitObjVel;
                        curObj->ObjHit->GetLinearVelocitySim(hitObjVel);
                        hsVector3 relativevel=LinearVelocity-hitObjVel;
                        curObj->ObjHit->SetHitForce(relativevel * 10.0f * (*curObj).ObjHit->GetMass(), (*curObj).locHit);
                    }
                }
                HitsDynamic.clear();
            }
        }
    }
}
コード例 #14
0
void plWalkingStrategy::Apply(float delSecs)
{
    hsVector3 velocity = fController->GetLinearVelocity();
    hsVector3 achievedVelocity = fController->GetAchievedLinearVelocity();

    // Add in gravity if the avatar's z velocity isn't being set explicitly
    if (hsABS(velocity.fZ) < 0.001f)
    {
        // Get our previous z velocity.  If we're on the ground, clamp it to zero at
        // the largest, so we won't launch into the air if we're running uphill.
        float prevZVel = achievedVelocity.fZ;
        if (IsOnGround())
            prevZVel = hsMinimum(prevZVel, 0.0f);

        velocity.fZ = prevZVel + (kGravity * delSecs);
    }

    // If we're airborne and the velocity isn't set, use the velocity from
    // the last frame so we maintain momentum.
    if (!IsOnGround() && velocity.fX == 0.0f && velocity.fY == 0.0f)
    {
        velocity.fX = achievedVelocity.fX;
        velocity.fY = achievedVelocity.fY;
    }

    if (!fGroundHit && fSlidingNormals.Count())
    {
        // We're not on solid ground, so we should be sliding against whatever
        // we're hitting (like a rock cliff). Each vector in fSlidingNormals is
        // the surface normal of a collision that's too steep to be ground, so
        // we project our current velocity onto that plane and slide along the
        // wall.
        //
        // Also, sometimes PhysX reports a bunch of collisions from the wall,
        // but nothing from underneath (when there should be). So if we're not
        // touching ground, we offset the avatar in the direction of the
        // surface normal(s). This doesn't fix the issue 100%, but it's a hell
        // of a lot better than nothing, and suitable duct tape until a future
        // PhysX revision fixes the issue.
        //
        // Yes, there's room for optimization here if we care.
        hsVector3 offset(0.0f, 0.0f, 0.0f);
        for (int i = 0; i < fSlidingNormals.GetCount(); i++)
        {
            offset += fSlidingNormals[i];
            hsVector3 velNorm = velocity;

            if (velNorm.MagnitudeSquared() > 0.0f)
                velNorm.Normalize();

            if (velNorm * fSlidingNormals[i] < 0.0f)
            {
                hsVector3 proj = (velNorm % fSlidingNormals[i]) % fSlidingNormals[i];
                if (velNorm * proj < 0.0f)
                    proj *= -1.0f;

                velocity = velocity.Magnitude() * proj;
            }
        }
        if (offset.MagnitudeSquared() > 0.0f)
        {
            // 5 ft/sec is roughly the speed we walk backwards.
            // The higher the value, the less likely you'll trip
            // the bug, and this seems reasonable.
            offset.Normalize();
            velocity += offset * 5.0f;
        }
    }

    if (velocity.fZ < kTerminalVelocity)
        velocity.fZ = kTerminalVelocity;

    // Convert to a displacement vector
    hsVector3 displacement = velocity * delSecs;

    // Reset vars and move the controller
    fController->SetPushingPhysical(nil);
    fController->SetFacingPushingPhysical(false);
    fGroundHit = fFalseGround = fHeadHit = false;
    fSlidingNormals.SetCount(0);

    unsigned int collideResults = 0;
    unsigned int collideFlags = 1<<plSimDefs::kGroupStatic | 1<<plSimDefs::kGroupAvatarBlocker | 1<<plSimDefs::kGroupDynamic;
    if (!fController->IsSeeking())
        collideFlags |= (1<<plSimDefs::kGroupExcludeRegion);

    fController->Move(displacement, collideFlags, collideResults);

    if ((!fGroundHit) && (collideResults & kBottom))
        fFalseGround = true;

    if (collideResults & kTop)
        fHeadHit = true;
}
コード例 #15
0
void ControllableObject::Update(float msec, set<Action> actions)
{
	bool moveStatusBg = isMoving;
	Renderer* r = &Renderer::Instance();
	if (actions.find(MOVE_CAM_FORWARD) != actions.end())
	{
		isMoving = true;
		//if (fwDir.Length() == 0)
			fwDir = r->GetCamDirection();
		body->setActivationState(1);
		body->applyCentralForce(btVector3(fwDir.x * 500, fwDir.y * 500, fwDir.z * 500));
	}
	else
	{
		fwDir = Vector3(0, 0, 0);
	}
	if (actions.find(MOVE_CAM_BACKWARD) != actions.end())
	{
		isMoving = true;
		//if (bwDir.Length() == 0)
			bwDir = r->GetCamDirection().Inverse();
		body->setActivationState(1);
		body->applyCentralForce(btVector3(bwDir.x * 500, bwDir.y * 500, bwDir.z * 500));
	}
	else
	{
		bwDir = Vector3(0, 0, 0);
	}
	if (actions.find(MOVE_CAM_LEFT) != actions.end())
	{
		isMoving = true;
		//if (lfDir.Length() == 0)
			lfDir = r->GetCamLeft().Inverse();
		body->setActivationState(1);
		body->applyCentralForce(btVector3(lfDir.x * 500, lfDir.y * 500, lfDir.z * 500));
	}
	else
	{
		lfDir = Vector3(0, 0, 0);
	}
	if (actions.find(MOVE_CAM_RIGHT) != actions.end())
	{
		isMoving = true;
		//if (rtDir.Length() == 0)
			rtDir = r->GetCamLeft();
		body->setActivationState(1);
		body->applyCentralForce(btVector3(rtDir.x * 500, rtDir.y * 500, rtDir.z * 500));
	}
	else
	{
		rtDir = Vector3(0, 0, 0);
	}
	if ((actions.find(JUMP) != actions.end()) && (IsOnGround()))
	{
		isMoving = true;
		if (!Controller::Instance().IsContinuous(JUMP))
		{
			//if (upDir.Length() == 0)
			upDir = r->GetCamUp();
			body->setActivationState(1);
			body->applyCentralForce(btVector3(upDir.x * 20000, upDir.y * 20000, upDir.z * 20000));
			ResourceManager::Instance().GetResource<SoundEffectResource>("jumping.wav")->Play();
		}
	}
	else
	{
		upDir = Vector3(0, 0, 0);
	}

	if (((GetPosition() - GetPreviousPosition()).Length() == 0) && !((moveStatusBg == false) && (isMoving == true)))
	{
		isMoving = false;
	}
	PhysicsObject::Update(msec, actions);
}