stnKrisna / Flow

An STL only, "bring-your-own AI agent" flow field navigation library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Flow cover image

Documentation

Features

Planned features

  • Serialization
  • Deserialization
  • User embeded cell data
  • Cell exit restriction - Cell direction can only point to a certain direction.
  • Dynamic/real-time reaction - Flow direction is able to adapt to a dynamic environment without having to recalculate every single cell.

Example

Here is an example usage of this library.

Building flow field from ASCII map

flow::Field field(10, 8);

char map[] = "\
wwwwwwwwww\
w........w\
www.ww.www\
www.ww.www\
www.ww.www\
www.ww.www\
w........w\
w........w";

for (auto cell = field.begin(); cell != field.end(); ++cell) {
  cell->setAllowDiagonal(true);
  switch (map[cell.idx]) {
    case '.':
      cell->setEntryDir(flow::Directions::NORTH |
              flow::Directions::EAST |
              flow::Directions::SOUTH |
              flow::Directions::WEST);
      break;
    case 'w':
      cell->setEntryDir(0);
      cell->setAllowDiagonal(false);
      break;
  }
}

One-way traffic

char map[] = "\
wwwwwwwwww\
w........w\
www4ww1www\
www4ww1www\
www4ww1www\
www4ww1www\
w........w\
w........w";

for (auto cell = field.begin(); cell != field.end(); ++cell) {
  cell->setAllowDiagonal(true);
  switch (map[cell.idx]) {
    case '.':
      cell->setEntryDir(flow::Directions::NORTH |
              flow::Directions::EAST |
              flow::Directions::SOUTH |
              flow::Directions::WEST);
      break;
    case '1':
      cell->setEntryDir(flow::Directions::NORTH);
      break;
    case '4':
      cell->setEntryDir(flow::Directions::SOUTH);
      break;
    case 'w':
      cell->setEntryDir(0);
      cell->setAllowDiagonal(false);
      break;
  }
}

// Or use the "at" function to get a specific cell
field.at(1, 0).setEntryDir(flow::Directions::NORTH |
        flow::Directions::EAST |
        flow::Directions::SOUTH |
        flow::Directions::WEST);

STL-like cell iteration

// Begin-end loop
for (auto itr = field.begin(); itr != field.end(); ++itr) {
  // Print the index of the iterator
  std::cout << itr.idx << std::endl;

  // You can use the arrow operator (->) to access the cell
  itr->setEntryDir(flow::Directions::NORTH |
    flow::Directions::EAST |
    flow::Directions::SOUTH |
    flow::Directions::WEST);
}

// Range based loop
for (auto& cell : field) {
  // Convert every cell to a wall
  cell.setEntryDir(0);
}

for (auto cell : field) {
  // Everything is now a wall
  std::cout << cell.isWall() << " ";
}

Grid-based navigation

// BYO vector object
if (enemy.position == enemy.desiredPos) {
  uint16_t newPos_x = 0;
  uint16_t newPos_y = 0;

  field.getNextCell(0, (int)enemy.pos.x, (int)enemy.pos.y, &newPos_x, &newPos_y);

  enemy.desiredPos.x = newPos_x;
  enemy.desiredPos.y = newPos_y;
}

Vector-based navigation

// BYO vector object
Vector2 enemyDir;

// Get the normalized vector of the direction
field.getDirection(0, (int)enemy.pos.x, (int)enemy.pos.y, &enemyDir.x, &enemyDir.y);

// BYO vector math
enemy.pos += enemy.speed * enemyDir;

Inspiration

This project is inspired from this paper:

  • S. Patil, J. Van Den Berg, S. Curtis, M. C. Lin, en D. Manocha, “Directing crowd simulations using navigation fields”, IEEE transactions on visualization and computer graphics, vol 17, no 2, bll 244–254, 2010.

About

An STL only, "bring-your-own AI agent" flow field navigation library

License:MIT License


Languages

Language:C++ 99.7%Language:Shell 0.3%