Crafty icon indicating copy to clipboard operation
Crafty copied to clipboard

Documentation for hit function leads to 'too many recursion"

Open mitija opened this issue 7 years ago • 2 comments

The documentation for the hit function (http://craftyjs.com/api/Collision.html#-hit) provides an example, which I have found may lead to the game entering an infinite recursion if two events are triggered at the same time.

Here is a fix (on a simplified example):

Crafty.e('2D, DOM, Color, Fourway, Collision')
    .attr({ x:0, y:0, w:32, h:32})
    .color('#F00')
    .fourway()
    .bind('Move', function(evt) {
        if (this.hit('wall')) {
            this.x = this.lastOKPosition.x;
            this.y = this.lastOKPosition.y;
        }
        else {
            this.lastOKPosition = {x: this.x, y: this.y};
        }
    });

This relies on the last know OK position, instead of the event position which may also be in collision with 'wall'. I suggest updating the official documentation so that people don't get stuck with this bug.

For information I am working with Firefox

mitija avatar Jun 30 '18 06:06 mitija

So the issue is this block?

if (hitData.type === 'SAT') { // SAT, advanced collision resolution
  // move player back by amount of overlap
  this.x -= hitData.overlap * hitData.nx;
  this.y -= hitData.overlap * hitData.ny;
} 

Where backing out the entity by just the amount necessary to end the first collision can cause a second collision?

starwed avatar Jun 30 '18 15:06 starwed

No I haven't tried the hitData of type SAT. I have only tried MBR. The issue is with this code:

{ // MBR, simple collision resolution
            // move player to previous position
            this.x = evt._x;
            this.y = evt._y;
}

From what I understand, I got the error when I was pressing both key 'arrow down' and 'arrow left' at the same time, while my entity was just above another item of type wall.

This triggered twice the 'Move' event, one for the key down - which would place the entity one down inside the wall in x0, y0+1, and then one for the key left which would position the entity to x0-1, y0+1. When Crafty would handle the second event, it would position back the entity to x0, y0+1, which is still within the wall; hence the infinite loop. I hope it's clear!

The code which causes the infinite loop is this one:

Crafty.init(500,350, document.getElementById('game'));
Crafty.e('2D, DOM, Color, Fourway, Collision')
    .attr({ x:0, y:0, w:32, h:32})
    .color('#F00')
    .fourway()
    .bind('Move', function(evt) {
        if (this.hit('wall')) {
            this.x = evt._x;
            this.y = evt._y;
        }
    });

Crafty.e('2D, DOM, Color, wall')
    .attr({ x: 200, y:200, w: 100, h:20 })
    .color('#555');

If you run it, you can trigger the bug by hitting the wall while pressing both 'down' and 'left' arrows keys at the same time.

mitija avatar Jul 01 '18 06:07 mitija