MULTIMEDIA

Game Programming with DirectX : Time-Based Simulations (part 2) - The Route Class

5/15/2013 7:36:08 PM

The Route Class

The purpose of the Route class is to store a list of paths that form the animation route. The Route class has the functions AddLinePath(), which adds a StraightLinePath object to the list, AddCurvePath(), which adds a CurvePath object to the list, GetStartTime() to get the time of the animation for time-based updates, and GetPosition(), which returns the current position based on the time passed in as a parameter. The Route class also has two member variables: a pointer to the Path class, which acts as the root node in the link list, and a timer variable. The Route class declaration is shown in Listing 7.

Listing 7. The Route Class
class Route
{
   public:
      Route();
      ~Route();

      bool AddLinePath(Vector3D start, Vector3D end);

      bool AddCurvePath(Vector3D p1, Vector3D cnt1,
                        Vector3D cnt2, Vector3D p2);

      float GetStartTime();
      Vector3D GetPosition(float time);

      void Release()

   private:
      Path *m_path;
      float m_startTime;
};

The Route class’s GetStartTime() function returns the class’s timer value, the constructor initializes the two variables, and the destructor calls the Release() function. In the Release() function the Release() function of the Path class object is called to cause a recursive transversal through the link list to delete all nodes. Once that has occurred, the root node itself is deleted and set to NULL. The constructor, destructor, and GetStartTime() and Release() functions are shown in Listing 8.

Listing 8. The Route Class’s Constructor, Destructor, GetStartTime() Function and Release() Function
Route::Route()
{
   m_path = NULL;
   m_startTime = 0;
}

Route::~Route()
{
   Release()
}

float Route::GetStartTime()
{
   return m_startTime;
}

void Route::Release()
{
   if(m_path)
   {
      m_path->Release()
      delete m_path;
      m_path = NULL;
   }
}

					  

The AddLinePath() and AddCurvePath() functions are fairly straightforward. They begin by testing if the root node of the link list is NULL. If it is, then we can simply allocate the node to a new instance of the type of path we are creating and set the node’s start and total times. The start time is 0 in this case, and the total time is set to depend on the length of the path.

If the root node is not NULL, then a pointer to the root node is created, and we use that pointer to move through the link list until we find a free spot. Once we find that spot, it is allocated to the appropriate path type, the total time is set to the length of the path, and the start time is set to the start time plus the total time of the previous path. This allows us to know when each path starts, how long it is, and when it ends. The ending time of a path isn’t stored, since the next path in the list will have that same value as its start time.

The AddLinePath() function is shown in Listing 9, and AddCurvePath is shown in Listing 10.

Listing 9. The AddLinePath() Function
bool Route::AddLinePath(Vector3D start, Vector3D end)
{
   Path *ptr = NULL;

   if(m_path == NULL)
   {
      // Allocate data for the root node.
      m_path = new StraightLinePath(start, end);


      // Make sure all went well.
      if(m_path == NULL)
         return false;

      // Since this is the start node, its start m_total is 0.
      m_path->m_start = 0;
      m_path->m_total = Vector3D(start - end).Magnitude();
   }
   else
   {
      // Prepare to move through root until we find a NULL spot.
      ptr = m_path;

      // Search to a node without a next pointer.
      while(ptr->m_next != NULL)
         ptr = ptr->m_next;

      // Create the m_next path.
      ptr->m_next = new StraightLinePath(start, end);

      // Error checking.
      if(ptr->m_next == NULL)
         return false;

      // This start is determined by the total of the last path.
      ptr->m_next->m_start = ptr->m_total + ptr->m_start;

      ptr->m_next->m_total = Vector3D(start - end).Magnitude();
   }

   return true;
}

					  

Listing 10. The AddCurvePath() Function
bool Route::AddCurvePath(Vector3D p1, Vector3D cnt1,
                         Vector3D cnt2, Vector3D p2)
{
   Path *ptr = NULL;

   if(m_path == NULL)
   {
      // Allocate data for the root node.
      m_path = new CurvePath(p1, cnt1, cnt2, p2);

      // Make sure all went well.
      if(m_path == NULL)
         return false;

      // Since this is the start node, its start is 0.
      m_path->m_start = 0;

      float Length01 = Vector3D(cnt1 - p1).Magnitude();
      float Length12 = Vector3D(cnt2 - cnt1).Magnitude();
      float Length23 = Vector3D(p2 - cnt2).Magnitude();
      float Length03 = Vector3D(p2 - p1).Magnitude();
      m_path->m_total = (Length01 + Length12 + Length23) *
                           0.5f + Length03 * 0.5f;
   }
   else
   {
      // Prepare to move through root until we find a NULL spot.
      ptr = m_path;

      // Search to a node without a next pointer.
      while(ptr->m_next != NULL)
         ptr = ptr->m_next;

      // Create the m_next path in our list.
      ptr->m_next = new CurvePath(p1, cnt1, cnt2, p2);

      // Error checking.
      if(ptr->m_next == NULL)
         return false;

      // This start is determined by the total of the last path.
      ptr->m_next->m_start = ptr->m_total + ptr->m_start;

      float Length01 = Vector3D(cnt1 - p1).Magnitude();
      float Length12 = Vector3D(cnt2 - cnt1).Magnitude();
      float Length23 = Vector3D(p2 - cnt2).Magnitude();
      float Length03 = Vector3D(p2 - p1).Magnitude();

      ptr->m_next->m_total = (Length01 + Length12 + Length23) *
                             0.5f + Length03 * 0.5f;
   }

   return true;
}

					  

The last function in the Route class is the GetPosition() function. This function takes the time as a parameter and loops through each path until it finds a path that falls within the time passed in the parameter of the function. Once it finds this path, it calls the path’s GetPathPos() to return the interpolated position of the path within which the time falls. The function also resets the Route class’s timer once the animation is complete to simulate a looping effect. The GetPosition() function is shown in Listing 11.

Listing 11. The GetPosition() Function
Vector3D Route::GetPosition(float time)
{
   Path *ptr = m_path;
   Vector3D nullPos;

   // Error checking.
   if(m_path == NULL)
      return nullPos;

   // Initialize the start time if it has not been already.
   if(m_startTime == 0)
      m_startTime = (float)timeGetTime();

   // Loop through each path to see where this object is.
   do
   {
      // Check if the object falls in along this path.
      if(time >= ptr->m_start &&
         time < ptr->m_start + ptr->m_total)
      {
         // Calculate distance traveled within this path.
         time -= ptr->m_start;

         // Parameter as a percent traveled.
         return ptr->GetPathPos(time / ptr->m_total);
      }
      else
      {
         // Reset to loop through the route again.
         if(ptr->m_next == 0)
            m_startTime = (float)timeGetTime();
      }

      ptr = ptr->m_next;

   }while(ptr != NULL);

   return nullPos;
}					 
Other  
 
Top 10
Review : Sigma 24mm f/1.4 DG HSM Art
Review : Canon EF11-24mm f/4L USM
Review : Creative Sound Blaster Roar 2
Review : Philips Fidelio M2L
Review : Alienware 17 - Dell's Alienware laptops
Review Smartwatch : Wellograph
Review : Xiaomi Redmi 2
Extending LINQ to Objects : Writing a Single Element Operator (part 2) - Building the RandomElement Operator
Extending LINQ to Objects : Writing a Single Element Operator (part 1) - Building Our Own Last Operator
3 Tips for Maintaining Your Cell Phone Battery (part 2) - Discharge Smart, Use Smart
REVIEW
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
VIDEO TUTORIAL
- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 1)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 2)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 3)
Popular Tags
Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Biztalk Exchange Server Microsoft LynC Server Microsoft Dynamic Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Indesign Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe After Effects Adobe Photoshop Adobe Fireworks Adobe Flash Catalyst Corel Painter X CorelDRAW X5 CorelDraw 10 QuarkXPress 8 windows Phone 7 windows Phone 8
Visit movie_stars's profile on Pinterest.