Can anyone see anything wrong with this?

It’s my collision script which i’ve been working on for the past few days…I thought I had it correct, but it still seems all messed up. It’s taking away too many bricks. It takes away the brick it hits and takes the last brick left on the board (most bottom right brick)

It’s driving me crazy.


public void checkBrickCollision()
	{
		int ballLeft = (int)ball.ballRect.x;
		int ballRight = (int)ball.ballRect.x + (int)ball.ballRect.width;
		int ballTop = (int)ball.ballRect.y + (int)ball.ballRect.height;
		int ballBottom = (int)ball.ballRect.y;
		
		 
		
			for (int i=0;i<level.getBrickCount();i++) {
				
				if (level.bricks[i].GetVisible() == true) {
					
				
		Vector2 Top = new Vector2(ballLeft + (ball.ballRect.width / 2),ballTop );
		Vector2 TopLeft = new Vector2(ballLeft,ballBottom+ball.ballRect.height);
		Vector2 TopRight = new Vector2(ballLeft + ball.ballRect.width,ballBottom+ball.ballRect.height);
		
		
		Vector2 Bottom = new Vector2(ballLeft + (ball.ballRect.width/2),ballBottom);
		Vector2 BottomLeft = new Vector2(ballLeft,ballBottom);
		Vector2 BottomRight = new Vector2(ballLeft + ball.ballRect.width,ballBottom);
		
		Vector2 Right = new Vector2(ballRight,ballBottom + ball.ballRect.height/2);
		Vector2 Left = new Vector2(ballLeft,ballBottom + ball.ballRect.height/2);
		
		
		//int brickLeft = (int)bricks[i].brickRect.x;
		//int brickRight = (int)bricks[i].brickRect.x +(int)bricks[i].brickRect.width;
		//int brickTop = (int)bricks[i].brickRect.y + (int)bricks[i].brickRect.height;
		//int brickBottom = (int)bricks[i].brickRect.x;
		
		if (ball.getRect().overlaps(level.bricks[i].getRect()))
			//System.out.println("Overlapped");
		
		{
		
			
			
			if (level.bricks[i].getRect().contains(Bottom.x,Bottom.y)) {
				ball.ballSpeedY = -ball.ballSpeedY;
				level.bricks[i].isVisible = false;
		
				level.brickCount--;
				System.out.println("Top");
				return;
				
			}
			
			if (level.bricks[i].brickRect.contains(TopLeft.x,TopLeft.y)) {
				ball.ballSpeedX = -ball.ballSpeedX;
				ball.ballSpeedY = -ball.ballSpeedY;
				level.bricks[i].isVisible = false;
		
				level.brickCount--;
				System.out.println("BottomRight");
				return;
			}
			
		
			
			if (level.bricks[i].brickRect.contains(TopRight.x,TopRight.y)) {
				ball.ballSpeedX = -ball.ballSpeedX;
				ball.ballSpeedY = -ball.ballSpeedY;
				level.bricks[i].isVisible = false;
		
				level.brickCount--;
				System.out.println("BottomLeft");
				return;
			}
		
			
			if (level.bricks[i].brickRect.contains(BottomLeft.x,BottomLeft.y)) {
				ball.ballSpeedX = -ball.ballSpeedX;
				ball.ballSpeedY = -ball.ballSpeedY;
				level.bricks[i].isVisible = false;
		
				level.brickCount--;
				System.out.println("TopRight");
				return;
			}
			
			
			if (level.bricks[i].brickRect.contains(BottomRight.x,BottomRight.y)) {
				ball.ballSpeedX = -ball.ballSpeedX;
				ball.ballSpeedY = -ball.ballSpeedY;
				level.bricks[i].isVisible = false;
				System.out.println("TopLeft");
				level.brickCount--;

				return;
			}
			
			
			if (level.bricks[i].brickRect.contains(Top.x,Top.y)) {
				
				ball.ballSpeedY = -ball.ballSpeedY;
				
				level.bricks[i].isVisible = false;
		
				level.brickCount--;
				System.out.println("Bottom");
				return;
				
			}
			if (level.bricks[i].brickRect.contains(Left.x,Left.y)) {
				
				
								
				ball.ballSpeedX = -ball.ballSpeedX;
				level.bricks[i].isVisible = false;
		
				level.brickCount--;
				System.out.println("Right");
				return;
				
			}
			if (level.bricks[i].brickRect.contains(Right.x,Right.y)) {
				
					
				ball.ballSpeedX = -ball.ballSpeedX;
				level.bricks[i].isVisible = false;
		
				level.brickCount--;
				System.out.println("Left");
				return;
				
			}
			
				System.out.println(level.getBrickCount());
				
		}
		
		}	
		
	
	}
	
	}

EDIT

This is my Level class:


package com.psillicoder.brickbreaker;
import java.util.*;
import com.psillicoder.brickbreaker.Brick;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class Level {
   final int BLANK = 0;
   final int BLUE = 1;
   
   public int brickCount;
   int ROW = 12;
   int COL = 12;
   public Brick[] bricks = new Brick[(ROW)* (COL)];
   int board[][] = new int[ROW][COL];
   
   public Level() {
	      board = new int[][] {
            {2,2,2,2,2,2,2,2,2,2,2,2,},
            {3,3,3,3,3,3,3,3,3,3,3,3,},
            {1,1,1,1,1,1,1,1,1,1,1,1,},
            {1,3,1,3,1,1,3,3,3,3,3,1,},
            {1,3,1,3,1,1,1,1,3,1,1,1,},
            {1,3,3,1,1,1,1,1,3,1,1,1,},
            {1,3,1,3,1,1,1,1,3,1,1,1,},
            {1,3,1,3,1,1,1,1,3,1,1,1,},
            {1,1,1,1,1,1,1,1,1,1,1,1,},
            {3,3,3,3,3,3,3,3,3,3,3,3,},
            {2,2,2,2,2,2,2,2,2,2,2,2,},
            {1,1,1,1,1,1,1,1,1,1,1,1,},
      };
   }


	

	public void LoadBricks() {
		this.brickCount = 0;
		for (int x = 0; x < ROW; x++) {
			for (int y = 0; y < COL;y++) {
				
				if (board[x][y] != 0) {
				bricks[this.brickCount] = new Brick(board[x][y],y*32 + 20,-x*16 + 575, true);
				this.brickCount++;
				}
				if (board[x][y] == 0) {
					//this.brickCount++;
					}
				
			}
		}
		
		
	}
	
	public void drawBricks(SpriteBatch batch) {
		
		int intBricks = brickCount;
		
		for (int i=0;i<intBricks;i++) {
			if (bricks[i].GetVisible() == true) {
				bricks[i].draw(batch);
			
			}
			if (bricks[i].GetVisible()==false) {
				//this.brickCount--;
				
			}
			
				
			
			
			
		}
	
	}
	
	

	public int getBrickCount() {
		return bricks.length;
	}
	
	
	
	
}

Are you following the zetcode.com breakout tutorial? There’s a more easier way to bounce of from bricks. Calculate the distances between objects and you can predict the way it collides.


int xd = Math.abs( (ball.x + ball.width - brick.x - brick.width) /2 );
int yd = Math.abs( (ball.y + ball.height - brick.y - brick.height) /2 );

if (xd > yd)
{
    // Collision on top or bottom, reverse y velocity
    ball.ballSpeedY = -ball.ballSpeedY;
}
if (yd > xd)
{
    // Collision on left or right, reverse x velocity
    ball.ballSpeedX = -ball.ballSpeedX;
}
if (xd == yd)
{
    // Collision on corners, reverse both
    ball.ballSpeedX = -ball.ballSpeedX;
    ball.ballSpeedY = -ball.ballSpeedY;
}

I originally wrote the code from scratch but kept having trouble with it acting weird, so I implemented the method used on zetcode. Your way seems a lot better and more efficient. I’m going to implement it. I’m not sure if I fully understand the code though. I understand its measuring distance…but how? Sorry, I feel like an idiot. I’m not sure what I’m missing.

I’ve got it implemented now, but it still seems to be calling more than one of the side checks. It takes away extra bricks from where I have each removing one from level.brickCount.


	public void checkBrickCollision()
	{
		for (int i=0;i<level.getBrickCount();i++) {
				
				if (level.bricks[i].GetVisible() == true) {
					if (ball.getRect().overlaps(level.bricks[i].getRect()))
					{
		
			
			
			int xd = (int) Math.abs( (ball.ballRect.x + ball.ballRect.width - level.bricks[i].brickRect.x - level.bricks[i].getRect().width) /2 );
			int yd = (int) Math.abs( (ball.ballRect.y + ball.ballRect.height - level.bricks[i].brickRect.y - level.bricks[i].getRect().height) /2 );
			
			if (xd > yd)
			{
			    // Collision on top or bottom, reverse y velocity
			    ball.ballSpeedY = -ball.ballSpeedY;
			    level.bricks[i].isVisible = false;
			    level.brickCount--;
			    System.out.println("Top/Bottom");
			    return;
			}
		
		
			if (yd > xd)
			{
			    // Collision on left or right, reverse x velocity
			    ball.ballSpeedX = -ball.ballSpeedX;
			    level.bricks[i].isVisible = false;
			    level.brickCount--;
			    System.out.println("Sides");
			    return;
			}
			
			if (xd == yd)
			{
			    // Collision on corners, reverse both
			    ball.ballSpeedX = -ball.ballSpeedX;
			    ball.ballSpeedY = -ball.ballSpeedY;
			    level.bricks[i].isVisible = false;
			    level.brickCount--;
			    System.out.println("Corners");
			    return;
			}			
		}		
	}
}
}
	

Also, sometimes the ball will go straight through a column when it’s going straight up. It is only calling the sides in the console.

This just determines the side of collision and reverses the direction. Upon collision, before calculating the sides, align the ball outside the brick. So that this appears on the screen like ball touched the brick just at that instant and the side detection will be correct. These are my methods in my engine.

[icode]alignWith()[/icode]


public void alignWith(GObject other){
    // Get the intersection rectangle
    Rectangle i = getBounds().intersection(other.getBounds());
    if (i.width > i.height){
        // A vertical collision
        if (getY()<other.getY()){
            // We're on top of other
            setY(other.getY()-getHeight());
        } else if (getY()>other.getY()){
            // We're below other
            setY(other.getY()+other.getHeight());
        }
    } else {
        // A horizontal collision
        if (getX()<other.getX()){
            // We're left to other
            setX(other.getX()-getWidth());
        } else if (getX()>other.getX()){
            // We're right to other
            setX(other.getX()+other.getWidth());
        }
    }
}

[icode]bounce()[/icode]


public void bounce(GObject other){
    int xd = (int) ((other.x + other.getWidth() / 2) - (x + getWidth() / 2));
    int yd = (int) ((other.y + other.getHeight() / 2) - (y + getHeight() / 2));
    if (xd < 0) {
        xd = -xd;
    }
    if (yd < 0) {
        yd = -yd;
    }
    if (xd > yd) {
        dx = -dx;
    } else {
        dy = -dy;
    }
}

And in my game, I’ll call this as


public void collision(GObject other)
{
    if (other instanceof Brick)
    {
        alignWith(other);
        bounce(other);
    }
}

This is working perfectly in both my engines (GEJ and GECS). Also a screenshot of the problem describes it more.

I get what you’re saying. I’m going to try to implement it. The only thing I don’t understand is why you would check if i.width > i.height to find out if its a vertical collision or a horizontal collision? Since my brick is wider than it is tall, then wouldn’t it always return a vertical collision?

I’m trying to implement this but i’m having trouble getting the intersection rectangle…I’ve tried passing the rectangle and adding .intersects but it doesn’t seem to be a defined method…All I have is a boolean overlap. I’m confused.