Add Cohesion behavior and RadiusProximity caching

This commit is contained in:
Francois Belair 2020-01-09 12:24:55 -05:00
parent ac99344633
commit 34b58a6bba
5 changed files with 98 additions and 28 deletions

View File

@ -20,10 +20,20 @@ _global_script_classes=[ {
"path": "res://src/behaviors/GSTArrive.gd"
}, {
"base": "GSTSteeringBehavior",
"class": "GSTAvoidCollisions",
"language": "GDScript",
"path": "res://src/behaviors/GSTAvoidCollisions.gd"
}, {
"base": "GSTSteeringBehavior",
"class": "GSTBlend",
"language": "GDScript",
"path": "res://src/behaviors/GSTBlend.gd"
}, {
"base": "GSTSteeringBehavior",
"class": "GSTCohesion",
"language": "GDScript",
"path": "res://src/behaviors/GSTCohesion.gd"
}, {
"base": "GSTPursue",
"class": "GSTEvade",
"language": "GDScript",
@ -39,6 +49,11 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://src/behaviors/GSTFlee.gd"
}, {
"base": "GSTArrive",
"class": "GSTFollowPath",
"language": "GDScript",
"path": "res://src/behaviors/GSTFollowPath.gd"
}, {
"base": "GSTProximity",
"class": "GSTInfiniteProximity",
"language": "GDScript",
@ -54,6 +69,11 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://src/behaviors/GSTMatchOrientation.gd"
}, {
"base": "Reference",
"class": "GSTPath",
"language": "GDScript",
"path": "res://src/GSTPath.gd"
}, {
"base": "GSTSteeringBehavior",
"class": "GSTPriority",
"language": "GDScript",
@ -107,13 +127,17 @@ _global_script_classes=[ {
_global_script_class_icons={
"GSTAgentLocation": "",
"GSTArrive": "",
"GSTAvoidCollisions": "",
"GSTBlend": "",
"GSTCohesion": "",
"GSTEvade": "",
"GSTFace": "",
"GSTFlee": "",
"GSTFollowPath": "",
"GSTInfiniteProximity": "",
"GSTLookWhereYouGo": "",
"GSTMatchOrientation": "",
"GSTPath": "",
"GSTPriority": "",
"GSTProximity": "",
"GSTPursue": "",

View File

@ -11,3 +11,4 @@ var max_angular_acceleration: = 0.0
var linear_velocity: = Vector3.ZERO
var angular_velocity: = 0.0
var bounding_radius: = 0.0
var tagged: = false

View File

@ -0,0 +1,27 @@
extends GSTSteeringBehavior
class_name GSTCohesion
# Group behavior that produces linear acceleration that attempts to move the agent towards the
# center of mass of the agents in the area defined by the defined Proximity.
var center_of_mass: Vector3
var proximity: GSTProximity
func _init(agent: GSTSteeringAgent, proximity: GSTProximity).(agent) -> void:
self.proximity = proximity
func _calculate_steering(acceleration: GSTTargetAcceleration) -> GSTTargetAcceleration:
acceleration.set_zero()
center_of_mass = Vector3.ZERO
var neighbor_count = proximity.find_neighbors(funcref(self, "_report_neighbor"))
if neighbor_count > 0:
center_of_mass *= 1.0 / neighbor_count
acceleration.linear = (center_of_mass - agent.position).normalized() * agent.max_linear_acceleration
return acceleration
func _report_neighbor(neighbor: GSTSteeringAgent) -> bool:
center_of_mass += neighbor.position
return true

View File

@ -1,16 +1,16 @@
extends Reference
class_name GSTProximity
# Defines an area that is used by group behaviors to find and process the owner's neighbors.
var agent: GSTSteeringAgent
var agents: = []
func _init(agent: GSTSteeringAgent, agents: Array) -> void:
self.agent = agent
self.agents = agents
func find_neighbors(callback: FuncRef) -> int:
return 0
extends Reference
class_name GSTProximity
# Defines an area that is used by group behaviors to find and process the owner's neighbors.
var agent: GSTSteeringAgent
var agents: = []
func _init(agent: GSTSteeringAgent, agents: Array) -> void:
self.agent = agent
self.agents = agents
func find_neighbors(callback: FuncRef) -> int:
return 0

View File

@ -6,28 +6,46 @@ class_name GSTRadiusProximity
var radius: = 0.0
var _last_frame: = 0
var _scene_tree: SceneTree
func _init(agent: GSTSteeringAgent, agents: Array, radius: float).(agent, agents) -> void:
self.radius = radius
_scene_tree = Engine.get_main_loop()
func find_neighbors(callback: FuncRef) -> int:
var agent_count: = agents.size()
var neighbor_count: = 0
var owner_position: = agent.position
for i in range(agent_count):
var current_agent: = agents[i] as GSTSteeringAgent
if current_agent != agent:
var distance_squared: = owner_position.distance_squared_to(current_agent.position)
var range_to: = radius + current_agent.bounding_radius
if distance_squared < range_to * range_to:
var current_frame: = _scene_tree.get_frame() if _scene_tree else -_last_frame
if current_frame != _last_frame:
_last_frame = current_frame
var owner_position: = agent.position
for i in range(agent_count):
var current_agent: = agents[i] as GSTSteeringAgent
if current_agent != agent:
var distance_squared: = owner_position.distance_squared_to(current_agent.position)
var range_to: = radius + current_agent.bounding_radius
if distance_squared < range_to * range_to:
if callback.call_func(current_agent) == true:
current_agent.tagged = true
neighbor_count += 1
continue
current_agent.tagged = false
else:
for i in range(agent_count):
var current_agent = agents[i] as GSTSteeringAgent
if current_agent != agent and current_agent.tagged:
if callback.call_func(current_agent) == true:
neighbor_count += 1
continue
return neighbor_count