Breakout game, rectagle collision detection - java

I am trying to make a copy of the breakout game, but I have problems with checking if two objects (the ball and paddle) intersects.
I have this method for collision detection for now:
public static void handleCollisions() {
System.out.println(ball.getBounds()); // just to check that they
System.out.println(paddle.getBounds()); //are there and moving correct
if (ball.getBounds().intersects(paddle.getBounds())) {
System.out.println("collision");
}
}
But even though the rectangles for sure intersect at some points, the method never detects anything. I suppose I have done something wrong with some of the classes.
Here is the main classes:
package assignment1;
import java.awt.*;
import java.awt.event.*;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import javax.swing.*;
import javax.swing.plaf.basic.BasicBorders.RadioButtonBorder;
import java.util.Random;
public class Breakout extends TimerTask implements KeyListener {
public static Vector bricks;
public static Ball ball;
public static Paddle paddle;
public static PaintingPanel panel;
public static boolean gameRunning;
public static Breakout game;
public Breakout()
{
}
public static void setupGame()
{
Paddle paddle = new Paddle(350, 790, 100, 10); //initial paddle creation
Ball ball = new Ball(393, 790, 7);
showGUI();
}
public static void beginGame()
{
gameRunning = true;
}
public void run()
{
if(gameRunning == true)
{
Ball.move();
Paddle.move();
handleCollisions();
if(Ball.x < 0 || Ball.x > 800 || Ball.y < 0 || Ball.y > 790){
gameRunning = false;
System.out.println("Game over");
}
}
}
public static void stopGame()
{
}
public static void handleCollisions()
{
System.out.println(ball.getBounds());
System.out.println(paddle.getBounds());
if (ball.getBounds().intersects(paddle.getBounds()))
{
System.out.println("Yay");
}
}
public static void main(String[] args)
{
Timer t = new Timer();
t.schedule(new Breakout(), 0, 40);
panel = new PaintingPanel(PaintingPanel.contents);
setupGame();
beginGame();
while (gameRunning == true)
{
panel.repaint();
}
// TODO a lot
}
private static void showGUI()
{
JFrame frame = new JFrame("Breakout");
game = new Breakout();
frame.addKeyListener(game);
frame.add(panel);
frame.setSize(1000,1000);
frame.setLocationRelativeTo(null); // create game window
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void keyPressed(KeyEvent e) {
Paddle.keyPressed(e);
}
public void keyReleased(KeyEvent e) {
Paddle.keyReleased(e);
}
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
package assignment1;
import java.awt.*;
import java.util.Vector;
import javax.swing.*;
public class PaintingPanel extends JPanel{
public static Vector contents;
public PaintingPanel(Vector contents)
{
contents = new Vector();
contents.addElement(Breakout.paddle);
contents.addElement(Breakout.ball);
System.out.println(contents);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setBackground(Color.GREEN);
g2d.drawRect(2, 2, 800, 800);
Breakout.paddle.paintThis(g2d);
Breakout.ball.paintThis(g2d);
}
}
package assignment1;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
public class Paddle {
public static int PADDLE_SIZE = 100;
public static int PADDLE_THICKNESS = 10;
public static int centreX = 400; // X Centre of the paddle
public static int centreY = 795; // Y Centre of the paddle
public static int paddleX = centreX - (PADDLE_SIZE/2); // Top left X coordinate
public static int paddleY = centreY -(PADDLE_THICKNESS/2); // Top left Y coordinate
public static int dirX;
public Paddle(int paddleX, int paddleY, int PADDLE_SIZE, int PADDLE_THICKNESS)
{
this.paddleX = paddleX;
this.paddleY = paddleY;
this.PADDLE_SIZE = PADDLE_SIZE;
this.PADDLE_THICKNESS = PADDLE_THICKNESS;
System.out.println("Paddle created at " + paddleX + ", " + paddleY + ", " + PADDLE_SIZE + ", " + PADDLE_THICKNESS);
}
public static void paintThis(Graphics g)
{
g.setColor(Color.BLACK);
g.fillRect(paddleX, paddleY, PADDLE_SIZE, PADDLE_THICKNESS);
g.drawRect(paddleX, paddleY, PADDLE_SIZE, PADDLE_THICKNESS);
}
public static Rectangle getBounds()
{
return new Rectangle(paddleX, paddleX, PADDLE_SIZE, PADDLE_THICKNESS);
}
public static void move()
{
paddleX = paddleX + dirX;
}
public static void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_LEFT)
{
dirX = -10;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
{
dirX = 10;
}
else {}
}
public static void keyReleased(KeyEvent e)
{
dirX = 0;
}
}
package assignment1;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Random;
public class Ball {
public static int x;
public static int y;
public static int radius;
public final static Color colour = Color.RED;
public static double dirX;
public static double dirY;
public static int speed = 0;
public Ball(int x, int y, int radius)
{
this.x = x;
this.y = y;
this.radius = radius;
dirX = 0;
dirY = -Math.sqrt(1 - dirX*dirX);
System.out.println("Ball created at " + x + ", " + y + ", " + dirX + ", " + dirY);
}
public static void paintThis(Graphics g)
{
g.setColor(colour);
int width = radius*2;
g.fillOval(x, y, width, width);
g.drawOval(x, y, width, width);
}
public static Rectangle getBounds()
{
return new Rectangle(x, y, radius*2, radius*2);
}
public static void move()
{
x = (int) (x-dirX*speed); //check for inaccuracy
y = (int) (y-dirY*speed);
System.out.println("Moved, New X = " + x + ", new Y = "+ y);
}
public void reflect(boolean horizontal, boolean vertical)
{
if (vertical == true)
{
dirX = 0-dirX;
}
if (horizontal == true)
{
dirY = 0-dirY;
}
}
public boolean intersects(Paddle paddle) {
if (getBounds().intersects(Paddle.getBounds())){
return true;
}
else return false;
}
}
https://dl.dropboxusercontent.com/u/65678182/assignment1.rar

The getBounds() method in the Paddle class seems to be the problem. You are returning a Rectangle with upper left coordinates of paddleX and paddleX. I think you meant
return new Rectangle(paddleX, paddleY, PADDLE_SIZE, PADDLE_THICKNESS);
instead.

Related

Space Invaders Alien Array Issue - Java

I am developing a space invaders application for a college assignment and I've come into a problem where the aliens change direction one by one as they hit a wall rather than the whole array of objects switching direction when any alien touches the boundary. I hae a feeling it is an issue in my for loop where my move method containing reverseDirection() method acts on each element individually but I do not know how to fix this and any help would be greatly appreciated. Here is my code for you;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.*;
public class InvadersApplication extends JFrame implements Runnable {//, KeyListener {
private static final Dimension WindowSize = new Dimension(800, 600);
private static final int NUMALIENS = 16;
private Alien AliensArray[] = new Alien[NUMALIENS];
private Image alienImage;
private Image playerImage;
private String workingDirectory = "C:\\Users\\brads\\IdeaProjects\\Assignment3\\src\\workingDirectory\\";
private Player playerShip;
private BufferStrategy strategy;
public InvadersApplication() {
System.out.println(System.getProperty("user.dir"));
setDefaultCloseOperation(EXIT_ON_CLOSE);
Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
int x = screenSize.width / 2 - WindowSize.width / 2;
int y = screenSize.height / 2 - WindowSize.height / 2;
setBounds(x, y, WindowSize.width, WindowSize.height);
this.setTitle("Alien Invaders App");
ImageIcon playerIcon = new ImageIcon(workingDirectory + "player_ship.png");
playerImage = playerIcon.getImage();
ImageIcon alienIcon = new ImageIcon(workingDirectory + "alien_ship_1.png");
alienImage = alienIcon.getImage();
playerShip = new Player(playerImage);
// addKeyListener(this);
setVisible(true);
createBufferStrategy(2);
strategy = getBufferStrategy();
for (int i = 0; i < NUMALIENS; i++) {
AliensArray[i] = new Alien(alienImage);
AliensArray[i].setPosition(70 * (i%4), 70 * (i/4));
AliensArray[i].setXspeed(1);
}
Thread thread1 = new Thread(this);
thread1.start();
repaint();
}
#Override
public void run(){
while(true){
try{
for(int i = 0; i < NUMALIENS; i++) {
AliensArray[i].move();
}
repaint();
Thread.sleep(5);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/* public void keyPressed(KeyEvent e) {
int KeyCode = e.getKeyCode();
if (KeyCode == KeyEvent.VK_LEFT) {
playerShip.movePlayer(-8);
} else if (KeyCode == KeyEvent.VK_RIGHT) {
playerShip.movePlayer(8);
}
}
*/
public void keyReleased(KeyEvent e){
}
public void keyTyped(KeyEvent e){}
public void paint(Graphics g){
g = strategy.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillRect(0,0,800,600);
for(int i=0; i < NUMALIENS; i++){
AliensArray[i].paint(g);
}
// playerShip.paint(g);
//playerShip.paintPlayer(g);
strategy.show();
this.repaint();
}
public static void main(String[] args){
InvadersApplication x = new InvadersApplication();
}
}
Sprite2D class;
public class Sprite2D{
protected int x = 0,y = 30;
protected Image myImage;
public Sprite2D(Image myImage){
this.x = x;
this.y = y;
this.myImage = myImage;
}
public void setPosition(int xx, int yy){
x = xx;
y = yy;
}
public void paint(Graphics g){
g.drawImage(myImage, x,y, null);
}
}
Alien subclass of sprite2D;
import java.awt.*;
import java.util.Random;
import javax.swing.*;
public class Alien extends Sprite2D {
private int xi;
private int xj;
public Alien(Image myImage) {
super(myImage);
this.myImage = myImage;
this.x = x;
this.y = y;
this.xi = xi;
this.xj = xj;
}
// #Override
// public void setPosition(int xx, int yy){
// xx = x;
// yy = y;
//
// }
public void move() {
y+=xj;
x+= xi;
if(x >= 750) {
reverseDirection();
x = x + xi;
}
else if (x < 0)
{
reverseDirection();
x = x + xi;
}
}
public void setXspeed(int xi) {
this.xi = xi;
}
public void setYspeed(int xj) {
this.xj = xj;
}
public void reverseDirection() {
xi = -xi;
System.out.println("reverse");
}
// #Override
// public void paint(Graphics g) {
//
//
// g.drawImage(myImage, xx, yy, null);
// }
}

Java 2D Platformer Collision Detection for multiple Rectangles

I am working on a 2D platformer in Java for an assignment. The assignment specifies I must use an abstract shape class to draw shapes. The problem I am having is getting my collision detection to work with multiple Rectangle Objects which I am using as platforms - I store these in a list. At the moment my collision detection will move my player regardless of which platform I have collided with, so if I collide with a platform from the right it will move me to the top of that platform because it's still checking another platform below me, and will assume I've hit that, therefore moving me to the top of the platform. I was wondering how I can change this so that my collision detection also detects which platform I have collided with and collide relative to that platform (as opposed to every platform).
Here's what is currently happening:
Expected Output:
My player should stop where it is when colliding with platforms.
My App class:
package A2;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
public class App extends JFrame {
public App() {
final Player player = new Player(200, 100);
final ArrayList<Rectangle> platforms = new ArrayList<>();
platforms.add(new Rectangle(100, 500, 400 ,10));
platforms.add(new Rectangle(500, 100, 10 ,400));
JPanel mainPanel = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
player.draw(g);
for(Rectangle r : platforms){
r.draw(g);
}
}
};
mainPanel.addKeyListener(new InputControl(this, player, platforms));
mainPanel.setFocusable(true);
add(mainPanel);
setLayout(new GridLayout());
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(600, 600);
}
public static void main(String[] args) {
App app = new App();
app.setVisible(true);
}
}
abstract class Shape {
public void draw(Graphics g) { }
}
My input handling class:
package A2;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import static java.awt.event.KeyEvent.*;
public class InputControl implements ActionListener, KeyListener {
App app;
Player player;
Timer time = new Timer(5, this);
ArrayList<Rectangle> platforms;
ArrayList<Integer> keyList = new ArrayList<>();
boolean keyReleased = false;
boolean keyPressed = false;
boolean[] keyUp = new boolean[256];
boolean[] keyDown = new boolean[256];
boolean topCollision = false;
boolean rightCollision = false;
boolean leftCollision = false;
boolean botCollision = false;
boolean onGround = false;
private static final double GRAVITY = 2;
private static final int MAX_FALL_SPEED = 5;
double Xoverlap = 0;
double Yoverlap = 0;
boolean collision = false;
public InputControl(App app, Player player, ArrayList<Rectangle> platforms) {
this.app = app;
this.player = player;
this.platforms = platforms;
time.start();
}
public void gravity(){
if(player.yVelocity > MAX_FALL_SPEED){
player.yVelocity = MAX_FALL_SPEED;
}
player.yVelocity += GRAVITY;
}
public void momentum(){}
public void actionPerformed(ActionEvent e) {
Rectangle2D offset = player.getOffsetBounds();
for(int i = 0; i < platforms.size(); i++) {
Rectangle r = platforms.get(i);
//If collision
if (offset.intersects(r.obj.getBounds2D())) {
//Collision on Y axis
if (offset.getX() + offset.getWidth() > r.obj.getX() &&
offset.getX() < r.obj.getX() + r.obj.getWidth() &&
offset.getY() + offset.getHeight() > r.obj.getY() &&
offset.getY() + player.yVelocity < r.obj.getY() + r.obj.getHeight()) {
player.y -= (offset.getY() + offset.getHeight()) - r.obj.getY();
}
//Collision on X axis
if (offset.getX() + offset.getWidth() + player.xVelocity > r.obj.getX() &&
offset.getX() + player.xVelocity < r.obj.getX() + r.obj.getWidth() &&
offset.getY() + offset.getHeight() > r.obj.getY() &&
offset.getY() < r.obj.getY() + r.obj.getHeight()) {
player.x -= (offset.getX() + offset.getHeight()) - r.obj.getX();
}
}
else {
player.x += player.xVelocity;
player.y += player.yVelocity;
}
}
player.x += player.xVelocity;
player.y += player.yVelocity;
app.repaint();
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() >= 0 && e.getKeyCode() < 256) {
keyDown[e.getKeyCode()] = true;
keyUp[e.getKeyCode()] = false;
keyPressed = true;
keyReleased = false;
}
if (keyDown[VK_UP]) {
player.yVelocity = -1;
}
if (keyDown[VK_RIGHT]){
player.xVelocity = 1;
}
if (keyDown[VK_LEFT]) {
player.xVelocity = -1;
}
if (keyDown[VK_DOWN]) {
player.yVelocity = 1;
}
}
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() >= 0 && e.getKeyCode() < 256) {
keyDown[e.getKeyCode()] = false;
keyUp[e.getKeyCode()] = true;
keyPressed = false;
keyReleased = true;
}
if(keyUp[VK_RIGHT] || keyUp[VK_LEFT]){
player.xVelocity = 0;
}
if(keyUp[VK_UP]){
player.yVelocity = 0;
}
}
public void keyTyped(KeyEvent e) { }
}
My Player class:
package A2;
import java.awt.*;
import java.awt.geom.Rectangle2D;
public class Player extends Shape {
public double xVelocity;
public double yVelocity;
public double x;
public double y;
public double width = 60;
public double height = 60;
public double weight = 5;
public Rectangle2D obj;
public Player(double x, double y) {
this.x = x;
this.y = y;
obj = new Rectangle2D.Double(x, y, width, height);
}
public Rectangle2D getOffsetBounds(){
return new Rectangle2D.Double( x, y, width, height);
}
public void draw(Graphics g) {
Color c =new Color(1f,0f,0f,0.2f );
obj = new Rectangle2D.Double(x, y, width, height);
g.setColor(Color.BLACK);
Graphics2D g2 = (Graphics2D)g;
g2.fill(obj);
g.drawString("(" + String.valueOf(x) + ", " + String.valueOf(y) + ")", 10, 20);
g.drawString("X Speed: " + String.valueOf(xVelocity) + " Y Speed: " + String.valueOf(yVelocity) + ")", 10, 35);
g.setColor(c);
}
}
My Rectangle class:
package A2;
import java.awt.*;
import java.awt.geom.Rectangle2D;
public class Rectangle extends Shape {
public double width;
public double height;
public double x;
public double y;
boolean hasCollided = false;
public Rectangle2D obj;
public Rectangle(double x, double y, double width, double height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
obj = new Rectangle2D.Double(x, y, width, height);
}
public void draw(Graphics g) {
g.setColor(Color.ORANGE);
Graphics2D g2 = (Graphics2D)g;
g2.fill(obj);
}
}
First, define ColorRectangle class that extends Shape and provide logic for drawing:
// extends java.awt.Shape
abstract class ColorRectangle extends Rectangle {
private static final long serialVersionUID = -3626687047605407698L;
private final Color color;
protected ColorRectangle(int x, int y, int width, int height, Color color) {
super(x, y, width, height);
this.color = color;
}
public void draw(Graphics2D g) {
g.setColor(color);
g.fillRect(x, y, width, height);
}
}
Second, define separate class for represent Player and Platform:
public final class Player extends ColorRectangle {
private static final long serialVersionUID = -3909362955417024742L;
public Player(int width, int height, Color color) {
super(0, 0, width, height, color);
}
}
public final class Platform extends ColorRectangle {
private static final long serialVersionUID = 6602359551348037628L;
public Platform(int x, int y, int width, int height, Color color) {
super(x, y, width, height, color);
}
public boolean intersects(Player player, int offsX, int offsY) {
return intersects(player.x + offsX, player.y + offsY, player.width, player.height);
}
}
Third, define class that contains logic of demo application. Actually, you could split logic for demo and logic for board (including actiona and key listeners), but these classes are very simple, so in given case, no need to split it.
public class CollisionDetectionDemo extends JFrame {
public CollisionDetectionDemo() {
setLayout(new GridLayout());
add(new MainPanel());
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(600, 600);
}
private static class MainPanel extends JPanel implements ActionListener, KeyListener {
private static final long serialVersionUID = 8771401446680969350L;
private static final int OFFS = 5;
private final Player player = new Player(60, 60, Color.BLACK);
private final List<Platform> platforms = Arrays.asList(
new Platform(100, 500, 400, 10, Color.ORANGE),
new Platform(500, 100, 10, 410, Color.RED),
new Platform(150, 300, 100, 10, Color.BLUE),
new Platform(150, 100, 100, 10, Color.GREEN));
private MainPanel() {
player.x = 200;
player.y = 200;
new Timer(5, this).start();
setFocusable(true);
addKeyListener(this);
}
private void drawPlayerPosition(Graphics g) {
g.setColor(Color.BLACK);
g.drawString(String.format("(%d, %d)", player.x, player.y), 10, 20);
}
private void movePlayer(int offsX, int offsY) {
if (!intersects(player, offsX, offsY)) {
player.x += offsX;
player.y += offsY;
}
}
private boolean intersects(Player player, int offsX, int offsY) {
for (Platform platform : platforms)
if (platform.intersects(player, offsX, offsY))
return true;
return false;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Color color = g.getColor();
drawPlayerPosition(g);
player.draw((Graphics2D)g);
platforms.forEach(platform -> platform.draw((Graphics2D)g));
g.setColor(color);
}
#Override
public void actionPerformed(ActionEvent event) {
repaint();
}
#Override
public void keyTyped(KeyEvent event) {
}
#Override
public void keyPressed(KeyEvent event) {
if (event.getKeyCode() == VK_UP)
movePlayer(0, -OFFS);
else if (event.getKeyCode() == VK_DOWN)
movePlayer(0, OFFS);
else if (event.getKeyCode() == VK_LEFT)
movePlayer(-OFFS, 0);
else if (event.getKeyCode() == VK_RIGHT)
movePlayer(OFFS, 0);
}
#Override
public void keyReleased(KeyEvent event) {
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new CollisionDetectionDemo().setVisible(true));
}
}

JFrame add only one class

I'am making a game, and my JFrame add only one class, i don't getting error, but one of two classes dosen't show. I am try to make JFrame frame 2 = new JFrame();, but nothing.
Game.java:
import java.awt.Component;
import javax.swing.JFrame;
public class Game{
private static final int WIDTH = 800;
private static final int HEIGHT = 600;
private static final String TITLE = "Game Dev [ Week #1 ]";
public static void main(String[] args){
JFrame frame = new JFrame();
Player player = new Player();
Rabbit rabbit = new Rabbit();
// Draw on the map
player.setPlayer(250,250);
rabbit.setRabbit(200,200);
// Draw on the map
frame.add(player);
frame.add(rabbit); // Add only this
// Window
frame.setVisible(true);
frame.setSize(WIDTH,HEIGHT);
frame.setTitle(TITLE);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Player.java:
public class Player extends JPanel implements ActionListener, KeyListener{
// Varibles
Timer time = new Timer(5, this);
static int x; double velX = 0;
static int y; double velY = 0;
private BufferedImage player;
boolean W = false;
boolean A = false;
boolean S = false;
boolean D = false;
public void setPlayer(int x, int y){
this.x = x;
this.y = y;
}
public Player(){
time.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
try {
player = ImageIO.read(getClass().getResourceAsStream("/Player.png"));
} catch (IOException e){
e.printStackTrace();
}
}
// Draw player
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(player, (int)x, (int)y, 100, 100, null);
}
// Set the start up position of player
public void actionPerformed(ActionEvent e){
x += velX;
y += velY;
repaint();
}
// Functions for keyEvent
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if(key == KeyEvent.VK_W) // UP
velY = -0.5;
if(key == KeyEvent.VK_A) // LEFT
velX = -0.5;
if(key == KeyEvent.VK_S) // DOWN
velY = 1.5;
if(key == KeyEvent.VK_D) // RIGHT
velX = 1.5;
}
public void keyTyped(KeyEvent e){}
// IF any key released
public void keyReleased(KeyEvent arg0) {
velX = 0;
velY = 0;
W = false;
A = false;
S = false;
D = false;
}
}
Rabbit.java:
public class Rabbit extends JPanel implements ActionListener{
static int x; double velX = 0;
static int y; double velY = 0;
BufferedImage rabbit;
public void setRabbit(int x, int y){
this.x = x;
this.y = y;
}
public Rabbit(){
try {
rabbit = ImageIO.read(getClass().getResourceAsStream("/Rabbit.png"));
} catch (IOException e){
e.printStackTrace();
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(rabbit, (int)x, (int)y, 100, 100, null);
}
public void actionPerformed(ActionEvent e){
x += velX;
y += velY;
repaint();
}
}
What's happening is that the JFrame is not combining the graphics for Player and Rabbit; rather, it is placing the player as a panel, and then placing the rabbit. So, the player and the rabbit are always separated. What you want is the Player and Rabbit classes NOT to extend JPanel, but to have a method called paint(Graphics). That way, you can make a class called GamePanel that extends JPanel, and create new methods setPlayer(Player) and setRabbit(Rabbit). The GamePanel class should look like this:
public class GamePanel extends JPanel {
Player player;
Rabbit rabbit;
public void setPlayer(Player player) {
this.player = player;
}
public void setRabbit(Rabbit rabbit) {
this.rabbit = rabbit;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
player.paint(g);
rabbit.paint(g);
}
}
and your Player class should look like this:
public class Player {
public void paint(Graphics g) {
// How to paint the graphics in the player class
}
}
and your Rabbit class should look the same, except as public class Rabbit.
Hope that helps!
EDIT: Full Script
package game;
import java.awt.Graphics;
public interface Displayable {
public void paint(Graphics graphics);
}
package game;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.ImageObserver;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Rabbit implements Displayable {
private int x, y;
private Image image;
public Rabbit(int x, int y) throws IOException {
this.x = x;
this.y = y;
this.image = ImageIO.read(new File("RABBIT_FILE")); // Replace
// "RABBIT_FILE"
// with the image
// file you have
}
public void paint(Graphics graphics) {
graphics.drawImage(this.image, this.x, this.y, new ImageObserver() {
public boolean imageUpdate(Image img, int infoflags, int x, int y,
int width, int height) {
return false;
}
});
/**
* Optional: JDK 8 only:
*
* graphics.drawImage(this.image, this.x, this.y, (Image img, int
* infoflags, int x0, int y0, int width0, int height0) -> false);
* //Lambda Expression
*/
}
public void setCoordinates(int x, int y) {
this.x = x;
this.y = y;
}
}
package game;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.ImageObserver;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Player implements Displayable {
private int x, y;
private Image image;
public Player(int x, int y) throws IOException {
this.x = x;
this.y = y;
this.image = ImageIO.read(new File("PLAYER_FILE")); // Replace
// "PLAYER_FILE"
// with the image
// file you have
}
public void paint(Graphics graphics) {
graphics.drawImage(this.image, this.x, this.y, new ImageObserver() {
public boolean imageUpdate(Image img, int infoflags, int x, int y,
int width, int height) {
return false;
}
});
/**
* Optional: JDK 8 only:
*
* graphics.drawImage(this.image, this.x, this.y, (Image img, int
* infoflags, int x0, int y0, int width0, int height0) -> false);
* //Lambda Expression
*/
}
public void setCoordinates(int x, int y) {
this.x = x;
this.y = y;
}
}
package game;
import java.awt.Graphics;
import javax.swing.JPanel;
public final class GamePanel extends JPanel {
private static final long serialVersionUID = -385535147711891740L;
private Player player;
private Rabbit rabbit;
public void setPlayer(Player player) {
this.player = player;
}
public void setRabbit(Rabbit rabbit) {
this.rabbit = rabbit;
}
public GamePanel(Player player, Rabbit rabbit) {
this.setPlayer(player);
this.setRabbit(rabbit);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
this.player.paint(g);
this.rabbit.paint(g);
}
}
package game;
import javax.swing.JFrame;
public final class Main {
public static void main(String... args) {
try {
JFrame frame = new JFrame("Player & Rabbit Game"); // Or whatever
// title
// you have in mind
GamePanel panel = new GamePanel(new Player(0, 0), new Rabbit(0, 0));
frame.add(panel);
frame.setVisible(true);
frame.setDefaultCloseOperation(3);
frame.setExtendedState(6);
} catch (Exception e) {
// Handle Exception if file is corrupted, unable to be read to an
// image, or does not exist
}
}
}

Java 4-Way Pong, Stuck With Checking for Collisions

I am working on a 4 Way Pong Program. I have it to the point where my paddles will move with mouse movement, and the ball will bounce around the screen.
I am stuck when it comes to figuring out how to check for collisions between the ball and the paddles (which will increase the score) and between the ball and the edges of the JPanel (which will end the game).
Any guidance is greatly appreciated...
Game Class
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Game extends JPanel {
JFrame window = new JFrame();
Timer timer = new Timer(30, new ActionHandler());
ArrayList<Ball> balls = new ArrayList<Ball>();
ArrayList<Paddle> horizPaddles = new ArrayList<Paddle>();
ArrayList<Paddle> vertPaddles = new ArrayList<Paddle>();
Paddle pTop;
Paddle pBottom;
Paddle pRight;
Paddle pLeft;
Ball b;
int score = 0;
JLabel scoreLabel;
//==========================================================
public Game() {
window.setBounds(100,100,900,500);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setTitle("4 Way Pong");
window.setResizable(false);
JPanel scorePanel = new JPanel(true);
scoreLabel = new JLabel("Current Score: " + Integer.toString(score));
scoreLabel.setFont(new Font("sansserif", Font.PLAIN, 20));
scoreLabel.setForeground(Color.RED);
scorePanel.add(scoreLabel);
JPanel buttons = new JPanel(true);
Container con = window.getContentPane();
con.setLayout(new BorderLayout());
con.add(this, BorderLayout.CENTER);
con.add(buttons, BorderLayout.SOUTH);
con.add(scorePanel, BorderLayout.NORTH);
this.setBackground(Color.BLACK);
this.addMouseMotionListener(new MouseMoved());
ButtonCatch bc = new ButtonCatch();
JButton btn;
btn = new JButton("New Game");
btn.addActionListener(bc);
buttons.add(btn);
btn = new JButton("Swap Colors");
btn.addActionListener(bc);
buttons.add(btn);
btn = new JButton("High Scores");
btn.addActionListener(bc);
buttons.add(btn);
btn = new JButton("Save Score");
btn.addActionListener(bc);
buttons.add(btn);
btn = new JButton("Quit");
btn.addActionListener(bc);
buttons.add(btn);
timer.start();
window.setVisible(true);
}
//==========================================================
public static void main(String[] args) {
new Game();
}
//==========================================================
public void update() {
for(Ball b : balls) {
b.move(getWidth() + 30, getHeight() + 25);
}
//checkSideCollision();
//checkHorizPaddleCollision();
//checkVertPaddleCollision();
repaint();
}
//==========================================================
public void checkSideCollision() {
if(b.getyPos() > getHeight()) {
JOptionPane.showMessageDialog(null, "Game Over. You Scored " + score + ".", "GAME OVER", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}
//==========================================================
public void checkHorizPaddleCollision() {
if(b.getxPos() == pBottom.getX() && b.getyPos() == pBottom.getY()) {
//b.yPos = b.yPos - 5;
score++;
}
}
//==========================================================
public void checkVertPaddleCollision() {
}
//==========================================================
public class ButtonCatch implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
switch(e.getActionCommand()) {
case "Quit": JOptionPane.showMessageDialog(null, "You Quit... No Score Recorded", "Game Over", JOptionPane.INFORMATION_MESSAGE); System.exit(0);
case "New Game": newGame(); break;
case "Swap Colors": swapColors(); break;
case "High Scores": try { displayScores(); } catch (Exception e1) { System.out.println(e1.getMessage()); } break;
case "Save Score": try { saveScore(); } catch (Exception e2) { System.out.println(e2.getMessage()); } break;
}
}
}
//==========================================================
public void paint(Graphics g) {
super.paint(g);
for(Ball b : balls) {
b.draw(g);
}
for(Paddle p : horizPaddles) {
p.draw((Graphics2D) g);
}
for(Paddle p : vertPaddles) {
p.draw((Graphics2D) g);
}
}
//==========================================================
//FIX FOR DISPLAYING SCORES
private void displayScores() throws Exception {
}
//==========================================================
//FIX -- Store Score in a File
private void saveScore() throws Exception {
int userScore = score;
String name = JOptionPane.showInputDialog("Enter Your Name: ");
JOptionPane.showMessageDialog(null, "Saved!\n" + name + " scored " + userScore, "Score Recorded", JOptionPane.INFORMATION_MESSAGE);
}
//==========================================================
private void swapColors() {
for(Ball b : balls) {
if(b.color.equals(Color.red)) {
b.setColor(Color.yellow);
} else if (b.color.equals(Color.yellow)) {
b.setColor(Color.blue);
} else {
b.setColor(Color.red);
}
}
}
//==========================================================
private void newGame() {
//CREATE BALL
balls.clear();
b = new Ball();
b.color = Color.red;
b.dx = (int)(Math.random() * 4) + 1;
b.dy = (int)(Math.random() * 4) + 1;
b.xPos = (int)(Math.random() * 4) + 1;
b.yPos = (int)(Math.random() * 4) + 1;
balls.add(b);
//CREATE PADDLES
horizPaddles.clear();
vertPaddles.clear();
// bottom
pBottom = new Paddle();
pBottom.x = getWidth() / 2;
pBottom.y = getHeight();
pBottom.setX(pBottom.getX()-20);
pBottom.setY(pBottom.getY()-20);
pBottom.setWidth(100);
pBottom.setHeight(20);
horizPaddles.add(pBottom);
//top
pTop = new Paddle();
pTop.x = getWidth() / 2;
pTop.y = getHeight();
pTop.setX(0 + pTop.getX());
pTop.setY(0);
pTop.setWidth(100);
pTop.setHeight(20);
horizPaddles.add(pTop);
//left
pLeft = new Paddle();
pLeft.x = getWidth() / 2;
pLeft.y = getHeight();
pLeft.setX(0);
pLeft.setY(pLeft.getY() / 2);
pLeft.setWidth(20);
pLeft.setHeight(100);
vertPaddles.add(pLeft);
//right
pRight = new Paddle();
pRight.x = getWidth() / 2;
pRight.y = getHeight();
pRight.setX(875);
pRight.setY(pRight.getY() / 2);
pRight.setWidth(20);
pRight.setHeight(100);
vertPaddles.add(pRight);
timer.start();
}
//==========================================================
public class ActionHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent arg0) {
update();
}
}
//==========================================================
public class MouseMoved implements MouseMotionListener {
#Override
public void mouseMoved(MouseEvent e) {
for(Paddle p : horizPaddles) {
p.x = e.getX();
}
for(Paddle p : vertPaddles) {
p.y = e.getY();
}
}
#Override public void mouseDragged(MouseEvent e) {}
}
}
Paddle Class
import java.awt.Color;
import java.awt.Graphics2D;
public class Paddle implements Drawable{
public int x, y, width, height;
public Paddle() {
super();
}
public Paddle(int x, int y, int width, int height) {
super();
setX(x);
setY(y);
setWidth(width);
setHeight(height);
}
#Override
public void draw(Graphics2D g) {
g.setColor(Color.green);
g.fillRect(x, y, width, height);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
}
Ball Class
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.io.IOException;
import java.io.RandomAccessFile;
import javax.swing.JPanel;
public class Ball implements Comparable<Ball>, Cloneable{
private static int count = 0;
public static final int NAME_LENGTH = 20;
public String name = "";
public int xPos=0, yPos=0, dx = 3, dy = 2;
public Color color = Color.red;
public static void resetCounter() { count = 0; }
public Ball() {name = "Rock: " + ++count;}
public Ball(RandomAccessFile file) {
load(file);
}
public void load(RandomAccessFile file) {
try {
xPos = file.readInt();
yPos = file.readInt();
dx = file.readInt();
dy = file.readInt();
color = new Color( file.readInt() );
byte[] n = new byte[NAME_LENGTH];
file.readFully(n);
name = new String(n).trim();
System.out.println(name);
} catch (IOException e) {
e.printStackTrace();
}
}
public void save(RandomAccessFile file) {
try {
file.writeInt(xPos);
file.writeInt(yPos);
file.writeInt(dx);
file.writeInt(dy);
file.writeInt(color.getRGB());
file.writeBytes( getStringBlock(name, NAME_LENGTH) );
} catch (IOException e) {
e.printStackTrace();
}
}
private String getStringBlock(String string, int len) {
StringBuilder sb = new StringBuilder(name);
sb.setLength(len);
return sb.toString();
}
public void draw(Graphics g) {
g.setColor(color);
g.fillOval(xPos, yPos, 25, 25);
g.setColor(Color.black);
g.drawOval(xPos, yPos, 25, 25);
}
public void setColor(Color c) {
color = c;
}
public void move(int width, int height) {
xPos+=dx;
yPos+=dy;
if(xPos + 50 > width) {
xPos = width - 50;
dx = -dx;
}
if(yPos + 50 > height) {
yPos = height - 50;
dy = -dy;
}
if(xPos < 0) {
xPos = 0;
dx = -dx;
}
if(yPos < 0) {
yPos = 0;
dy = -dy;
}
}
#Override
public int compareTo(Ball arg0) {
return 0;
}
public int getxPos() {
return xPos;
}
public int getyPos() {
return yPos;
}
}
Thanks again...
For the Paddle-Ball collisions, I think calling this method on a timer might suffice:
public void checkPaddleCollisions(){
Rectangle a = new Rectangle(pTop.getX(), pTop.getY(), pTop.getWidth(), pTop.getHeight());
Rectangle b = ... //Do this for all the paddles.
Rectangle ball = new Rectangle(ball.getX(), ball.getY(), ball.getWidth(), ball.getHeight());
if(a.intersects(ball) || b.intersects(ball) || c.intersects(ball) || d.intersects(ball)){
//Increment score and bounce ball.
}
}
As for collisions with the edge, I think you could do something similar, just create 4 rectangles representing the edges of the screen.

Help with adding a paddle to a JFrame

This is an excerise i have to complete for a uni course, its not a marked assignment and i could do with a bit of help. I can get the ball to appear on the screen and bounce of the sides, it doesnt matter at the moment if it falls through the bottom of the screen and i can get the paddle to appear on the screen at different times but i cant get them both to appear at the same time. Help please
Here are my classes
MainClass
package movingball;
public class Main
{
public static void main (String []args)
{
MovingBall world = new MovingBall("Moving Ball");
world.setVisible(true);
world.move();
}
}
BallClass
package movingball;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
public class Ball
{
private final int RADIUS = 10;
private Point pos;
private Color ballColour;
private int yChange = 2;
private int xChange = 1;
private int height, width;
private int change;
public Ball (int frameWidth, int frameHeight)
{
change = 3;
ballColour = Color.RED;
width = frameWidth;
height = frameHeight;
pos = new Point();
pos.x = (int)(Math.random() * (width - RADIUS)) + RADIUS;
pos.y = (int)(Math.random() * (height/2 - RADIUS)) + RADIUS;
}
//There are lots of ways you can updateBallState
//Note that the menu bar occupies some of the visible space
public void move()
{
if(pos.y < RADIUS)
{
yChange = - yChange;
}
if(pos.x < RADIUS)
{
xChange = -xChange;
}
if(pos.x > width - RADIUS)
{
xChange = -xChange;
}
if(pos.y < height - RADIUS)
{
pos.translate(xChange, yChange);
}
if(pos.x < width - RADIUS)
{
pos.translate(xChange, yChange);
}
}
public void updateBallState()
{
if (pos.y + change < height - 3*RADIUS)
{
pos.translate(0, change);
// change++; //accelerate
}
}
//This method can be called with a provided graphics context
//to draw the ball in its current state
public void draw(Graphics g)
{
g.setColor(ballColour);
g.fillOval(pos.x - RADIUS, pos.y - RADIUS, 2*RADIUS, 2*RADIUS);
}
public void bounce()
{
yChange = -yChange;
pos.translate(xChange, yChange);
}
public Point getPosition()
{
return pos;
}
}
BallGame
package movingball;
import java.awt.Graphics;
import java.awt.event.*;
public class BallGame extends MovingBall
{
private Paddle myPaddle = new Paddle(FRAME_WIDTH, FRAME_HEIGHT);
public BallGame(String title)
{
super(title);
addKeyListener(new KeyList());
}
public void paint(Graphics g)
{
super.paint(g);
myPaddle.paint(g);
if(isContact())
{
myBall.bounce();
}
else
{
myPaddle.paint(g);
}
}
public boolean isContact()
{
if (myPaddle.area().contains(myBall.getPosition()))
{
return true;
}
else
{
return false;
}
}
public class KeyList extends KeyAdapter
{
public void keyPressed(KeyEvent k)
{
if(k.getKeyCode() == KeyEvent.VK_LEFT)
{
myPaddle.moveLeft();
}
if(k.getKeyCode() == KeyEvent.VK_RIGHT)
{
myPaddle.moveRight();
}
}
}
}
MovingBall class
package movingball;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MovingBall extends JFrame
{
protected final int FRAME_WIDTH = 240;
protected final int FRAME_HEIGHT = 320;
protected Ball myBall = new Ball(FRAME_WIDTH, FRAME_HEIGHT);
public MovingBall (String title)
{
super(title);
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void paint(Graphics g)
{
super.paint(g);
myBall.draw(g);
}
public void move()
{
while(true)
{
myBall.move();
repaint();
try
{
Thread.sleep(50);
}
catch(InterruptedException e)
{
System.exit(0);
}
}
}
}
Paddle class
package movingball;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Paddle
{
private Color paddleColour = Color.GREEN;
private int x,y;
private int paddleWidth = 20;
private int paddleHeight = 10;
private int move = 5;
/** Creates a new instance of Paddle */
public Paddle(int frameWidth, int frameHeight)
{
x =(int)(Math.random()*(frameWidth - paddleWidth));
y = frameHeight - paddleHeight;
}
public void moveRight()
{
x = x + move;
}
public void moveLeft()
{
x = x - move;
}
public Rectangle area()
{
return new Rectangle(x,y, paddleWidth, paddleHeight);
}
public void paint(Graphics g)
{
g.setColor(paddleColour);
g.fillRect(x,y,paddleWidth, paddleHeight);
}
}
Here are a couple of pointers to get you started. I have a lot of things to suggest but I'll just say this to get you further than you are now. You want your JFrame to be double-buffered. That's the first step. To do this, create a new buffer strategy for your JFrame after making it visible:
world.setVisible(true);
world.createBufferStrategy(2);
As for why your Paddle isn't painting? You're going to kick yourself. Look at this line:
MovingBall world = new MovingBall("Moving Ball");
You're not actually creating a BallGame, which is where the logic for painting the paddle is contained! (BallGame.paint()) Try:
BallGame world = new BallGame("Moving Ball");

Categories

Resources