mirror of
https://github.com/Relintai/godot-steering-ai-framework.git
synced 2024-11-10 00:52:10 +01:00
Fix init time setters and export Follow variables
The use of `not is_inside_tree()` before setting the setting class' value meant that the starting values would always be the default. Moving the value setting before checking for tree readiness fixes the issue.
This commit is contained in:
parent
86cd22cfde
commit
6e6f27505c
@ -2,7 +2,7 @@ extends Node2D
|
||||
|
||||
|
||||
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, 200, 2.0) 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
|
||||
export(float, 0, 500, 10) var deceleration_radius := 125.0 setget set_deceleration_radius
|
||||
|
||||
@ -36,34 +36,32 @@ func _draw():
|
||||
|
||||
|
||||
func set_arrival_tolerance(value: float) -> void:
|
||||
arrival_tolerance = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
arrival_tolerance = value
|
||||
arriver.arrive.arrival_tolerance = value
|
||||
update()
|
||||
|
||||
|
||||
func set_deceleration_radius(value: float) -> void:
|
||||
deceleration_radius = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
deceleration_radius = value
|
||||
arriver.arrive.deceleration_radius = value
|
||||
update()
|
||||
|
||||
|
||||
func set_max_linear_speed(value: float) -> void:
|
||||
max_linear_speed = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
max_linear_speed = value
|
||||
arriver.agent.max_linear_speed = value
|
||||
|
||||
|
||||
func set_max_linear_acceleration(value: float) -> void:
|
||||
max_linear_acceleration = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
max_linear_acceleration = value
|
||||
arriver.agent.max_linear_acceleration = value
|
||||
|
@ -5,11 +5,11 @@ onready var player := $Player
|
||||
onready var gui := $GUI
|
||||
onready var turret := $Turret
|
||||
|
||||
export(int, 0, 359) var max_angular_speed := 90 setget set_max_angular_speed
|
||||
export(int, 0, 359) var max_angular_accel := 5 setget set_max_angular_accel
|
||||
export(int, 0, 180) var align_tolerance := 5 setget set_align_tolerance
|
||||
export(int, 0, 359) var deceleration_radius := 45 setget set_deceleration_radius
|
||||
export(float, 0, 1000) var player_speed := 600.0 setget set_player_speed
|
||||
export(int, 0, 359, 2) var max_angular_speed := 120 setget set_max_angular_speed
|
||||
export(int, 0, 359, 2) var max_angular_accel := 10 setget set_max_angular_accel
|
||||
export(int, 0, 180, 2) var align_tolerance := 5 setget set_align_tolerance
|
||||
export(int, 0, 359, 2) var deceleration_radius := 45 setget set_deceleration_radius
|
||||
export(float, 0, 1000, 40) var player_speed := 600.0 setget set_player_speed
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
@ -24,40 +24,40 @@ func _ready() -> void:
|
||||
|
||||
|
||||
func set_align_tolerance(value: int) -> void:
|
||||
align_tolerance = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
align_tolerance = value
|
||||
turret.face.alignment_tolerance = deg2rad(value)
|
||||
|
||||
|
||||
func set_deceleration_radius(value: int) -> void:
|
||||
deceleration_radius = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
deceleration_radius = value
|
||||
turret.face.deceleration_radius = deg2rad(value)
|
||||
|
||||
|
||||
func set_max_angular_accel(value: int) -> void:
|
||||
max_angular_accel = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
max_angular_accel = value
|
||||
turret.agent.max_angular_acceleration = deg2rad(value)
|
||||
|
||||
|
||||
func set_max_angular_speed(value: int) -> void:
|
||||
max_angular_speed = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
max_angular_speed = value
|
||||
turret.agent.max_angular_speed = deg2rad(value)
|
||||
|
||||
|
||||
func set_player_speed(value: float) -> void:
|
||||
player_speed = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
player_speed = value
|
||||
player.speed = player_speed
|
||||
|
@ -5,7 +5,7 @@ var face: GSTFace
|
||||
var agent := GSTSteeringAgent.new()
|
||||
|
||||
var _accel := GSTTargetAcceleration.new()
|
||||
var _angular_drag := 0.01
|
||||
var _angular_drag := 0.1
|
||||
var _cannon: Rect2
|
||||
|
||||
onready var collision_shape := $CollisionShape2D
|
||||
|
@ -1,8 +1,71 @@
|
||||
extends Node2D
|
||||
|
||||
|
||||
onready var drawer := $Drawer
|
||||
export(float, 0, 2000, 40) var max_linear_speed := 600.0 setget set_max_linear_speed
|
||||
export(float, 0, 200, 10.0) var max_linear_acceleration := 40.0 setget set_max_linear_acceleration
|
||||
export(float, 0, 100, 0.1) var arrival_tolerance := 10.0 setget set_arrival_tolerance
|
||||
export(float, 0, 500, 10) var deceleration_radius := 100.0 setget set_deceleration_radius
|
||||
export(float, 0, 5, 0.1) var predict_time := 0.3 setget set_predict_time
|
||||
export(float, 0, 200, 10.0) var path_offset := 20.0 setget set_path_offset
|
||||
|
||||
onready var drawer := $Drawer
|
||||
onready var follower := $PathFollower
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
$PathFollower.setup()
|
||||
follower.setup(
|
||||
path_offset,
|
||||
predict_time,
|
||||
max_linear_acceleration,
|
||||
max_linear_speed,
|
||||
deceleration_radius,
|
||||
arrival_tolerance
|
||||
)
|
||||
|
||||
|
||||
func set_max_linear_speed(value: float) -> void:
|
||||
max_linear_speed = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
follower.agent.max_linear_speed = value
|
||||
|
||||
|
||||
func set_max_linear_acceleration(value: float) -> void:
|
||||
max_linear_acceleration = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
follower.agent.max_linear_acceleration = value
|
||||
|
||||
|
||||
func set_arrival_tolerance(value: float) -> void:
|
||||
arrival_tolerance = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
follower.follow.arrival_tolerance = value
|
||||
|
||||
|
||||
func set_deceleration_radius(value: float) -> void:
|
||||
deceleration_radius = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
follower.follow.deceleration_radius = value
|
||||
|
||||
|
||||
func set_predict_time(value: float) -> void:
|
||||
predict_time = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
follower.follow.prediction_time = value
|
||||
|
||||
|
||||
func set_path_offset(value: float) -> void:
|
||||
path_offset = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
follower.follow.path_offset = value
|
||||
|
@ -1,9 +1,10 @@
|
||||
[gd_scene load_steps=6 format=2]
|
||||
[gd_scene load_steps=7 format=2]
|
||||
|
||||
[ext_resource path="res://demos/FollowPath/Drawer.gd" type="Script" id=1]
|
||||
[ext_resource path="res://assets/sprites/small_circle.png" type="Texture" id=2]
|
||||
[ext_resource path="res://demos/FollowPath/PathFollower.gd" type="Script" id=3]
|
||||
[ext_resource path="res://demos/FollowPath/FollowPathDemo.gd" type="Script" id=4]
|
||||
[ext_resource path="res://assets/theme/gdquest.theme" type="Theme" id=5]
|
||||
|
||||
[sub_resource type="CircleShape2D" id=1]
|
||||
radius = 16.0
|
||||
@ -24,3 +25,28 @@ shape = SubResource( 1 )
|
||||
[node name="Sprite" type="Sprite" parent="PathFollower"]
|
||||
modulate = Color( 0.960784, 0.231373, 0.0392157, 1 )
|
||||
texture = ExtResource( 2 )
|
||||
|
||||
[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 = "Follow Path Demo
|
||||
Use the mouse to draw a path on screen and watch the [color=red]red \"Agent\"[/color] follow it to the end."
|
||||
text = "Follow Path Demo
|
||||
Use the mouse to draw a path on screen and watch the red \"Agent\" follow it to the end."
|
||||
scroll_active = false
|
||||
|
@ -6,17 +6,29 @@ onready var path := GSTPath.new([
|
||||
Vector3(global_position.x, global_position.y, 0),
|
||||
Vector3(global_position.x, global_position.y, 0)
|
||||
], true)
|
||||
onready var follow := GSTFollowPath.new(agent, path, 20, 0)
|
||||
onready var follow := GSTFollowPath.new(agent, path, 0, 0)
|
||||
|
||||
var _velocity := Vector2.ZERO
|
||||
var _accel := GSTTargetAcceleration.new()
|
||||
var _valid := false
|
||||
var _drag := 0.1
|
||||
|
||||
|
||||
func setup() -> void:
|
||||
func setup(
|
||||
path_offset: float,
|
||||
predict_time: float,
|
||||
max_accel: float,
|
||||
max_speed: float,
|
||||
decel_radius: float,
|
||||
arrival_tolerance: float
|
||||
) -> void:
|
||||
owner.drawer.connect("path_established", self, "_on_Drawer_path_established")
|
||||
agent.max_linear_acceleration = 20
|
||||
agent.max_linear_speed = 200
|
||||
follow.path_offset = path_offset
|
||||
follow.prediction_time = predict_time
|
||||
agent.max_linear_acceleration = max_accel
|
||||
agent.max_linear_speed = max_speed
|
||||
follow.deceleration_radius = decel_radius
|
||||
follow.arrival_tolerance = arrival_tolerance
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
@ -24,6 +36,7 @@ func _physics_process(delta: float) -> void:
|
||||
_update_agent()
|
||||
_accel = follow.calculate_steering(_accel)
|
||||
_velocity += Vector2(_accel.linear.x, _accel.linear.y)
|
||||
_velocity = _velocity.linear_interpolate(Vector2.ZERO, _drag)
|
||||
_velocity = _velocity.clamped(agent.max_linear_speed)
|
||||
_velocity = move_and_slide(_velocity)
|
||||
|
||||
|
@ -3,12 +3,12 @@ extends Node2D
|
||||
|
||||
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 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(float, 0, 2000, 40.0) var max_linear_speed := 600.0 setget set_max_linear_speed
|
||||
export(float, 0, 200, 2.0) var max_linear_accel := 40.0 setget set_max_linear_accel
|
||||
export(float, 0, 300, 2.0) var proximity_radius := 140.0 setget set_proximity_radius
|
||||
export(float, 0, 10000, 100) var separation_decay_coefficient := 2000.0 setget set_separation_decay_coef
|
||||
export(float, 0, 2, 0.1) var cohesion_strength := 0.1 setget set_cohesion_strength
|
||||
export(float, 0, 6, 0.1) var separation_strength := 1.5 setget set_separation_strength
|
||||
export var show_proximity_radius := true setget set_show_proximity_radius
|
||||
|
||||
|
||||
@ -25,56 +25,56 @@ func _ready() -> void:
|
||||
|
||||
|
||||
func set_max_linear_speed(value: float) -> void:
|
||||
max_linear_speed = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
max_linear_speed = value
|
||||
spawner.set_max_linear_speed(value)
|
||||
|
||||
|
||||
func set_max_linear_accel(value: float) -> void:
|
||||
max_linear_accel = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
max_linear_accel = value
|
||||
spawner.set_max_linear_accel(value)
|
||||
|
||||
|
||||
func set_proximity_radius(value: float) -> void:
|
||||
proximity_radius = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
proximity_radius = value
|
||||
spawner.set_proximity_radius(value)
|
||||
|
||||
|
||||
func set_show_proximity_radius(value: bool) -> void:
|
||||
show_proximity_radius = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
show_proximity_radius = value
|
||||
spawner.set_show_proximity_radius(value)
|
||||
|
||||
|
||||
func set_separation_decay_coef(value: float) -> void:
|
||||
separation_decay_coefficient = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
separation_decay_coefficient = value
|
||||
spawner.set_separation_decay_coef(value)
|
||||
|
||||
|
||||
func set_cohesion_strength(value: float) -> void:
|
||||
cohesion_strength = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
cohesion_strength = value
|
||||
spawner.set_cohesion_strength(value)
|
||||
|
||||
|
||||
func set_separation_strength(value: float) -> void:
|
||||
separation_strength = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
separation_strength = value
|
||||
spawner.set_separation_strength(value)
|
||||
|
@ -1,13 +1,41 @@
|
||||
[gd_scene load_steps=4 format=2]
|
||||
[gd_scene load_steps=5 format=2]
|
||||
|
||||
[ext_resource path="res://demos/GroupBehaviors/Member.tscn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://demos/GroupBehaviors/Spawner.gd" type="Script" id=2]
|
||||
[ext_resource path="res://demos/GroupBehaviors/GroupBehaviorsDemo.gd" type="Script" id=3]
|
||||
[ext_resource path="res://assets/theme/gdquest.theme" type="Theme" id=4]
|
||||
|
||||
[node name="GroupBehaviorsDemo" type="Node2D"]
|
||||
script = ExtResource( 3 )
|
||||
cohesion_strength = 0.2
|
||||
separation_strength = 4.5
|
||||
|
||||
[node name="Spawner" type="Node2D" parent="."]
|
||||
position = Vector2( 512, 300 )
|
||||
script = ExtResource( 2 )
|
||||
member = ExtResource( 1 )
|
||||
|
||||
[node name="GUI" type="PanelContainer" parent="."]
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 14.0
|
||||
theme = ExtResource( 4 )
|
||||
__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 = "Group Behavior Demo
|
||||
Each of the \"Agents\" are both attempting to stay separated and within reach of their nearest group's center of mass."
|
||||
text = "Group Behavior Demo
|
||||
Each of the \"Agents\" are both attempting to stay separated and within reach of their nearest group's center of mass."
|
||||
scroll_active = false
|
||||
|
@ -40,12 +40,13 @@ func _draw() -> void:
|
||||
draw_circle(Vector2.ZERO, proximity.radius, Color(0, 1, 0, 0.1))
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
func _physics_process(delta: float) -> void:
|
||||
agent.position.x = global_position.x
|
||||
agent.position.y = global_position.y
|
||||
if blend:
|
||||
acceleration = blend.calculate_steering(acceleration)
|
||||
_velocity += Vector2(acceleration.linear.x, acceleration.linear.y)
|
||||
_velocity = _velocity.linear_interpolate(Vector2.ZERO, 0.1)
|
||||
_velocity = _velocity.clamped(agent.max_linear_speed)
|
||||
move_and_slide(_velocity)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
extends Node2D
|
||||
# Wraps the ships' positions around the world border, and controls their rendering clones.
|
||||
# Wraps the ships' positions around the world border.
|
||||
|
||||
|
||||
var _world_bounds: Vector2
|
||||
|
@ -4,7 +4,7 @@ extends KinematicBody2D
|
||||
|
||||
onready var agent := GSTSteeringAgent.new()
|
||||
|
||||
export var thruster_strength := 250.0
|
||||
export var thruster_strength := 175.0
|
||||
export var side_thruster_strength := 10.0
|
||||
export var max_velocity := 300.0
|
||||
export var max_angular_velocity := 2.0
|
||||
|
@ -1,9 +1,9 @@
|
||||
extends Node2D
|
||||
|
||||
|
||||
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
|
||||
export(float, 0, 2000, 40) var max_linear_speed := 120.0 setget set_max_linear_speed
|
||||
export(float, 0, 200, 2) var max_linear_accel := 10.0 setget set_max_linear_accel
|
||||
export(float, 0, 5, 0.1) var predict_time := 1.0 setget set_predict_time
|
||||
|
||||
onready var pursuer := $BoundaryManager/Pursuer
|
||||
onready var seeker := $BoundaryManager/Seeker
|
||||
@ -15,26 +15,26 @@ func _ready() -> void:
|
||||
|
||||
|
||||
func set_max_linear_speed(value: float) -> void:
|
||||
max_linear_speed = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
max_linear_speed = value
|
||||
pursuer.agent.max_linear_speed = value
|
||||
seeker.agent.max_linear_speed = value
|
||||
|
||||
|
||||
func set_max_linear_accel(value: float) -> void:
|
||||
max_linear_accel = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
max_linear_accel = value
|
||||
pursuer.agent.max_linear_acceleration = value
|
||||
seeker.agent.max_linear_acceleration = value
|
||||
|
||||
|
||||
func set_predict_time(value: float) -> void:
|
||||
predict_time = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
predict_time = value
|
||||
pursuer._behavior.max_predict_time = value
|
||||
|
@ -12,8 +12,7 @@ script = ExtResource( 4 )
|
||||
__meta__ = {
|
||||
"_editor_description_": "Toy demo to demonstrate the use of the Pursue contrasted to the more naive Seek steering behavior."
|
||||
}
|
||||
max_linear_speed = 120.0
|
||||
predict_time = 1.0
|
||||
max_linear_speed = 200.0
|
||||
|
||||
[node name="BoundaryManager" type="Node2D" parent="."]
|
||||
script = ExtResource( 3 )
|
||||
|
@ -14,7 +14,7 @@ var _behavior: GSTSteeringBehavior
|
||||
var _linear_velocity := Vector2()
|
||||
var _linear_drag_coefficient := 0.025
|
||||
var _angular_velocity := 0.0
|
||||
var _angular_drag := 1.0
|
||||
var _angular_drag := 0.1
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
@ -22,13 +22,16 @@ func _ready() -> void:
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
_update_agent()
|
||||
|
||||
accel = _orient_behavior.calculate_steering(accel)
|
||||
_angular_velocity += accel.angular
|
||||
|
||||
if _angular_velocity < 0:
|
||||
_angular_velocity += _angular_drag * delta
|
||||
elif _angular_velocity > 0:
|
||||
_angular_velocity -= _angular_drag * delta
|
||||
_angular_velocity = clamp(
|
||||
lerp(_angular_velocity, 0, _angular_drag),
|
||||
-agent.max_angular_speed,
|
||||
agent.max_angular_speed
|
||||
)
|
||||
|
||||
rotation += _angular_velocity * delta
|
||||
|
||||
@ -37,8 +40,6 @@ func _physics_process(delta: float) -> void:
|
||||
_linear_velocity = _linear_velocity.linear_interpolate(Vector2.ZERO, _linear_drag_coefficient)
|
||||
_linear_velocity = _linear_velocity.clamped(agent.max_linear_speed)
|
||||
_linear_velocity = move_and_slide(_linear_velocity)
|
||||
|
||||
_update_agent()
|
||||
|
||||
|
||||
func setup(predict_time: float, max_linear_speed: float, max_linear_accel: float) -> void:
|
||||
|
@ -43,10 +43,10 @@ func _ready() -> void:
|
||||
|
||||
|
||||
func set_behavior_mode(mode: int) -> void:
|
||||
behavior_mode = mode
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
behavior_mode = mode
|
||||
match mode:
|
||||
Mode.SEEK:
|
||||
for child in spawner.get_children():
|
||||
@ -57,26 +57,26 @@ func set_behavior_mode(mode: int) -> void:
|
||||
|
||||
|
||||
func set_max_linear_speed(value: float) -> void:
|
||||
max_linear_speed = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
max_linear_speed = value
|
||||
for child in spawner.get_children():
|
||||
child.agent.max_linear_speed = value
|
||||
|
||||
|
||||
func set_max_linear_accel(value: float) -> void:
|
||||
max_linear_accel = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
max_linear_accel = value
|
||||
for child in spawner.get_children():
|
||||
child.agent.max_linear_acceleration = value
|
||||
|
||||
|
||||
func set_player_speed(value: float) -> void:
|
||||
player_speed = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
player_speed = value
|
||||
player.speed = player_speed
|
||||
|
Loading…
Reference in New Issue
Block a user