first
This commit is contained in:
89
script/pathfindingGridLoad.gd
Normal file
89
script/pathfindingGridLoad.gd
Normal file
@@ -0,0 +1,89 @@
|
||||
extends Node3D
|
||||
class_name PathfindingGridLoader
|
||||
|
||||
var loading: bool = false # when this is true the grid starts loading
|
||||
var loading_done: bool = false # when the grid is loaded, this becomes true
|
||||
|
||||
@export var height: float= 0.2 ##Choose a height that is just above the floor
|
||||
@export var lengthX: int = 50 ##How far the grid generates in the x direction, generates as a rectangle
|
||||
@export var lengthZ: int = 50 ##How far the grid generates in the z direction, generates as a rectangle
|
||||
@export var point_density: float = 1 ##How many points per unit of grid, cannot be = 0
|
||||
@export var minimum_connections_per_point: int = 3
|
||||
@export var wallCollisionLayer: int = 0b100
|
||||
|
||||
var astar: AStar2D = AStar2D.new()
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
if loading == false: return
|
||||
if loading_done == true: return
|
||||
generatePoints()
|
||||
connectPointsToNeighbors()
|
||||
killPointsWithoutFriends(minimum_connections_per_point)
|
||||
addWeightToPoints()
|
||||
loading = false
|
||||
loading_done = true
|
||||
|
||||
func loadGrid() -> void:
|
||||
loading = true
|
||||
|
||||
func castRay(startPoint:Vector3,endPoint: Vector3,collisionMask:int = 0xFFFFFFFF,hitFromInside: bool = true) -> bool: ##Returns true if the ray collides and false if it doesn't
|
||||
var space_state = get_world_3d().direct_space_state
|
||||
var rayQueryParam = PhysicsRayQueryParameters3D.create(startPoint,endPoint)
|
||||
rayQueryParam.collision_mask = collisionMask
|
||||
rayQueryParam.hit_from_inside = hitFromInside
|
||||
return space_state.intersect_ray(rayQueryParam).size()
|
||||
|
||||
func checkPoint(point: Vector2) -> bool: ## only ever call this from physics process as it uses physics for raycast and may not work on idle callback
|
||||
var floorDetected: bool = castRay(Vector3(point.x,height,point.y),Vector3(point.x,-(height*1.5),point.y))
|
||||
var wallDetected: bool = castRay(Vector3(point.x,height,point.y),Vector3(point.x,-(height*1.5),point.y),wallCollisionLayer) #Walls are on collision layer 3 (0b100)
|
||||
if !wallDetected && floorDetected:
|
||||
return true
|
||||
else:
|
||||
return false
|
||||
|
||||
func getPointsInRadius(origin: Vector2,radius: float, maxPoints: int = 9) -> Array[int]: #Origin point is always index 0 in the array
|
||||
var pointIDs: Array[int]
|
||||
for point in maxPoints:
|
||||
var id = astar.get_closest_point(origin)
|
||||
if (astar.get_point_position(id) - origin).length() <= radius:
|
||||
pointIDs.push_back(id)
|
||||
astar.set_point_disabled(id)
|
||||
for id in pointIDs:
|
||||
astar.set_point_disabled(id,false)
|
||||
return pointIDs
|
||||
|
||||
func connectIfValid(id1: int, id2: int):
|
||||
var point1 := astar.get_point_position(id1)
|
||||
var point2 := astar.get_point_position(id2)
|
||||
|
||||
if !castRay(Vector3(point1.x,height,point1.y),Vector3(point2.x,height,point2.y)):
|
||||
astar.connect_points(id1,id2)
|
||||
|
||||
func generatePoints() -> void:
|
||||
var currentPoint: Vector2
|
||||
var currentID: int = 0
|
||||
for x in lengthX*point_density:
|
||||
for z in lengthZ*point_density:
|
||||
currentPoint = Vector2((x/point_density + self.global_position.x),z/point_density + self.global_position.z)
|
||||
if checkPoint(currentPoint):
|
||||
astar.add_point(currentID,currentPoint)
|
||||
currentID += 1
|
||||
|
||||
func connectPointsToNeighbors() -> void:
|
||||
for id in astar.get_point_ids():
|
||||
var neighborPoints: Array[int]
|
||||
neighborPoints = getPointsInRadius(astar.get_point_position(id),(1/point_density)*1.5)
|
||||
for point in neighborPoints.size()-1:
|
||||
connectIfValid(neighborPoints[0],neighborPoints[point+1])
|
||||
|
||||
func killPointsWithoutFriends(minConnections: int) -> void: ##Really mean and evil and fucked up function
|
||||
var cullPoints: Array[int]
|
||||
for id in astar.get_point_ids():
|
||||
if astar.get_point_connections(id).size() < minConnections:
|
||||
cullPoints.push_back(id)
|
||||
for point in cullPoints:
|
||||
astar.remove_point(point)
|
||||
|
||||
func addWeightToPoints() -> void: #Add weight depending on number of connections
|
||||
for id in astar.get_point_ids():
|
||||
astar.set_point_weight_scale(id,8 - astar.get_point_connections(id).size())
|
||||
Reference in New Issue
Block a user