Advertisement
jewalky

Untitled

Mar 9th, 2017
311
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.31 KB | None | 0 0
  1. class PathNode
  2. {
  3.     int x;
  4.     int y;
  5.    
  6.     int fScore;
  7.     int gScore;
  8.    
  9.     PathNode cameFrom;
  10.    
  11.     PathNode Init(int x, int y)
  12.     {
  13.         self.x = x;
  14.         self.y = y;
  15.         gScore = 2147483647;
  16.         fScore = 2147483647;
  17.         cameFrom = null;
  18.         return self;
  19.     }
  20. }
  21.  
  22. class PathfindingHandler : EventHandler
  23. {
  24.     const RESOLUTION = 32;
  25.     const CNT_X = 65536/RESOLUTION;
  26.     const CNT_Y = 65536/RESOLUTION;
  27.  
  28.     Sector SBlockMap[CNT_Y][CNT_X];
  29.  
  30.     private void MakeNull(int x1, int y1, int x2, int y2)
  31.     {
  32.         int x,y,dx,dy,dx1,dy1,px,py,xe,ye,i;
  33.         dx=x2-x1;
  34.         dy=y2-y1;
  35.         dx1=abs(dx);
  36.         dy1=abs(dy);
  37.         px=2*dy1-dx1;
  38.         py=2*dx1-dy1;
  39.         if(dy1<=dx1)
  40.         {
  41.             if(dx>=0)
  42.             {
  43.                 x=x1;
  44.                 y=y1;
  45.                 xe=x2;
  46.             }
  47.             else
  48.             {
  49.                 x=x2;
  50.                 y=y2;
  51.                 xe=x1;
  52.             }
  53.             SBlockMap[y][x] = null;
  54.             for(i=0;x<xe;i++)
  55.             {
  56.                 x=x+1;
  57.                 if(px<0)
  58.                 {
  59.                     px=px+2*dy1;
  60.                 }
  61.                 else
  62.                 {
  63.                     if((dx<0 && dy<0) || (dx>0 && dy>0))
  64.                     {
  65.                         y=y+1;
  66.                     }
  67.                     else
  68.                     {
  69.                         y=y-1;
  70.                     }
  71.                     px=px+2*(dy1-dx1);
  72.                 }
  73.                 SBlockMap[y][x] = null;
  74.             }
  75.         }
  76.         else
  77.         {
  78.             if(dy>=0)
  79.             {
  80.                 x=x1;
  81.                 y=y1;
  82.                 ye=y2;
  83.             }
  84.             else
  85.             {
  86.                 x=x2;
  87.                 y=y2;
  88.                 ye=y1;
  89.             }
  90.             SBlockMap[y][x] = null;
  91.             for(i=0;y<ye;i++)
  92.             {
  93.                 y=y+1;
  94.                 if(py<=0)
  95.                 {
  96.                     py=py+2*dx1;
  97.                 }
  98.                 else
  99.                 {
  100.                     if((dx<0 && dy<0) || (dx>0 && dy>0))
  101.                     {
  102.                         x=x+1;
  103.                     }
  104.                     else
  105.                     {
  106.                         x=x-1;
  107.                     }
  108.                     py=py+2*(dx1-dy1);
  109.                 }
  110.                 SBlockMap[y][x] = null;
  111.             }
  112.         }
  113.     }
  114.    
  115.     vector2 RelToAbs(vector2 rel)
  116.     {
  117.         return (rel.x + 32768, rel.y + 32768);
  118.     }
  119.    
  120.     vector2 AbsToRel(vector2 abs)
  121.     {
  122.         return (abs.x - 32768, abs.y - 32768);
  123.     }
  124.    
  125.     override void WorldLoaded(WorldEvent ev)
  126.     {
  127.         for (int y = 0; y < 65536; y += RESOLUTION)
  128.         {
  129.             for (int x = 0; x < 65536; x += RESOLUTION)
  130.             {
  131.                 Sector s = Sector.PointInSector(AbsToRel((x, y)));
  132.                 SBlockMap[y/RESOLUTION][x/RESOLUTION] = s;
  133.             }
  134.         }
  135.        
  136.         // now, go mark all cells that have 1-sided lines as null
  137.         for (int i = 0; i < level.lines.Size(); i++)
  138.         {
  139.             Line l = level.lines[i];
  140.             if (!l.backsector || l.flags & Line.ML_BLOCKING)
  141.             {
  142.                 vector2 v1 = RelToAbs(l.v1.p);
  143.                 vector2 v2 = RelToAbs(l.v2.p);
  144.                 MakeNull(v1.x/RESOLUTION, v1.y/RESOLUTION, v2.x/RESOLUTION, v2.y/RESOLUTION);
  145.             }
  146.         }
  147.        
  148.         int notwalkable = 0;
  149.         for (int y = 0; y < CNT_Y; y++)
  150.         {
  151.             for (int x = 0; x < CNT_X; x++)
  152.             {
  153.                 if (!SBlockMap[y][x])
  154.                     notwalkable++;
  155.             }
  156.         }
  157.        
  158.         TestIt();
  159.     }
  160.    
  161.     Array<PathNode> Path;
  162.    
  163.     int HeuristicCostEstimate(PathNode a, PathNode b)
  164.     {
  165.         return ((a.x-b.x, a.y-b.y).Length())*16;
  166.     }
  167.    
  168.     double Ang180(double ang)
  169.     {
  170.         if (ang > 180)
  171.             ang = -(ang-180);
  172.         return ang;
  173.     }
  174.    
  175.     int GetCost(PathNode a, PathNode b)
  176.     {
  177.         // get angle difference
  178.         return 1;
  179.     }
  180.    
  181.     Array<PathNode> nodes;
  182.     PathNode GetNode(int x, int y)
  183.     {
  184.         int s = nodes.Size();
  185.         for (int i = 0; i < s; i++)
  186.         {
  187.             PathNode n = nodes[i];
  188.             if (n.x == x && n.y == y)
  189.                 return n;
  190.         }
  191.         PathNode n = new('PathNode').Init(x, y);
  192.         nodes.Push(n);
  193.         return n;
  194.     }
  195.    
  196.     Array<PathNode> closedSet;
  197.     Array<PathNode> openSet;
  198.     Array<PathNode> neighbours;
  199.     void AddNeighbourMaybe(PathNode ref, int xDelta, int yDelta)
  200.     {
  201.         int newX = ref.x+xDelta;
  202.         int newY = ref.y+yDelta;
  203.         if (newX < 0 || newX >= CNT_X)
  204.             return;
  205.         if (newY < 0 || newY >= CNT_Y)
  206.             return;
  207.         if (!SBlockMap[newY][newX])
  208.             return;
  209.         PathNode n = GetNode(newX, newY);
  210.         if (closedSet.Find(n)!=closedSet.Size()) return;
  211.         //Console.Printf("adding %d, %d", newX*RESOLUTION-32768, newY*RESOLUTION-32768);
  212.         neighbours.Push(n);
  213.     }
  214.    
  215.     bool FindPath(PathNode start, PathNode goal)
  216.     {
  217.         Path.Clear();
  218.         closedSet.Clear();
  219.         openSet.Clear();
  220.         openSet.Push(start);
  221.         start.gScore = 0;
  222.         start.fScore = HeuristicCostEstimate(start, goal);
  223.         start.cameFrom = null;
  224.        
  225.         int iter = 0;
  226.        
  227.         while (openSet.Size())
  228.         {
  229.             PathNode current = null;
  230.             int s = openSet.Size();
  231.             for (int i = 0; i < s; i++)
  232.             {
  233.                 PathNode currentP = openSet[i];
  234.                 if (!current || currentP.fScore < current.fScore)
  235.                     current = currentP;
  236.             }
  237.            
  238.             if (current == goal) // path found
  239.             {
  240.                 // trace path.
  241.                 PathNode p = current;
  242.                 while (p)
  243.                 {
  244.                     Path.Insert(0, p);
  245.                     p = p.cameFrom;
  246.                 }
  247.                 return true;
  248.             }
  249.            
  250.             openSet.Delete(openSet.Find(current));
  251.             closedSet.Push(current);
  252.             neighbours.Clear();
  253.             AddNeighbourMaybe(current, -1, 0);
  254.             AddNeighbourMaybe(current, 1, 0);
  255.             AddNeighbourMaybe(current, 0, -1);
  256.             AddNeighbourMaybe(current, 0, 1);
  257.             // diagonal
  258.             //AddNeighbourMaybe(current, -1, -1);
  259.             //AddNeighbourMaybe(current, -1, 1);
  260.             //AddNeighbourMaybe(current, 1, -1);
  261.             //AddNeighbourMaybe(current, 1, 1);
  262.             //Console.Printf("node %d, %d; neighbours = %d", current.x*RESOLUTION-32768, current.y*RESOLUTION-32768, neighbours.Size());
  263.            
  264.             //iter++;
  265.             //if (iter > 150)
  266.                 //break;
  267.            
  268.             for (int i = 0; i < neighbours.Size(); i++)
  269.             {
  270.                 PathNode neighbour = neighbours[i];
  271.                 int tentative_gScore = current.gScore + GetCost(current, neighbour);
  272.                 // check if it exists already
  273.                 if (openSet.Find(neighbour)==openSet.Size())
  274.                     openSet.Push(neighbour);
  275.                 else if (tentative_gScore >= neighbour.gScore)
  276.                     continue;
  277.                
  278.                 // this path is the best until now, record it
  279.                 neighbour.cameFrom = current;
  280.                 neighbour.gScore = tentative_gScore;
  281.                 neighbour.fScore = tentative_gScore + HeuristicCostEstimate(neighbour, goal);
  282.             }
  283.         }
  284.        
  285.         return false;
  286.     }
  287.    
  288.     bool FindPathByCoordinates(vector2 a, vector2 b)
  289.     {
  290.         nodes.Clear();
  291.         a = RelToAbs(a);
  292.         b = RelToAbs(b);
  293.         PathNode p_a = GetNode(a.x/RESOLUTION, a.y/RESOLUTION);
  294.         PathNode p_b = GetNode(b.x/RESOLUTION, b.y/RESOLUTION);
  295.         return FindPath(p_a, p_b);
  296.     }
  297.    
  298.     Actor testActor;
  299.     int testTicks;
  300.     int testIdx;
  301.  
  302.     void LogBlockmapAt(int x, int y)
  303.     {
  304.         Console.Printf("blockmap at %d,%d=%d", x, y, !!SBlockMap[(y+32768)/RESOLUTION][(x+32768)/RESOLUTION]);
  305.     }
  306.    
  307.     void TestIt()
  308.     {
  309.         testActor = Actor.Spawn('PlasmaBall', (0, 0, 2));
  310.         testTicks = 0;
  311.         testIdx = 0;
  312.         bool found = FindPathByCoordinates((testActor.pos.x, testActor.pos.y), (players[consoleplayer].mo.pos.x, players[consoleplayer].mo.pos.y));
  313.         Console.Printf("found = %d; path = %d", found, Path.Size());
  314.     }
  315.    
  316.     override void WorldTick()
  317.     {
  318.         if (!testActor)
  319.             return;
  320.            
  321.         if (Path.Size() <= testIdx+1)
  322.             return;
  323.            
  324.         testTicks++;
  325.         if (testTicks > 2)
  326.         {
  327.             testIdx++;
  328.             PathNode pn = Path[testIdx];
  329.             vector2 newPos = AbsToRel((pn.x*RESOLUTION, pn.y*RESOLUTION));
  330.             testActor.SetOrigin((newPos.x, newPos.y, testActor.pos.z), true);
  331.             testTicks = 0;
  332.            
  333.             bool found = FindPathByCoordinates((testActor.pos.x-16, testActor.pos.y-16), (players[consoleplayer].mo.pos.x, players[consoleplayer].mo.pos.y));
  334.             Console.Printf("found = %d; path = %d", found, Path.Size());
  335.         }
  336.     }
  337. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement