Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Collision groups don't collide with self #2801

Closed
ikiselev1989 opened this issue Nov 9, 2023 · 4 comments
Closed

Collision groups don't collide with self #2801

ikiselev1989 opened this issue Nov 9, 2023 · 4 comments

Comments

@ikiselev1989
Copy link

Hi!
There is not clear for me about collision groups.
I use this code from docs. And it's not working as I expect.
code

import { Engine, CollisionGroupManager, CollisionGroup} from 'excalibur';

const engine = new Engine({
  width: 600,
  height: 400,
});

engine.start();

const playersGroup = CollisionGroupManager.create('player')
const npcGroup = CollisionGroupManager.create('npcGroup')
const floorGroup = CollisionGroupManager.create('floorGroup')
const enemyGroup = CollisionGroupManager.create('enemyGroup')

// Define your rules
const playersCanCollideWith = CollisionGroup.collidesWith([
  playersGroup, // collide with other players
  floorGroup, // collide with the floor
  enemyGroup, // collide with enemies
])

console.log(playersGroup.canCollide(playersGroup)) // should be true?
console.log(playersCanCollideWith.canCollide(playersCanCollideWith)) // should be true?
@eonarheim
Copy link
Member

@ikiselev1989 This is a great question!

Generally speaking collision groups do not collide with themselves, except for the special built-in group called CollisionGroup.All

In your example the group playersCanCollideWith does collide with the playersGroup, floorGroup, and enemyGroup

console.log(playersCanCollideWith.canCollide(playersGroup)); // true
console.log(playersCanCollideWith.canCollide(floorGroup)); // true
console.log(playersCanCollideWith.canCollide(enemyGroup)); // true

A way to think about collision groups is as different "categories" (other engines like Unity call collision groups "layers"). Each group is represented by a 32 bit integer represented by a power of 2. CollisionGroupManager works by assigning a unique power of 2 to each group (meaning only 32 groups are possible).

So the groups in binary in your example are:

playersGroup = 0b0001
npcGroup     = 0b0010
floorGroup   = 0b0100
enemyGroup   = 0b1000

Each group also contains a mask, this mask has the bit position of the groups it can collided with set to 1. The player group is the least significant bit (furthest right) if a mask has that bit set to 1 it means it collides with the player group.

By default the mask for a collision group is set to collide with every group apart from itself.

playersGroupMask = 0b11111111_11111111_11111111_11111110
npcGroupMask     = 0b11111111_11111111_11111111_11111101
floorGroupMask   = 0b11111111_11111111_11111111_11111011
enemyGroupMask   = 0b11111111_11111111_11111111_11110111

The canCollide logic basically performs a bitwise AND between the group and the target layer's mask, so if we say playersGroup.canCollide(playersGroup) that is 0b0001 & 0b11111111_11111111_11111111_11111110 = 0 meaning they can't collide.

The CollisionGroup.collidesWith(...) helper makes a new group that is all of the categories OR'd together then invertedSo in the example above creating the const playersCanCollideWith = CollisionGroup.collidesWith([ playersGroup, floorGroup, enemyGroup, ]) group

playersCanCollideWith = ~(0b0001 | 0b0100 | 0b1000) = 0b0010
playersCanCollideWithMask = ~(0b0010) = 0b11111111_11111111_11111111_11111101

Notice the final group is actually equivalent to the npcGroup, which has the mask bits set for player, floor, and enemy. This means playersCanCollideWith can collide with player, floor, and enemy.

Apologies for the long explanation, hopefully that makes sense.

Documentation/API Question

I'll endeavor to improve the documentation here, and perhaps Excalibur needs to think about the API because it causes confusion. Perhaps we should rename the type CollisionGroup to something like CollisionLayer or maybe retool the API to provide more clarity? Open to suggestions! @jedeen @kamranayub @alanag13 Thoughts?

@eonarheim
Copy link
Member

@ikiselev1989 I've updated the docs with a more thorough explaination https://excaliburjs.com/docs/collisiongroups/

The team also spoke offline and we are potentially renaming this feature to CollisionFilter

@ikiselev1989
Copy link
Author

Thanks a lot for your answer! Will deep into docs =)

@eonarheim
Copy link
Member

Going to close this for now! Let me know if you have any other issues!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants