Coder Social home page Coder Social logo

wei858910 / crystalpathfinding Goto Github PK

View Code? Open in Web Editor NEW

This project forked from d-mozulyov/crystalpathfinding

0.0 0.0 0.0 1 MB

Extremely fast and most simple A*/WA* library

Home Page: http://www.gamedev.ru/code/forum/?id=148004

License: MIT License

C++ 3.63% Pascal 96.37%

crystalpathfinding's Introduction

CrystalPathFinding (CPF)

Simple and effective library with an open source intended for the searching of the shortest paths by algorithms A*/WA* for maps based on tiles with 4 (simple), 8 (diagonal/diagonalex) or 6 (hexagonal) neighbors.

Library features:

  • Cross-platform: Windows x86/x64, Linux x86/x64, Mac OS, iOS, Android, Windows Mobile, and also other platforms accessible to the compilers Delphi and FreePascal
  • Extremely high performance
  • Smart constructing of a path
  • Limit is 16 million of cells (e.g. 4000x4000)
  • Sector test
  • Optional: OOP or procedural interface
  • Caching and search from several starting points support
  • Up to 255 types of tiles, weight is from 0.1 to 100.0
  • Contains demonstration projects

Demo_x86.zip, Demo_x64.zip

Help

The library contains 2 main objects: TTileMap (map of tiles) and TTileMapWeights (tile weights array). The tile can take any value from 1 till 255. The tile’s weight is indicated in the range from 0.1 to 100.0, if the tile weight is from 0.0 to 0.1 then the tile is considered to be impassable. If the TTileMapWeights is not indicated during the searching then all the weights are considered to be 1. The tile with number 0 (TILE_BARRIER) is considered to be a barrier, passing through which is impossible. The modes of the maps mkDiagonal and mkDiagonalEx are different in a way how the paths round the tile-barriers.

The SectorTest parameter helps to improve the search speed dramatically if the map is divided into "areas" and to build the path from one "area" to another is impossible.

The Caching parameter is always recommended to set to true if it is not supposed to change the destination point or weights array.

The array of Excludes has a large value. It is possible to organize complex searches with the help of this feature in which, for example, one game unit do not contact with the others. In such cases it is recommended to rebuild the paths by changing the destination point, unit strength or the position of at least one of the game units. Accordingly, if not the whole path of the game unit interests you but only the next point then the search parameter FullPath is recommended to set to false (watch the example below).

Basic types and contants
  typedef unsigned short ushort;
  typedef unsigned char uchar;
  struct TPoint
  {
      long X;
      long Y;
      TPoint(){}
      TPoint(long x, long y):X(x),Y(y){}
  };  

  // handle type
  typedef size_t TCPFHandle;

  // kind of map
  typedef uchar TTileMapKind; enum {mkSimple, mkDiagonal, mkDiagonalEx, mkHexagonal}; 

  // result of find path function
  struct TTileMapPath
  {
      size_t  Index;  
	  TPoint* Points;
      size_t  Count;
      double  Distance;
  };

  // path finding parameters
  struct TTileMapParams
  {
      TPoint* Starts;
      size_t StartsCount;
      TPoint Finish;
      TCPFHandle Weights;
      TPoint* Excludes;
      size_t ExcludesCount;
  };

  // map tile barrier
  #define TILE_BARRIER 0  
Tile weights object
  struct TTileMapWeights
  {
	// constructor and destructor
	TTileMapWeights();
	~TTileMapWeights();

    // internal descriptor
    TCPFHandle Handle; 

    // tile weight values
	float getValue(uchar Tile);
	void setValue(uchar Tile, float Value);
  }; 
Tile map object
  struct TTileMap
  {
	// constructor and destructor
	TTileMap(ushort AWidth, ushort AHeight, TTileMapKind AKind, bool ASameDiagonalWeight = false);
	~TTileMap();

    // internal descriptor
    TCPFHandle Handle; 

    // basic parameters
    ushort Width;
	ushort Height;
	TTileMapKind Kind;
	bool SameDiagonalWeight;

    // important variable parameters!
	bool SectorTest;
	bool Caching;

	// update methods
	void Clear();
	void Update(uchar* ATiles, ushort X, ushort Y, ushort AWidth, ushort AHeight, ptrdiff_t Pitch = 0);
	uchar getTile(ushort X, ushort Y);
	void setTile(ushort X, ushort Y, uchar Value);

	// path finding
	TTileMapPath FindPath(const TTileMapParams Params, bool FullPath = true);
	TTileMapPath FindPath(const TPoint Start, const TPoint Finish,
	  TCPFHandle Weights = 0, TPoint* Excludes = NULL, size_t ExcludesCount = 0, bool FullPath = true);
	TTileMapPath FindPath(TPoint* Starts, size_t StartsCount, const TPoint Finish,
	  TCPFHandle Weights = 0, TPoint* Excludes = NULL, size_t ExcludesCount = 0, bool FullPath = true);
  }; 
Simple example

http://www.policyalmanac.org/games/aStarTutorial.htm

  TTileMap Map(8, 6, mkDiagonalEx);

  Map.setTile(4, 1, TILE_BARRIER);
  Map.setTile(4, 2, TILE_BARRIER);
  Map.setTile(4, 3, TILE_BARRIER);

  TPoint Start(2, 2);
  TPoint Finish(6, 2);
  printf("A* Pathfinding [%d, %d] --> [%d, %d]...\n", Start.X, Start.Y, Finish.X, Finish.Y);
  TTileMapPath Path = Map.FindPath(Start, Finish);

  printf("Distance = %0.2f (%d points):\n", Path.Distance, Path.Count);
  for (size_t i = 0; i < Path.Count; i++)
    printf("[%d, %d]\n", Path.Points[i].X, Path.Points[i].Y);

Output:

A* Pathfinding [2, 2] --> [6, 2]... 
Distance = 6.83 (7 points): 
[2, 2] 
[3, 3] 
[3, 4] 
[4, 4] 
[5, 4] 
[6, 3] 
[6, 2]
Example of many game units paths updating
void Game::UpdateBotsPaths()
{
   // clear one point paths
   for (int i = 0; i < Bots.Count; i++)
     Bots[i].NextPoint = Bots.Point;
   
   // finding next path point for every unit
   for (int i = 0; i < Bots.Count; i++)
   {
      // detect excluded points
      vector<TPoint> Excludes;
      for (int j = 0; j < Bots.Count; j++)
      if (i != j)
      {
         Excludes.push_back(Bots[j].Point);

         if (Bots[j].Point != Bots[j].NextPoint)
           Excludes.push_back(Bots[j].NextPoint);
      }
    
      // fill parameters, find path (one next point)
      TTileMapParams Params;
      Params.Starts = &Bots[i].Point;
      Params.StartsCount = 1;
      Params.Finish = this.TargetPoint;
      Params.Weights = NULL/* this.Weights.Handle */;
      Params.ExcludesCount = Excludes.size(); 
      if (Params.ExcludesCount) Params.Excludes = &Excludes[0];
      TTileMapPath Path = this.Map.FindPath(Params, false/* false means next point needed only */);
      if (Path.Count > 1)
        Bots[i].NextPoint = Path.Points[1];
   }
}

crystalpathfinding's People

Contributors

d-mozulyov avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.