Detect collision between corners of objects

Asked

Viewed 673 times

11

I’m writing a game based on Breakout, but I can’t think of a way to detect the collision between the corner of the ball area and the paddle, so I can reverse the horizontal direction of the ball.

In my class Ball, I have a method that takes care of the movement of the ball, and when it detects collision, it just reverses the vertical direction(axis y).

import java.awt.Graphics2D;
import java.awt.Rectangle;

public class Ball {

    private int x = 0;
    private int y = 15;
    private final int DIAMETER = 30;
    private int xSpeed = 1;
    private int ySpeed = 1;

    private Board board;

    public Ball(Board board) {
        this.board = board;
        y = board.paddle.getTopY() - DIAMETER;
        x = board.getPreferredSize().width / 2 - DIAMETER / 2;
    }

    public void move() {

        if (x > board.getWidth() - DIAMETER || x < 0) {
            xSpeed = -xSpeed;
        }

        if (y < 15) {
            ySpeed = -ySpeed;
        }

        if (y > board.getHeight() - DIAMETER) {
            board.gameOver();
        }

        //entre nesta if quando uma colisão é detectada
        if (collision()) {
            y = board.paddle.getTopY() - DIAMETER;
        }

        x += xSpeed;
        y += ySpeed;
    }

    public void setSpeed(int speed) {
        this.xSpeed = speed;
        this.ySpeed = speed;
    }

    public void paint(Graphics2D g2) {
        g2.fillOval(x, y, DIAMETER, DIAMETER);
    }

    public boolean collision() {
        //detecta colisão entre a area da bola e o paddle
        return board.paddle.getBounds().intersects(this.getBounds());
    }

    public Rectangle getBounds() {
        return new Rectangle(x, y, DIAMETER, DIAMETER);
    }
}

The result so far:

inserir a descrição da imagem aqui

Only when the area of the ball collides with the corner of the paddle, it continues the trajectory of the x axis, and to simulate a more real physics, I would like to be able to detect when the collision occurs at the ends of the objects and reverse the trajectory of the x axis of the ball. How do I detect it?

As there are 4 different large classes, not to mess up the question, I put a fully executable and complete example of the code in gist.

  • Paddle is the area the ball walks?

  • @jbueno Paddle is the "horizontal bar" that the player controls on the sides to hit the ball.

  • (x, y) would be the left top point of the square circumscribed to the circle?

  • @jbueno x e y na classe ball seria isso: http://i.imgur.com/Oxobalm.jpg

1 answer

11


In the case of this game, what you want to do is very simple.

When your collision happens, the ball is necessarily touching the top of the staff (paddle). Thus, the axis value y doesn’t matter. You need to compare the axis value x relatively.

By relative I mean you need to check how much the value in x ball is offset from the value in x staff center. Do so (pseudo-code):

centro_bastao = bastao.x + (bastao.width / 2);
posRelativa = Math.abs(bola.x - centro_bastao) / (bastao.width / 2);

The value of posRelativa will be between 0 and 1 so that 0 means the ball is right in the center and 1 the ball is exactly at one end. If you want to know which end (that is, the side), remove the abs of the above code and check the sign (negative will be on the left and positive on the right). Then make the decision according to the value of this variable.

P.S.: Ideally you should move the ball using a vector speed (that is, a vector with the direction and magnitude of the speed of motion). Thus, it would be easier to "reflect" the vector simply rotating it according to the value of posRelativa and then reversing it (0 does not rotate, and the inverse is exactly the force to be applied back up). Escapes the scope of this site to teach a class but I suggest reading about it on the Internet. It’s an important thing know to develop games. This my other answer has something in that sense and can be useful too.

  • A discussion that we were having in the chat is that, when considering the limits of the circle as a rectangle, see method getBounds, this collision will be detected not when the circle itself touches the staff, but when the rectangle that defines its limit touches. That would generate an unexpected visual aspect, if I’m right.

  • Indeed, yes, but it does not fall within the scope of the problem, as commented by Diego.

  • 1

    @Andersoncarloswoss is totally right. But he doesn’t have free lunch: accuracy is costly. This problem you point to can be solved in several ways. Perfect pixel (pixel by pixel checking) is the most accurate, but the most costly. The AP could continue using rectangular bounding boxes for first detection and, if so, validate with a perfect pixel. Or use a circular Cor. There is a lot of material on the Internet about.

  • 1

    I’m reading the answer links. It is much more complex than I imagined, I will have to study, this concept of vector for speed is new to me xD

  • 1

    Believe me, it will be a good study for your gamedev career. : ) But you don’t necessarily need to use vectors in this first version. Good luck!

  • Here’s another tip: the book "Programming Game AI by Example" has an initial chapter of mathematics that is very useful. It has a section on vectors only. I suggest you buy the book (it will be very useful for you for a long time!), but if you look for you should find the PDF (illegal!) around. https://www.amazon.com/Programming-Example-Wordware-Developers-Library/dp/1556220782

  • 1

    Luiz, your formula worked! i only team that make a modification because of the fact of using rectangle in the collision, then what the program considers as position x is the (invisible) tip of the rectangle, and not the contact area of the sphere.[+]

  • 1

    [+], then I changed the formula to the following: posRelativa = ((bola.x + bola.diametro/2) - centro_bastao) / (bastao.width / 2); and I was able to make the inversion more realistic :D

  • @Luizvieira Not wanting to abuse his good will, but has idea how it would be possible to simulate a velocity vector in this case?

  • @jbueno Yes, it is possible. Instead of manipulating directly and individually x and y, use a vector to describe the movement of the ball. The code of my other answer I refer to has exactly this example. Take a look at collision detection, especially when one ball bumps into the other. The code detects this, and applies a "force" (sum a force vector in the current velocity vector of the ball) that propels it in the opposite direction. Gravity itself, in this same example, is also a force that continuously acts on the velocity vector (it is simply added to each frame).

Show 5 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.