Stable interface for both Animation player and Animated Sprite (#363)

Co-authored-by: Dennis Ploeger <develop@dieploegers.de>
This commit is contained in:
Dennis Ploeger
2021-08-10 21:35:01 +02:00
committed by GitHub
parent 61726bca81
commit 15bf1a8c81
11 changed files with 413 additions and 138 deletions

View File

@@ -107,17 +107,16 @@ func _process(delta: float) -> void:
last_deg = escoria.utils.get_deg_from_rad(angle)
last_dir = _get_dir_deg(last_deg, parent.animations)
var current_animation = ""
if parent.animation_sprite != null:
current_animation = parent.animation_sprite.animation
var animation_player: ESCAnimationPlayer = \
parent.get_animation_player()
var current_animation = animation_player.get_animation()
var animation_to_play = \
parent.animations.directions[last_dir].animation
if current_animation != animation_to_play:
if parent.animation_sprite.frames.has_animation(
animation_to_play
):
parent.animation_sprite.play(animation_to_play)
if animation_player.has_animation(animation_to_play):
animation_player.play(animation_to_play)
else:
current_animation = animation_to_play
escoria.logger.report_warnings(
@@ -241,19 +240,19 @@ func walk_stop(pos: Vector2) -> void:
walk_context.target_object.interactive:
var orientation = walk_context.target_object.node.interaction_direction
last_dir = orientation
parent.animation_sprite.play(
parent.get_animation_player().play(
parent.animations.idles[orientation].animation
)
pose_scale = -1 if parent.animations.idles[orientation].mirrored else 1
else:
parent.animation_sprite.play(
parent.get_animation_player().play(
parent.animations.idles[last_dir].animation
)
pose_scale = -1 if parent.animations.idles[last_dir].mirrored else 1
update_terrain()
yield(parent.animation_sprite, "animation_finished")
yield(parent.get_animation_player(), "animation_finished")
if walk_context.target_object:
escoria.logger.debug(
"%s arrived at %s" % [
@@ -399,9 +398,9 @@ func set_angle(deg: int, immediate = true) -> void:
# 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 != \
if parent.get_animation_player().get_animation() != \
parent.animations.idles[last_dir].animation:
parent.animation_sprite.play(
parent.get_animation_player().play(
parent.animations.idles[last_dir].animation
)
pose_scale = -1 if parent.animations.idles[last_dir].mirrored else 1
@@ -420,10 +419,10 @@ func set_angle(deg: int, immediate = true) -> void:
if dir < 0:
dir = parent.animations.dir_angles.size() - 1
parent.animation_sprite.play(
parent.get_animation_player().play(
parent.animations.idles[dir].animation
)
yield(parent.animation_sprite, "animation_finished")
yield(parent.get_animation_player(), "animation_finished")
pose_scale = -1 if parent.animations.idles[dir].mirrored else 1
update_terrain()

View File

@@ -38,7 +38,8 @@ func run(command_params: Array) -> int:
var obj = escoria.object_manager.objects[command_params[0]]
var anim_id = command_params[1]
var reverse = command_params[2]
var animator = (obj.node as ESCItem).get_animation_player()
var animator: ESCAnimationPlayer = \
(obj.node as ESCItem).get_animation_player()
if reverse:
animator.play_backwards(anim_id)
else:

View File

@@ -38,7 +38,8 @@ func run(command_params: Array) -> int:
var obj = escoria.object_manager.objects[command_params[0]]
var anim_id = command_params[1]
var reverse = command_params[2]
var animator = (obj.node as ESCItem).get_animation_player()
var animator: ESCAnimationPlayer = \
(obj.node as ESCItem).get_animation_player()
if reverse:
animator.play_backwards(anim_id)
else:

View File

@@ -38,28 +38,16 @@ func set_state(p_state: String, immediate: bool = false):
state = p_state
if node.has_method("get_animation_player"):
var animation_node = node.get_animation_player()
var animation_node: ESCAnimationPlayer = node.get_animation_player()
if animation_node:
animation_node.stop()
var actual_animator
if animation_node is AnimationPlayer:
if animation_node.has_animation(p_state):
if immediate:
animation_node.current_animation = p_state
animation_node.seek(
animation_node.get_animation(p_state).length
)
else:
animation_node.play(p_state)
elif animation_node is AnimatedSprite:
if animation_node.frames.has_animation(p_state):
if immediate:
animation_node.animation = p_state
animation_node.frame = \
animation_node.frames.get_frame_count(p_state)
else:
animation_node.play(p_state)
if animation_node.has_animation(p_state):
if immediate:
animation_node.seek_end(p_state)
else:
animation_node.play(p_state)
# Set the active value, thus hiding or showing the object

View File

@@ -0,0 +1,139 @@
# An abstraction class to expose the same animation methods for noth
# AnimatedSprite and AnimationPlayer
extends Node
class_name ESCAnimationPlayer
signal animation_finished(name)
# The actual player node
var _player_node: Node
# A AnimationPlayer typed reference to the player node (for intellisense)
var _animation_player: AnimationPlayer
# A AnimationPlayer typed reference to the player node (for intellisense)
var _animated_sprite: AnimatedSprite
# Wether the player node is of type AnimationPlayer (just for convenience)
var _is_animation_player: bool = false
# Create a new animation player
#
# #### Parameters
#
# - node: The actual player node
func _init(node: Node):
_player_node = node
if node is AnimationPlayer:
_is_animation_player = true
_animation_player = node
else:
_animated_sprite = node
# Return the currently playing animation
# **Returns** the currently playing animation name
func get_animation() -> String:
if _is_animation_player:
return _animation_player.current_animation
else:
return _animated_sprite.animation
# Returns a list of all animation names
# **Returns** A list of all animation names
func get_animations() -> PoolStringArray:
if _is_animation_player:
return _animation_player.get_animation_list()
else:
return _animated_sprite.frames.get_animation_names()
# Wether the animation is playing
# **Returns: Wether the animation is playing**
func is_playing() -> bool:
return _player_node.is_playing()
# Stop the animation
func stop():
_player_node.stop()
# Play the animation
#
# #### Parameters
#
# - name: The animation name to play
# - backwards: Play backwards
func play(name: String, backwards: bool = false):
if _player_node.is_connected(
"animation_finished",
self,
"_on_animation_finished"
):
_player_node.disconnect(
"animation_finished",
self,
"_on_animation_finished"
)
_player_node.connect(
"animation_finished",
self,
"_on_animation_finished",
[name]
)
if backwards and _is_animation_player:
_animation_player.play_backwards(name)
elif backwards:
_animated_sprite.play(name, true)
else:
_player_node.play(name)
# Play the given animation backwards
#
# #### Parameters
#
# - name: Animation to play
func play_backwards(name: String):
self.play(name, true)
# Check if the given animation exists
#
# #### Parameters
#
# - name: Name of the animation to check
# **Returns** Wether the animation player has the animation
func has_animation(name: String) -> bool:
if _is_animation_player:
return _animation_player.has_animation(name)
else:
return _animated_sprite.frames.has_animation(name)
# Play an animation and directly skip to the end
#
# #### Parameters
#
# - name: Name of the animation to play
func seek_end(name: String):
if _is_animation_player:
_animation_player.current_animation = name
_animation_player.seek(_animation_player.get_animation(name).length)
else:
_animated_sprite.animation = name
_animated_sprite.frame = _animated_sprite.frames.get_frame_count(name)
# Transport the animation_finished signal
#
# #### Parameters
#
# - name: Name of the animation played
func _on_animation_finished(name: String):
emit_signal("animation_finished", name)

View File

@@ -120,15 +120,13 @@ export(int) var speed: int = 300
# Speed damp of this item if movable
export(float) var v_speed_damp: float = 1.0
# The node used to play animations
export(NodePath) var animation_player_node: NodePath = "" \
setget _set_animation_player_node
# ESCAnimationsResource (for walking, idling...)
var animations: ESCAnimationResource
# The movable subnode
var _movable: ESCMovable = null
# Reference to the animation node (null if none was found)
var animation_sprite = null
# Reference to the current terrain
var terrain: ESCTerrain
@@ -140,6 +138,13 @@ var collision: Node
var inventory_item: ESCInventoryItem = null setget ,_get_inventory_item
# The movable subnode
var _movable: ESCMovable = null
# The identified animation player
var _animation_player: ESCAnimationPlayer = null
# Add the movable node, connect signals, detect child nodes
# and register this item
func _ready():
@@ -194,8 +199,20 @@ func _ready():
# Return the animation player node
func get_animation_player():
return animation_sprite
func get_animation_player() -> Node:
if _animation_player == null:
var player_node_path = animation_player_node
if player_node_path == "":
for child in self.get_children():
if child is AnimatedSprite or \
child is AnimationPlayer:
player_node_path = child.get_path()
if not has_node(player_node_path):
escoria.logger.error(
"Can not find node at path %s" % player_node_path
)
_animation_player = ESCAnimationPlayer.new(get_node(player_node_path))
return _animation_player
# Return the position the player needs to walk to to interact with this
@@ -327,29 +344,20 @@ func set_angle(deg: int, immediate = true):
# Play the talking animation
func start_talking():
if animation_sprite.is_playing():
animation_sprite.stop()
animation_sprite.play(animations.speaks[_movable.last_dir].animation)
if get_animation_player().is_playing():
get_animation_player().stop()
get_animation_player().play(animations.speaks[_movable.last_dir].animation)
# Stop playing the talking animation
func stop_talking():
if animation_sprite.is_playing():
animation_sprite.stop()
animation_sprite.play(animations.idles[_movable.last_dir].animation)
if get_animation_player().is_playing():
get_animation_player().stop()
get_animation_player().play(animations.idles[_movable.last_dir].animation)
# Detect the child nodes and set respective references
func _detect_children() -> void:
# Detect animation player
for n in get_children():
if n is AnimatedSprite:
animation_sprite = n
continue
if n is AnimationPlayer:
animation_sprite = n
continue
# Initialize collision variable.
for c in get_children():
if c is CollisionShape2D or c is CollisionPolygon2D:
@@ -380,3 +388,23 @@ func _get_property_list():
"hint_string": "ESCAnimationResource"
})
return properties
# Set the node path to the animation player
#
# #### Parameters
#
# - node_path: Path to the player node
func _set_animation_player_node(node_path: NodePath):
if node_path == "":
animation_player_node = node_path
return
assert(has_node(node_path), "Node with path %s not found" % node_path)
assert(
get_node(node_path) is AnimatedSprite or \
get_node(node_path) is AnimationPlayer,
"Selected node has to be an AnimatedSprite or AnimationPlayer node"
)
animation_player_node = node_path

View File

@@ -107,7 +107,7 @@ var result_angles = []
func _ready():
# Find player animations
$player_animations.add_item("")
for anim_name in $player.get_animation_player.get_sprite_frames().get_animation_names():
for anim_name in $player.get_animation_player().get_animations():
$player_animations.add_item(anim_name)
# Set initial angles

View File

@@ -0,0 +1,113 @@
<!-- Auto-generated from JSON by GDScript docs maker. Do not edit this document directly. -->
# ESCAnimationPlayer
**Extends:** [Node](../Node)
## Description
An abstraction class to expose the same animation methods for noth
AnimatedSprite and AnimationPlayer
## Method Descriptions
### \_init
```gdscript
func _init(node: Node)
```
Create a new animation player
#### Parameters
- node: The actual player node
### get\_animation
```gdscript
func get_animation() -> String
```
Return the currently playing animation
**Returns** the currently playing animation name
### get\_animations
```gdscript
func get_animations() -> PoolStringArray
```
Returns a list of all animation names
**Returns** A list of all animation names
### is\_playing
```gdscript
func is_playing() -> bool
```
Wether the animation is playing
**Returns: Wether the animation is playing**
### stop
```gdscript
func stop()
```
Stop the animation
### play
```gdscript
func play(name: String, backwards: bool = false)
```
Play the animation
#### Parameters
- name: The animation name to play
- backwards: Play backwards
### play\_backwards
```gdscript
func play_backwards(name: String)
```
Play the given animation backwards
#### Parameters
- name: Animation to play
### has\_animation
```gdscript
func has_animation(name: String) -> bool
```
Check if the given animation exists
#### Parameters
- name: Name of the animation to check
**Returns** Wether the animation player has the animation
### seek\_end
```gdscript
func seek_end(name: String)
```
Play an animation and directly skip to the end
#### Parameters
- name: Name of the animation to play
## Signals
- signal animation_finished(name):

View File

@@ -188,6 +188,14 @@ export var v_speed_damp: float = 1
Speed damp of this item if movable
### animation\_player\_node
```gdscript
export var animation_player_node: NodePath = ""
```
The node used to play animations
### animations
```gdscript
@@ -196,14 +204,6 @@ var animations: ESCAnimationResource
 ESCAnimationsResource (for walking, idling...)
### animation\_sprite
```gdscript
var animation_sprite
```
Reference to the animation node (null if none was found)
### terrain
```gdscript
@@ -234,7 +234,7 @@ be loaded, if inventory_item_scene_file is set.
### get\_animation\_player
```gdscript
func get_animation_player()
func get_animation_player() -> Node
```
Return the animation player node

View File

@@ -14,99 +14,99 @@ region = Rect2( 120, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=2]
atlas = ExtResource( 4 )
region = Rect2( 0, 0, 24, 70 )
region = Rect2( 24, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=3]
atlas = ExtResource( 2 )
atlas = ExtResource( 5 )
region = Rect2( 0, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=4]
atlas = ExtResource( 2 )
atlas = ExtResource( 5 )
region = Rect2( 24, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=5]
atlas = ExtResource( 2 )
atlas = ExtResource( 5 )
region = Rect2( 48, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=6]
atlas = ExtResource( 6 )
region = Rect2( 0, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=7]
atlas = ExtResource( 6 )
region = Rect2( 24, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=8]
atlas = ExtResource( 2 )
region = Rect2( 0, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=9]
atlas = ExtResource( 2 )
region = Rect2( 24, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=10]
atlas = ExtResource( 2 )
region = Rect2( 48, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=11]
atlas = ExtResource( 4 )
region = Rect2( 48, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=7]
[sub_resource type="AtlasTexture" id=12]
atlas = ExtResource( 7 )
region = Rect2( 0, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=8]
[sub_resource type="AtlasTexture" id=13]
atlas = ExtResource( 7 )
region = Rect2( 24, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=9]
[sub_resource type="AtlasTexture" id=14]
atlas = ExtResource( 7 )
region = Rect2( 48, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=10]
[sub_resource type="AtlasTexture" id=15]
atlas = ExtResource( 7 )
region = Rect2( 72, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=11]
[sub_resource type="AtlasTexture" id=16]
atlas = ExtResource( 7 )
region = Rect2( 96, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=12]
[sub_resource type="AtlasTexture" id=17]
atlas = ExtResource( 4 )
region = Rect2( 144, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=13]
[sub_resource type="AtlasTexture" id=18]
atlas = ExtResource( 4 )
region = Rect2( 168, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=14]
[sub_resource type="AtlasTexture" id=19]
atlas = ExtResource( 4 )
region = Rect2( 192, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=15]
[sub_resource type="AtlasTexture" id=20]
atlas = ExtResource( 4 )
region = Rect2( 216, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=16]
[sub_resource type="AtlasTexture" id=21]
atlas = ExtResource( 4 )
region = Rect2( 240, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=17]
[sub_resource type="AtlasTexture" id=22]
atlas = ExtResource( 4 )
region = Rect2( 264, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=18]
[sub_resource type="AtlasTexture" id=23]
atlas = ExtResource( 4 )
region = Rect2( 288, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=19]
[sub_resource type="AtlasTexture" id=24]
atlas = ExtResource( 4 )
region = Rect2( 312, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=20]
atlas = ExtResource( 4 )
region = Rect2( 24, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=21]
atlas = ExtResource( 5 )
region = Rect2( 0, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=22]
atlas = ExtResource( 5 )
region = Rect2( 24, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=23]
atlas = ExtResource( 5 )
region = Rect2( 48, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=24]
atlas = ExtResource( 6 )
region = Rect2( 0, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=25]
atlas = ExtResource( 6 )
region = Rect2( 24, 0, 24, 70 )
atlas = ExtResource( 4 )
region = Rect2( 0, 0, 24, 70 )
[sub_resource type="AtlasTexture" id=26]
atlas = ExtResource( 4 )
@@ -137,49 +137,49 @@ animations = [ {
}, {
"frames": [ SubResource( 2 ) ],
"loop": true,
"name": "idle_down",
"speed": 5.0
}, {
"frames": [ SubResource( 3 ), SubResource( 4 ), SubResource( 5 ), SubResource( 4 ), SubResource( 5 ) ],
"loop": true,
"name": "speak_down",
"speed": 6.0
}, {
"frames": [ SubResource( 6 ) ],
"loop": true,
"name": "idle_right",
"speed": 5.0
}, {
"frames": [ SubResource( 7 ), SubResource( 8 ), SubResource( 9 ), SubResource( 10 ), SubResource( 11 ) ],
"loop": true,
"name": "speak_right",
"speed": 5.0
}, {
"frames": [ SubResource( 12 ), SubResource( 13 ), SubResource( 14 ), SubResource( 13 ) ],
"loop": true,
"name": "walk_down",
"speed": 6.0
}, {
"frames": [ SubResource( 15 ), SubResource( 16 ), SubResource( 17 ), SubResource( 18 ), SubResource( 19 ) ],
"loop": true,
"name": "walk_right",
"speed": 6.0
}, {
"frames": [ SubResource( 20 ) ],
"loop": true,
"name": "idle_down_right",
"speed": 5.0
}, {
"frames": [ SubResource( 21 ), SubResource( 22 ), SubResource( 23 ) ],
"frames": [ SubResource( 3 ), SubResource( 4 ), SubResource( 5 ) ],
"loop": true,
"name": "speak_down_right",
"speed": 6.0
}, {
"frames": [ SubResource( 24 ), SubResource( 25 ), SubResource( 24 ), SubResource( 25 ), SubResource( 25 ) ],
"frames": [ SubResource( 6 ), SubResource( 7 ), SubResource( 6 ), SubResource( 7 ), SubResource( 7 ) ],
"loop": true,
"name": "speak_up",
"speed": 3.0
}, {
"frames": [ SubResource( 8 ), SubResource( 9 ), SubResource( 10 ), SubResource( 9 ), SubResource( 10 ) ],
"loop": true,
"name": "speak_down",
"speed": 6.0
}, {
"frames": [ SubResource( 11 ) ],
"loop": true,
"name": "idle_right",
"speed": 5.0
}, {
"frames": [ SubResource( 12 ), SubResource( 13 ), SubResource( 14 ), SubResource( 15 ), SubResource( 16 ) ],
"loop": true,
"name": "speak_right",
"speed": 5.0
}, {
"frames": [ SubResource( 17 ), SubResource( 18 ), SubResource( 19 ), SubResource( 18 ) ],
"loop": true,
"name": "walk_down",
"speed": 6.0
}, {
"frames": [ SubResource( 20 ), SubResource( 21 ), SubResource( 22 ), SubResource( 23 ), SubResource( 24 ) ],
"loop": true,
"name": "walk_right",
"speed": 6.0
}, {
"frames": [ SubResource( 25 ) ],
"loop": true,
"name": "idle_down",
"speed": 5.0
}, {
"frames": [ SubResource( 26 ), SubResource( 27 ), SubResource( 28 ), SubResource( 27 ) ],
"loop": true,
"name": "walk_up",

View File

@@ -89,6 +89,11 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://addons/escoria-core/game/core-scripts/resources/esc_animationname.gd"
}, {
"base": "Node",
"class": "ESCAnimationPlayer",
"language": "GDScript",
"path": "res://addons/escoria-core/game/core-scripts/esc_animation_player.gd"
}, {
"base": "Resource",
"class": "ESCAnimationResource",
"language": "GDScript",
@@ -486,6 +491,7 @@ _global_script_class_icons={
"DecGlobalCommand": "",
"ESCActionManager": "",
"ESCAnimationName": "",
"ESCAnimationPlayer": "",
"ESCAnimationResource": "",
"ESCBackground": "",
"ESCBackgroundMusic": "",