Exemplo n.º 1
0
// This function handles the collision between the ball and a wall
void World::wall_collide_handler(const CollisionEntry& colEntry)
   {
   // First we calculate some numbers we need to do a reflection
   NodePath renderNp = m_windowFrameworkPtr->get_render();
   // The normal of the wall
   LVector3f norm = colEntry.get_surface_normal(renderNp) * -1;
   // The current speed
   float curSpeed = m_ballV.length();
   // The direction of travel
   LVector3f inVec = m_ballV / curSpeed;
   // Angle of incidence
   float velAngle = norm.dot(inVec);
   LPoint3f hitDir = colEntry.get_surface_point(renderNp) - m_ballRootNp.get_pos();
   hitDir.normalize();
   // The angle between the ball and the normal
   float hitAngle = norm.dot(hitDir);

   // Ignore the collision if the ball is either moving away from the wall
   // already (so that we don't accidentally send it back into the wall)
   // and ignore it if the collision isn't dead-on (to avoid getting caught on
   // corners)
   if(velAngle > 0 && hitAngle > .995)
      {
      // Standard reflection equation
      LVector3f reflectVec = (norm * norm.dot(inVec * -1) * 2) + inVec;

      // This makes the velocity half of what it was if the hit was dead-on
      // and nearly exactly what it was if this is a glancing blow
      m_ballV = reflectVec * (curSpeed * (((1-velAngle)*.5)+.5));
      // Since we have a collision, the ball is already a little bit buried in
      // the wall. This calculates a vector needed to move it so that it is
      // exactly touching the wall
      LPoint3f disp = (colEntry.get_surface_point(renderNp) -
                       colEntry.get_interior_point(renderNp));
      LPoint3f newPos = m_ballRootNp.get_pos() + disp;
      m_ballRootNp.set_pos(newPos);
      }
   }
Exemplo n.º 2
0
// Accepts arrow keys to move either the player or the menu cursor,
// Also deals with grid checking and collision detection
void World::move()
   {
   // If the camera-left key is pressed, move camera left.
   // If the camera-right key is pressed, move camera right.

   NodePath cameraNp = m_windowFrameworkPtr->get_camera_group();
   cameraNp.look_at(m_ralph);
   if(m_keyMap[K_cam_left] != false)
      {
      cameraNp.set_x(cameraNp, -20 * ClockObject::get_global_clock()->get_dt());
      }
   if(m_keyMap[K_cam_right] != false)
      {
      cameraNp.set_x(cameraNp, +20 * ClockObject::get_global_clock()->get_dt());
      }

   // save ralph's initial position so that we can restore it,
   // in case he falls off the map or runs into something.

   LPoint3f startPos = m_ralph.get_pos();

   // If a move-key is pressed, move ralph in the specified direction.

   if(m_keyMap[K_left])
      {
      m_ralph.set_h(m_ralph.get_h() + 300 * ClockObject::get_global_clock()->get_dt());
      }
   if(m_keyMap[K_right])
      {
      m_ralph.set_h(m_ralph.get_h() - 300 * ClockObject::get_global_clock()->get_dt());
      }
   if(m_keyMap[K_forward])
      {
      m_ralph.set_y(m_ralph, -25 * ClockObject::get_global_clock()->get_dt());
      }

   // If ralph is moving, loop the run animation.
   // If he is standing still, stop the animation.

   if(m_keyMap[K_forward] || m_keyMap[K_left] || m_keyMap[K_right])
      {
       if(!m_isMoving)
          {
          m_ralph.loop("run", true);
          m_isMoving = true;
          }
      }
   else
      {
      if(m_isMoving)
         {
         m_ralph.stop("run");
         m_ralph.pose("walk", 5);
         m_isMoving = false;
         }
      }

   // If the camera is too far from ralph, move it closer.
   // If the camera is too close to ralph, move it farther.

   LPoint3f camVec = m_ralph.get_pos() - cameraNp.get_pos();
   camVec.set_z(0);
   float camDist = camVec.length();
   camVec.normalize();
   if(camDist > 10.0)
      {
      cameraNp.set_pos(cameraNp.get_pos() + camVec*(camDist-10));
      camDist = 10.0;
      }
   if(camDist < 5.0)
      {
      cameraNp.set_pos(cameraNp.get_pos() - camVec*(5-camDist));
      camDist = 5.0;
      }

   // Now check for collisions.

   NodePath renderNp = m_windowFrameworkPtr->get_render();
   m_collisionTraverser.traverse(renderNp);

   // Adjust ralph's Z coordinate.  If ralph's ray hit terrain,
   // update his Z. If it hit anything else, or didn't hit anything, put
   // him back where he was last frame.

   m_ralphGroundHandlerPtr->sort_entries();
   if(m_ralphGroundHandlerPtr->get_num_entries() > 0 &&
      m_ralphGroundHandlerPtr->get_entry(0)->get_into_node()->get_name() == "terrain")
      {
      m_ralph.set_z(m_ralphGroundHandlerPtr->get_entry(0)->get_surface_point(renderNp).get_z());
      }
   else
      {
      m_ralph.set_pos(startPos);
      }

   // Keep the camera at one foot above the terrain,
   // or two feet above ralph, whichever is greater.

   m_camGroundHandlerPtr->sort_entries();
   if(m_camGroundHandlerPtr->get_num_entries() > 0 &&
      m_camGroundHandlerPtr->get_entry(0)->get_into_node()->get_name() == "terrain")
      {
      cameraNp.set_z(m_camGroundHandlerPtr->get_entry(0)->get_surface_point(renderNp).get_z()+1.0);
      }
   if(cameraNp.get_z() < m_ralph.get_z() + 2.0)
      {
      cameraNp.set_z(m_ralph.get_z() + 2.0);
      }

   // The camera should look in ralph's direction,
   // but it should also try to stay horizontal, so look at
   // a floater which hovers above ralph's head.

   m_floaterNp.set_pos(m_ralph.get_pos());
   m_floaterNp.set_z(m_ralph.get_z() + 2.0);
   cameraNp.look_at(m_floaterNp);
   }