Need Help with Timer Not Acting Properly

Version 4.2.2

Hi everyone, I am following the official 2D game tutorial on the Godot website using GDScript in the latest public version, and I had to alter the code somewhat from the original example to fit the game I am making - a Flappy Bird inspired game with my own characters and settings.

I followed the part that explains how to add timers later on after adding your player code, but for some strange reason the bird jumping doesn’t work after I added a timer to ensure you couldn’t spam the jump constantly, even though the condition is true when you first start, namely that the jumpertimedout is set to 1 at the start of the program, which is what the condition is told to check for specifically in addition to having pressed the jump key.

The example I have shown for everyone with Godot 4.2.2 downloaded is:

Link to My Game Being Developed

I figured it out - the code was right, I was just using too small a number - now I am figuring out how to make it glide up smoothly rather than just teleport up instantly.

Okay, I tried using the “move_toward” method given in this tutorial, but unfortunately it didn’t work at all, even though I made sure to set everything up correctly to the best of my ability.

The link to the latest version of my game is still in my very first post, because I just simply update the link as I add and remove code.

move_toward increases the value by the delta parameter, without going over. In your code this line is moving the bird by 1 pixel toward their starting position, 1 pixel is that last parameter.

$AnimatedSprite2D.position = $AnimatedSprite2D.position.move_toward(jumpposition,1)

Since you want a animation over time, you would have to repeat this move_toward function every frame. However I would recommend using a Tween!

if (Input.is_action_pressed("jump") and jumptimertimedout == 1):
	var jump_tween := create_tween()
	jump_tween.tween_property(self, "position", jumpposition, 1.0).set_trans(Tween.TRANS_QUAD)
	jumptimertimedout = 0
	await jump_tween.finished
	jumptimertimedout = 1

You will want to tweak the parameters. In this example jumpposition is the end value, I would recommend using position + a upward vector of jump height. 1.0 is how long the tween takes, a much shorter time will look and feel better.

These parameters may be a better starting point.

jump_tween.tween_property(self, "position", position + Vector2(0, -100), 0.2).set_trans(Tween.TRANS_QUAD)

Thank you so much for the solution!

1 Like

Unfortunately, after following the directions exactly, it only works exactly one time and then never again - do you know how to correct that?

Maybe jumptimertimedout is being declared a float. Floats (any decimal number) are very very bad at comparing equality.

It’s good to add types to all your variables, especially if you are not intializing them. Here the types as I would add them.

@export var speed: float = 400 # how fast the player will move in pixels per second.
var screen_size: Vector2 # size of the game window.
var jumptimertimedout: int
var jumpposition: Vector2

Of course you could declare it a boolean too, which would make a little more sense

var jumptimertimedout: bool = true

# used like so
if (Input.is_action_pressed("jump") and jumptimertimedout):
	var jump_tween := create_tween()
	jump_tween.tween_property(self, "position", jumpposition, 1.0).set_trans(Tween.TRANS_QUAD)
	jumptimertimedout = false
	await jump_tween.finished
	jumptimertimedout = true

Thank you so much for this as well!

Unfortunately, it still does it exactly one time after I have implemented this fix - what the heck else is going on?

Even without the type declarations I do not have a single-jump issue. Did you change anything else in your project before putting it online?

That is so weird - I will upload my project with how it is on my end again, and the download is at the top per usual.

It’s uploaded now.

Two issues. The comparison is unecessary, booleans are what if statements look for. If you want to compare jumptimertimedout then it should be against true instead of false

	# compare == true or remove this to just `jumptimertimedout`
	if (Input.is_action_pressed("jump") and jumptimertimedout == false):
		var jump_tween := create_tween()
		jump_tween.tween_property(self, "position", jumpposition, 0.5).set_trans(Tween.TRANS_QUAD)
		jumptimertimedout = false
		await jump_tween.finished
		jumptimertimedout = true

		position = position.clamp(Vector2.ZERO, screen_size)

And jumptimertimedout should be initialied to true so you can jump at the start.

Seems like the downward movement was removed too.

Okay, now it works correctly, and I figured out part of the problem is that the tween transitions through midway through the height rather than the full height to the top, so I will figure out some way to fix that.

However, everything else works 100% correctly, like the tweening now works infinitely as far as I can tell rather than just only once, and after I re-added the change the position y by down 2 pixels it works correctly again.

I know why it does that - it’s because the jump position is declared only once at the beginning of the code, rather than continously being updated as the player’s position changes, so I fixed that and it works perfectly now.


I have added obstacle movement because I want it to be a side-scroller, using the way the tutorial explains how to add an enemy/obstacle (so using RigidBody2D and not Area2D, as that is how the official tutorial does it), but even though moving the obstacle to the right works flawlessly, moving it to the left looks very jittery rather than playing the animation smoothly like normal.

I have uploaded the version with the bug/glitch to the first post, per usual.

Do you guys think it might be because it’s registering incorrectly that it is off screen when it moves to the left of the starting position?

The rabbit also disappears when it hits the old position before the obstacle moved, but I will fix that problem later and just want to focus on the fact the obstacle doesn’t move properly to the left.

A RigidBody2D is a physics controlled Node, unless you freeze it (and even then some), the RigidBody2D will act according to physics and fight your scripts. I’m certain an Area2D would work better in your case.

Awesome idea!

Thank you for that!

I figured that was the appropriate solution/alternative way of doing it from how the manual states it exactly, because the player is already an Area2D, but wasn’t sure if that would work or not because of how specific the tutorial is about that detail.