I have a A* pathfinding algorythm located within a module script that could be required()'d
The pathfinding algorythm would just open nodes at an aburtary direction until it hits a wall
Idk what to do
Is this problem occuring just because of my incorrect maths or logic?
--strategic_oof
local Pathing01 = {}
local NodeId=0
local function RoundToNearest(v: Vector3, Size: number): Vector3
return Vector3.new(
math.round(v.X/Size)*Size,
math.round(v.Y/Size)*Size,
math.round(v.Z/Size)*Size
)
end
local function HeuristicFunction(a: Vector3, b: Vector3): number
return math.abs(a.X - b.X) + math.abs(a.Y - b.Y) + math.abs(a.Z - b.Z)
end
local function FindOpenNode(Pos: Vector3, Data: {}): {} -- a function to find a node in the open set since we use arrays
for i,v in Data.OpenNodes do
if v.Position==Pos then
return v
end
end
end
function Pathing01.CreateParameters(): {}
local t={
--AgentCanClimb=false,
--AgentCanJump=true,
--AgentMovementSpeed=16,
--AgentJumpPower=50,
--AgentHight=5,
--AgentWidth=4,
IgnoreParts={},
GridSize=2
}
--50 / 6.94444444444 = 7.2
--t.JumpDistance = 2 * t.AgentJumpPower * t.AgentMovementSpeed / workspace.Gravity
--t.Actions={
-- "Jump",
-- "Climb",
-- "Swim"
--}
t.ValidMovements={ --the more movements the more computer resourses the algorithm needs
Vector3.new(1,0,0) * t.GridSize,
Vector3.new(-1,0,0) * t.GridSize,
Vector3.new(0,0,1) * t.GridSize,
Vector3.new(0,0,-1) * t.GridSize,
Vector3.new(1,0,1) * t.GridSize,
Vector3.new(-1,0,-1) * t.GridSize,
Vector3.new(-1,0,1) * t.GridSize,
Vector3.new(1,0,-1) * t.GridSize
}
--print(t.ValidMovements)
return t
end
--function Pathing01.CreateBlankAction(Data: {}): {}
-- local Action={
-- Name=""
-- }
-- table.insert(Data.Actions,Action)
-- return Action
--end
function Pathing01.CreateNode(a: Vector3, b: Vector3, ParentNode: {}, GCost: number, Data: {}): {}
local Node={}
Node.Position=a
Node.ParentNode=ParentNode
Node.GCost=GCost
Node.HCost=HeuristicFunction(a,b)
Node.FCost=GCost+Node.HCost
if not Data.LowestFCost[1] then
Data.LowestFCost=Node
end
if Node.FCost<Data.LowestFCost.FCost then
Data.LowestFCost=Node
end
table.insert(Data.OpenNodes,Node)
Node.I=NodeId
NodeId+=1
local Ball=Instance.new("Part")
Ball.Shape=Enum.PartType.Ball
Ball.Size=Vector3.new(.8,.8,.8)
Ball.Position=Data.LowestFCost.Position
Ball.Anchored=true
Ball.CanCollide=false
Ball.CanQuery=false
Ball.Material=Enum.Material.Neon
Ball.BrickColor=BrickColor.White()
Ball.Parent=workspace
--Node.Open=true
return Node
end
function Pathing01.CheckPosOccupied(Pos: Vector3, Data: {}): boolean
if Data.Params.IgnoreParts[1] then
local op=OverlapParams.new()
op.FilterDescendantsInstances=Data.Params.IgnoreParts
op.FilterType=Enum.RaycastFilterType.Exclude
if workspace:GetPartBoundsInBox(CFrame.new(Pos),Vector3.new(Data.Params.AgentWidth*.9,Data.Params.AgentHight*.9,Data.Params.AgentWidth*.9),op)[1] then
return true
end
else
if workspace:GetPartBoundsInBox(CFrame.new(Pos),Vector3.new(Data.Params.AgentWidth*.9,Data.Params.AgentHight*.9,Data.Params.AgentWidth*.9))[1] then
return true
end
end
return false
end
function Pathing01.OpenNode(Node: {}, Data: {})
--Node.Open=false
for i, v in pairs(Data.OpenNodes) do
if v.I==Node.I then
table.remove(Data.OpenNodes,i)
table.insert(Data.ClosedNodes,Node)
break
end
end
local Ball=Instance.new("Part")
Ball.Shape=Enum.PartType.Ball
Ball.Size=Vector3.new(1,1,1)
Ball.Position=Data.LowestFCost.Position
Ball.Anchored=true
Ball.CanCollide=false
Ball.CanQuery=false
Ball.Material=Enum.Material.Neon
Ball.BrickColor=BrickColor.Red()
Ball.Parent=workspace
for i, v in Data.Params.ValidMovements do
local Pos=Node.Position+v
if Pathing01.CheckPosOccupied(Pos,Data)==false then
local CostToNeighbour=Node.GCost+(Node.Position-Pos).Magnitude
local Neighbour=FindOpenNode(Pos,Data)
print(Neighbour)
local NeighbourGCost=Neighbour and Neighbour.GCost or 0
if CostToNeighbour<NeighbourGCost or not Neighbour then
Pathing01.CreateNode(Pos,Data.EndPos,Node,CostToNeighbour,Data)
end
end
end
end
function Pathing01.ComputePath(StartPos: Vector3,EndPos: Vector3,Parameters: {})
StartPos=RoundToNearest(StartPos, Parameters.GridSize)
EndPos=RoundToNearest(EndPos, Parameters.GridSize)
local Data={}
--Data.Actions={}
Data.Params=Parameters
Data.OpenNodes={}
Data.ClosedNodes={}
Data.LowestFCost={}
Data.StartPos=StartPos
Data.EndPos=EndPos
Data.StartNode=Pathing01.CreateNode(StartPos,EndPos,nil,0,Data) Data.LowestFCost=Data.StartNode
local A=1000
local a=A
Pathing01.OpenNode(Data.StartNode, Data)
while Data.OpenNodes[1] do
--task.wait()
a-=a
if a<=0 then
task.wait()
a=A
end
Pathing01.OpenNode(Data.LowestFCost, Data)
if Data.LowestFCost.Position==EndPos then
break
end
end
print("Found Path")
local FinalNodes={}
while Data.LowestFCost do
task.wait()
local Ball=Instance.new("Part")
Ball.Shape=Enum.PartType.Ball
Ball.Size=Vector3.new(2,2,2)
Ball.Position=Data.LowestFCost.Position
Ball.Anchored=true
Ball.CanCollide=false
Ball.CanQuery=false
Ball.Material=Enum.Material.Neon
Ball.BrickColor=BrickColor.new("Lime green")
Ball.Parent=workspace
table.insert(FinalNodes,Data.LowestFCost.Position)
Data.LowestFCost=Data.LowestFCost.ParentNode
end
print("Done Path")
return FinalNodes
end
return Pathing01