hexus / phaser-arcade-slopes

:triangular_ruler: A Phaser CE plugin that brings sloped tile collision handling to the Arcade Physics engine
MIT License
126 stars 16 forks source link

False Collisions #14

Closed IkonOne closed 7 years ago

IkonOne commented 7 years ago

falsecollision

As seen in the example gif, the cowboy looking thing is moving at x speed and once it hits the corner, it is stopped and begins accelerating again. The expected behavior would be for it to continue without 'catching' the corner.

I haven't investigated the cause yet.

hexus commented 7 years ago

Does this not occur with the plugin disabled?

From a glance it might be because the plugin isn't really checking whether the body is moving into the tile on each axis, it's just checking for the shortest separating axis.

Depending on where your body ends up in the tile, it could affect separation and velocity differently, but I have indeed observed this problem myself and it bothers me, so it's something I will endeavour to fix.

Pure arcade physics works differently in the sense that it checks one axis before another, but SAT isn't quite the same.

IkonOne commented 7 years ago

No it doesn't happen without the plugin.

That was what I suspected the cause was. I'll get a pull request in later today once I get a test project up.

hexus commented 7 years ago

Cool, I'd be happy to look into a solution at some point. I think gravity that's higher than the player's X velocity is a good way to reproduce this.

IkonOne commented 7 years ago

This bit of code fixes the issue:

if (response.overlapN.x * body.velocity.x + response.overlapN.y * body.velocity.y < 0) {
    return false;
}

Placed hereish:

https://github.com/hexus/phaser-arcade-slopes/blob/master/src/ArcadeSlopes/SatSolver.js#L613

All this is doing is checking the sign of the dot product of overlapN and velocity. A negative value means that the vectors are pointing opposite directions. There could be fringe cases where this breaks though.

hexus commented 7 years ago

Yeah, I actually considered keeping this check at one point, as I'd observed the same check in Metanet's code, but left it out for some reason.

I'll implement this properly soon using the SAT vectors. Thanks for looking into this. :+1:

IkonOne commented 7 years ago

I saw you left a TODO for it somewhere in your code actually.

hexus commented 7 years ago

Ah, sounds like something I'd do. :full_moon_with_face: There's always something for me TODO.

hexus commented 7 years ago

Weird, applying that change breaks collisions for me. Using > 0 instead fixes collisions again, though I haven't verified if this still fixes your issue. This is most likely because I invert the overlap vectors for convenience.

if (response.overlapN.dot(body.slopes.velocity) > 0) {
    return false;
}

Does this snippet in the same location work for your use case?

Edit:

Actually, I've noticed this does cause a lot of issues elsewhere unfortunately - slipping through tiles in rather strange ways. Unfortunate, because I thought this had also solved a similar issue I'd noticed when travelling past corners of sloped tiles.

Even inverting the overlap vector back will exhibit the same issue:

if (response.overlapN.clone().scale(-1).dot(body.slopes.velocity) < 0) {
    return false;
}

Edit 2:

It does work with body.velocity instead of body.slopes.velocity, the latter of which isn't up to date at that point. Nice.

hexus commented 7 years ago

Hopefully the above commit should solve the issue now. :grin: :+1:

IkonOne commented 7 years ago

Yes this works great.

I would push back on the clone though. I think allocating memory for a single check is less than ideal.

hexus commented 7 years ago

Yeah, I totally agree. While it keeps the code "looking cleaner" I'm totally aware of the implication of cloning, which I do all over the place at the moment (sometimes unavoidably).

I'm planning to sweep the whole module for instantiations like this, among other things, for v0.3.0.