I am trying to build a basic Arcanoid/Breakout style game in JAVA. I am having trouble with the collision detection between the ball and the bricks. I am using bounding boxes around all entities in the game. When the ball hits the player's paddle, the collision is detected. When the ball hits the bricks coordinates, no collision is detected. Any one have any ideas. Code below.
Game.java
package com.seadnamcgillycuddy.unipong;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JOptionPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Game extends JPanel {
Ball ball = new Ball(this);
Paddle paddle = new Paddle(this);
Brick brick = new Brick(this, 50, 20);
Brick brick2 = new Brick(this, 75, 20);
Brick brick3 = new Brick(this, 100, 20);
Brick brick4 = new Brick(this, 125, 20);
Brick brick5 = new Brick(this, 150, 20);
Brick brick6 = new Brick(this, 175, 20);
Brick brick7 = new Brick(this, 200, 20);
Brick brick8 = new Brick(this, 225, 20);
Brick brick9 = new Brick(this, 250, 20);
int speed = 1;
private int getScore() {
return speed - 1;
}
public Game() {
addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
paddle.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
paddle.keyPressed(e);
}
});
setFocusable(true);
}
private void move() {
ball.move();
paddle.move();
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
ball.paint(g2d);
paddle.paint(g2d);
brick.paint(g2d);
brick2.paint(g2d);
brick3.paint(g2d);
brick4.paint(g2d);
brick5.paint(g2d);
brick6.paint(g2d);
brick7.paint(g2d);
brick8.paint(g2d);
brick9.paint(g2d);
g2d.setColor(Color.GRAY);
g2d.setFont(new Font("Verdana", Font.BOLD, 30));
g2d.drawString(String.valueOf(getScore()), 10, 30);
}
public void gameOver() {
JOptionPane.showMessageDialog(this, "Your Score Is: " + getScore(), "Game Over", JOptionPane.YES_NO_OPTION);
System.exit(ABORT);
}
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame("UniPong");
Game game = new Game();
frame.add(game);
frame.setSize(400, 750);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while (true){
game.move();
game.repaint();
Thread.sleep(10);
}
}
}
Ball.java
package com.seadnamcgillycuddy.unipong;
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class Ball {
private static final int DIAMETER = 10;
int x = 0;
int y = 0;
int xa = 1;
int ya = 1;
private Game game;
public Ball(Game game) {
this.game = game;
}
void move() {
boolean changeDirection = true;
if (x + xa < 0)
xa = game.speed;
else if (brickCollision()){
System.out.println("Collission!!!!");
}
else if (x + xa > game.getWidth() - DIAMETER)
xa = -game.speed;
else if (y + ya < 0)
ya = game.speed;
else if (y + ya > game.getHeight() - DIAMETER)
game.gameOver();
else if (collision()) {
ya = -game.speed;
y = game.paddle.getTopY() - DIAMETER;
game.speed++;
} else
changeDirection = false;
x = x + xa;
y = y + ya;
}
private boolean collision() {
return game.paddle.getBounds().intersects(getBounds());
}
private boolean brickCollision() {
return game.brick.getBounds().intersects(getBounds());
//return game.ball.getBounds().intersects(getBounds());
}
public void paint (Graphics2D g) {
g.fillOval(x, y, DIAMETER, DIAMETER);
}
public Rectangle getBounds() {
return new Rectangle(x, y, DIAMETER, DIAMETER);
}
}
Brick.java
package com.seadnamcgillycuddy.unipong;
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class Brick {
int Y;
int X;
private static final int WIDTH = 20;
private static final int HEIGHT = 10;
private Game game;
public Brick(Game game, int X, int Y) {
this.X = X;
this.Y = Y;
this.game = game;
}
public void paint(Graphics2D g) {
g.fillRect(X, Y, WIDTH, HEIGHT);
}
public Rectangle getBounds() {
return new Rectangle(X, Y, WIDTH, HEIGHT);
}
public int getBrickBottomY() {
return Y - HEIGHT;
}
}
Paddle.java
package com.seadnamcgillycuddy.unipong;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.Rectangle;
public class Paddle {
private static final int Y = 680;
private static final int WIDTH = 60;
private static final int HEIGHT = 10;
int x = 0;
int xa = 0;
private Game game;
public Paddle(Game game) {
this.game = game;
}
public void move () {
if (x + xa > 0 && x + xa < game.getWidth() - 60)
x = x + xa;
}
public void paint(Graphics2D g) {
g.fillRect(x, Y, WIDTH, HEIGHT);
}
public void keyReleased(KeyEvent e) {
xa = 0;
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT)
xa = -game.speed;
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
xa = game.speed;
}
public Rectangle getBounds() {
return new Rectangle(x, Y, WIDTH, HEIGHT);
}
public int getTopY() {
return Y - HEIGHT;
}
}
When you check for collisions with this line
return game.brick.getBounds().intersects(getBounds());
you're only checking intersection with one brick, brick, and not with the other 9 bricks you made, brick1, ..., brick9.
I'd recommend making an array of bricks, and then looping through them and checking collisions with each of them. Then, you can have as many bricks as you want and it won't take more code to check.
Related
I have been working on a Java project that makes a character move with the keys, but the keyListener is not working and registering my actions. I code in eclipse, and I think that problem is my GamePanel, Player, or me KeyChecker class. I am using a guide to help start this, so it is the same code as another project, but it does not work. Here is my code:
class Platformer:
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
public class Platformer {
public static void main(String[] args) {
MainFrame frame = new MainFrame();
frame.setSize(700,700);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setTitle("Platformer");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
class GamePanel:
I have tried changing the layout of the if statements if that was the original problem, but it did not change anything. I also tried changing the statements to just void instead of public void but that did not work either.
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements ActionListener{
Player player;
ArrayList<Wall> walls = new ArrayList<>();
Timer gameTimer;
public GamePanel() {
player = new Player(400, 300, this);
makeWalls();
gameTimer = new Timer();
gameTimer.schedule(new TimerTask() {
public void run() {
player.set();
repaint();
}
},0,17);
}
public void makeWalls() {
for (int i = 50; i < 650; i += 50) {
walls.add (new Wall(i, 600, 50, 50));
}
walls.add(new Wall(50, 550, 50, 50));
walls.add(new Wall(50, 500, 50, 50));
walls.add(new Wall(50, 450, 50, 50));
walls.add(new Wall(600, 550, 50, 50));
walls.add(new Wall(600, 500, 50, 50));
walls.add(new Wall(600, 450, 50, 50));
walls.add(new Wall(450, 550, 50, 50));
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D gtd = (Graphics2D) g;
player.draw(gtd);
for (Wall wall: walls) wall.draw(gtd);
}
public void KeyPressed(KeyEvent e) {
if (e.getKeyChar() == 'a')player.keyLeft = true;
if (e.getKeyChar() == 'w') player.keyUp = true;
if (e.getKeyChar() == 's') player.keyDown = true;
if (e.getKeyChar() == 'd') player.keyRight = true;
}
public void KeyReleased(KeyEvent e) {
if (e.getKeyChar() == 'a') player.keyLeft = false;
if (e.getKeyChar() == 'w') player.keyUp = false;
if (e.getKeyChar() == 's') player.keyDown = false;
if (e.getKeyChar() == 'd') player.keyRight = false;
}
public void actionPerformed(ActionEvent e) {
}
}
class Player:
I also tried the same things that I did for the GamePanel, but that did not work either.
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class Player {
GamePanel panel;
int x;
int y;
int width;
int height;
double xspeed;
double yspeed;
Rectangle hitBox;
boolean keyRight;
boolean keyLeft;
boolean keyUp;
boolean keyDown;
public Player(int x, int y, GamePanel panel) {
this.panel = panel;
this.x = x;
this.y = y;
width = 50;
height = 100;
hitBox = new Rectangle(x,y,width,height);
}
public void set() {
if (keyLeft && keyRight || !keyLeft && !keyRight) xspeed *= 0.8;
else if (keyLeft && !keyRight) xspeed --;
else if (keyRight && !keyLeft) xspeed ++;
if (xspeed > 0 && xspeed < 0.75) xspeed = 0;
if (xspeed < 0 && xspeed > - 0.75) xspeed = 0;
if (xspeed > 7) xspeed = 7;
if (xspeed < -7) xspeed = -7;
if (keyUp) {
hitBox.y++;
for(Wall wall: panel.walls) {
if (wall.hitBox.intersects(hitBox)) yspeed = -6;
}
hitBox.y --;
}
yspeed += .3;
hitBox.x += xspeed;
for(Wall wall: panel.walls) {
if (hitBox.intersects(wall.hitBox)) {
hitBox.x-= xspeed;
while(!wall.hitBox.intersects(hitBox)) hitBox.x += Math.signum(xspeed);
hitBox.x -= Math.signum(xspeed);
xspeed = 0;
x = hitBox.x;
}
}
hitBox.y += xspeed;
for(Wall wall: panel.walls) {
if (hitBox.intersects(wall.hitBox)) {
hitBox.y-= yspeed;
while(!wall.hitBox.intersects(hitBox)) hitBox.y += Math.signum(yspeed);
hitBox.y -= Math.signum(yspeed);
yspeed = 0;
y = hitBox.y;
}
}
x += xspeed;
y += yspeed;
hitBox.x = x;
hitBox.y = y;
}
public void draw(Graphics2D gtd) {
gtd.setColor(Color.BLACK);
gtd.fillRect(x, y, width, height);
}
}
class KeyChecker:
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class KeyChecker extends KeyAdapter{
GamePanel panel;
public KeyChecker(GamePanel panel) {
this.panel = panel;
}
public void KeyPressed(KeyEvent e) {
panel.KeyPressed(e);
}
public void KeyReleased(KeyEvent e) {
panel.KeyReleased (e);
}
}
class Wall:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class Wall {
int x;
int y;
int width;
int height;
Rectangle hitBox;
public Wall (int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = width;
hitBox = new Rectangle(x, y, width, height);
}
public void draw(Graphics2D gtd) {
gtd.setColor(Color.BLACK);
gtd.drawRect(x, y, width, height);
gtd.setColor(Color.WHITE);
gtd.fillRect(x + 1, y + 1, width - 2, height - 2);
}
}
class MainFrame:
import java.awt.Color;
import javax.swing.JFrame;
public class MainFrame extends JFrame{
public MainFrame() {
GamePanel panel = new GamePanel();
panel.setLocation(0,0);
panel.setSize(this.getSize());
panel.setBackground(Color.LIGHT_GRAY);
panel.setVisible(true);
this.add(panel);
addKeyListener(new KeyChecker(panel));
}
}
Thank you for your help.
The functions in KeyChecker should start with lower case, so public void keyPressed and keyReleased.
In addition, you should add implements KeyListener to the classes KeyChecker and GamePanel (remove ActionListener in GamePanel).
Then, add the unimplemented functions. Eclipse will ask you for it.
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
Remark, it's better to #Override the functions keyPressed and keyReleased, rather than creating new functions.
I tried them, it worked!
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));
}
}
I am a new coder. I am having trouble adding a start and stop button for this piece of example code that i am working off. I'm sure i have to mess with with Thread.sleep(10); in the game class. This code starts the game when the program is run. is there a way i could add start button to start the thread. I have created j button already. Thanks.
Game Class
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Game extends JPanel {
Ball ball = new Ball(this);
Racquet racquet = new Racquet(this);
public Game() {
addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
racquet.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
racquet.keyPressed(e);
}
});
setFocusable(true);
}
private void move() {
ball.move();
racquet.move();
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
ball.paint(g2d);
racquet.paint(g2d);
}
public void gameOver() {
JOptionPane.showMessageDialog(this, "Game Over", "Game Over", JOptionPane.YES_NO_OPTION);
System.exit(ABORT);
}
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame("Mini Tennis");
Game game = new Game();
frame.add(game);
frame.setSize(300, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while (true) {
game.move();
game.repaint();
Thread.sleep(10);
}
}
}
Ball Class
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class Ball {
private static final int DIAMETER = 30;
int x = 0;
int y = 0;
int xa = 1;
int ya = 1;
private Game game;
public Ball(Game game) {
this.game= game;
}
void move() {
if (x + xa < 0)
xa = 1;
if (x + xa > game.getWidth() - DIAMETER)
xa = -1;
if (y + ya < 0)
ya = 1;
if (y + ya > game.getHeight() - DIAMETER)
game.gameOver();
if (collision()){
ya = -1;
y = game.racquet.getTopY() - DIAMETER;
}
x = x + xa;
y = y + ya;
}
private boolean collision() {
return game.racquet.getBounds().intersects(getBounds());
}
public void paint(Graphics2D g) {
g.fillOval(x, y, DIAMETER, DIAMETER);
}
public Rectangle getBounds() {
return new Rectangle(x, y, DIAMETER, DIAMETER);
}
}
Racquet Class
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
public class Racquet {
private static final int Y = 330;
private static final int WIDTH = 60;
private static final int HEIGHT = 10;
int x = 0;
int xa = 0;
private Game game;
public Racquet(Game game) {
this.game = game;
}
public void move() {
if (x + xa > 0 && x + xa < game.getWidth() - WIDTH)
x = x + xa;
}
public void paint(Graphics2D g) {
g.fillRect(x, Y, WIDTH, HEIGHT);
}
public void keyReleased(KeyEvent e) {
xa = 0;
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT)
xa = -1;
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
xa = 1;
}
public Rectangle getBounds() {
return new Rectangle(x, Y, WIDTH, HEIGHT);
}
public int getTopY() {
return Y;
}
}
This is an mcve demonstrating the structure outlined in Hovercraft Full Of Eels comment :
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionListener;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class AnimationUsingTimer {
private Timer timer;
AnimationUsingTimer() {
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
AnimationPanel animationPanel = new AnimationPanel();
window.add(animationPanel);
JButton start = new JButton("Start");
start.addActionListener(e -> animationPanel.start());
window.add(start, BorderLayout.PAGE_START);
JButton stop = new JButton("Stop");
stop.addActionListener(e -> animationPanel.stop());
window.add(stop, BorderLayout.PAGE_END);
window.pack();
window.setVisible(true);
}
class AnimationPanel extends JPanel{
private BufferedImage img;
private Area ball, walls;
private final static int W = 450, H = 300, DIAMETER = 20;
private int x = W/2, y = H/2, xDelta = 3, yDelta = 2;
AnimationPanel() {
img = new BufferedImage(W, H, BufferedImage.TYPE_INT_RGB);
JLabel imageLabel = new JLabel(new ImageIcon(img));
add(imageLabel);
walls = new Area(new Rectangle(0,0,W,H));
ActionListener animate = e -> {
animate();
repaint();
};
timer = new Timer(50, animate);
}
public void animate() {
x+=xDelta; y+=yDelta;
ball = new Area(new Ellipse2D.Double(x, y, DIAMETER, DIAMETER));
if (checkCollision(ball,walls)) {
if ( x+DIAMETER>img.getWidth() || x<0 ) {
xDelta *= -1;
}
if(y+DIAMETER>img.getHeight() || y<0 ) {
yDelta *= -1;
}
}
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2D = img.createGraphics();
g2D.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2D.setColor(Color.CYAN);
g2D.fillRect(0, 0, img.getWidth(), img.getHeight());
if(ball != null){
g2D.setColor(Color.RED);
g2D.fill(ball);
}
g2D.dispose();
}
void start(){
timer.start();
}
void stop(){
timer.stop();
}
private boolean checkCollision(Area area1, Area area2) {
return area1.getBounds().intersects(area2.getBounds());
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new AnimationUsingTimer());
}
}
I am new to java code that is fresh code (I used to make minecraft mods) and I am trying to create a simple pong game. I have everything I believe I need for the game to play properly however it seems that the main game class is not calling the other classes when I need it to. Is there anything wrong here that you can see that I am missing? It would be a really great help.
Main Game Class
package crim.pong.main;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Game extends JPanel{
int x = 0;
int y = 0;
int xa = 1;
int ya = 1;
Ball ball = new Ball(this);
Racquet racquet = new Racquet(this);
private void moveBall(){
ball.move();
racquet.move();
}
#Override
public void paint(Graphics g){
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x, y, 30, 30);
ball.paint(g2d);
racquet.paint(g2d);
}
public void gameOver(){
JOptionPane.showMessageDialog(this, "Game Over", "Game Over", JOptionPane.YES_NO_OPTION);
System.exit(ABORT);
}
public static void main(String[] args) throws InterruptedException{
JFrame frame = new JFrame("Pong");
Game game = new Game();
frame.add(game);
frame.setSize(300, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while(true){
game.moveBall();
game.repaint();
Thread.sleep(10);
}
}
}
Keyboard class
package crim.pong.main;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class KeyboardInput extends JPanel{
public KeyboardInput(){
KeyListener listener = new MyKeyListener();
addKeyListener(listener);
setFocusable(true);
}
public static void main(String[] args){
JFrame frame = new JFrame("Pong");
KeyboardInput keyboardInput = new KeyboardInput();
frame.add(keyboardInput);
frame.setSize(200, 200);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public class MyKeyListener implements KeyListener{
#Override
public void keyTyped(KeyEvent e){
}
#Override
public void keyPressed(KeyEvent e){
System.out.println("keyPressed="+KeyEvent.getKeyText(e.getKeyCode()));
}
#Override
public void keyReleased(KeyEvent e){
System.out.println("keyReleased="+KeyEvent.getKeyText(e.getKeyCode()));
}
}
}
Ball class
package crim.pong.main;
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class Ball {
private static final int DIAMETER = 30;
int x = 0;
int y = 0;
int xa = 1;
int ya = 1;
private Game game;
public Ball(Game game){
this.game = game;
}
void move(){
if(x + xa < 0)
xa = 1;
if(x + xa > game.getWidth() - DIAMETER)
xa = -1;
if(y + ya < 0)
ya = 1;
if(y + ya > game.getHeight() - DIAMETER)
game.gameOver();
if(collision()){
ya = -1;
y = game.racquet.getTopY() - DIAMETER;
}
x = x - xa;
y = y - ya;
}
private boolean collision(){
return game.racquet.getBounds().intersects(getBounds());
}
public void paint(Graphics2D g){
g.fillOval(x, y, 30, 30);
}
public Rectangle getBounds(){
return new Rectangle(x, y, DIAMETER, DIAMETER);
}
}
Racquet class
package crim.pong.main;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
public class Racquet {
private static final int Y = 330;
private static final int WIDTH = 60;
private static final int HEIGHT = 20;
int x = 0;
int xa = 0;
private Game game;
public Racquet(Game game){
this.game = game;
}
public void move(){
if(x + xa > 0 && x + xa < game.getWidth() - 60)
x = xa + xa;
}
public void paint(Graphics2D g){
g.fillRect(x, 330, 60, 10);
}
public void keyReleased(KeyEvent e){
xa = 0;
}
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_LEFT)
xa = -1;
if(e.getKeyCode() == KeyEvent.VK_RIGHT)
xa = 1;
}
public Rectangle getBounds(){
return new Rectangle(x, Y, WIDTH, HEIGHT);
}
public int getTopY(){
return Y;
}
}
As mentioned in the comments you have 2 main class files. This is wrong.
A class with a 'main' function is the entry point of the program and obviously there can be only one entry point and presumably you have set this as 'Game'.
KeyboardInput should also not try to create a new JFrame. You only need one and it should be created by your 'Game' class.
If you want to keep the keyboard input in a seperate class then you want 'KeyboardInput' to implement KeyListener directly and then add it to the jframe created by 'Game', e.g.
(In 'Game')
KeyboardInput listener = new KeyboardInput();
addKeyListener(listener);
(In 'KeyboardInput')
public class KeyboardInput implements KeyListener
{
public void keyTyped(KeyEvent e){
//... etc etc
So I developed a game in Java and I'm getting othing while adding image to My JFrame,Its a ball and racket game,I'm using eclipse.I personally think its the directory problem,so for reference I've put the png files in src folder.!
Here is the Code for my Game2 Class:
package Challenger;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Game2 extends JPanel {
Ball ball = new Ball(this);
Ball ball2 = new Ball(this);
Racquet racquet = new Racquet(this);
float speed = (float) 1.0;
int score;
private JButton playMore;
private JButton exitPlease;
static JFrame frame = new JFrame("Challenger");
private Icon defaultImg;
private JLabel bck;
private int getScore() {
return score;
}
public Game2() {
addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
racquet.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
racquet.keyPressed(e);
}
});
setFocusable(true);
bck=new JLabel(new ImageIcon("bg.png"));
bck.setBounds(0, 0, 300, 400);
frame.add(bck);
}
private void move() {
ball.move();
if(score >= 10)
{
float tempSpeed = ball2.getSpeed();
ball2.move2(tempSpeed);
}
racquet.move();
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Graphics2D g3d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
ball.paint(g2d);
racquet.paint(g2d);
if( score >= 10)
{
ball2.paint(g3d);
}
g2d.setColor(Color.RED);
g2d.setFont(new Font("Verdana", Font.BOLD, 20));
g2d.drawString("Score: "+ String.valueOf(getScore()), 10, 30);
}
public void gameOver() {
JOptionPane.showMessageDialog(this, "Game Over", "Game Over", JOptionPane.YES_NO_OPTION);
JOptionPane.showMessageDialog(this, "Your score is: " + getScore(),
"Game Over", JOptionPane.YES_NO_OPTION);
JOptionPane.showMessageDialog(this, "Created By:\n1) DDP-FA12-BCS-009\n2) DDP-FA12-BCS-230\n3) DDP-FA12-BCS-165\n", "Game Over", JOptionPane.YES_NO_OPTION);
System.exit(ABORT);
}
public static void main(String[] args) throws InterruptedException {
Game2 game = new Game2();
frame.add(game);
frame.setSize(300, 400);
frame.setResizable(false);
frame.setVisible(true);
frame.setAlwaysOnTop(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while (true) {
game.move();
game.repaint();
Thread.sleep(10);
}
}
}
This is my Ball Class:
package Challenger;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class Ball {
private static final int DIAMETER = 30;
float x = 0;
float y = 0;
float xa = 1;
float ya = 1;
private Game2 game;
public Ball(Game2 game) {
this.game= game;
}
void move() {
boolean changeDirection = true;
if (x + xa < 0.0)
xa = game.speed;
else if (x + xa > game.getWidth() - DIAMETER)
xa = -game.speed;
else if (y + ya < 0.0)
ya = game.speed;
else if (y + ya > game.getHeight() - DIAMETER)
game.gameOver();
else if (collision()){
ya = -game.speed;
y = game.racquet.getTopY() - DIAMETER;
game.score++;
game.speed = (float) (game.speed + 0.10);
} else
changeDirection = false;
x = x + xa;
y = y + ya;
}
void move2(float speed) {
boolean changeDirection = true;
if (x + xa < 0.0)
xa = speed;
else if (x + xa > game.getWidth() - DIAMETER)
xa = -speed;
else if (y + ya < 0.0)
ya = speed;
else if (y + ya > game.getHeight() - DIAMETER)
game.gameOver();
else if (collision()){
ya = -speed;
y = game.racquet.getTopY() - DIAMETER;
game.score++;
speed = (float) (speed + 0.25);
} else
changeDirection = false;
x = x + xa;
y = y + ya;
}
public float getSpeed(){
return game.speed;
}
public void paint(Graphics2D g) {
g.setColor(Color.BLUE);
g.fillOval((int) x, (int) y, 30, 30);
}
private boolean collision() {
return game.racquet.getBounds().intersects(getBounds());
}
public Rectangle getBounds() {
return new Rectangle((int) x, (int) y, DIAMETER, DIAMETER);
}
}
and This is my Raquet Class:
package Challenger;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
public class Racquet {
int x = 0;
int xa = 0;
private static final int Y = 330;
private static final int WIDTH = 60;
private static final int HEIGHT = 10;
private Game2 game;
public Racquet(Game2 game) {
this.game= game;
}
public void move() {
if (x + xa > 0 && x + xa < game.getWidth()-60)
x = x + xa;
}
public void paint(Graphics2D g) {
g.setColor(Color.BLACK);
g.fillRect(x, 330, 60, 10);
}
public void keyReleased(KeyEvent e) {
xa = 0;
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT)
xa = (int) (-game.speed - 1);
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
xa = (int) (game.speed + 1);
}
public Rectangle getBounds() {
return new Rectangle(x, Y, WIDTH, HEIGHT);
}
public int getTopY() {
return Y;
}
}
You should embed resources using a URL like this
java.net.URL url = getClass().getResource("bg.png");
if (url != null) {
bck = new JLabel(new ImageIcon(url);
} else {
System.err.println("Could not find Image");
}
Your image should be in the same location as your class file, using this "bg.png" relative path. Note: .class file, not .java file.
ProjectRoot
bin
challenger
Racquet.class
Ball.class
Game2.class
bg.png
The above is Eclipse file structure. In Netbeans you want to look in build/classes/challenger/
If you're planning to have a painted panel for your game on top of your background, you may want to use a layered pane. You are adding the background label, then add the game panel to the frame. This will not give you a a layered effect
See How to Use a JLayeredPane