Passing layers for Physics2DShapeQueryParameters to check
Asked Answered
T

1

1

I'm currently developing a building system for my 2D top down game, and the last step is to check if there are any objects such as a tree or player obstructing the item from being placed. After doing some research I found out that using Physics2DShapeQueryParameters is the way to go. My only problem is I have no clue how to pass collision layers for it to check during the query using the .collision_layer method at line 3. Any insight is appreciated, thank you in advance!

var spaceState = get_world_2d().direct_space_state
var query = Physics2DShapeQueryParameters.new()
query.collision_layer = Layer1?????????? | Layer2????????????
var staticBody = get_node(itemName +"/StaticBody2D")
for shapeOwner in staticBody.get_shape_owners():
    var shape = staticBody.shape_owner_get_shape(shapeOwner, 0)
    shape.extents -= Vector2.ONE
    query.set_shape(shape)
    query.transform = staticBody.shapeOwner_get_owner(0).global_transform
    query.collide_with_areas = true
    var result = spaceState.intersect_shape(query,1)
    shape.extents += Vector2.ONE
    if result.size() != 0:
        canBePlaced = false
        return
canBePlaced = true
Tongs answered 17/8, 2021 at 2:25 Comment(0)
M
1

First of all, if you have an object with the collision layers you need, you can just copy it:

query.collision_layer = object.collision_layer

And for building the value, know they are powers of two:

  • Layer 1 is the first power of 2 (2 to the power of 0, which is equals to 1).
  • Layer 2 is the second power of 2 (2 to the power of 1, which is equals to 2).
  • Layer 3 is the third power of 2 (2 to the power of 2, which is equals to 4).

And so on.


All the examples below will be setting layers 6 and 8.

The following is inefficient but clear enough:

query.collision_layer = (int)pow(2, 5) + (int)pow(2, 7)

Remember that we are counting from 2 to the power of 0. So layer 6 is pow(2, 5).

This should - in theory - be more efficient (in practice, in Godot 3 GDScript, this make little difference because of the interpreter):

query.collision_layer = 1 << 5 | 1 << 7

This is bit shifting, to the left. It shift the binary representation of the value, in binary, to the left, the specified amount. The result is powers of two, working with integers. Unlike pow which works with floats.

With time, you might memorize some powers of two:

query.collision_layer = 32 | 128

Even better, we can use binary literals:

query.collision_layer = 0b100000 | 0b10000000

There you can visualize the layers. For example layer 6 is a 1 in the sixth position form the right, in binary.

Ah, that makes it easy to write the layers as a single literal:

query.collision_layer = 0b10100000

As you can see, each layer is actually an individual bit.

  • Layer 1 is the first bit (which has value of 1).
  • Layer 2 is the second bit (which has value of 2).
  • Layer 3 is the third bit (which has value of 4).

We are going from right to left, because the rightmost bit place has less value.

And so on. Just keep doubling.

Or get a list of powers of 2 online.

Until 2^31 (Layer 32) which comes as negative, because the last bit - of a 32 bit signed integer - is used to mark the sign of the number. The value is -2147483648.

You could also hover over the collision layers of a physics object in the Inspector panel, and it will tell you the bit number and value.

Morris answered 17/8, 2021 at 11:25 Comment(1)
This was really helpful, and very well explained, Thank you!Tongs

© 2022 - 2024 — McMap. All rights reserved.