How to limit rotation on a RigidBody2D?
Asked Answered
P

2

1

Currently I am making a clone of the game Flappy Bird for practice. I am representing the bird as a RigidBody2D.

extends RigidBody2D

func _ready():
    pass

func _input(event):
    if Input.is_action_just_pressed("input_action_flap"):
        bird_flap()

func _physics_process(delta):
    print(self.rotation_degrees)
    
    self.rotation_degrees = -45
    
    print(self.rotation_degrees)
    
func bird_flap():
    var des_linear_velocity_x : float = get_linear_velocity().x
    var des_linear_velocity_y : float = -750
    var des_angular_velocity  : float = -3
    
    set_linear_velocity(Vector2(des_linear_velocity_x, des_linear_velocity_y))
    set_angular_velocity(des_angular_velocity)

I am playing around with ways to limit the possible rotation of the Node. However, I am running into some issues.

-135.234329
-45
-137.498474
-45
-139.724884
-45
-141.914169
-45
-144.066986
-45
-146.183914
-45
-148.265564
-45
-150.312515
-45
-152.325363
-45

The values of the rotation seem to be flickering wildly due to Godot's built-in physics engine. And when I try to use the method clamp(...) - I subsequently experience wild flickering of my character sprite's rotation.

self.rotation = clamp(self.rotation, deg2rad(-45), deg2rad(+45))

Does anyone know how to fix this?

Parallelogram answered 18/8, 2020 at 3:14 Comment(0)
L
2

Directly altering the state of a physics body often needs to be done in the _integrate_forces method instead of the process methods. (see Note toward the top: RigidBody2D documentation)

Here I'm creating and setting a new transform.

func _integrate_forces(state):
    var rotation_radians = deg2rad(rotation_degrees)
    var new_rotation = clamp(rotation_radians, -0.78, 0.78)
    var new_transform = Transform2D(new_rotation, position)
    state.transform = new_transform

Remember that angular_velocity is still being applied though, which will cause your body to "stick" to max/min rotation. You can fix this by tuning angular_damp in the editor or manually changing your angular_velocity in code whenever you hit the target rotation_degrees.

Lath answered 18/8, 2020 at 21:16 Comment(5)
Do you happen to know the frequency that _integrate_forces(...) is called? I am weary of using it without a proper understanding of when exactly the method is run...Parallelogram
It runs each physics frame, which can be changed in your project settings and defaults to 60. docs.godotengine.org/en/stable/tutorials/physics/… The "Physics process callback" and "Using Rigidbody2D" sections of this documentation give some piecemeal information on it. The documentation could definitely stand to be more explicit. Important to note though. Putting a physics body to sleep will stop callbacks on integrate_forces.Lath
If I am interpreting this correctly, then _physics_process(...) and _integrate_forces(...) are more or less equal in every way (except for the aforementioned caveat regarding RigidBody2D, of course). Even when putting a physics body to sleep, both methods stop being called together. Is there even any substantial difference worth mentioning?Parallelogram
It's the only way to directly access the body's physics state. The process functions only give you delta between calls.Lath
@Parallelogram it looks like this answer lead you to solving the problem. Shouldn't you accept it?Springhead
S
1

Under the Deactivation dropdown, tick Lock Rotation

enter image description here

Skipton answered 24/12, 2023 at 14:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.