Advertisement

Java Class, How to Check Collision Between Entities in Same Array?

Started by June 07, 2022 07:11 PM
7 comments, last by frob 2 years, 6 months ago

Hi all.

I created a class named "wall" in my mobile java game. I have a player ship and easly detect collision between player and wall blocks.

My problem is how do i detect collision between wall blocks in same array. I want to check if the blocks intersects with each other. For example one block will carry on other block. Without collision detection i cannot do that.

Collision isnt working at green boxes in same array

Wall class:

public class Wall {

    Vector2 pozisyon = new Vector2();
    TextureRegion resim;
    Boolean hit;
    int wallfall = 1;

    public Wall(float x, float y, TextureRegion resim) {

        this.pozisyon.x = x;
        this.pozisyon.y = y;
        this.resim = resim;
    }

}

Main code:

/////////////////
private Array <Wall> walls = new Array<Wall>();
////////
for (int i = 0; i < 1; i++) {
   for (int q = 0; q < 2; q++) {
      walls.add(new Wall(900 + i * 250, 300 + q * 100, wall1));
   }
}
//////////
for (Wall wall : walls) {
    wallbox.set(wall.pozisyon.x, wall.pozisyon.y, 50, 50);//UPDATE
    oyunsayfasi.draw(wall.resim, wall.pozisyon.x, wall.pozisyon.y, 50, 50);//DRAW
}

I tries a code like this

for(int i = walls.size-1; i >= 0; i--) {
   walls.get(i);
   for(int j = walls.size-1; j >= 0; j--) {
      walls.get(j);
      if ((walls.get(j).pozisyon.y > walls.get(i).pozisyon.y+50) && (walls.get(j).pozisyon.y+50 < walls.get(i).pozisyon.y)) {
         if ((walls.get(j).pozisyon.x > walls.get(i).pozisyon.x+50) && (walls.get(j).pozisyon.x+50 < walls.get(i).pozisyon.x)){
            wall.pozisyon.y += 1;
         }
      }
   }
}

But it doesnt work :/ How could i solve this problem? Thanks for every help and idea. Best regards.

Writing that “it doesn't work” doesn't really describe what your issue is nor what you expect, but taking some guesses.

You're getting close with the two nested loops for the naive solution. To avoid overlap you'll want the inner loop to not overlap the ones the outer loop has already covered, in your case you're hitting each collision multiple times and also having each item test against itself. It won't scale for performance reasons, but once you remove the duplicates and the test against itself, you're probably fine for small scales. The fact that you check each one twice and also test each item against itself could each potentially be why “it doesn't work”, but you might be referring to different issues.

Your comparison looks a little weird as you're assuming fixed sizes of 50 units. Normally you create a collision function that takes two objects and returns true if they intersect. like bool intersects( rectangle A, rectangle B) or similar. That probably isn't the reason for “it doesn't work”, but since you're vague may be a source of the problems.

Your response if they overlap also seems weird. You have wall i, wall j, and an unnamed wall. If i and j are within 50 of each other, you bump the unnamed wall by 1 unit even though it wasn't the one you compared, and even though 1 may not be related to the 50 in the comparison. Again, that may or may not be what you mean by “it doesn't work” but is something that looks unexpected.

Are any of those the issues you're having with the code, or are you seeing and expecting something else?

Advertisement

I mean i tried a code like this

for(int i = walls.size-1; i >= 0; i--) { walls.get(i); for(int j = walls.size-1; j >= 0; j--) { walls.get(j); if ((walls.get(j).pozisyon.y > walls.get(i).pozisyon.y+50) && (walls.get(j).pozisyon.y+50 < walls.get(i).pozisyon.y)) { if ((walls.get(j).pozisyon.x > walls.get(i).pozisyon.x+50) && (walls.get(j).pozisyon.x+50 < walls.get(i).pozisyon.x)){ wall.pozisyon.y += 1; } } } }

and it doesnt work to detect collision, it is obvious isnt it?

How can i detect collision in entities between same array?

frob said:

Writing that “it doesn't work” doesn't really describe what your issue is nor what you expect, but taking some guesses.

You're getting close with the two nested loops for the naive solution. To avoid overlap you'll want the inner loop to not overlap the ones the outer loop has already covered, in your case you're hitting each collision multiple times and also having each item test against itself. It won't scale for performance reasons, but once you remove the duplicates and the test against itself, you're probably fine for small scales. The fact that you check each one twice and also test each item against itself could each potentially be why “it doesn't work”, but you might be referring to different issues.

Your comparison looks a little weird as you're assuming fixed sizes of 50 units. Normally you create a collision function that takes two objects and returns true if they intersect. like bool intersects( rectangle A, rectangle B) or similar. That probably isn't the reason for “it doesn't work”, but since you're vague may be a source of the problems.

Your response if they overlap also seems weird. You have wall i, wall j, and an unnamed wall. If i and j are within 50 of each other, you bump the unnamed wall by 1 unit even though it wasn't the one you compared, and even though 1 may not be related to the 50 in the comparison. Again, that may or may not be what you mean by “it doesn't work” but is something that looks unexpected.

Are any of those the issues you're having with the code, or are you seeing and expecting something else?

yusufabi said:
I mean i tried a code like this

for(int i = walls.size-1; i >= 0; i--) {
   walls.get(i);
   for(int j = walls.size-1; j >= 0; j--) {
      walls.get(j);
      if ((walls.get(j).pozisyon.y > walls.get(i).pozisyon.y+50) && (walls.get(j).pozisyon.y+50 < walls.get(i).pozisyon.y)) {
         if ((walls.get(j).pozisyon.x > walls.get(i).pozisyon.x+50) && (walls.get(j).pozisyon.x+50 < walls.get(i).pozisyon.x)) {
            wall.pozisyon.y += 1;
         }
      }
   }
}

and it doesnt work to detect collision, it is obvious isnt it?

How did you conclude “collision detection is not working”? The loops may not do exactly what you expect, but the if statement looks ok to me. Did you check whether you ever execute the “wall.pozisyon.y += 1;” statement?

Maybe the if statement works (detection works) but you are making a wrong change? In other words, maybe you are moving the wrong wall?

What is this “wall.pozisyon.y += 1;” that you are modifying? What wall is moving when you detect a collision?

Where is this “wall” relative to “walls.get(j)” and “walls.get(i)” ? Are you sure it is the wall you expect it is?

The problem with these things is that it is hard to see what is happening. A trick is to temporarily make a more visible change. If you can, change the color of “wall” instead of this very subtle “+1” move, or move it by a larger amount, or something else so it's very clearly visible that the code is indeed detecting collisions, and also that the wall you are modifying is correct.

Once you checked that, you can change it back to the movement that you need.

@Alberth hi Alberth

At my sample code if statement is working but all(2) walls moving up with +1. They are all moving but i cannot detect one object from array. My code is working for all objects.

My goal is in this game detect collision between objects in same array because i will create many boxes and they will stop falling down each other against gravity.

there is gravity and boxes are falling down. When a box falls on another one collision will be activate and stop to falling box on another boxes. If i can solve this problem. Like this:

for(int i = walls.size-1; i >= 0; i--) {
   walls.get(i);
   for(int j = walls.size-1; j >= 0; j--) {

This is the third time i see inefficient N-body loop in a couple of weeks ; )

With 'inefficient' i assume you want to collide each body with each other. But just once, not twice. Actually you do it twice: First i with j, then j with i.

To process each pair only once, loop could look like this:

for (int i=0; i<N-1; i++)
for (int j=i+1; j<N; j++)

Though, this example uses increasing indices, not decreasing as yours. But you get what i mean: It does only half of the work, and only what's actually needed.

However, the way you resolve collisions, your actual problem might come from the fact your solution depends on the order of input.
It may work if the boxes are sorted up to down, but not if they are sorted down to up. (or vice versa) And if order is random, it may sometimes work, sometimes not.
So eventually you want to sort order respecting direction of gravity, which also is no general solution, but could work for your case. (Doing it correctly brings us to rigid body constraint solvers)

(Did not read former replies)

Advertisement

Thank you JoeJ ? i owe you a coffee

JoeJ said:

for(int i = walls.size-1; i >= 0; i--) {
   walls.get(i);
   for(int j = walls.size-1; j >= 0; j--) {

This is the third time i see inefficient N-body loop in a couple of weeks ; )

With 'inefficient' i assume you want to collide each body with each other. But just once, not twice. Actually you do it twice: First i with j, then j with i.

To process each pair only once, loop could look like this:

for (int i=0; i<N-1; i++)
for (int j=i+1; j<N; j++)

Though, this example uses increasing indices, not decreasing as yours. But you get what i mean: It does only half of the work, and only what's actually needed.

However, the way you resolve collisions, your actual problem might come from the fact your solution depends on the order of input.
It may work if the boxes are sorted up to down, but not if they are sorted down to up. (or vice versa) And if order is random, it may sometimes work, sometimes not.
So eventually you want to sort order respecting direction of gravity, which also is no general solution, but could work for your case. (Doing it correctly brings us to rigid body constraint solvers)

(Did not read former replies)

JoeJ said:
(Did not read former replies)

Your was the first issue and part of the third issue of the four I pointed out.

@yusufabi It may seem a bit rough, but I recommend reading this paper about asking questions in technical forums. It will help both in asking and in responding to the replies you have received.

This topic is closed to new replies.

Advertisement