diff --git a/addons/escoria-core/game/core-scripts/behaviors/esc_movable.gd b/addons/escoria-core/game/core-scripts/behaviors/esc_movable.gd
index 81cb126f..a219dd0a 100644
--- a/addons/escoria-core/game/core-scripts/behaviors/esc_movable.gd
+++ b/addons/escoria-core/game/core-scripts/behaviors/esc_movable.gd
@@ -59,7 +59,7 @@ onready var task = MovableTask.NONE
# the destination position was reached
func _ready() -> void:
parent.add_user_signal("arrived")
-
+
# Main processing loop
#
@@ -70,8 +70,7 @@ func _process(delta: float) -> void:
if Engine.is_editor_hint():
return
- if task == MovableTask.WALK or \
- task == MovableTask.SLIDE:
+ if task == MovableTask.WALK or task == MovableTask.SLIDE:
var pos = parent.get_position()
var old_pos = pos
var next
@@ -247,7 +246,9 @@ func walk_stop(pos: Vector2) -> void:
)
pose_scale = -1 if parent.animations.idles[orientation].mirrored else 1
else:
- parent.animation_sprite.play(parent.animations.idles[last_dir].animation)
+ parent.animation_sprite.play(
+ parent.animations.idles[last_dir].animation
+ )
pose_scale = -1 if parent.animations.idles[last_dir].mirrored else 1
update_terrain()
@@ -351,7 +352,10 @@ func _get_dir_deg(deg: int, animations: ESCAnimationResource) -> int:
# - direction_angle: ESCDirectionAngle resource, containing the starting angle,
# and the size of interval
# eg: angle_start=90, angle_size=40 corresponds to angle between 90° and 130°
-func is_angle_in_interval(angle: float, direction_angle: ESCDirectionAngle) -> bool:
+func is_angle_in_interval(
+ angle: float,
+ direction_angle: ESCDirectionAngle
+) -> bool:
angle = wrapi(angle, 0, 360)
if angle == 0:
angle = 360
@@ -379,8 +383,8 @@ func is_angle_in_interval(angle: float, direction_angle: ESCDirectionAngle) -> b
#
# - deg int angle to set the character
# - immediate
-# If true, direction is switched immediately. Else, successive animations are
-# used so that the character turns to target angle.
+# If true, direction is switched immediately. Else, successive
+# animations are used so that the character turns to target angle.
func set_angle(deg: int, immediate = true) -> void:
if deg < 0 or deg > 360:
escoria.logger.report_errors(
@@ -388,18 +392,87 @@ func set_angle(deg: int, immediate = true) -> void:
["Invalid degree to turn to " + str(deg)]
)
moved = true
- last_deg = deg
- last_dir = _get_dir_deg(deg, parent.animations)
+
+ if immediate:
+ last_deg = deg
+ last_dir = _get_dir_deg(deg, parent.animations)
- # The character may have a state animation from before, which would be
- # resumed, so we immediately force the correct idle animation
- if parent.animation_sprite.animation != \
- parent.animations.idles[last_dir].animation:
- parent.animation_sprite.play(parent.animations.idles[last_dir].animation)
- pose_scale = -1 if parent.animations.idles[last_dir].mirrored else 1
+ # The character may have a state animation from before, which would be
+ # resumed, so we immediately force the correct idle animation
+ if parent.animation_sprite.animation != \
+ parent.animations.idles[last_dir].animation:
+ parent.animation_sprite.play(
+ parent.animations.idles[last_dir].animation
+ )
+ pose_scale = -1 if parent.animations.idles[last_dir].mirrored else 1
+ else:
+ var current_dir = last_dir
+ last_deg = deg
+ var target_dir = _get_dir_deg(deg, parent.animations)
+
+ var way_to_turn = get_shortest_way_to_dir(current_dir, target_dir)
+
+ var dir = current_dir
+ while dir != target_dir:
+ dir += way_to_turn
+ if dir >= parent.animations.dir_angles.size():
+ dir = 0
+ if dir < 0:
+ dir = parent.animations.dir_angles.size() - 1
+
+ parent.animation_sprite.play(
+ parent.animations.idles[dir].animation
+ )
+ yield(parent.animation_sprite, "animation_finished")
+ pose_scale = -1 if parent.animations.idles[dir].mirrored else 1
+
update_terrain()
+
# Returns the angle that corresponds to the current direction of the object.
func _get_angle() -> int:
return parent.animations.dir_angles[last_dir].animation
+
+
+# Return the shortest way to turn from a direction to another. Returned way is
+# either:
+# -1 (shortest way is to turn anti-clockwise)
+# 0 (already at the right direction)
+# 1 (clockwise).
+#
+# ####Parameters
+# - current_dir: integer corresponding to the starting direction as defined in
+# the attached ESCAnimationResource.directions.
+# - target_dir: integer corresponding to the target direction as defined in
+# the attached ESCAnimationResource.directions.
+#
+# *Returns*
+# Integer: -1 (anti-clockwise), 1 (clockwise) or 0 (no movement needed).
+func get_shortest_way_to_dir(current_dir: int, target_dir: int) -> int:
+ if current_dir < 0 or current_dir > parent.animations.dir_angles.size() - 1:
+ escoria.logger.report_errors(
+ "esc_movable.gd:get_shortest_way_to_dir()",
+ ["Invalid direction (current_dir) %s" % str(current_dir)]
+ )
+ if target_dir < 0 or target_dir > parent.animations.dir_angles.size() - 1:
+ escoria.logger.report_errors(
+ "esc_movable.gd:get_shortest_way_to_dir()",
+ ["Invalid direction (target_dir) %s " % str(target_dir)]
+ )
+
+ if current_dir == target_dir:
+ return 0
+
+ var internal = false
+ if max(current_dir, target_dir) - min(current_dir, target_dir) \
+ < parent.animations.dir_angles.size() / 2:
+ internal = true
+ else:
+ internal = false
+
+ if internal and current_dir < target_dir or \
+ (not internal and current_dir > target_dir):
+ return 1
+ else:
+ return -1
diff --git a/addons/escoria-core/game/core-scripts/esc/commands/change_scene.gd b/addons/escoria-core/game/core-scripts/esc/commands/change_scene.gd
index 71ffc151..43504541 100644
--- a/addons/escoria-core/game/core-scripts/esc/commands/change_scene.gd
+++ b/addons/escoria-core/game/core-scripts/esc/commands/change_scene.gd
@@ -92,7 +92,7 @@ func run(command_params: Array) -> int:
var script = escoria.esc_compiler.load_esc_file(
room_scene.esc_script
)
-
+
if script.events.has("setup"):
escoria.event_manager.queue_event(script.events["setup"])
var rc = yield(escoria.event_manager, "event_finished")
@@ -100,7 +100,10 @@ func run(command_params: Array) -> int:
rc = yield(escoria.event_manager, "event_finished")
if rc[0] != ESCExecution.RC_OK:
return rc[0]
-
+
+ escoria.main.scene_transition.fade_in()
+ yield(escoria.main.scene_transition, "transition_done")
+
# If scene was never visited, add "ready" event to the events stack
if not command_params[0] in self.readied_scenes \
and script.events.has("ready"):
@@ -111,9 +114,6 @@ func run(command_params: Array) -> int:
if rc[0] != ESCExecution.RC_OK:
return rc[0]
- escoria.main.scene_transition.fade_in()
- yield(escoria.main.scene_transition, "transition_done")
-
self.readied_scenes.append(command_params[0])
# Clear queued resources
diff --git a/addons/escoria-core/game/core-scripts/esc/commands/set_angle.gd b/addons/escoria-core/game/core-scripts/esc/commands/set_angle.gd
index 28fd2f6c..9a210111 100644
--- a/addons/escoria-core/game/core-scripts/esc/commands/set_angle.gd
+++ b/addons/escoria-core/game/core-scripts/esc/commands/set_angle.gd
@@ -1,4 +1,4 @@
-# `set_angle object degrees`
+# `set_angle object degrees [immediate]`
#
# Turns object to a degrees angle without animations. 0 sets object facing
# forward, 90 sets it 90 degrees clockwise ("east") etc. When turning to the
@@ -16,8 +16,8 @@ class_name SetAngleCommand
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new(
2,
- [TYPE_STRING, TYPE_INT],
- [null, null]
+ [TYPE_STRING, TYPE_INT, TYPE_BOOL],
+ [null, null, true]
)
@@ -36,10 +36,12 @@ func validate(arguments: Array):
# Run the command
func run(command_params: Array) -> int:
+ var immediate = command_params[2]
+
# HACK Countering the fact that angle_to_point() function gives
# angle against X axis not Y, we need to check direction using (angle-90°).
# Since the ESC command already gives the right angle, we add 90.
escoria.object_manager.get_object(command_params[0]).node\
- .set_angle(wrapi(int(command_params[1]) + 90, 0, 360))
+ .set_angle(wrapi(int(command_params[1]) + 90, 0, 360), immediate)
return ESCExecution.RC_OK
diff --git a/addons/escoria-core/game/scenes/transitions/transition.gd b/addons/escoria-core/game/scenes/transitions/transition.gd
index 6ef59579..3df22249 100644
--- a/addons/escoria-core/game/scenes/transitions/transition.gd
+++ b/addons/escoria-core/game/scenes/transitions/transition.gd
@@ -2,7 +2,7 @@
extends ColorRect
-# Emitted when the transition was player
+# Emitted when the transition was played
signal transition_done
diff --git a/docs/api/ESCMovable.md b/docs/api/ESCMovable.md
index bcb2551a..34298b63 100644
--- a/docs/api/ESCMovable.md
+++ b/docs/api/ESCMovable.md
@@ -181,20 +181,10 @@ Update the sprite scale and lighting
func is_angle_in_interval(angle: float, direction_angle: ESCDirectionAngle) -> bool
```
-Returns true if given angle is inside the interval given by a starting_angle
-and the size.
-
-#### Parameters
-
-- angle: Angle to test
-- direction_angle: ESCDirectionAngle resource, containing the starting angle,
- and the size of interval
-eg: angle_start=90, angle_size=40 corresponds to angle between 90° and 130°
-
### set\_angle
```gdscript
-func set_angle(deg: int, immediate = true) -> void
+func set_angle(deg: int, immediate = true) -> var
```
Sets character's angle and plays according animation.
@@ -203,5 +193,26 @@ Sets character's angle and plays according animation.
- deg int angle to set the character
- immediate
- If true, direction is switched immediately. Else, successive animations are
- used so that the character turns to target angle.
\ No newline at end of file
+ If true, direction is switched immediately. Else, successive
+ animations are used so that the character turns to target angle.
+
+### get\_shortest\_way\_to\_dir
+
+```gdscript
+func get_shortest_way_to_dir(current_dir: int, target_dir: int) -> int
+```
+
+ Return the shortest way to turn from a direction to another. Returned way is
+either:
+-1 (shortest way is to turn anti-clockwise)
+0 (already at the right direction)
+1 (clockwise).
+
+####Parameters
+- current_dir: integer corresponding to the starting direction as defined in
+the attached ESCAnimationResource.directions.
+- target_dir: integer corresponding to the target direction as defined in
+the attached ESCAnimationResource.directions.
+
+*Returns*
+Integer: -1 (anti-clockwise), 1 (clockwise) or 0 (no movement needed).
\ No newline at end of file
diff --git a/docs/api/SetAngleCommand.md b/docs/api/SetAngleCommand.md
index 3082ff3a..9f23bdd3 100644
--- a/docs/api/SetAngleCommand.md
+++ b/docs/api/SetAngleCommand.md
@@ -6,7 +6,7 @@
## Description
-`set_angle object degrees`
+`set_angle object degrees [immediate]`
Turns object to a degrees angle without animations. 0 sets object facing
forward, 90 sets it 90 degrees clockwise ("east") etc. When turning to the
diff --git a/docs/api/transition.gd.md b/docs/api/transition.gd.md
index 6ac4a749..13a636fa 100644
--- a/docs/api/transition.gd.md
+++ b/docs/api/transition.gd.md
@@ -36,4 +36,4 @@ Fade in the transition
## Signals
-- signal transition_done(): Emitted when the transition was player
+- signal transition_done(): Emitted when the transition was played
diff --git a/docs/esc.md b/docs/esc.md
index d03c758f..8cbdeb20 100644
--- a/docs/esc.md
+++ b/docs/esc.md
@@ -266,7 +266,7 @@ event ends.
Changes the "active" state of the object, value can be true or false.
Inactive objects are hidden in the scene.
-#### `set_angle object degrees` [API-Doc](api/SetAngleCommand.md)
+#### `set_angle object degrees [immediate]` [API-Doc](api/SetAngleCommand.md)
Turns object to a degrees angle without animations. 0 sets object facing
forward, 90 sets it 90 degrees clockwise ("east") etc. When turning to the
diff --git a/game/rooms/room01/esc/room01.esc b/game/rooms/room01/esc/room01.esc
index d04b04fd..8aceeb02 100755
--- a/game/rooms/room01/esc/room01.esc
+++ b/game/rooms/room01/esc/room01.esc
@@ -12,4 +12,9 @@
:ready
set_sound_state bg_music res://game/sfx/contemplation.ogg true
+
walk player r1_destination_point
+wait 2
+walk player r1_destination_point2
+wait 2
+set_angle player 225 false
diff --git a/game/rooms/room01/room01.tscn b/game/rooms/room01/room01.tscn
index db766f70..17fb883a 100644
--- a/game/rooms/room01/room01.tscn
+++ b/game/rooms/room01/room01.tscn
@@ -58,6 +58,7 @@ is_exit = true
tooltip_name = "Exit"
default_action = "walk"
dialog_color = Color( 1, 1, 1, 1 )
+animations = null
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Hotspots/r_door"]
polygon = PoolVector2Array( 1177.94, 348.61, 1175.95, 45.3759, 1276.06, 92.0953, 1277.95, 399.407 )
@@ -74,6 +75,7 @@ esc_script = "res://game/rooms/room01/esc/wall_item.esc"
tooltip_name = "Item on the wall"
default_action = "look"
dialog_color = Color( 1, 1, 1, 1 )
+animations = null
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Hotspots/item"]
polygon = PoolVector2Array( 635.586, 253.345, 568.928, 60.1716, 709.047, 120.028, 699.524, 247.903 )
@@ -109,6 +111,7 @@ esc_script = "res://game/rooms/room01/esc/wall_item_popupdialog.esc"
tooltip_name = "Item on the wall"
default_action = "look"
dialog_color = Color( 1, 1, 1, 1 )
+animations = null
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Hotspots/item2"]
polygon = PoolVector2Array( 635.586, 253.345, 568.928, 60.1716, 709.047, 120.028, 699.524, 247.903 )
@@ -137,7 +140,7 @@ __meta__ = {
}
[node name="player_start" type="Position2D" parent="."]
-position = Vector2( 76.7617, 437.649 )
+position = Vector2( 653.761, 443.306 )
script = ExtResource( 7 )
global_id = "r1_start"
@@ -146,3 +149,9 @@ position = Vector2( 476.984, 487.146 )
script = ExtResource( 7 )
global_id = "r1_destination_point"
interaction_direction = 4
+
+[node name="destination_point2" type="Position2D" parent="."]
+position = Vector2( 994.586, 458.862 )
+script = ExtResource( 7 )
+global_id = "r1_destination_point2"
+player_orients_on_arrival = false