Having trouble with passive collision

55 views
Skip to first unread message

Jordan Roher

unread,
Aug 11, 2017, 1:45:40 AM8/11/17
to excaliburjs
I'm confused about collision between passive and active actors. I've got two questions, but the second one is most important.

First, a technicality:
  • The documentation for Actor.addCollisionGroup() says "Once in a collision group(s) actors will only collide with other actors in that group."
  • But Actor.onCollidesWith() says "Register a handler to fire when this actor collides with another in a specified group"
Q: How can an actor collide with a different group if they're set to only collide with members of their own group?

Second, in practice:
  • I have a Player A (derived from actor) who has active collision. She's moved around with keyboard keys.
    Player A is set to the "player" collision group using this.addCollisionGroup("player");
  • I have an Trigger T (derived from actor) who has passive collision. It's an invisible area on the map which, when Player A touches it, triggers an event.
    It's set to the "trigger" collision group using this.addCollisionGroup("trigger");
  • Player A is set to watch for collisions with trigger T using this code in a function called after Player A is constructed:
    this.onCollidesWith(CollisionGroups.Trigger, (trigger: Trigger) => {
    trigger.triggerCinematic();
    });
That onCollidesWith function is never called. I know that it should be, because when I set the Trigger class to Active collision, I can bump into it and push it around.

The documentation for the passive collision type says it only raises events, which makes me think I should have the onCollidesWith function on the Player class, right?

Q: How can I raise an event when Player A walks over Trigger T without making the Trigger class have active collision?



... addendum: I've tried setting both classes to the same collision group, but neither of them raise a collision event. I don't think passive actors raise collision events.

... addendum 2: I set both classes to active. My player bumps into it, but neither class raises a collision event. I suspect either addCollisionGroup or onCollidesWith may be malfunctioning.

Erik Onarheim

unread,
Aug 12, 2017, 11:16:54 AM8/12/17
to excal...@googlegroups.com, jor...@roher.me
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.

I've made a fiddle demonstrating the problem: https://codepen.io/eonarheim/pen/LjjeEm also have opened an issue https://github.com/excaliburjs/Excalibur/issues/862  

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

--
You received this message because you are subscribed to the Google Groups "excaliburjs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to excaliburjs+unsubscribe@googlegroups.com.
To post to this group, send email to excal...@googlegroups.com.
Visit this group at https://groups.google.com/group/excaliburjs.
To view this discussion on the web visit https://groups.google.com/d/msgid/excaliburjs/9da8080a-2819-4191-a7ca-84706b9f8965%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages