0 votes

Hello friends, I'd like to receive some help:
Somehow the way godot is counting the pixels is way off.
I have this object of10px wide 42px height, that has a rectangle2D as a collisionbox with extents of 5,21...
Based on a tutorial series on slope detection with unity I stated coding my own for Godot, this includes a system that generates raycast on specific sides of an object. You just have to tell the script you want "n" rays and it will take care of putting then evenly on the side.
Everything ok, with the setup I believe. But the raycast and also the drawline() I shot through code are off, taking double the space visually. I tweaked and changed the rectangle to make it wider for testing purposes and it simply continued the wrong pattern.
enter image description here
enter image description here
The main problem is that if I look at the prints the value it is giving me is not wrong at all... For an example, on the screenshot I set 3 rays, one will be at the bottom-left corner, other in the middle and the last on the bottom right corner, all with the same distance from one-another. The same happens if with whatever number I tested: It distributes then on the width of the box evenly and within the limits if you look at the prints, yet for the engine it looks like it has double the ammount of space to use for distribution of the rays.

To illustrate a little more, here I put 5 rays:
enter image description here

The code is as follow:

func corner(skin=false):
    var extent = get_node("CollisionShape2D").get_shape().get_extents()
    var corners = {
        "top_left": get_global_pos()-extent,
        "top_right": get_global_pos()+Vector2(extent.x,-extent.y),
        "bottom_left": get_global_pos()+Vector2(-extent.x,extent.y),
        "bottom_right": get_global_pos()+ extent
    }
    if skin:
        corners.top_left +=Vector2(SKIN_SIZE,SKIN_SIZE)
        corners.top_right +=Vector2(-SKIN_SIZE,SKIN_SIZE)
        corners.bottom_left +=Vector2(SKIN_SIZE,-SKIN_SIZE)
        corners.bottom_right +=Vector2(-SKIN_SIZE,-SKIN_SIZE)
    return corners

func calculate_ray_spacing():
    var extent = get_node("CollisionShape2D").get_shape().get_extents()*2
    print("EXTENT VALUE: ",extent)
    horizontal_raycast = clamp(horizontal_raycast,2,100)
    vertical_raycast = clamp(vertical_raycast,2,100)

    horizontal_ray_spacing = float(extent.y / (horizontal_raycast-1))
    vertical_ray_spacing = float(extent.x / (vertical_raycast-1))
    print("Vertical ray space: ", vertical_ray_spacing)

func vertical_collision():
    # Get the direction the character is moving to create the rays:
    var directionY = sign(velocity.y)
    var rayLenght = abs(velocity.y) + SKIN_SIZE
#   print("ray_Lenght: ", rayLenght)
    for i in range(vertical_raycast):
        var raycast_origin
        #If moving up, set the origin to the top_left point of the actor
        if directionY < 0:
            raycast_origin = corner(true).top_left

        #If moving down set the origin to the bottom_left point of the actor:
        else:
            raycast_origin = corner(true).bottom_left
#           print ("POSITION: ", get_global_pos())
        print("---------------\nRaycast Vertical count: ",vertical_raycast)
        print ("RAYCAST ORIGIN: ",raycast_origin)
        print("Bottom right: ",corner().bottom_right)
#   
        print("VERTICAL RAY SPACING: ",vertical_ray_spacing)
        raycast_origin+= Vector2(1,0)*((vertical_ray_spacing*i)+velocity.x)
        print("RAYCAST ORIGIN AFTER LOOP ", i," ", raycast_origin)
        var hit = space.intersect_ray(Vector2(raycast_origin.x+(vertical_ray_spacing*i),raycast_origin.y),Vector2(raycast_origin.x+(vertical_ray_spacing*i),raycast_origin.y +(directionY*rayLenght)),[self],rcollision_layer_mask)
        if hit.size():
            var object = mark_scn.instance()
            get_parent().add_child(object)
            object.set_global_pos(Vector2(raycast_origin.x+(vertical_ray_spacing*i),raycast_origin.y +(directionY*rayLenght)))
            print("Origin of ray ",str(i),": ",Vector2(raycast_origin.x+(vertical_ray_spacing*i),raycast_origin.y +(directionY*rayLenght)),"Position of collision of ray ", i,": ", Vector2(raycast_origin.x+(vertical_ray_spacing*i),raycast_origin.y +(directionY*rayLenght)) )
            print("Corner bottom right: ", corner(true).bottom_right)
#           
#           print("COLIDED!")
            var distanceY = abs((hit.position.y - raycast_origin.y))
#           print("Distance",distanceY)
            velocity.y = (distanceY-SKIN_SIZE)*directionY
            rayLenght = distanceY

The link for the project:
https://dl.dropboxusercontent.com/u/11321796/Godot/test-slope.zip

in Engine by (233 points)

1 Answer

0 votes
Best answer

So, thanks to a friend I managed to see the error, the problem was that I was assigning a value on the loop with raycast_origin+= Vector2(1,0)*((vertical_ray_spacing*i)+velocity.x)*directionY and also assigning it again on the line bellow:

var hit = space.intersect_ray(Vector2(raycast_origin.x+(vertical_ray_spacing*i),raycast_origin.y),Vector2(raycast_origin.x+(vertical_ray_spacing*i),raycast_origin.y +(directionY*rayLenght)),[self],rcollision_layer_mask)

The right way, would be:

var hit = space.intersect_ray(raycast_origin,Vector2(raycast_origin.x,raycast_origin.y +(directionY*rayLenght)),[self],rcollision_layer_mask)

Since after I created the code, I just copy-and-pasted it, this error kept its consistency at the draw_line method too, so not only visually I was getting this bug, but also on the collision detection.

A big thanks to MarianoRGD, as he spoted the problem after some minutes looking at the code.

by (233 points)
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 Frequently asked questions and 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 [email protected] with your username.