Improve and review the available demos

- simplify code when possible
- add a simple info panel
- adhere to the "new" gdscript guidelines
This commit is contained in:
Răzvan C. Rădulescu 2020-01-16 17:04:27 +02:00
parent 1a37b2bee0
commit 1f44bace3e
17 changed files with 185 additions and 160 deletions

View File

@ -1,9 +1,6 @@
extends Node2D
onready var target := $Target
onready var arriver := $Arriver
export(float, 0, 2000, 40) var max_linear_speed := 800.0 setget set_max_linear_speed
export(float, 0, 200, 1) var max_linear_acceleration := 80.0 setget set_max_linear_acceleration
export(float, 0, 100, 0.1) var arrival_tolerance := 25.0 setget set_arrival_tolerance
@ -14,9 +11,10 @@ const COLORS := {
arrival_tolerance = Color(0.5, 0.7, 0.9, 0.2)
}
onready var arriver := $Arriver
func _ready() -> void:
target.position = arriver.global_position
arriver.setup(
max_linear_speed,
max_linear_acceleration,
@ -28,13 +26,13 @@ func _ready() -> void:
func _unhandled_input(event: InputEvent) -> void:
if event is InputEventMouseButton and event.button_index == BUTTON_LEFT and event.is_pressed():
arriver.target.position = Vector3(event.position.x, event.position.y, 0)
target.position = event.position
update()
func _draw():
draw_circle(target.position, deceleration_radius, COLORS.deceleration_radius)
draw_circle(target.position, arrival_tolerance, COLORS.arrival_tolerance)
var target_position := Vector2(arriver.target.position.x, arriver.target.position.y)
draw_circle(target_position, deceleration_radius, COLORS.deceleration_radius)
draw_circle(target_position, arrival_tolerance, COLORS.arrival_tolerance)
func set_arrival_tolerance(value: float) -> void:

View File

@ -23,9 +23,6 @@ shape = SubResource( 1 )
modulate = Color( 0.952941, 0.172549, 0.0431373, 1 )
texture = ExtResource( 4 )
[node name="Target" type="Node2D" parent="."]
position = Vector2( 0, 1 )
[node name="GUI" type="PanelContainer" parent="."]
anchor_right = 1.0
margin_right = 1024.0
@ -40,10 +37,15 @@ __meta__ = {
margin_right = 1024.0
margin_bottom = 87.0
[node name="Label" type="Label" parent="GUI/MarginContainer"]
[node name="RichTextLabel" type="RichTextLabel" parent="GUI/MarginContainer"]
margin_left = 16.0
margin_top = 16.0
margin_right = 1008.0
margin_bottom = 71.0
rect_min_size = Vector2( 0, 55 )
bbcode_enabled = true
bbcode_text = "Arrive Demo
Mouse click to make the [color=red]red \"Player\"[/color] move to the [color=yellow]yellow target[/color]"
text = "Arrive Demo
Mouse click to make the red \"Player\" move to the yellow target"
scroll_active = false

View File

@ -9,14 +9,10 @@ onready var agent := GSTAgentLocation.new()
func _physics_process(delta: float) -> void:
var movement := _get_movement()
move_and_slide(movement * speed)
_update_agent()
agent.position = Vector3(global_position.x, global_position.y, 0)
func _get_movement() -> Vector2:
return Vector2(
Input.get_action_strength("sf_right") - Input.get_action_strength("sf_left"),
Input.get_action_strength("sf_down") - Input.get_action_strength("sf_up"))
func _update_agent() -> void:
agent.position = Vector3(global_position.x, global_position.y, 0)

View File

@ -6,10 +6,22 @@ onready var spawner := $Spawner
export var max_linear_speed := 100.0 setget set_max_linear_speed
export var max_linear_accel := 25.0 setget set_max_linear_accel
export var proximity_radius := 140.0 setget set_proximity_radius
export var show_proximity_radius := true setget set_show_proximity_radius
export var separation_decay_coefficient := 2000.0 setget set_separation_decay_coef
export var cohesion_strength := 0.3 setget set_cohesion_strength
export var separation_strength := 1.5 setget set_separation_strength
export var show_proximity_radius := true setget set_show_proximity_radius
func _ready() -> void:
spawner.setup(
max_linear_speed,
max_linear_accel,
proximity_radius,
separation_decay_coefficient,
cohesion_strength,
separation_strength,
show_proximity_radius
)
func set_max_linear_speed(value: float) -> void:

View File

@ -1,10 +1,10 @@
extends KinematicBody2D
var agent := GSTSteeringAgent.new()
var separation: GSTSeparation
var cohesion: GSTCohesion
var proximity: GSTRadiusProximity
var agent := GSTSteeringAgent.new()
var blend := GSTBlend.new(agent)
var acceleration := GSTTargetAcceleration.new()
var draw_proximity := false
@ -41,18 +41,14 @@ func _draw() -> void:
func _process(delta: float) -> void:
update_agent()
agent.position.x = global_position.x
agent.position.y = global_position.y
if blend:
acceleration = blend.calculate_steering(acceleration)
_velocity = (_velocity + Vector2(acceleration.linear.x, acceleration.linear.y)).clamped(agent.max_linear_speed)
_velocity += Vector2(acceleration.linear.x, acceleration.linear.y)
_velocity = _velocity.clamped(agent.max_linear_speed)
move_and_slide(_velocity)
func set_neighbors(neighbor: Array) -> void:
proximity.agents = neighbor
func update_agent() -> void:
var current_position := global_position
agent.position.x = current_position.x
agent.position.y = current_position.y

View File

@ -4,7 +4,15 @@ extends Node2D
export var member: PackedScene
func _ready() -> void:
func setup(
max_linear_speed: float,
max_linear_accel: float,
proximity_radius: float,
separation_decay_coefficient: float,
cohesion_strength: float,
separation_strength: float,
show_proximity_radius: bool
) -> void:
var followers := []
for i in range(19):
var follower := member.instance()
@ -12,14 +20,14 @@ func _ready() -> void:
follower.position += Vector2(rand_range(-60, 60), rand_range(-60, 60))
followers.append(follower)
follower.setup(
owner.max_linear_speed,
owner.max_linear_accel,
owner.proximity_radius,
owner.separation_decay_coefficient,
owner.cohesion_strength,
owner.separation_strength
max_linear_speed,
max_linear_accel,
proximity_radius,
separation_decay_coefficient,
cohesion_strength,
separation_strength
)
if i == 0 and owner.show_proximity_radius:
if i == 0 and show_proximity_radius:
follower.draw_proximity = true
follower.update()
var agents := []

View File

@ -2,10 +2,6 @@ extends Node2D
# Wraps the ships' positions around the world border, and controls their rendering clones.
onready var ShipType := preload("res://demos/PursueSeek/Ship.gd")
onready var ships := [$Player, $Pursuer, $Seeker]
var _clones := {}
var _world_bounds: Vector2
@ -14,54 +10,8 @@ func _ready() -> void:
ProjectSettings["display/window/size/width"],
ProjectSettings["display/window/size/height"]
)
for i in range(ships.size()):
var ship: Node2D = ships[i]
var world_pos := ship.position
for i in range(3):
var ship_clone := ShipType.new()
ship_clone.position.x = world_pos.x if i == 1 else (world_pos.x - _world_bounds.x)
ship_clone.position.y = world_pos.y if i == 0 else (world_pos.y - _world_bounds.y)
ship_clone.rotation = ship.rotation
ship_clone.tag = i
ship_clone.name = ship.name + "Clone"
add_child(ship_clone)
ship_clone.generate_sprite(ship.get_node("Sprite"))
_clones[ship_clone] = ship
func _physics_process(delta: float) -> void:
for clone in _clones.keys():
var original: Node2D = _clones[clone]
var world_pos: Vector2 = original.position
if world_pos.y < 0:
original.position.y = _world_bounds.y + world_pos.y
elif world_pos.y > _world_bounds.y:
original.position.y = (world_pos.y - _world_bounds.y)
if world_pos.x < 0:
original.position.x = _world_bounds.x + world_pos.x
elif world_pos.x > _world_bounds.x:
original.position.x = (world_pos.x - _world_bounds.x)
var tag: int = clone.tag
if tag != 2:
if world_pos.x < _world_bounds.x/2:
clone.position.x = world_pos.x + _world_bounds.x
else:
clone.position.x = world_pos.x - _world_bounds.x
else:
clone.position.x = world_pos.x
if tag != 0:
if world_pos.y < _world_bounds.y/2:
clone.position.y = world_pos.y + _world_bounds.y
else:
clone.position.y = world_pos.y - _world_bounds.y
else:
clone.position.y = world_pos.y
clone.rotation = original.rotation
for ship in get_children():
ship.position = ship.position.posmodv(_world_bounds)

View File

@ -1,4 +1,4 @@
extends "res://demos/PursueSeek/Ship.gd"
extends KinematicBody2D
# Controls the player ship's movements based on player input.
@ -25,7 +25,7 @@ func _physics_process(delta: float) -> void:
angular_drag,
delta
)
rotation += (_angular_velocity * delta)
rotation += _angular_velocity * delta
_linear_velocity = _calculate_linear_velocity(
movement.y,
@ -38,18 +38,17 @@ func _physics_process(delta: float) -> void:
)
_linear_velocity = move_and_slide(_linear_velocity)
_update_agent(_linear_velocity, rotation)
_update_agent()
func _calculate_angular_velocity(
horizontal_movement: float,
current_velocity: float,
thruster_strength: float,
max_velocity: float,
ship_drag: float,
delta: float) -> float:
horizontal_movement: float,
current_velocity: float,
thruster_strength: float,
max_velocity: float,
ship_drag: float,
delta: float
) -> float:
var velocity := clamp(
current_velocity + thruster_strength * horizontal_movement * delta,
-max_velocity,
@ -62,14 +61,14 @@ func _calculate_angular_velocity(
func _calculate_linear_velocity(
vertical_movement: float,
current_velocity: Vector2,
facing_direction: Vector2,
ship_drag_coefficient: float,
strength: float,
max_speed: float,
delta: float) -> Vector2:
vertical_movement: float,
current_velocity: Vector2,
facing_direction: Vector2,
ship_drag_coefficient: float,
strength: float,
max_speed: float,
delta: float
) -> Vector2:
var actual_strength := 0.0
if vertical_movement > 0:
actual_strength = strength
@ -87,10 +86,10 @@ func _get_movement() -> Vector2:
Input.get_action_strength("sf_up") - Input.get_action_strength("sf_down"))
func _update_agent(velocity: Vector2, orientation: float) -> void:
func _update_agent() -> void:
agent.position.x = global_position.x
agent.position.y = global_position.y
agent.linear_velocity.x = velocity.x
agent.linear_velocity.y = velocity.y
agent.linear_velocity.x = _linear_velocity.x
agent.linear_velocity.y = _linear_velocity.y
agent.angular_velocity = _angular_velocity
agent.orientation = orientation
agent.orientation = rotation

View File

@ -1,13 +1,18 @@
extends Node2D
onready var pursuer := $BoundaryManager/Pursuer
onready var seeker := $BoundaryManager/Seeker
export(float, 0, 2000, 40) var max_linear_speed := 200.0 setget set_max_linear_speed
export(float, 0, 200, 1) var max_linear_accel := 10.0 setget set_max_linear_accel
export(float, 0, 5, 0.1) var predict_time := 2.0 setget set_predict_time
onready var pursuer := $BoundaryManager/Pursuer
onready var seeker := $BoundaryManager/Seeker
func _ready() -> void:
pursuer.setup(predict_time, max_linear_speed, max_linear_accel)
seeker.setup(predict_time, max_linear_speed, max_linear_accel)
func set_max_linear_speed(value: float) -> void:
if not is_inside_tree():

View File

@ -1,9 +1,10 @@
[gd_scene load_steps=6 format=2]
[gd_scene load_steps=7 format=2]
[ext_resource path="res://demos/PursueSeek/Pursuer.gd" type="Script" id=1]
[ext_resource path="res://demos/PursueSeek/Player.gd" type="Script" id=2]
[ext_resource path="res://demos/PursueSeek/BoundaryManager.gd" type="Script" id=3]
[ext_resource path="res://demos/PursueSeek/PursueVSSeekDemo.gd" type="Script" id=4]
[ext_resource path="res://assets/theme/gdquest.theme" type="Theme" id=5]
[ext_resource path="res://assets/sprites/triangle.png" type="Texture" id=6]
[node name="PursueVSSeekDemo" type="Node2D"]
@ -22,6 +23,9 @@ position = Vector2( 49.2031, 556.936 )
rotation = 1.5708
collision_mask = 2
script = ExtResource( 2 )
thruster_strength = 600.0
side_thruster_strength = 20.0
max_velocity = 900.0
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="BoundaryManager/Player"]
polygon = PoolVector2Array( 0, -32, -24, 32, 24, 32 )
@ -31,7 +35,7 @@ modulate = Color( 0.968627, 0.188235, 0.0352941, 1 )
texture = ExtResource( 6 )
[node name="Pursuer" type="KinematicBody2D" parent="BoundaryManager"]
position = Vector2( 868.495, 87.9043 )
position = Vector2( 868.495, 200 )
collision_layer = 2
script = ExtResource( 1 )
@ -43,7 +47,7 @@ modulate = Color( 0.756863, 0.952941, 0.054902, 1 )
texture = ExtResource( 6 )
[node name="Seeker" type="KinematicBody2D" parent="BoundaryManager"]
position = Vector2( 821.24, 87.9043 )
position = Vector2( 821.24, 200 )
collision_layer = 2
script = ExtResource( 1 )
use_seek = true
@ -54,3 +58,30 @@ polygon = PoolVector2Array( 0, -32, -24, 32, 24, 32 )
[node name="Sprite" type="Sprite" parent="BoundaryManager/Seeker"]
modulate = Color( 0.278431, 0.815686, 0.14902, 1 )
texture = ExtResource( 6 )
[node name="GUI" type="PanelContainer" parent="."]
margin_right = 1024.0
margin_bottom = 14.0
theme = ExtResource( 5 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="MarginContainer" type="MarginContainer" parent="GUI"]
margin_right = 1024.0
margin_bottom = 116.0
[node name="RichTextLabel" type="RichTextLabel" parent="GUI/MarginContainer"]
margin_left = 16.0
margin_top = 16.0
margin_right = 1008.0
margin_bottom = 100.0
rect_min_size = Vector2( 0, 84 )
bbcode_enabled = true
bbcode_text = "Pursue vs. Seek Demo
Move the player around with WASD and notice the [color=yellow]yellow Pursuer[/color] and the [color=green]green Seeker[/color] follow
the [color=red]red \"Ship\"[/color] around"
text = "Pursue vs. Seek Demo
Move the player around with WASD and notice the yellow Pursuer and the green Seeker follow
the red \"Ship\" around"
scroll_active = false

View File

@ -1,4 +1,4 @@
extends "res://demos/PursueSeek/Ship.gd"
extends KinematicBody2D
# Represents a ship that chases after the player.
@ -18,24 +18,7 @@ var _angular_drag := 1.0
func _ready() -> void:
_setup()
func _setup() -> void:
if use_seek:
_behavior = GSTSeek.new(agent, player_agent)
else:
_behavior = GSTPursue.new(agent, player_agent, owner.predict_time)
_orient_behavior = GSTLookWhereYouGo.new(agent)
_orient_behavior.alignment_tolerance = 0.001
_orient_behavior.deceleration_radius = PI/2
agent.max_angular_acceleration = 2
agent.max_angular_speed = 5
agent.max_linear_acceleration = owner.max_linear_accel
agent.max_linear_speed = owner.max_linear_speed
_update_agent()
set_physics_process(false)
func _physics_process(delta: float) -> void:
@ -47,7 +30,7 @@ func _physics_process(delta: float) -> void:
elif _angular_velocity > 0:
_angular_velocity -= _angular_drag * delta
rotation = rotation + _angular_velocity * delta
rotation += _angular_velocity * delta
accel = _behavior.calculate_steering(accel)
_linear_velocity += Vector2(accel.linear.x, accel.linear.y)
@ -58,6 +41,25 @@ func _physics_process(delta: float) -> void:
_update_agent()
func setup(predict_time: float, max_linear_speed: float, max_linear_accel: float) -> void:
if use_seek:
_behavior = GSTSeek.new(agent, player_agent)
else:
_behavior = GSTPursue.new(agent, player_agent, predict_time)
_orient_behavior = GSTLookWhereYouGo.new(agent)
_orient_behavior.alignment_tolerance = 0.001
_orient_behavior.deceleration_radius = PI/2
agent.max_angular_acceleration = 2
agent.max_angular_speed = 5
agent.max_linear_acceleration = max_linear_accel
agent.max_linear_speed = max_linear_speed
_update_agent()
set_physics_process(true)
func _update_agent() -> void:
agent.position.x = global_position.x
agent.position.y = global_position.y

View File

@ -1,13 +0,0 @@
extends KinematicBody2D
# Represents a basic ship
var tag: int = 0
func generate_sprite(sprite: Sprite) -> void:
var new_sprite = Sprite.new()
new_sprite.texture = sprite.texture
new_sprite.modulate = sprite.modulate
new_sprite.name = "Sprite"
add_child(new_sprite)

View File

@ -6,7 +6,7 @@ var rect: Rect2
func _ready() -> void:
var extents := ($CollisionShape2D.shape as RectangleShape2D).extents
var extents: Vector2 = $CollisionShape2D.shape.extents
rect = Rect2(-extents, extents*2)

View File

@ -2,14 +2,8 @@ extends KinematicBody2D
# Class to control the player in basic left/right up/down movement.
onready var agent := GSTAgentLocation.new()
export var speed := 200.0
func _get_movement() -> Vector2:
return Vector2( Input.get_action_strength("sf_right") - Input.get_action_strength("sf_left"),
Input.get_action_strength("sf_down") - Input.get_action_strength("sf_up"))
var speed: float
var agent := GSTAgentLocation.new()
func _physics_process(delta: float) -> void:
@ -19,3 +13,8 @@ func _physics_process(delta: float) -> void:
move_and_slide(movement * speed)
agent.position = Vector3(global_position.x, global_position.y, 0)
func _get_movement() -> Vector2:
return Vector2( Input.get_action_strength("sf_right") - Input.get_action_strength("sf_left"),
Input.get_action_strength("sf_down") - Input.get_action_strength("sf_up"))

View File

@ -7,6 +7,7 @@ enum Mode { FLEE, SEEK }
export(Mode) var behavior_mode := Mode.SEEK setget set_behavior_mode
export(float, 0, 2000, 40) var max_linear_speed := 200.0 setget set_max_linear_speed
export(float, 0, 500, 0.5) var max_linear_accel := 10.0 setget set_max_linear_accel
export(float) var player_speed := 600.0 setget set_player_speed
var camera_boundaries: Rect2
@ -26,6 +27,8 @@ func _ready() -> void:
var rng := RandomNumberGenerator.new()
rng.randomize()
player.speed = player_speed
for i in range(spawner.entity_count):
var new_pos := Vector2(
rng.randf_range(-camera_boundaries.size.x/2, camera_boundaries.size.x/2),
@ -69,3 +72,11 @@ func set_max_linear_accel(value: float) -> void:
max_linear_accel = value
for child in spawner.get_children():
child.agent.max_linear_acceleration = value
func set_player_speed(value: float) -> void:
if not is_inside_tree():
return
player_speed = value
player.speed = player_speed

View File

@ -1,9 +1,10 @@
[gd_scene load_steps=10 format=2]
[gd_scene load_steps=11 format=2]
[ext_resource path="res://demos/SeekFlee/Boundary.gd" type="Script" id=1]
[ext_resource path="res://demos/SeekFlee/Player.gd" type="Script" id=2]
[ext_resource path="res://demos/SeekFlee/SeekFleeDemo.gd" type="Script" id=3]
[ext_resource path="res://demos/SeekFlee/Spawner.gd" type="Script" id=4]
[ext_resource path="res://assets/theme/gdquest.theme" type="Theme" id=5]
[ext_resource path="res://demos/SeekFlee/Seeker.tscn" type="PackedScene" id=6]
[ext_resource path="res://assets/sprites/large_circle.png" type="Texture" id=7]
@ -75,3 +76,31 @@ shape = SubResource( 3 )
[node name="Spawner" type="Node2D" parent="."]
script = ExtResource( 4 )
Entity = ExtResource( 6 )
[node name="CanvasLayer" type="CanvasLayer" parent="."]
[node name="GUI" type="PanelContainer" parent="CanvasLayer"]
margin_right = 1024.0
margin_bottom = 116.0
theme = ExtResource( 5 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="MarginContainer" type="MarginContainer" parent="CanvasLayer/GUI"]
margin_right = 1024.0
margin_bottom = 116.0
[node name="RichTextLabel" type="RichTextLabel" parent="CanvasLayer/GUI/MarginContainer"]
margin_left = 16.0
margin_top = 16.0
margin_right = 1008.0
margin_bottom = 100.0
rect_min_size = Vector2( 0, 84 )
bbcode_enabled = true
bbcode_text = "Seek & Flee Demo
Move the [color=red]red \"Player\"[/color] around with WASD and notice the [color=blue]blue \"Enemies\"[/color] and the seek/flee
the \"Player\""
text = "Seek & Flee Demo
Move the red \"Player\" around with WASD and notice the blue \"Enemies\" and the seek/flee
the \"Player\""

View File

@ -15,8 +15,8 @@ var _nearest_point_on_segment: Vector3
var _nearest_point_on_path: Vector3
func _init(waypoints: Array, is_open := false) -> void:
self.is_open = is_open
func _init(waypoints: Array, open := false) -> void:
self.open = open
create_path(waypoints)
_nearest_point_on_segment = waypoints[0]
_nearest_point_on_path = waypoints[0]