0
\$\begingroup\$

I'm trying to get the collision between two squares. I've made a Rectangle object that overlays each one and updates the position every tick.

Then I made a collision method that checks whether they are intersecting or not. It just uses rectangle1.intersects(rectangle2);

That works fine, and it detects the collision, however I can't move when it detects it.

This is my move and collision method at the moment.

public void move(int xa, int ya, Player opponent) {
    if (collision(opponent)) {
        return;
    }

    this.x += xa;
    this.y += ya;

}

public boolean collision(Player opponent) {
    if (rectangle.instersects(opponent.rectangle) return true;
    return false;
}

The detection and stuff works fine, but I can't move. I see why I can't, because the method is returning before it moves anything, but I'm just completely lost for whatever reason on where to go with it. I'm sure it's an easy fix and I'm just not seeing something.

\$\endgroup\$
1
  • \$\begingroup\$ Darren, no need to update the question with [Solved]. Just create an answer of your own and mark it as accepted if that's your answer. \$\endgroup\$
    – House
    Oct 1, 2013 at 0:16

2 Answers 2

1
\$\begingroup\$

There are a couple ways you can go about solving this. They vary in complication and difficulty.

What I suggest starting with is testing your move before you actually move the rectangle, or move the rectangle back if there's a collision. Basically, your problem is that the rectangle moves to a position where it is colliding with something:

          --------                 --------
          |      |                 |      |
--------  |      |            -----|--    |
|      |  --------    -->     |    --|-----
|      |                      |      |        
--------                      --------
        (1)                        (2)

And then it stays there, unresponsive to the collision. When you run move under condition (2), the rectangles are still considered to be colliding and no move will be carried out, even if that move resolves the collision.

If you prevent it moving there in the first place, then it's free to continue moving in other directions. Code would look something like the following:

public void move(int xa, int ya, Player opponent) {
    this.x += xa;
    this.y += ya;

    if (collision(opponent)) {
        this.x -= xa;
        this.y -= ya;
    }
}

This method can lead to odd collisions though, depending on the velocity at which your rectangle moves. If it attempts to move 10 units but a collision occurs in 9, then it's prevented from moving in a direction even though it isn't flush against the colliding object.

To solve that, things get a little more complicated. To give an overview, you determine the magnitude of penetration along the direction one rectangle was traveling, and back it up along that direction to the point where it's no longer colliding. If the rectangle can bounce, an even more detailed implementation will determine where the rectangle should be considering that it collided mid-timestep. If you're interested on how to get started on those options, I recommend reading through Metanet Software's collision detection tutorials.

\$\endgroup\$
1
  • \$\begingroup\$ I figured it out on my own after a while. I think I went down a way more complex route than needed, but it seems to work perfectly. It checks every side and changes the acceleration values accordingly. I posted my new code in an edit on my question. \$\endgroup\$
    – Darren
    Oct 1, 2013 at 0:02
1
\$\begingroup\$

I like using a simplified version of the SAT (separating axis theorem).

Basically, You collapse your 2D rectangles down to a cardinal axis (eg: X or Y) by flattening the 2D point to a 1D point. Then, you simply look for an overlap. If you do this in both axis, you can be sure that there's an actual intersection.

This is pretty handy when you've got a number of objects in the "scene" as you can very quickly determine possible intersection of a number of objects.

\$\endgroup\$
4
  • \$\begingroup\$ SAT actually stands for Separating Axis Theorem. \$\endgroup\$ Oct 1, 2013 at 2:51
  • \$\begingroup\$ TEST, or a certain christer eriksson will be very unhappy with you. (realtimecollisiondetection.net/blog/?p=103) \$\endgroup\$
    – Matt D
    Oct 1, 2013 at 3:28
  • \$\begingroup\$ Then I stand corrected. However, as the algorithm is stated in the form of a theorem, and is considered a consequence of the Separating Hyperplane Theorem, the terminology seems acceptable to me. \$\endgroup\$ Oct 1, 2013 at 3:43
  • \$\begingroup\$ Ah semantics. Either way, its a very useful algorithm :) and the simplified SAT is even more so as you dont need to find any actual separating axis! \$\endgroup\$
    – Matt D
    Oct 1, 2013 at 3:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .