A C++ implementation of an action list data structure for games.

 
//------------------------------------------------------------------------------
// Header File
//------------------------------------------------------------------------------

#include "action.h"
#include 
#include 

namespace crusher
{

  /* list of concurrently or sequentially running actions */
  class action_list : public action
  {
    public:
      // typedefs
      typedef int lane_id;

      // ctor / dtor
      action_list(void);
      ~action_list(void);

      // public methods
      void update(float dt);
      void push_back(action* back, lane_id id = 0);
      void push_front(action* front, lane_id id = 0);
      void clear(void);
      void clear_lane(lane_id clear_id);

      bool empty(void) const;
      bool lane_empty(lane_id id) const;

    private:
      // private types
      typedef std::list<action*> action_container;
      typedef std::map<lane_id, action_container> lane_map;
      typedef std::pair<lane_id, action_container> lane_pair;

      // private members
      lane_map _lanes;
      int _size;

  }; // class action_list

} // namespace crusher



//------------------------------------------------------------------------------
// Implementation File
//------------------------------------------------------------------------------

#include "action_list.h"

using namespace crusher;

action_list::action_list(void)
  : _size(0)
{
}

action_list::~action_list(void)
{
  clear();
}

void action_list::update(float dt)
{
  if (is_paused())
    return;

  // update all action lanes
  for (auto& lane_pair : _lanes)
  {
    // update actions until blocking action
    action_container& lane = lane_pair.second;
    for (auto it = lane.begin(); it != lane.end();)
    {
      action* cur_action = *it;

      // don't update if paused
      if (!cur_action->is_paused())
      {
        // start if hasn't started
        if (!cur_action->is_started())
        {
          cur_action->_started = true;
          cur_action->startup();
        }

        cur_action->update(dt);

        // remove if finished
        if (cur_action->is_finished())
        {
          cur_action->shutdown();
          delete cur_action;
          it = lane.erase(it);
          --_size;
          continue;
        }
      }

      // remaining actions blocked
      if (cur_action->is_blocking())
        break;

      ++it;
    }
  }

  // finish if empty
  if (empty())
    set_finished();
}

void action_list::push_back(action* back, lane_id id)
{
  _lanes[id].push_back(back);
  ++_size;
}

void action_list::push_front(action* front, lane_id id)
{
  _lanes[id].push_front(front);
  ++_size;
}

void action_list::clear(void)
{
  // delete all actions
  for (auto& lane : _lanes)
  {
    // delete all actions in lane
    for (action* action : lane.second)
      delete action;
  }

  _lanes.clear();
  _size = 0;
}

void action_list::clear_lane(lane_id clear_id)
{
  auto lane = _lanes.find(clear_id);
  if (lane != _lanes.end())
  {
    // delete all actions in lane
    action_container& clear_lane = lane->second;
    for (action* action : clear_lane)
      delete action;

    clear_lane.clear();
  }
}

bool action_list::empty(void) const
{
  return (_size == 0);
}

bool action_list::lane_empty(lane_id id) const
{
  auto lane = _lanes.find(id);
  if (lane == _lanes.end())
    return true;
  
  return lane->second.empty();
}

Leave a Reply

Your email address will not be published. Required fields are marked *