Recently I started fiddling around with pathfinding. I created a WayPoint component to determin a possible way to another actor which is defined over other waypoints. My grid is looking somewhat like this:
The goal was to find a way to the red circled waypoint. A waypoint can have up to eight neigbours. I didn't include the SelectionController or any other component to save some space ;)
The target-actor has a component which implements a similar interface as WayPointComponent but with some minor differences in functionality attached to it.
class WayPointComponent : public ActorComponent
{
public:
WayPointComponent(Engine* game, mango::int32 dist)
: ActorComponent("WayPointComponent"), m_Game(game), m_MinPointDistance(dist)
{}
virtual void Update()
{
}
virtual void Move(Vector2 motion)
{
}
virtual void SetPosition(Vector2 pos)
{
}
static void FindPath_th(WayPointComponent* wp)
{
wp->FindPath();
}
virtual void FindPath()
{
SelectionController* selection = (SelectionController*)GetOwner()->FindComponent("SelectionController"); //the selection controller is used to identify the selected waypoint
Actor* target = &selection->GetSelectedActor();
if (target && GetOwner()->GetActorName() != target->GetActorName())
{
Actor* bestNeighbour = GetClosestNeghbourTo(target);
WayPointComponent* wp = (WayPointComponent*)bestNeighbour->FindComponent("WayPointComponent");
//wp->FindPath();
Util::LaunchBackgroundTask(mango::bind<void>(FindPath_th, wp)); //The actor who is selected won't launch a new task.
GraphicProperties* graphics = (GraphicProperties*)bestNeighbour->FindComponent("GraphicProp");
if (graphics->GetOwner()->GetActorName() != target->GetActorName())
{
graphics->SetActiveAnimation(AnimationIDs::idleOnWay); //Sets the animation of every element on the part to a purple flashing square
}
}
}
virtual void Init()
{
Vector2 pos = GetOwner()->GetPosition();
std::string neighbour1 = std::string("square(") + mango::to_string(pos.X - m_MinPointDistance) + std::string("|") + mango::to_string(pos.Y ) + std::string(")");
std::string neighbour2 = std::string("square(") + mango::to_string(pos.X + m_MinPointDistance) + std::string("|") + mango::to_string(pos.Y ) + std::string(")");
std::string neighbour3 = std::string("square(") + mango::to_string(pos.X ) + std::string("|") + mango::to_string(pos.Y - m_MinPointDistance) + std::string(")");
std::string neighbour4 = std::string("square(") + mango::to_string(pos.X ) + std::string("|") + mango::to_string(pos.Y + m_MinPointDistance) + std::string(")");
std::string neighbour5 = std::string("square(") + mango::to_string(pos.X - m_MinPointDistance) + std::string("|") + mango::to_string(pos.Y - m_MinPointDistance) + std::string(")");
std::string neighbour6 = std::string("square(") + mango::to_string(pos.X + m_MinPointDistance) + std::string("|") + mango::to_string(pos.Y + m_MinPointDistance) + std::string(")");
std::string neighbour7 = std::string("square(") + mango::to_string(pos.X - m_MinPointDistance) + std::string("|") + mango::to_string(pos.Y + m_MinPointDistance) + std::string(")");
std::string neighbour8 = std::string("square(") + mango::to_string(pos.X + m_MinPointDistance) + std::string("|") + mango::to_string(pos.Y - m_MinPointDistance) + std::string(")");
if (m_Game->FindActor(neighbour1))
{
m_Neighbours.push_back(m_Game->FindActor(neighbour1));
}
if (m_Game->FindActor(neighbour2))
{
m_Neighbours.push_back(m_Game->FindActor(neighbour2));
}
if (m_Game->FindActor(neighbour3))
{
m_Neighbours.push_back(m_Game->FindActor(neighbour3));
}
if (m_Game->FindActor(neighbour4))
{
m_Neighbours.push_back(m_Game->FindActor(neighbour4));
}
if (m_Game->FindActor(neighbour5))
{
m_Neighbours.push_back(m_Game->FindActor(neighbour5));
}
if (m_Game->FindActor(neighbour6))
{
m_Neighbours.push_back(m_Game->FindActor(neighbour6));
}
if (m_Game->FindActor(neighbour7))
{
m_Neighbours.push_back(m_Game->FindActor(neighbour7));
}
if (m_Game->FindActor(neighbour8))
{
m_Neighbours.push_back(m_Game->FindActor(neighbour8));
}
}
private:
virtual Actor* GetClosestNeghbourTo(Actor* target)
{
Actor* favorite = m_Neighbours.front();
Vector2 favWay = target->GetPosition() - favorite->GetPosition();
float favDist = sqrtf((float)mango::power(favWay.X, 2) + (float)mango::power(favWay.Y, 2));
for (mango::int32 current = 0; m_Neighbours.size() > current; ++current)
{
Vector2 newWay = target->GetPosition() - m_Neighbours.at(current)->GetPosition();
float newDist = sqrtf((float)mango::power(newWay.X, 2) + (float)mango::power(newWay.Y, 2));
if (newDist < favDist)
{
favDist = newDist;
favorite = m_Neighbours.at(current);
}
}
return favorite;
}
mango::vector<Actor*> m_Neighbours;
Engine* m_Game;
mango::int32 m_MinPointDistance;
};
Is there a better way to determine the path to the target or is looking for the actor with the smallest distance the best approach for this?
Edit
Vector2
is a 2DVector (x, y)
. Vector3
would be (x, y, z)
ActorComponent is the BaseComponent class all components have to inherit from
Components are attached to actors and will be activated, updated or addressed by the owning actor.
Actor is the base type of all non-Component entities in the Engine which can interact with each other.
mango::
is a utility namespace with a number of math and utility functions like a custom::vector
, a power function and a lot of typedefs.
ActorComponent
? What isVector2
? What is in themango
namespace? Where are your includes? In the current state, this code is not really fit for review. Please add all components required to get a full overview of the code and a minimal compilable example. \$\endgroup\$ActorComponent
)) or you might not be satisfied with what we can do for you. Also, without seeing your includes, how are we supposed to verify that your code works or even compiles? \$\endgroup\$