Problem with collisions (intersections) in java game development using JFrame

45 Views Asked by At

I am making a 2d java game, where player needs to shoot tiles. I encountered a bug in my code, the bullet destroys nearby tiles, but not always and not properly.

PROBLEM VIDEO RECORD

You see, I want bullets to destroy the tile that it touches, and a tile at up, left, right, botton... You got it. Here is my code, I think I messed up something as always.

In my opinion the error is in the player class because it handles the destruction.

Short version of Player.java: (no imports, etc).

public class Player{
    public int pointX;
    public int pointY;
    public int velocityX;
    public int defaultVelX = 15;
    public int cooldown = 2;
    public boolean shooting = false;
    public Tile hitTile = null;
    YeahGame yg;
    Shot shot;
    TileManager tm;

    public Player(int x, int y, YeahGame yg) {
        this.pointX = x;
        this.pointY = y;
        this.yg = yg;
        tm = yg.tm;
    }
    public void shoot() {
        if (!shooting) {
            shot = new Shot(pointX, pointY, yg);
            shooting = true;
        }
    }
    public void Hit(int offsetX, int offsetY, int level) {
        Tile tl = tm.GetTile(hitTile.x + offsetX, hitTile.y + offsetY);
        if (tl != null && tl.isActive) {
            if (level >= tl.level) {
                tl.isActive = false;
            } else {
                tl.level -= level;
            }
        }
    }
    public void DestroyTiles() {
        Hit(0,0,1);
        Hit(1,0,1);
        Hit(0,1,1);
        Hit(-1,0,1);
        Hit(0,-1,1);
        if (cooldown > 0) {
            cooldown--;
        } else if (cooldown == 0) {
            tm.NewLayer();
            cooldown = 2;
        }
    }
    public boolean bulletCollision() {
        boolean is = false;
        if (shooting) {
            for (ArrayList<Tile> sampleRow : tm.rows) {
                for (Tile tile : sampleRow) {
                    if (tile.isActive) {
                        Rectangle shotRect = new Rectangle(shot.pointX+yg.tileSize/4, shot.pointY+yg.tileSize/4, yg.tileSize/2, yg.tileSize/2);
                        Rectangle tileRect = new Rectangle(tile.x * yg.tileSize, tile.y * yg.tileSize, yg.tileSize, yg.tileSize);

                        if (tileRect.intersects(shotRect)) {
                            is = true;
                            hitTile = tile;
                            break;
                        }
                    }
                }
                if (is) {
                    break;
                }
            }
        }
        return is;
    }
    public void update() {
        if (shooting) {
            shot.update();
            if (bulletCollision()) {
                DestroyTiles();
                shooting = false;
                shot = null;
            }
            else if (shot.pointY < 0) {
                shooting = false;
                shot = null;
            }
        }
    }
    public void draw(Graphics g) {
        g.setColor(Color.red);
        g.fillRect(pointX, pointY, yg.tileSize, yg.tileSize);
        if (shooting) {
            shot.draw(g);
        }
    }
}
2

There are 2 best solutions below

0
Emil Coder On BEST ANSWER

Ok guys, the problem was in a function that I accidentally didn't include in my code here on stackoverflow. Here is the error part of the code:

for (ArrayList<Tile> sampleRow : rows) {
 for (Tile tile : sampleRow) {
  if (tile.isActive) {
   tile.y += 1;
   if (tile.y == (yg.height/yg.tileSize)-yg.tileSize) {
    yg.failed = true;
   }
  }
 }
}

You see, it moves all the tiles down except disabled ones. They were over each other, blocking the collision detection, so I made it so every tile goes down, even disabled ones.

for (ArrayList<Tile> sampleRow : rows) {
 for (Tile tile : sampleRow) {
  tile.y += 1;
  if (tile.isActive) {
   if (tile.y == (yg.height/yg.tileSize)-yg.tileSize) {
    yg.failed = true;
   }
  }
 }
}
4
Valerij Dobler On

It looks like that when your bullet hits, it does not register previously destroyed tiles.

The main issue with your code is, that you didn't separate your code properly by responsibilities, which obfuscates the flow of information for you and anyone trying to help you.

The Player shouldn't be responsible for clearing the field, that is what the playing field should do itself.

You should have an internal representation of your playing field, and when a game tick is happening, you can first do your physics simulations and then render it to the screen.

And try to keep your naming scheme, take a look at the Java naming conventions.

And for game design, I could recommend the book "Game Programming Patterns" By Robert Nystrom.