Пример #1
0
void ThirdPersonCameraBase::ZoomIn()
{
#ifdef _DEBUG
std::cout << "ZOOM IN!\n";
#endif
  static const float ZOOM_VEL = Engine::Instance()->GetConfigFloat("pool_zoom_vel");
  Assert(ZOOM_VEL > 0);

  // Only zoom in if the distance from the camera to the target is
  // greater than the min.
  static const float DIST_MIN = Engine::Instance()->GetConfigFloat("pool_zoom_min_dist");
  Vec3f v = m_orientation.GetVertex() - m_lookAtPos;
  if (v.SqLen() > (DIST_MIN*DIST_MIN))
  { 
    m_zoomVel = -ZOOM_VEL; 
  }
  else
  {
    // Stop zooming immediately, as we can't wait until we decelerate to
    // a stop. By that time we will be much too close.
    m_zoomVel = 0;
#ifdef _DEBUG
std::cout  << "ZOOM IN: Can't zoom closer, dist to target is " << sqrt(v.SqLen()) << "\n";
#endif
  }
}
Пример #2
0
void Ve1ObjectChar::MoveTo(const Vec3f& newpos)
{
  m_newPos = newpos;
  m_isMoving = true;

  Vec3f dir = GetPos() - newpos;
  float sqLen = dir.SqLen();
  // TODO Check if distance is greater than last time - if so, we have missed the target!

  static const float STOP_DIST = ROConfig()->GetFloat("stop-dist", 10.0f);
  if (sqLen < STOP_DIST)
  {
    SetVel(Vec3f(0, 0, 0));
    m_isMoving = false; // Not sure why this wasn't here
  }
  // TODO enable this when we are reliably resetting sqLenLastTime, otherwise sometimes characters won't move
  /*
  else if (sqLen > sqLenLastTime)
  {
    SetVel(Vec3f(0, 0, 0));
    m_isMoving = false; // Not sure why this wasn't here
  }
  */
  else
  {
    dir.Normalise();
    SetVel(-dir * SPEED);

    // Work out direction to face
    SetDir(RadToDeg(atan2((double)m_vel.x, (double)m_vel.z)));
  }
  sqLenLastTime = sqLen;
}
Пример #3
0
void AIFly::Update()
{
  Assert(m_npc);
  Assert(m_target);

  m_npc->SetAnim("fly"); // why not just in OnActivated?? TODO

  // Accelerate towards point above player's head
  Vec3f a = (m_target->GetPos() + Vec3f(0, 50.0f, 0)) - m_npc->GetPos();
  a.Normalise();
  a *= 50.0f; // TODO CONFIG
  m_npc->SetAcc(a);

  // Cap speed 
  a = m_npc->GetVel();
  float speedSq = a.SqLen();
  const float MAX_SPEED = 50.0f; // TODO CONFIG
  if (speedSq > MAX_SPEED * MAX_SPEED)
  {
    a.Normalise();
    a *= MAX_SPEED;
    m_npc->SetVel(a);
  }

  float degs = RadToDeg(atan2(a.x, a.z));
  m_npc->SetDir(degs);
}
Пример #4
0
void ThirdPersonCameraBase::ZoomOut()
{
#ifdef _DEBUG
std::cout << "ZOOM OUT!\n";
#endif
  static const float ZOOM_VEL = Engine::Instance()->GetConfigFloat("pool_zoom_vel");
  Assert(ZOOM_VEL > 0);

  // Stop zooming if we are too far away.
  static const float DIST_MAX = Engine::Instance()->GetConfigFloat("pool_zoom_max_dist");
  Vec3f v = m_orientation.GetVertex() - m_lookAtPos;
  if (v.SqLen() < (DIST_MAX*DIST_MAX))
  { 
    m_zoomVel = ZOOM_VEL; 
  }
  else
  {
#ifdef _DEBUG
std::cout  << "ZOOM OUT: Can't zoom out, dist to target is " << sqrt(v.SqLen()) << "\n";
#endif
  }
}
Пример #5
0
void AIChasePet::Update()
{
  AI::Update();
  Assert(m_npc);
  // Head towards target
  Vec3f aim = m_target->GetPos();
  Vec3f vel = aim - m_npc->GetPos();

  static const float MAX_DIST = ROConfig()->GetFloat("dino-chase-dist"); 
  static const float MAX_DIST_SQ = MAX_DIST * MAX_DIST;

  float sqlen = vel.SqLen();
  if (sqlen < 1.0f)
  {
std::cout << "AI chase: " << Describe(m_npc) << " has reached target " <<
  Describe(m_target) << "!\n";

    m_npc->DecideAI();
  }
  else if (sqlen < MAX_DIST_SQ) 
  {
    vel.Normalise();

    static const float SPEED = ROConfig()->GetFloat("dino-chase-speed"); 
    vel *= SPEED;
    Vec3f v = m_npc->GetVel();
    v.x = vel.x;
    v.z = vel.z;
    m_npc->SetVel(v);
    float degs = RadToDeg(atan2(vel.x, vel.z)); 

    m_npc->SetDir(degs);
    m_npc->SetIsControlled(true); 
    m_npc->SetAnim("run");
  }
  else
  {
#ifdef _DEBUG
    std::cout << m_npc->GetTypeName() << " giving up chase\n";
#endif
    m_npc->SetAI(AIIdle::NAME);
  }
}
Пример #6
0
void Spring::Update()
{
  // Vector between spring ends
  Vec3f v = m_particles[0]->GetPos() - m_particles[1]->GetPos();
  Vec3f newVec = v;
  // Force along this line proportional to distance
  // == Hooke's Law, springs
  float len = sqrt(v.SqLen());
  if (len < 0.00001f) // TODO
  {
    return; // zero length spring, so do nothing
  }

  //len = std::min(m_maxLength, len);
  v.Normalise();

  // Force at spring ends is proportional to squash/stretch distance
  Vec3f forceAtEnd = v * ((len - m_naturalLength) * m_k);
  m_particles[0]->AddForce(-forceAtEnd);
  m_particles[1]->AddForce(forceAtEnd);

  // If max spring length exceeded, pull ends together
  if (len > m_maxLength)
  {
std::cout << "Spring exceeds max length (" << m_maxLength << ")\n";

    // TODO Take masses into account!
    float dist = (len - m_maxLength) * 0.5f; // move each end this dist
    Vec3f moveVec = v * dist;
    m_particles[0]->Move(-moveVec);
    m_particles[1]->Move(moveVec);
  }
  else if (len < m_minLength)
  {
std::cout << "Spring under min length (" << m_minLength << ")\n";
    // TODO Take masses into account!

    float dist = (len - m_minLength) * 0.5f; // move each end this dist
    Vec3f moveVec = v * dist;
    m_particles[0]->Move(-moveVec);
    m_particles[1]->Move(moveVec);
  }

  /*
  // Set box centre and extents
  Vec3f centre = (m_particles[0]->GetPos() + m_particles[1]->GetPos()) * 0.5f;
  m_box.SetCentre(centre);
  m_box.SetExtents(Vec3f(len * 0.5f, 0.2f, 1.0f));

  // Align box with line seg connecting end points
  Vec3f xAxis = v;
  // Create a zAxis perpendicular to xAxis
  Vec3f up(0, 1.0f, 0);
  // Choose new up vector if xAxis is vertical!
  const float VERTICAL = 0.9f;
  float dot = DotProduct(xAxis, up);
  if (fabs(dot) > VERTICAL)
  {
    up = Vec3f(1.0f, 0, 0); // TODO may face other dir
  }
  Vec3f zAxis = CrossProduct(xAxis, up);
  Vec3f yAxis = CrossProduct(xAxis, zAxis);
  m_box.SetAxes(xAxis, yAxis);
  */

/*
  // Twist spring
  m_oldVec.Normalise();
  newVec.Normalise();
  float theta = acos(DotProduct(m_oldVec, newVec));
  if (fabs(theta) > 0.001f)
  {
    Vec3f axis = CrossProduct(m_oldVec, newVec);
    axis.Normalise();
    Quaternion q(axis, theta);
    q = GetQuat() * q;
    SetQuat(q);
  }
*/
  m_oldVec = newVec;
}
Пример #7
0
void Player::Update()
{
  if (m_isLoggedIn)
  {
    Ve1ObjectChar::Update();
  }
  else if (m_sceneNode)
  {
    Matrix m;
    m.Translate(m_pos);
    m_sceneNode->SetLocalTransform(m);

    // Set shadow AABB to same as Scene Node so we don't cull it by mistake
    m_shadow->SetAABB(*(m_sceneNode->GetAABB()));

    static const float XSIZE = ROConfig()->GetFloat("player-aabb-x", 30.0f);
    static const float YSIZE = ROConfig()->GetFloat("player-aabb-y", 100.0f);

    GetAABB()->Set(
      m_pos.x - XSIZE, m_pos.x + XSIZE,
      m_pos.y, m_pos.y + YSIZE,
      m_pos.z - XSIZE, m_pos.z + XSIZE);

    /*
    DISABLED for 2D look and feel
    TurnToFaceDir();
    */
  }

  if (m_hidden)
  {
    return;
  }

  // Stop moving if we are close enough to the destination
  // TODO This ends up happening every frame, only do it if we are moving
  if (true) //m_isMoving)
  {
    Vec3f dir = GetPos() - m_newPos;
    dir.y = 0; // ignore y coord for now
    static const float STOP_DISTANCE = ROConfig()->GetFloat("stop-dist", 20.0f);
    if (dir.SqLen() < STOP_DISTANCE) 
    {
      SetVel(Vec3f(0, 0, 0));
      m_newPos = GetPos();
      SetArrowVis(false);
      m_isMoving = false;
    }
  }
  else
  {
    //Assert(GetVel().SqLen() == 0);
  }

  if (m_sceneNode)
  {
    // Set shadow AABB to same as Scene Node so we don't cull it by mistake
    m_nameTag->SetAABB(*(m_sceneNode->GetAABB()));
  }

  if (m_ignorePortalId != -1)
  {
    GameObject* g = TheGame::Instance()->GetGameObject(m_ignorePortalId);
    if (g)
    {
      const AABB& aabb = g->GetAABB();
      if (!GetAABB()->Intersects(aabb))
      {
        // No longer intersecting portal
        m_ignorePortalId = -1;
      }
    }
    else
    {
      m_ignorePortalId = -1; // ?
    }
  }

  if (IsLocalPlayer())
  {
    TheGSMain::Instance()->SetHeartNum(m_stamina);

    if (m_stamina <= 0)
    {
      // Player now has to go back to the spaceship to regenerate or something.
      if (!m_isDead)
      {
        LurkMsg lm("You need to return to your spaceship to recover from your injuries!", 
          Colour(1, 1, 1, 1), Colour(1, 0, 0, 1), AMJU_CENTRE); 
        TheLurker::Instance()->Queue(lm);
      }

      m_isDead = true;
    }
  }
}
Пример #8
0
void Ve1ObjectChar::Update()
{
  // Not safe to do anything if the Terrain has not been created yet
  if (!TerrainReady())
  {
    return;
  }

  // TODO Not if underwater ?
  // TODO Put in base class, so we can drop things ?
  static const float GRAVITY = ROConfig()->GetFloat("gravity", -50.0f); 
  m_acc.y = GRAVITY;

  Ve1Object::Update();

  if (IsHidden())
  {
    return;
  }

  // Handle wall collisions with terrain and any building
  if (HandleWalls(GetTerrain()->GetCollisionMesh(), m_oldPos, m_pos))
  {
    m_recalcHeading = true;
  }

  HasCollisionMesh* h = dynamic_cast<HasCollisionMesh*>(m_collidingObject);
  if (h)
  {
    if (HandleWalls(h->GetCollisionMesh(), m_oldPos, m_pos))
    {
      m_recalcHeading = true;
    }
  }

  HandleFloor(GetTerrain()->GetCollisionMesh());
  if (h)
  {  
    HandleFloor(h->GetCollisionMesh());
  }

  // Recalc heading if we are not colliding
  if (m_collidingObject)
  {
    m_recalcHeading = true;
  }


  if (true) //m_recalcHeading)
  {
    m_recalcHeading = false;
    if (m_isMoving)
    {
      MoveTo(m_newPos);
    }
  }
  m_collidingObject = 0;

/*
  // Stop moving if we are close enough to the destination
  // TODO This ends up happening every frame, only do it if we are moving
  if (m_isMoving)
  {
    Vec3f dir = GetPos() - m_newPos;
    dir.y = 0; // ignore y coord for now
    if (dir.SqLen() < 1.0f) // TODO CONFIG
    {
      SetVel(Vec3f(0, 0, 0));
      m_newPos = GetPos();
      SetArrowVis(false);
      m_isMoving = false;
    }
  }
  else
  {
    Assert(GetVel().SqLen() == 0);
  }
*/

  if (m_sceneNode)
  {
    Matrix m;
    m.Translate(m_pos);
    m_sceneNode->SetLocalTransform(m);
    //m_sceneNode->Update(); // done for whole scene graph elsewhere

    if (m_shadow)
    {
      // Set shadow AABB to same as Scene Node so we don't cull it by mistake
      m_shadow->SetAABB(*m_sceneNode->GetAABB());
    }

    if (m_effect)
    {
      m_effect->SetAABB(*m_sceneNode->GetAABB());
    }

    static const float XSIZE = ROConfig()->GetFloat("player-aabb-x", 30.0f);
    static const float YSIZE = ROConfig()->GetFloat("player-aabb-y", 100.0f);

    GetAABB()->Set(
      m_pos.x - XSIZE, m_pos.x + XSIZE,
      m_pos.y, m_pos.y + YSIZE,
      m_pos.z - XSIZE, m_pos.z + XSIZE);

    /*
    NOT FOR 2D
    TurnToFaceDir();
    */

    Ve1Character* vc = dynamic_cast<Ve1Character*>(m_sceneNode.GetPtr());
    if (vc) //// && vc->GetMd2())
    {
      Vec3f v = m_vel;
      v.y = 0;
      float speed = v.SqLen();

      // TODO Simplify -- either moving or idle.
      // NB Speeds should be an avatar variable and level up

      static const float MAX_SPEED = 100.0f; // TODO CONFIG
      static const float RUN_SPEED = MAX_SPEED * 0.5f;
      static const float WALK_SPEED = RUN_SPEED * 0.5f;

      if (speed > RUN_SPEED)
      {
        vc->SetAnim(Ve1Character::ANIM_RUN);
      }
      else if (speed > WALK_SPEED)
      {
        vc->SetAnim(Ve1Character::ANIM_WALK);
      }
      else
      {
        vc->SetAnim(Ve1Character::ANIM_IDLE);
      }
    }
  }
}