Red
Red

Reputation: 25

Java Hit Detection/Collision between objects

Being new to coding, I watched a video on how to create Pong. That went well, and as a result I wanted to try and recreate Brick Breaker using some of the coding techniques that were used for Pong. So far I have the ball, paddle, and the base of the game. However, the ball does not collide properly with the paddle, instead of bouncing of it passes through.

Code for base game:

import java.applet.Applet;
import java.awt.Color;
import java.awt.Image;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class Breaker extends Applet implements Runnable, KeyListener{
final int WIDTH = 600, HEIGHT= 400;
Thread thread;
Graphics gfx;
Image img;
Ball b1;
Player p1;

public void init() {
    this.resize(WIDTH, HEIGHT);
    this.addKeyListener(this);
    b1 = new Ball();
    p1 = new Player(1);
    img = createImage(WIDTH,HEIGHT);
    gfx = img.getGraphics();
    thread = new Thread(this);
    thread.start();
}

public void paint(Graphics g) {
    gfx.setColor(Color.black);
    gfx.fillRect(0, 0, WIDTH, HEIGHT);
    b1.draw(gfx);
    p1.draw(gfx);
    g.drawImage(img, 0, 0, this);
}

public void update (Graphics g) {
    paint(g);
}

@Override
public void keyPressed(KeyEvent e) {
    if(e.getKeyCode() == KeyEvent.VK_LEFT){
        p1.setLeftAccel(true);
    }
    else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
        p1.setRightAccel(true);
    }

}

@Override
public void keyReleased(KeyEvent e) {
    if(e.getKeyCode() == KeyEvent.VK_LEFT){
        p1.setLeftAccel(false);
    }
    else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
        p1.setRightAccel(false);
    }
}

@Override
public void run() {
    for(;;) {

        p1.move();
        b1.move();
        b1.checkPlayerCollision(p1);

        repaint();
        getToolkit().sync();
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

@Override
public void keyTyped(KeyEvent arg0) {   
}
}

Ball:

import java.awt.Graphics;
import java.awt.Color;

public class Ball {
int score;
double xVel, yVel, x, y;

public Ball() {
    x= 350;
    y = 250;
    xVel= 0;
    yVel = 1;
}

public void draw(Graphics g) {
    g.setColor(Color.white);
    g.fillOval((int)x - 10, (int)y - 10, 20, 20);
}

public void checkPlayerCollision(Player p1) {
    if (x <= 50) {
        if(x >= p1.getX() && x <= p1.getX() + 10)
            xVel = -xVel;
    }
    else if (x >= 680) {
        xVel = -xVel;
    }
}

public void move() {
    x += xVel;
    y += yVel;

    if (y < 10) //Bounce at top side of screen
        yVel = -yVel;
    if (x < 10) // Bounce at left side of screen
        xVel = -xVel;
}

public int getX() {
    return (int)x;
}

public int getY() {
    return (int)y;
}


}

Player:

import java.awt.Color;
import java.awt.Graphics;

public class Player implements Paddle {
double x, xVel;
boolean leftAccel, rightAccel;
int player, y;

public Player(int player) {
    leftAccel = false; rightAccel = false;
    x=260; xVel=0;
}

@Override
public void draw(Graphics g) {
    g.setColor(Color.white);
    g.fillRect((int)x, 380, 80, 10);

}

@Override
public void move() {
    if(leftAccel){
        xVel -= 2;
    }
    else if (rightAccel) {
        xVel += 2;
    }
    else if (!leftAccel && !rightAccel) {
        xVel = 0;
    }
    if(xVel >= 5) {
        xVel = 5;
    }
    else if (xVel <= -5) {
        xVel = -5;
    }
    x += xVel;

    if(x < 0)
        x=0; //Collision with left wall
    if(x > 520)
        x = 520; //Collision with right wall

}

public void setLeftAccel(boolean input) {
    leftAccel = input;
}

public void setRightAccel(boolean input) {
    rightAccel = input;
}

@Override
public int getX() {
    return (int)x;

}
}

Paddle:

import java.awt.Graphics;

public interface Paddle {
public void draw(Graphics g);
public void move();
public int getX();

}

I don't completely understand hit detection yet, so I just messed with what was used for pong, however, that doesn't work (and I'm sure it might look weird).

Upvotes: 0

Views: 434

Answers (1)

Kalkran
Kalkran

Reputation: 334

Collision detection can be hard to wrap your head around sometimes. What really helps me is to draw on a piece of paper the things I need to check for and write the checks in code one by one. It's also a good idea to keep your axes in mind, it's really easy to mix up an x and a y, but they will have an important effect on gameplay. My eye was drawn to your checkPlayerCollision function as it seemed a little off, I have changed some checks around and commented what each check/function is doing.

public void checkPlayerCollision(Player p1) {
    if (
        // Is the ball at or below paddle height?
        y <= 50
        // AND Is the ball right of the left side of the paddle?
        && x >= p1.getX()
        // AND Is the ball left of the right side of the paddle?
        && x <= p1.getX() + 10
    ) {
        // Collision with the paddle! 
        // (Ball is lower than y=50 and between left and right side of the paddle!)
        // As we want the ball to go back up, we will be changing its velocity
        // along the Y-axis.
        yVel -= yVel;
    } else if (x >= 680) {
        // This checks whether the ball went too far to the right..?
        xVel -= xVel;
    }
}

Best tip I can give you: grab a piece of paper and just draw a simple grid or graph and use that to draw out different things you need to check. Be sure to label your (0,0) point so when you work with the different borders, you know which ones are 0 (usually top and left borders) and which ones are equal to width and height of the canvas.

Upvotes: 1

Related Questions