animationgame-developmentgame-enginegodottween

I am a newbie who wants to make a game


I started my game dev journey in Godot. I have an issue, I am making a Google Dino / Geometry Dash lookalike game that includes a flat surface (for now), color gates (checkpoints in red, green and blue) and a player who is a triangle.

On user input (LMB or SPACEBAR at the moment), the triangle should rotate -120 degrees landing on a specific color so it can pass through the oncoming 'color checkpoint'.

I started with AnimationPlayer but have switched to Tweens as I figured out they should give me more control over the animation. The issue is that the pivot point doesn't change after the first rotation but rather goes 'below' the imaginary surface and that's it meaning on 4 inputs it completes a rotation around the original pivot point. The entire code in GDScript for Player is down below. Also, on every animation input it seems to 'artificially' moves slightly backwards which makes no sense. I am new to this and really have no idea what I am doing or how to fix it. I spent hours troubleshooting it and still haven't moved on to actually making the background surface and the color checkpoints.

enter image description here

extends CharacterBody2D

var tween: Tween
var side_length = 50  
var rotation_angle = -120  
var current_rotation = 0  

func _input(event):
    if event is InputEventKey and event.pressed and event.keycode == KEY_SPACE:
        start_roll()

    if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
        start_roll()

func start_roll():
    if tween and tween.is_running():
        return  

    
    current_rotation += rotation_angle

    
    var pivot_offset = Vector2(-side_length / 2, side_length * sqrt(3) / 6)
    var pivot_point = position + pivot_offset.rotated(deg_to_rad(current_rotation - rotation_angle))

    
    var new_pivot_offset = pivot_offset.rotated(deg_to_rad(current_rotation))
    var new_position = pivot_point - new_pivot_offset

    
    tween = create_tween()
    tween.set_parallel(true) 

    
    tween.tween_property(self, "rotation_degrees", current_rotation, 0.5) \
        .set_trans(Tween.TRANS_SINE) \
        .set_ease(Tween.EASE_IN_OUT)

    
    tween.tween_property(self, "position", new_position, 0.5) \
        .set_trans(Tween.TRANS_SINE) \
        .set_ease(Tween.EASE_IN_OUT)
 

    tween.tween_property(self, "position", new_position, 0.5) \
        .set_trans(Tween.TRANS_SINE) \
        .set_ease(Tween.EASE_IN_OUT)

Solution

  • I solved the issue by doing it via AnimationPlayer node.

    First, add AnimationPlayer as a child of your Player node. Next, configure it (quick note you will need another Node2D as a child of Player to act as a pivot/rotation point if that's what you need.) by keyframing both position and rotation (in my case, first rotation happens followed by position i.e. player moving back into original position after rotation).

    And that's it! Obviously due to more complexity and unique mechanics of my game, I also had Player code that dealt with 'correct' side on the ground and to make sure animation can't be triggered by user input while it's still in motion.

    In my case specifically, I also had an issue where first rotation would 'double' meaning triangle doing 240 degrees instead of 120 but luckily I solved this by adding this:

    func _ready() -> void:
        Animation_Player.play("rotation")
        pass