0 votes

So i've started a new game project that has an oldschool 3d dungeoncrawler map.
Made dungeon with gridmap all fine.

Now i want to make playermovement in set steps. Everytime the player hits
a button he moves to the next cell in the grid. The movement is also supposed to be
smooth so i interpolate the movement.

This is the code i have so far for forward movement and left turn:

extends KinematicBody

var t = 0.0
var forwardFlag
var leftTurnFlag

var playerPoint = self.transform
var forwardPoint = self.transform
var leftTurnPoint = self.transform

func _ready():
    #changing target points for later interpolation
    forwardPoint.origin += Vector3(0,0,-2)
    leftTurnPoint = leftTurnPoint.rotated(Vector3(0,1,0), deg2rad(90))
    leftTurnPoint = leftTurnPoint.orthonormalized()

    print(self.transform)
    print(leftTurnPoint)

func _physics_process(delta):
    if Input.is_action_just_pressed("forward"):
        forwardFlag = true

    if Input.is_action_just_pressed("left"):
        leftTurnFlag = true

    if forwardFlag:
        t += delta
        self.transform = self.transform.interpolate_with(forwardPoint,t)
        print(self.transform.basis)
        print(forwardPoint.basis)


        if self.transform == forwardPoint:
            forwardFlag = false
            #update coresponding Point
            forwardPoint.origin += Vector3(0,0,-2)
            #reset t for interpolation speed
            t = 0

    if leftTurnFlag:
        t += delta

        self.transform = self.transform.interpolate_with(leftTurnPoint,t)

        print(self.transform.basis)
        print(leftTurnPoint.basis)      


        if self.transform == leftTurnPoint:
            leftTurnFlag = false
            #update coresponding Point
            leftTurnPoint = leftTurnPoint.rotated(Vector3(0,1,0), deg2rad(90))
            leftTurnPoint = leftTurnPoint.orthonormalized()
            print(self.transform)
            print(leftTurnPoint)
            #reset t for interpolation speed
            t = 0

The forward movement works fine and dandy but for the rotation there comes up this problem:
When i print out each transform.basis values:
player: ((0, 0, 1), (0, 1, 0), (-1, 0, 0))
target: ((-0, 0, 1), (0, 1, 0), (-1, 0, -0))

the check if the interpolation is done isnt possible because the target.basis has -0 values.
The big question now is: Why?
Is there a reason why we have 0 and -0 values in these Datatypes?
And if this is by design and important is there:
a) a better way to accomplish my goal
or b) a more efficient way to test the end of interpolation than to go through the
target.basis and reset each -0 to 0 each time

Thanks a lot for anyone that can help with this.

in Engine by (16 points)

1 Answer

0 votes

The problem here is that you try to compare floating point values for equality.
As you can read here (for details), this doesn't work properly by simply using ==:
https://floating-point-gui.de/errors/comparison/

I looked at Basis and found the function is_equal_approx(otherbasis).
https://docs.godotengine.org/en/3.1/classes/class_basis.html#class-basis-method-is-equal-approx

It is undocumented but by its naming that should be the comparison function you search for.

(Just for information:) Looking in the godot code, this function actually tests Math::isequalapprox for all 9 values in the Basis. This is the function in math_funcs.h:

static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b) {
    real_t tolerance = CMP_EPSILON * abs(a);
    if (tolerance < CMP_EPSILON) {
        tolerance = CMP_EPSILON;
    }
    return abs(a - b) < tolerance;
}

static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b, real_t tolerance) {
    return abs(a - b) < tolerance;
}
by (3,240 points)

Thanks for the help.

though when i use the basis.isequalapprox in my code it still
gives only false value back. I rewrote the check in my own code checking
for all 9 values and eventually got it working fine.

Can you send me a link to the sourcecode of this function? Cause i have no
idea how to find a specific function in the sourcecode.

thanks for the help :3

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.