[attachment=5073:Untitled.png]
To figure out distance you need to do tilewalks because as shown in this picture the coordinate system is a bit strange!
So basically I want to draw an overlay with the amount of movable spaces so players can see how far they are moving... Well after much coding I came up with a very complicated solution to a very easy to solve problem and I was wondering if anyone could help me find an easier way.
I wrote a function to do a standard tilewalk given a set of coordinates and returns the next space you would be on depending on what direction you move (compass directions)
here is that function (below)
But the problem is as you go up in movements it takes way more processing, exponentially more, for a movement of 10 spaces it takes over 30k lookup's to see if that tile is already on the list (99.9999% of them are already on the list but the cost to look up if they are is what is killing me)
POINT OverlayManager::TileWalk(int Direction, int Xstart,int Ystart) //walks in a direction returns new space
{
POINT NewLoc;
switch (Direction)
{
case DIRN: //NORTH
{
if(Xstart&1) //if X is odd we need a special case to also make X less
{
if(Ystart&1) // if y is odd also
{
NewLoc.x = Xstart +1;
NewLoc.y = Ystart -1;
}
else //else y is even
{
NewLoc.x = Xstart;
NewLoc.y = Ystart -1;
}
}
else //X is even
{
if(Ystart&1) // if y is odd also
{
NewLoc.x = Xstart +1;
NewLoc.y = Ystart -1;
}
else //else y is even
{
NewLoc.x = Xstart;
NewLoc.y = Ystart -1;
}
}
}break;
case DIRE: //East
{
if(Xstart&1) //if X is odd we need a special case to also make X less
{
if(Ystart&1) // if y is odd also
{
NewLoc.x = Xstart +1;
NewLoc.y = Ystart +1;
}
else //else y is even
{
NewLoc.x = Xstart;
NewLoc.y = Ystart +1;
}
}
else //X is even
{
if(Ystart&1) // if y is odd also
{
NewLoc.x = Xstart +1;
NewLoc.y = Ystart +1;
}
else //else y is even
{
NewLoc.x = Xstart;
NewLoc.y = Ystart +1;
}
}
}break;
case DIRS: //South
{
if(Xstart&1) //if X is odd we need a special case
{
if(Ystart&1) // if y is odd also
{
NewLoc.x = Xstart ;
NewLoc.y = Ystart +1;
}
else //else y is even
{
NewLoc.x = Xstart -1;
NewLoc.y = Ystart +1;
}
}
else //X is even
{
if(Ystart&1) // if y is odd also
{
NewLoc.x = Xstart ;
NewLoc.y = Ystart +1;
}
else //else y is even
{
NewLoc.x = Xstart -1;
NewLoc.y = Ystart +1;
}
}
}break;
case DIRW: //West
{
if(Xstart&1) //if X is odd we need a special case
{
if(Ystart&1) // if y is odd also
{
NewLoc.x = Xstart ;
NewLoc.y = Ystart -1;
}
else //else y is even
{
NewLoc.x = Xstart -1;
NewLoc.y = Ystart -1;
}
}
else //X is even
{
if(Ystart&1) // if y is odd also
{
NewLoc.x = Xstart ;
NewLoc.y = Ystart -1;
}
else //else y is even
{
NewLoc.x = Xstart -1;
NewLoc.y = Ystart -1;
}
}
}break;
}
return NewLoc;
}
And what I do is I have a base function to add our start location and tile walk in every direction and build up a lookup vector that only contains the tiles we have determined are in the overlay.
void OverlayManager::AddStandardMovementOverLay(int OriginX, int OriginY, int MoveSpaces, int OffSetX, int OffSetY)
{
OverLays.clear(); //clear out other overlays
CurrentOffSetX = OffSetX;
CurrentOffSetY = OffSetY;
int X = OriginX;
int Y = OriginY;
AddSingleOverLay(X, Y);
for(int a=0;a<4;a++) //For each direction
{
AddAllNodes(a, X, Y, MoveSpaces-1);
}
}
void OverlayManager::AddSingleOverLay(int X, int Y)
{
if(IsOnList(X,Y) == false) //don't add duplicates
{
OTILE NewTile;
NewTile.colour = D3DCOLOR_ARGB(255,255,255,255);
NewTile.mapx = X;
NewTile.mapy = Y;
NewTile.onscreenx = 0;
NewTile.onscreeny = 0;
OverLays.push_back(NewTile);
}
}
void OverlayManager::AddAllNodes(int Dir, int StartX, int StartY, int Moves)
{
POINT Current;
Current.x = StartX;
Current.y= StartY;
if (Moves == 0)
{
return;
}
switch (Dir)
{
case DIRN: //NORTH
{
Current = TileWalk(DIRN, Current.x, Current.y);
AddSingleOverLay(Current.x, Current.y);
//for(int i=0;i<Moves;i++)
//{
AddAllNodes(DIRN, Current.x, Current.y, Moves -1);
AddAllNodes(DIRE, Current.x, Current.y, Moves -1);
AddAllNodes(DIRW, Current.x, Current.y, Moves -1);
//}
}break;
case DIRE: //EAST
{
Current = TileWalk(DIRE, Current.x, Current.y);
AddSingleOverLay(Current.x, Current.y);
//for(int i=0;i<Moves;i++)
//{
AddAllNodes(DIRE, Current.x, Current.y, Moves -1);
AddAllNodes(DIRN, Current.x, Current.y, Moves -1);
AddAllNodes(DIRS, Current.x, Current.y, Moves -1);
//}
}break;
case DIRS: //South
{
Current = TileWalk(DIRS, Current.x, Current.y);
AddSingleOverLay(Current.x, Current.y);
//for(int i=0;i<Moves;i++)
//{
AddAllNodes(DIRS, Current.x, Current.y, Moves -1);
AddAllNodes(DIRE, Current.x, Current.y, Moves -1);
AddAllNodes(DIRW, Current.x, Current.y, Moves -1);
//}
}break;
case DIRW: //West
{
Current = TileWalk(DIRW, Current.x, Current.y);
AddSingleOverLay(Current.x, Current.y);
//for(int i=0;i<Moves;i++)
//{
AddAllNodes(DIRN, Current.x, Current.y, Moves -1);
AddAllNodes(DIRW, Current.x, Current.y, Moves -1);
AddAllNodes(DIRS, Current.x, Current.y, Moves -1);
//}
}break;
}
}
Edit: I fixed a huge bug in my addallnodes code, it made it faster but im still interested in seeing other solutions!(from 1 million to 30k lookup's)