RapidGameFramework
Reusable Godot managers for data-driven small games
Loading...
Searching...
No Matches
animation_state_manager.gd
Go to the documentation of this file.
1extends RefCounted
2
3
7
8const DEFAULT_DIRECTIONS := ["down", "left", "right", "up"]
9
10
11
12func direction_name(value, fallback:String = "down") -> String:
13 if value is String:
14 var text = str(value).to_lower()
15 return text if DEFAULT_DIRECTIONS.has(text) else fallback
16 var vector = _vector_from_any(value)
17 if vector.length() <= 0.001:
18 return fallback
19 if abs(vector.x) > abs(vector.y):
20 return "right" if vector.x > 0.0 else "left"
21 return "down" if vector.y > 0.0 else "up"
22
23
24
25func get_state_key(entity:Dictionary, options:Dictionary = {}) -> String:
26 var base_state = str(options.get("state", entity.get("state", "idle"))).strip_edges().to_lower()
27 if base_state == "":
28 base_state = "idle"
29 var fallback_direction = str(options.get("default_direction", "down"))
30 var direction_value = entity.get("facing", entity.get("velocity", [0, 0]))
31 if options.has("direction"):
32 direction_value = options.get("direction")
33 var direction = direction_name(direction_value, fallback_direction)
34 if not bool(options.get("directional", true)):
35 return base_state
36 return "%s_%s" % [base_state, direction]
37
38
39
40func get_sprite_candidates(entity:Dictionary, options:Dictionary = {}) -> Array:
41 var candidates := []
42 var explicit = str(entity.get("sprite_id", "")).strip_edges()
43 if explicit != "":
44 candidates.append(explicit)
45 var base_id = str(options.get("base_id", entity.get("animation_id", entity.get("archetype", entity.get("id", entity.get("kind", "entity")))))).strip_edges()
46 var kind = str(entity.get("kind", entity.get("type", "entity"))).strip_edges()
47 var state_key = get_state_key(entity, options)
48 if base_id != "":
49 candidates.append("%s_%s" % [base_id, state_key])
50 var base_state = state_key.split("_")[0]
51 candidates.append("%s_%s" % [base_id, base_state])
52 if kind != "":
53 candidates.append("%s_%s" % [kind, state_key])
54 var kind_base_state = state_key.split("_")[0]
55 candidates.append("%s_%s" % [kind, kind_base_state])
56 return _unique_non_empty(candidates)
57
58
59
60func required_sprite_ids(base_id:String, states:Array = [], directions:Array = DEFAULT_DIRECTIONS) -> Array:
61 var ids := []
62 var state_list = states if not states.is_empty() else ["idle", "move", "attack", "hurt", "death"]
63 for state in state_list:
64 var state_name = str(state)
65 if state_name == "":
66 continue
67 if state_name == "death" or state_name == "hurt":
68 ids.append("%s_%s" % [base_id, state_name])
69 continue
70 for direction in directions:
71 ids.append("%s_%s_%s" % [base_id, state_name, str(direction)])
72 return _unique_non_empty(ids)
73
74
75func _unique_non_empty(values:Array) -> Array:
76 var result := []
77 for value in values:
78 var text = str(value).strip_edges()
79 if text != "" and not result.has(text):
80 result.append(text)
81 return result
82
83
84func _vector_from_any(value) -> Vector2:
85 if value is Vector2:
86 return value
87 if value is Vector2i:
88 return Vector2(float(value.x), float(value.y))
89 if value is Array and value.size() >= 2:
90 return Vector2(float(value[0]), float(value[1]))
91 if value is Dictionary and value.has("velocity"):
92 return _vector_from_any(value.get("velocity"))
93 if value is Dictionary and value.has("facing"):
94 return _vector_from_any(value.get("facing"))
95 if value is Dictionary and value.has("x") and value.has("y"):
96 return Vector2(float(value.get("x", 0.0)), float(value.get("y", 0.0)))
97 return Vector2.ZERO