0

I'm trying to simulate perfect elastic collision between 3 blocks. The two on the edges have a way greater mass than the one in the center. Let's call the heavier ones h1 and h2, and the lighter l1. When they get to a position when l1 is the only thing separating the h1 and h2, l1 kind of bounces off of one of them, but then enters in the other, and it either has already checked for collisions between them or he detects the collision and gets back inside the other. I don't know how to explain it in a better way, sorry. Here's a portion of my code:

detectCollisions = function() {
    var left1 = this.x;
    var right1 = left1 + this.width;
    for (var j = 0; j < collidingThings.length; j++) {
        if (collidingThings[j] == this) continue;
        var left2 = collidingThings[j].x;
        var right2 = left2 + collidingThings[j].width;
        if (right1 > left2 && right2 > left1) {
            this.collide(collidingThings[j]);
        }
    }
}

I'm only detecting sideways collisions because for my purpose I only need that. This function is called in the update() function of each object, after it has moved. Here is function collide:

collide = function (object) {
    var m1 = this.mass;
    var m2 = object.mass;
    var v1 = this.velocity;
    var v2 = object.velocity;

    var v1f = ((m1 - m2) * v1 + 2 * m2 * v2) / (m1 + m2);
    var v2f = ((m2 - m1) * v2 + 2 * m1 * v1) / (m1 + m2);

    this.x -= this.velocity;
    object.x -= object.velocity;

    this.velocity = v1f;
    object.velocity = v2f;
}

The problem is probably here, I just don't know the correct idea. I have tried a bunch of ideas which yielded to a bunch of weird results. What is happening with this is l1 bounces between h1 and h2, until in kind of breaks free, I think he get's so fast that he can move enough to completely pass one of the other two blocks, than he escapes. Any links I should read, any idea of what to do? Any help would be appreciated. Thanks

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Osmar
  • 198
  • 9
  • If the colliding object is moving you have to include its velocity in the collision detection. The position of the object in the next frame is its current position + its velocity. – Peterrabbit Sep 25 '22 at 14:20
  • @Peterrabbit I am doign that. As I mentioned: "This function (detectCollisions) is called in the update() function of each object, after it has moved.". Is that what you mean or did I understood it wrong? – Osmar Sep 25 '22 at 15:23
  • You update after the move of the current frame but you detect the collision for the next frame ( at least that would be expectable) so you'd had to add the updated velocity to your collision detection. – Peterrabbit Sep 25 '22 at 16:27

2 Answers2

0

The condition if (right1 > left2 && right2 > left1) { tests whether there's a collision at both left and right edges of the body in question. Test either edge with a disjunction...

if (right1 > left2 || right2 > left1) {
danh
  • 62,181
  • 10
  • 95
  • 136
  • I don't know why you would say that, I really don't. It's not correct, and it's not close to. No, my code doesn't check for collision in both edges simultaneously, and no, yours don't test either one or another. Your piece of code would always be true, even when no collision is happening. Maybe the title of my question is bad cause my problem isn't on collision detection, probably should have said collision simulation, idk – Osmar Sep 25 '22 at 22:26
  • @Osmar, it might be me misunderstanding. I thought left1 and right 1 are the left and right edges of one of the objects, and left2 and right2 are the left and right edges of the other. The two conditions are either an overlap where object1 is on the left, with its right side touching object2, or the reverse, where object2 is on the left with it's right side touching object1. But maybe I'm very mixed up. – danh Sep 25 '22 at 22:29
  • but think with me, let's imagine the 4 edges of the 2 objects: | | | | left1 right1 left2 right2 in this situation they are not colliding, right? But let's look at the condition: (right1 > left2 || right2 > left1) this is false but this is true and if the first object was to the right of the other, than the first condition would be true even when no collision is occurring – Osmar Sep 25 '22 at 22:44
  • ok apparently line breaks and big spaces can't happen, but just draw the two rectangles somewhere and check for the conditions. You will understand why it would always be true – Osmar Sep 25 '22 at 22:45
  • I did make a drawing. Maybe my dyslexia is kicking in, but I can see two conditions where the expression is false, for example when left1 is smaller than right1 and right1 is smaller than left2 the left2 is smaller than right2. I can also see conditions where the disjunction is true, for example when the two rectangles overlap. But I trust your understanding of your own code better than mine. Happy to delete this answer if it is a distraction – danh Sep 25 '22 at 22:54
  • I mean left1 is always smaller than right1, and true, when right1 is smaller than left2 the first condition is false, but if such condition is false than right2 must be bigger than left1, leading to the second condition to be true. That's the problem – Osmar Sep 25 '22 at 23:06
0

Answering my own question: As my scenario is simple (objects only move sideways), it's not that complicated of a situation. I don't know how the method I used here would work in other cases, eitherway. So I kinda removed that whole detectCollisions function, and did it while moving the object. Before moving anything I looped over all other colliding possibilities, and if I detected that I either collided or completelly passed an objects (here is the important part. Somethimes when the speed was too big, from one frame to the other, one object would just jump another). If any of the two are true, I just move the object as far as it can go before hitting the other, and call the collide function on them. That's basically it, my question is answered, thanks to everyone

Osmar
  • 198
  • 9