0

I am trying to create a Billiards game for my project and I am having difficulty in adding the stick and the balls at the same time. Also, when I add the balls the background of the JFrame goes white, it is actually supposed to be green (the color of the table).

Your help will be much appreciated.

I tried using Graphics. For example g2d.setBackground(Color.green). Which did not work

public class Practice_Window implements MouseListener, MouseMotionListener, KeyListener {

    JFrame Practice_Mode = new JFrame(); 
    Balls myBalls = new Balls(); 
    Stick myStick = new Stick(); 

    public void PracticeWindow()
    {

        Practice_Mode.setSize(1000, 500);
        Practice_Mode.setVisible(true); 
        Practice_Mode.setResizable(false);
        Practice_Mode.setTitle("Practice Mode");
        Practice_Mode.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Practice_Mode.getContentPane().setBackground(new Color(0, 1, 0, 0.5f)); //Not visible after i add my balls
        Practice_Mode.getRootPane().setBorder(BorderFactory.createMatteBorder(10, 10, 10, 10, Color.GREEN));

        Practice_Mode.add(myBalls);
        //Practice_Mode.add(myStick); 

        //JPanel p = new JPanel();

        //Timer t= new Timer(10, myBalls); 


    }

//BALL CLASS
public class Balls extends JPanel implements ActionListener
{
    double Size = 35;

    double REDxSpeed = 5; 
    double REDySpeed = 5;
    double REDSpeed = 0;


    double YELLOWxSpeed = 2; 
    double YELLOWySpeed = 3; 
    double YELLOWSpeed = 0;


    double WHITExSpeed = 4; 
    double WHITEySpeed = 2; 
    double WHITESpeed = 0;

    double friction = 0.2; 

    boolean Collision = false; 

    Ellipse2D.Double red = new Ellipse2D.Double(200, 200, Size, Size);
    Ellipse2D.Double yellow = new Ellipse2D.Double(300, 300, Size, Size); 
    Ellipse2D.Double white = new Ellipse2D.Double(150, 400, Size, Size);

    Timer t = new Timer(10, this); 


    Balls()
    {
        t.start(); 
    }

    @Override
    public void actionPerformed(ActionEvent e) //Things are moving here
    {

        //RED BALL
        red.x += REDxSpeed; 
        red.y += REDySpeed; 
        REDSpeed = Math.sqrt(REDxSpeed*REDxSpeed + REDySpeed*REDySpeed); 

        repaint(); 

        if(red.x < 0 || red.x > getWidth() - red.width)
        {
            REDxSpeed = -REDxSpeed; 
        }

        if(red.y < 0 || red.y > getHeight() - red.height)
        {
            REDySpeed = -REDySpeed; 
        }

        //YELLOW BALL
        yellow.x += YELLOWxSpeed; 
        yellow.y += YELLOWySpeed; 
        YELLOWSpeed = Math.sqrt(YELLOWxSpeed*YELLOWxSpeed + YELLOWySpeed*YELLOWySpeed); 

        repaint(); 

        if(yellow.x < 0 || yellow.x > getWidth() - yellow.width)
        {
            YELLOWxSpeed = -YELLOWxSpeed; 
        }

        if(yellow.y < 0 || yellow.y > getHeight() - yellow.height)
        {
            YELLOWySpeed = -YELLOWySpeed; 
        }

        //WHITE BALL
        white.x += WHITExSpeed; 
        white.y += WHITEySpeed; 
        WHITESpeed = Math.sqrt(WHITExSpeed*WHITExSpeed + WHITESpeed*WHITEySpeed);
        repaint(); 

        if(white.x < 0 || white.x > getWidth() - white.width)
        {
            WHITExSpeed = -WHITExSpeed; 
        }

        if(white.y < 0 || white.y > getHeight() - white.height)
        {
            WHITEySpeed = -WHITEySpeed; 
        }
        Collision_Detection(); 
    }

    public void paintComponent(Graphics g) //DRAWING MY BALLS
    {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D)g; 
        //g2d.setBackground(Color.green);

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(Color.red);
        g2d.fill(red);

        g2d.setColor(Color.yellow);
        g2d.fill(yellow);

        g2d.setColor(Color.black);
        g2d.fill(white);
    }

//STICK CLASS
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Rectangle2D;

import javax.swing.*; 

public class Stick extends JPanel implements MouseListener, MouseMotionListener, ActionListener {
    int xLocation = 50; 
    int yLocation = 50; 
    int Width = 50;  
    int Height = 15;

    Rectangle2D.Double stick = new Rectangle2D.Double(200, 200, Width, Height); 

    Timer t = new Timer(10, this); 

    Stick()
    {
        t.start();
    }

    public void PaintComponent(Graphics g)
    {
        super.paintComponent(g); 
        Graphics2D g2d = (Graphics2D)g; 

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);


        g2d.setColor(Color.ORANGE);
        g2d.fill(stick);

    }
Frakcool
  • 10,915
  • 9
  • 50
  • 89
  • **1)** There's a lot of code here, and it's hard to read as it doesn't follow [Java naming conventions](https://www.oracle.com/technetwork/java/codeconventions-135099.html) `firstWordLowerCaseVariable`, `firstWordLowerCaseMethod()`, `FirstWordUpperCaseClass` and `ALL_WORDS_LOWER_CASE_CONSTANT`. **2)** On your `Stick` class, you have a method `PaintComponent`, it should be `paintComponent` (Java is case sensible), add `@Override` annotation to get warnings from Java compiler. **3)** Why you have so much spacing between lines? It makes it harder to read – Frakcool May 01 '19 at 14:12
  • 4) You're making your frame visible before adding all the elements to it. `Practice_Mode.setVisible(true);` should be the last line on that class after adding all the components. 5) `red`, `yellow`, `white` variable names make me think of colors and not on the balls, change them to `redBall`, `yellowBall`, `whiteBall`, this way they are more descriptive. 6) Make `myBalls` not opaque (`setOpaque(false)`), see https://stackoverflow.com/a/4416644/2180785 – Frakcool May 01 '19 at 14:22

2 Answers2

2

I am having difficulty in adding the stick and the balls at the same time.

So why are you trying to write your entire application at once without doing any testing along the way? Why do you have Timers in the code? Why do you have KeyListeners?

Learn to develop applications one step at a time. Write a little code do some testing. When it works add more functionality. Get the basic right first before adding more complicated logic.

Practice_Mode.add(myBalls);
//Practice_Mode.add(myStick); 

The default layout manager of a JFrame is the BorderLayout. By default, when you add a component to the frame (and don't specify a constraint) the component goes to the CENTER. Only a single component can be added to the CENTER so only the last component added will be visible.

Your basic design is wrong. You don't want to have separate panels for the balls and stick. You want to have a single "BilliardsGameBoard" panel that will paint multiple objects. So this panel will paint all the balls and the stick. This way all the objects are managed by the same class.

You should also not be creating individual objects with variable names. This limits the number of object you can control. Instead, keep the objects you want to paint in an ArrayList, then the painting method iterates through the ArrayList and paints each object.

See: get width and height of JPanel outside of the class for a working example of this approach.

I add the balls the background of the JFrame goes white,

Practice_Mode.getContentPane().setBackground(new Color(0, 1, 0, 0.5f)); 

Don't use alpha values when you specify your color. For green you can just use:

practiceMode.getContentPane().setBackground( Color.GREEN );
camickr
  • 321,443
  • 19
  • 166
  • 288
0

Your stick and balls are extending JPanel, which is typically used as a container to group a bunch of JComponents, which are buttons and UI elements. The graphical errors you see is likely Java trying to line up your panels side by side using the default BorderLayout, because it thinks you want panels of buttons and stuff when you are just trying to achieve freeform shapes.

A better approach would be to to render your stick and balls as primitive shapes on a JPanel, rather than as JPanels themselves. This is accomplished by making them implement Shape or at least giving them draw methods; the Primitives tutorial would be of use. This question also has somebody in a somewhat similar situation as yourself, and has answers relevant to you.

Brandon McKenzie
  • 1,655
  • 11
  • 26