How to have the hitbox and character centre change when an animation is playing?

Godot Version

4.4.1

Question

Hi there,

I am making a 2d platformer game. I have this animation for my character where they perform a jumping attack. However, the translation of the character is completely done by the sprite sheet. This means its hit box and ray casts will remain in place while it does its animation.

How can i move the hitbox and other elements such that its always on top of the character?

Honestly, in my opinion, you’d be better off editing the animation so the player stays in place relatively and you use physics for the jump attack. However here’s how I did it for a slide animation:

const SLIDE = "slide"
const STANDING_COLLISON_TRANSLATION = Vector3(-1.0, 1.5, 0.0)
const SLIDING_COLLISON_TRANSLATION = Vector3(-16.0, 9.0, -72.4)

func _translate_collision_shape(translation: Vector3) -> void:
	collision_shape_2d.position.x = translation.x
	collision_shape_2d.position.y = translation.y
	collision_shape_2d.rotation_degrees = translation.z

##larger function here
		if Input.is_action_just_pressed(SLIDE):
			state = State.SLIDE
			speed = dash_speed
			_translate_collision_shape(SLIDING_COLLISON_TRANSLATION)
			slide_timer.start(slide_duration)

func _on_slide_complete() -> void:
	state = State.IDLE
	_translate_collision_shape(STANDING_COLLISON_TRANSLATION)

I got those coordinates for each frame by making the changes in the editor and recording them. I used a Vector3 simply because it can store 3 floats easily. It’s an unorthodox use so I want to make it clear.

You will have to do that for every frame of the animation which will probably require you to figure out how to track the number of frames in _physics_process and update the coords each frame. I would do something like this:

const JUMP_ATTACK = "jump_attack"
#Assuming 8 frames, which will be numbered 0-7 internally
const JUMP_ATTACK_TRANSLATIONS = [
	Vector3(-1.0, 1.5, 0.0),
	Vector3(-16.0, 9.0, -72.4),
	Vector3(-1.0, 1.5, 0.0),
	Vector3(-16.0, 9.0, -72.4),
	Vector3(-1.0, 1.5, 0.0),
	Vector3(-16.0, 9.0, -72.4),
	Vector3(-1.0, 1.5, 0.0),
	Vector3(-16.0, 9.0, -72.4)
]

var jump_attack_frame: int = 0
var is_jump_attacking := false

func _translate_collision_shape(translation: Vector3) -> void:
	collision_shape_2d.position.x = translation.x
	collision_shape_2d.position.y = translation.y
	collision_shape_2d.rotation_degrees = translation.z

func _physics_process(delta: float) -> void:
	if Input.is_action_just_pressed(JUMP_ATTACK):
		is_jump_attacking = true
		animated_sprite_2d.play("jump_attack")
	if is_jump_attacking:
		_translate_collision_shape(jump_attack_frame)
		jump_attack_frame += 1
		if jump_attack+frame >= JUMP_ATTACK_TRANSLATIONS.size():
			jump_attack_frame = 0
			is_jump_attacking = false
1 Like

To make your life easier, just center the sprites in the sprite sheet.
You can also use the Animation Player to animate collision shapes, but I wouldn’t recommend this unless for slight changes to the shape of the collision box.

1 Like