DevLog 20250722: (Special Project) Correct Physics Handling



This content originally appeared on DEV Community and was authored by Charles Zhang

Overview

This little project deals with very simple (2D) right body physics. I will not spoil all the fun – essentially we control a 2D rocket. It would be fun to visualize data processing in such a fashion on a node canvas – kind of matches our Divooka visual programming scheme.

The hypothesis is that at least for 2-dimensional cruise control, a simple PID should be able to do something useful, and it’s with that gut I am set to experiment a bit to verify my idea.

I’ve done some experiments in July last year but ended up not going far due to technical challenges.

Challenge

The challenge was to get it working properly with physics setup. Per RigidBody2D doc:

Force Doc

So is it relative or global? Without being able to visualize the force, it’s a bit hard to tell also whether to use a force, or to use impulse.

Impulse Doc

It’s been a while and I almost gave up – never really have time to create our own physics engine. But Godot got a new physics kernel and I thought maybe give it a try.

Some Inspiration

I’ve been doing some analytics and talking with ChatGPT on a new airship design that puts the air vessel at the bottom of the ship instead of hanging overhead – that inspired me maybe there are two things with current setup that’s not working:

Schema

After fixing a few API calls related to GraphEdit get_children() change. I was looking at the force application code once again:

func _physics_process(delta):   
    # Remark: We are not using to_global directly because of issues with viewport transform
    var left_anchor = %LeftThrusterCenterOfAction.position
    var right_anchor = %RightThrusterCenterOfAction.position

    # Remark: applied force is RELATIVE to the body (aka. current object)
    apply_force(Vector2(0, -1).rotated(rotation + _left_engine_angle_degrees / 180.0 * PI) * _left_engine_thrust, left_anchor)
    apply_force(Vector2(0, -1).rotated(rotation + _right_engine_angle_degrees / 180.0 * PI) * _right_engine_thrust, right_anchor)

Again, it’s really simple once we figure out what’s the right way to do things.

References


This content originally appeared on DEV Community and was authored by Charles Zhang