0

I'm new to Java and I've recently been trying to make an Atari Breakout game. I managed to get the player moving and the ball to bounce but not at the same time in the JFrame (the component that was added the latest is the one that is being shown). I made two seperate classes for the player and the ball (both extending from JPanel) and I think that might be the problem, though I don't really know.

Anyway, this is the code for the player:

import java.awt.Color;
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.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Rectangle2D;
import javax.swing.JPanel;
import javax.swing.Timer;


public class Player extends JPanel implements ActionListener, KeyListener{
    Timer t = new Timer(5,this);
    int x=200,vel=0;
    boolean outOfBoundsR = true, outOfBoundsL = true;
    public Player(){
        t.start();
        addKeyListener(this);
        setFocusable(true);
    }
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        Rectangle r= g2.getClipBounds();
        r.x = x;
        g2.setColor(Color.blue);
        g2.fill(new Rectangle2D.Double(r.getX(),350,100,5));
        if(r.getX()>385){
            vel=0;
            outOfBoundsR = false;
        }else if(r.getX()<0){
            vel=0;
            outOfBoundsL = false;
        }

    }
    public void actionPerformed(ActionEvent e){
        repaint();
        x+=vel;
    }
    public void right(){
        vel = 1;
    }
    public void left(){
        vel = -1;
    }
    public void keyPressed(KeyEvent e){
        int key = e.getKeyCode();
        if(key == KeyEvent.VK_RIGHT&&outOfBoundsR){
            outOfBoundsL=true;
            right();
        } else if(key == KeyEvent.VK_LEFT&&outOfBoundsL){
            outOfBoundsR=true;
            left();
        }

    }
    public void keyReleased(KeyEvent e) {vel = 0;}
    public void keyTyped(KeyEvent e) {}
}

This is the code for the ball:

 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.KeyListener;
 import java.awt.geom.Ellipse2D;
 import java.awt.geom.Rectangle2D;
 import javax.print.attribute.standard.Media;
 import javax.swing.JPanel;
 import javax.swing.Timer;

public class Ball extends JPanel implements ActionListener{
    Timer t = new Timer(5,this);
    double velx = 0, vely = -1, x = 250, y = 330;

    public Ball(){
        t.start();
        setFocusable(true);
    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        Rectangle r = g2.getClipBounds();
        r.x = (int) x;
        r.y = (int) y;
        g2.fill(new Ellipse2D.Double(r.getX(), r.getY(), 8, 8));
        if(r.getY() < 0 || r.getY() > 355){
            vely -= (vely*2);
        }else if(r.getX() < 0 || r.getX() > 480){
            velx -= (velx*2);
        }
    }

    public void actionPerformed(ActionEvent e) {
        repaint();
        x += velx;
        y += vely;
    }

}

And this is the code for the GUI:

import javax.swing.JFrame;

public class Gui extends JFrame{

    public static void main(String[] args) {

        JFrame f= new JFrame(); // the frame
        Ball b = new Ball();    // the ball
        Player p = new Player();// the player

        f.getContentPane().add(p);
        f.getContentPane().add(b);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(500,400);
        f.setVisible(true);
    }

}

Thanks in advance! (I know this was a bit long...)

Ofri Adiv
  • 41
  • 1
  • 6
  • 2
    The player and the ball are not conceptually panels. You want one panel that draws the game, and independent classes for entities like player and ball. – khelwood Dec 21 '15 at 09:49
  • 2
    Short answer is, don't. Instead, use a single component which does all the rendering, then use POJO objects which maintain the basic information about each entity and which are capable for been painted from your main "render" component – MadProgrammer Dec 21 '15 at 09:52
  • 1
    The larger problem is, your container (frame) is managed by a layout manager (`BorderLayout` in this instance) which will prevent the components from interacting with each other. If you wished to continue using component based "entities", then you will need to write your own layout manager to manage them. See [this example](http://stackoverflow.com/questions/13022754/java-bouncing-ball/13022788#13022788) for what my previous comment is talking about – MadProgrammer Dec 21 '15 at 10:00

2 Answers2

1

I don't know how you want your Ball and Player objects to interact, but in your example f.getContentPane().add(...) translates to f.getContentPane().add(..., BorderLayout.CENTER). Therefore, p is replaced by b in the subsequent call to add - the content pane of JFrame makes use of a BorderLayout by default.

Have a look at the Swing layout manager tutorial for more information.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
PA001
  • 451
  • 3
  • 12
  • Conceptually, yes, actually no. If `BorderLayout` receives no constraint when it's `addLayoutComponent` is called, it defaults it to the `CENTER` position – MadProgrammer Dec 21 '15 at 09:54
  • Correct, that's what I meant by saying: `f.getContentPane().add(...)` translates to `f.getContentPane().add(..., BorderLayout.CENTRE)` - probably not as clear as I could have been! – PA001 Dec 21 '15 at 10:40
0

I think that better way to do it is make player and ball as component and make next object which can be JPanel as a game. But your way should work too. Problem can be with chosen layout in your frame. I can suggest this changes for you.

   public static void main(String[] args) {

      JFrame f= new JFrame(); // the frame
      Ball b = new Ball();    // the ball
      Player p = new Player();// the player

      f.getContentPane().add(p, BorderLayout.CENTRE);
      f.getContentPane().add(b, BorderLayout.EAST);
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      f.setSize(500,400);
      f.setVisible(true);
   }
Ján Яabčan
  • 743
  • 2
  • 10
  • 20