Hi Jordan,
The gist beween active and passive collision types is that active will respond with a physics interaction after collision with other active or fixed types, and passive will recieve collision events but do not physically interact with other objects.
TLDR; Collision Groups don't seem to work right as you've noted I've opened an bug to fix this/re-think collision groups. I think this may have been a regression when we overhauled the collision system. There is a custom Trigger and "Group" type that can also be used for this kind of purpose.
First question:
Unfortunately, I think the documentation is incorrect. Collision groups are meant collide with other actors outside of their group. Collision groups are really meant as a tag to identify when an actor collides with another group of that tag. So ".onCollidesWith(group: string, func: (actor: Actor) => void)" is a way to register when a collision with that specific group happens.
However I don't think they are working :(
Second question:
Per your addenda, yes I do believe that addCollisionGroup and onCollidesWith aren't working as expected :( By default triggers are passive collision type to prevent them from bumping into active objects and events are definitely still thrown between these two on vanilla collision events (just not in the collision group case).
There is a simpler way to make this happen, triggers will trigger their callback when any collision happens with them. You can also specify the number of times the trigger can be triggered, in this case once. This example will fire the trigger for any active actor.
var triggerFunc = () => {
console.log("triggered")
}
var trigger1 = new ex.Trigger(200, 100, 20, 20, triggerFunc, 1);
If you want to scope the trigger to specific actors, you must extend the base trigger. I think this should do it (here is a fiddle with that in there along with the repro of the issue
https://codepen.io/eonarheim/pen/LjjeEm)
interface ITriggerOptions {
pos?: ex.Vector;
width?: number;
height?: number;
// action to take when triggered
trigger?: () => void;
// Returns true if the triggers should fire on the collided actor
filter?: (actor: ex.Actor) => boolean;
// -1 if it should repeat forever
repeat?: number;
}
class FilteredTrigger extends ex.Trigger {
public filter: (actor: ex.Actor) => boolean = () => true;
constructor(opts: ITriggerOptions ) {
super(opts.pos.x, opts.pos.y, opts.width, opts.height, opts.trigger, opts.repeat);
}
public collides(other: ex.Actor) {
if (this.filter(other)) {
return super.collides(other);
}
return null;
}
}
Additionally, there is a concept of "Groups" which can be used for this purpose. But I'd really recommend the trigger approach above or sticking to generic collision events '.on('collision', handler)' and avoiding groups in general.
var blockGroup = engine.currentScene.createGroup("blocks");
blockGroup.add(actor);
blockGroup.on('collision', function (e: ex.CollisionEvent) {
if (e.other === player) {
//console.log("collision with player!");
player.color.r += 1;
player.color.g -= 1;
player.color.b -= 1;
}
});
Hopefully this helps,
Erik