feat: Implement Phase 16 - Move To: Walk and Run
- Introduced a new action type `move_to` allowing children to direct a stickman to a destination using either Walk or Run styles. - Updated the ActionEditor UI to include Walk/Run buttons for selecting movement styles. - Ensured compatibility with existing `walk_to` actions by converting them to the new `move_to` format during loading. - Defined clear success criteria for the implementation, including distinct movement animations and behavior for both Walk and Run. - Established a comprehensive verification contract to ensure functionality across various terrains and scenarios.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
@tool
|
||||
extends EditorScript
|
||||
|
||||
## Unified animation generator: bakes walk_left, walk_right and stand_up into
|
||||
## Unified animation generator: bakes walk_left, walk_right, run_right and stand_up into
|
||||
## the open scene's AnimationPlayer. Supersedes the old create_walk.gd.
|
||||
##
|
||||
## Note: runtime ragdoll recovery does NOT play the baked stand_up — StickmanRig
|
||||
@@ -10,6 +10,7 @@ extends EditorScript
|
||||
## baked stand_up is kept as an authored reference / manual-play animation.
|
||||
|
||||
const STAND_UP_DURATION := 2.0
|
||||
const RUN_ANIMATION_DURATION := 0.75
|
||||
|
||||
## IK target marker node paths (relative to the rig root), keyed by marker name.
|
||||
const POSE_PATHS: Dictionary = {
|
||||
@@ -58,9 +59,11 @@ func _run() -> void:
|
||||
push_error("EditorScript: AnimationPlayer node not found under root.")
|
||||
return
|
||||
|
||||
_generate_walk_animation(anim_player, "walk_right", false)
|
||||
_generate_walk_animation(anim_player, "walk_left", true)
|
||||
_generate_pose_animation(anim_player, "stand_up", STAND_UP_DURATION, POSE_DOWN, POSE_STANDING)
|
||||
_generate_run_in_place_animation(anim_player, "run_in_place", false)
|
||||
_generate_run_in_place_animation(anim_player, "run_right", false)
|
||||
#_generate_walk_animation(anim_player, "walk_right", false)
|
||||
#_generate_walk_animation(anim_player, "walk_left", true)
|
||||
#_generate_pose_animation(anim_player, "stand_up", STAND_UP_DURATION, POSE_DOWN, POSE_STANDING)
|
||||
|
||||
|
||||
func _generate_walk_animation(anim_player: AnimationPlayer, anim_name: String, flip_x: bool) -> void:
|
||||
@@ -132,3 +135,53 @@ func _add_animation(anim_player: AnimationPlayer, anim_name: String, anim: Anima
|
||||
|
||||
lib.add_animation(anim_name, anim)
|
||||
print("Successfully generated '%s' animation!" % anim_name)
|
||||
|
||||
|
||||
func _generate_run_in_place_animation(anim_player: AnimationPlayer, anim_name: String, flip_x: bool = false) -> void:
|
||||
var anim = Animation.new()
|
||||
anim.length = RUN_ANIMATION_DURATION
|
||||
anim.loop_mode = Animation.LOOP_LINEAR
|
||||
var dir_mult: float = -1.0 if flip_x else 1.0
|
||||
|
||||
# Contact, down, break, and up poses with arms counter-swinging against the legs.
|
||||
var raw_tracks = {
|
||||
"IK_Targets/Torso:position": [
|
||||
Vector2(0, 15), Vector2(0, -30), Vector2(0, 15), Vector2(0, -30), Vector2(0, 15)
|
||||
],
|
||||
"IK_Targets/Torso:rotation": [0.30, 0.36, 0.28, 0.20, 0.30],
|
||||
"IK_Targets/Head:position": [
|
||||
Vector2(100, -605), Vector2(100, -642), Vector2(100, -605), Vector2(100, -642), Vector2(100, -605)
|
||||
],
|
||||
"AnimationTargets/Right_Leg_Base:position": [
|
||||
Vector2(80, 390), Vector2(-120, 290), Vector2(-80, 260), Vector2(110, 240), Vector2(80, 390)
|
||||
],
|
||||
"AnimationTargets/Left_Leg_Base:position": [
|
||||
Vector2(-80, 260), Vector2(110, 240), Vector2(80, 390), Vector2(-120, 290), Vector2(-80, 260)
|
||||
],
|
||||
"IK_Targets/Right_Hand:position": [
|
||||
Vector2(-250, -205), Vector2(-167, -40), Vector2(35, 0), Vector2(237, -40),
|
||||
Vector2(320, -225), Vector2(237, -35), Vector2(35, 15), Vector2(-167, -35), Vector2(-250, -205)
|
||||
],
|
||||
"IK_Targets/Left_Hand:position": [
|
||||
Vector2(320, -225), Vector2(237, -30), Vector2(55, 15), Vector2(-167, -35),
|
||||
Vector2(-250, -205), Vector2(-167, -40), Vector2(55, 0), Vector2(237, -40), Vector2(320, -225)
|
||||
]
|
||||
}
|
||||
|
||||
var times = [0.0, 0.1875, 0.375, 0.5625, RUN_ANIMATION_DURATION]
|
||||
var arm_times = [0.0, 0.09375, 0.1875, 0.28125, 0.375, 0.46875, 0.5625, 0.65625, RUN_ANIMATION_DURATION]
|
||||
|
||||
for path in raw_tracks:
|
||||
var track_idx = anim.add_track(Animation.TYPE_VALUE)
|
||||
anim.track_set_path(track_idx, path)
|
||||
anim.track_set_interpolation_type(track_idx, Animation.INTERPOLATION_CUBIC)
|
||||
anim.track_set_interpolation_loop_wrap(track_idx, true)
|
||||
|
||||
var key_times: Array = arm_times if path.ends_with("_Hand:position") else times
|
||||
for i in range(raw_tracks[path].size()):
|
||||
var value: Variant = raw_tracks[path][i]
|
||||
if value is Vector2:
|
||||
value = Vector2(value.x * dir_mult, value.y)
|
||||
anim.track_insert_key(track_idx, key_times[i], value)
|
||||
|
||||
_add_animation(anim_player, anim_name, anim)
|
||||
|
||||
Reference in New Issue
Block a user