I create a JFrame, followed by a JPanel and the set the parameters. I have a JPanel called boardSquares where each square would be coloured later on.
Once I attempt to add the checker to the board, the board colours are re-arranged.
I have had numerous attempts to fix this but have not succeeded. I am also sure that there is a better way to do this. Below is some code. All help is appreciated!
public void paintComponent(Graphics g)
{
g.setColor(Color.BLUE);
g.fillOval(0, 0, 30, 30);
}
public static void checkerBoard()
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
boardSquares[i][j] = new JPanel();
if ((i + j) % 2 == 0)
{
boardSquares[i][j].setBackground(Color.BLACK);
}
else
{
boardSquares[i][j].setBackground(Color.WHITE);
}
frameOne.add(boardSquares[i][j]);
}
}
}
Look at this example https://www.javaworld.com/article/3014190/learn-java/checkers-anyone.html
And I've little bit upgrade your example
Sorry, I don't have much time for it
import java.awt.*;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.Color;
import java.awt.Graphics;
public class Circle extends JPanel
{
public static JFrame frameOne = new JFrame("Frame 1");
public static Circle boardSquares[][] = new Circle[8][8];
public static void main(String[] args)
{
checkerBoard();
frameOne.setSize(new Dimension(400,400));
frameOne.getContentPane().setLayout(new GridLayout(8,8,0,0));
frameOne.setBackground(Color.BLACK);
frameOne.setVisible(true);
frameOne.setResizable(false);
frameOne.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
boardSquares[1][1].setChecker(true);
}
private Color c;
private boolean checker;
public Circle(int i, int j) {
super();
//setBorder(new Border());
//set
if ((i + j) % 2 == 0)
{
c = Color.DARK_GRAY;
}
else
{
c = Color.WHITE;
}
}
void setChecker(boolean ch) {
checker = ch;
}
public static void checkerBoard()
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
boardSquares[i][j] = new Circle(i, j);
frameOne.add(boardSquares[i][j]);
}
}
}
public void paintComponent(Graphics g)
{
g.setColor(c);
g.fillRect(0, 0, 40, 40);
if (checker) {
g.setColor(Color.BLUE);
g.fillOval(4, 4, 32, 32);
}
}
}
I would create a separate board class and override the paintComponent method to draw the actual grid.
Then I would give the board a grid layout and add panels to hold the checkers.
There is an issue with the margin of the checker, but that may be due to the size of the panels. You can mess around with this. I fixed this by applying a border layout to the panel.
Finally, avoid using "magic numbers". Try to declare some instance variables inside your classes and pass their value in via the constructor or some setter/mutator methods.
Application.java
package game.checkers;
import java.awt.*;
import java.lang.reflect.InvocationTargetException;
import javax.swing.SwingUtilities;
public class Application implements Runnable {
public static final String APP_NAME = "Checkers Game";
private GameFrame gameFrame;
private GameBoard checkerBoard;
#Override
public void run() {
initialize();
Checker redChecker = new Checker(50, Color.RED);
Checker greenChecker = new Checker(50, Color.GREEN);
Checker blueChecker = new Checker(50, Color.BLUE);
checkerBoard.placeChecker(redChecker, 1, 5);
checkerBoard.placeChecker(greenChecker, 2, 4);
checkerBoard.placeChecker(blueChecker, 3, 3);
redChecker.addMouseListener(new CheckerMouseListener(redChecker));
greenChecker.addMouseListener(new CheckerMouseListener(greenChecker));
blueChecker.addMouseListener(new CheckerMouseListener(blueChecker));
}
protected void initialize() {
gameFrame = new GameFrame(APP_NAME);
checkerBoard = new GameBoard(8, 8);
checkerBoard.setPreferredSize(new Dimension(400, 400));
gameFrame.setContentPane(checkerBoard);
gameFrame.pack();
gameFrame.setVisible(true);
}
public static void main(String[] args) {
try {
SwingUtilities.invokeAndWait(new Application());
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
}
GameFrame.java
package game.checkers;
import javax.swing.JFrame;
public class GameFrame extends JFrame {
private static final long serialVersionUID = 6797487872982059625L;
public GameFrame(String title) {
super(title);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
GameBoard.java
package game.checkers;
import java.awt.*;
import javax.swing.JPanel;
public class GameBoard extends JPanel {
private static final long serialVersionUID = 5777309661510989631L;
private static final Color[] DEFAULT_TILE_COLORS = new Color[] { Color.LIGHT_GRAY, Color.WHITE };
private BoardZone[][] zones;
private Color[] tileColors;
private int rows;
private int cols;
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = rows;
}
public int getCols() {
return cols;
}
public void setCols(int cols) {
this.cols = cols;
}
public GameBoard(int rows, int cols, Color[] tileColors) {
super();
this.rows = rows;
this.cols = cols;
this.tileColors = tileColors;
initialize();
}
public GameBoard(int rows, int cols) {
this(rows, cols, DEFAULT_TILE_COLORS);
}
protected void initialize() {
this.setLayout(new GridLayout(rows, cols, 0, 0));
generateZones();
}
private void generateZones() {
this.setLayout(new GridLayout(rows, cols, 0, 0));
this.zones = new BoardZone[rows][cols];
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
this.add(zones[row][col] = new BoardZone());
}
}
}
public void placeChecker(Checker checker, int row, int col) {
zones[row][col].add(checker);
}
public Checker getChecker(int row, int col) {
return (Checker) zones[row][col].getComponent(0);
}
public void removeChecker(Checker checker, int row, int col) {
zones[row][col].remove(checker);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int tileWidth = this.getWidth() / cols;
int tileHeight = this.getHeight() / rows;
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
int x = col * tileWidth;
int y = row * tileHeight;
g.setColor(tileColors[(row + col) % 2]);
g.fillRect(x, y, tileWidth, tileHeight);
}
}
}
}
Checker.java
package game.checkers;
import java.awt.*;
import javax.swing.JComponent;
public class Checker extends JComponent {
private static final long serialVersionUID = -4645763661137423823L;
private int radius;
private Color color;
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public String getHexColor() {
return String.format("#%06X", getColor() == null ? 0 : getColor().getRGB());
}
public Checker(int radius, Color color) {
super();
this.setPreferredSize(new Dimension(radius, radius));
this.radius = radius;
this.color = color;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (this.radius <= 0 || this.color == null) {
return; // Do not draw it.
}
g.setColor(this.color);
g.fillOval(0, 0, this.radius - 1, this.radius - 1);
}
}
BoardZone.java
package game.checkers;
import java.awt.BorderLayout;
import javax.swing.JPanel;
public class BoardZone extends JPanel {
private static final long serialVersionUID = 8710283269464564251L;
public BoardZone() {
this.setOpaque(false);
this.setLayout(new BorderLayout());
}
}
CheckerMouseListener.java
package game.checkers;
import java.awt.event.*;
public class CheckerMouseListener implements MouseListener {
private Checker target;
public CheckerMouseListener(Checker target) {
this.target = target;
}
private String getCheckerName() {
String hexCode = target.getHexColor();
switch (hexCode) {
case "#FFFF0000":
return "RED";
case "#FF00FF00":
return "GREEN";
case "#FF0000FF":
return "BLUE";
default:
return hexCode;
}
}
#Override
public void mouseReleased(MouseEvent e) {
System.out.println("Released click over " + getCheckerName() + " checker.");
}
#Override
public void mousePressed(MouseEvent e) {
System.out.println("Pressed on " + getCheckerName() + " checker.");
}
#Override
public void mouseExited(MouseEvent e) {
System.out.println("Finished hovering over " + getCheckerName() + " checker.");
}
#Override
public void mouseEntered(MouseEvent e) {
System.out.println("Began hovering over " + getCheckerName() + " checker.");
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Clicked on " + getCheckerName() + " checker.");
}
}
Related
Right now I have code to be able to randomize colored squares over a 25x25 board. What I'm trying to do is be able to make those colored squares turn white once pressed on and once it turns white, you can't reverse it. I was thinking about using Listeners but I'm not sure how to start.
Here is what I have to create the randomized squares.
import java.awt.*;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
public class ColoredBoxes {
//Selected Colors
private Color[] availableColors = new Color[] {Color.YELLOW, Color.RED, Color.BLUE, Color.GREEN};
public static void main(String[] args) {
new ColoredBoxes();
}
public ColoredBoxes() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Collapse");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
//Size of the board
protected static final int ROWS = 25;
protected static final int COLS = 25;
protected static final int BOX_SIZE = 25;
private List<Color> colors;
//RandomColors across the given board size.
public TestPane() {
int length = ROWS * COLS;
colors = new ArrayList<Color>();
for (int index = 0; index < length; index++) {
int randomColor = (int) (Math.random() * availableColors.length);
colors.add(availableColors[randomColor]);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(COLS * BOX_SIZE, ROWS * BOX_SIZE);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int xOffset = (getWidth() - (COLS * BOX_SIZE)) / 2;
int yOffset = (getHeight() - (ROWS * BOX_SIZE)) / 2;
System.out.println("...");
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
int index = (row * COLS) + col;
g2d.setColor(colors.get(index));
g2d.fillRect(xOffset + (col * BOX_SIZE), yOffset + (row * BOX_SIZE), BOX_SIZE, BOX_SIZE);
}
}
g2d.dispose();
}
}
}
Any help is much appreciated.
To change color on click, you just need a MouseListener, in the mouseClicked() method you must convert the click coordinates to row and column of the color grid, change that color and then ask the component to repaint.
Here the implementation, I just replaced your 1-dimensional color list with a 2-dimension color array, since it simplify the representation and the conversion from x,y to row,col.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ColoredBoxes {
//Selected Colors
private Color[] availableColors = new Color[] {Color.YELLOW, Color.RED, Color.BLUE, Color.GREEN};
//This is the color that will be set when a cell is clicked
private static final Color CLICKED_COLOR = Color.white;
public static void main(String[] args) {
new ColoredBoxes();
}
public ColoredBoxes() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Collapse");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
//Size of the board
protected static final int ROWS = 25;
protected static final int COLS = 25;
protected static final int BOX_SIZE = 25;
//Since you have a ROWSxCOLS color grid better use a 2-dimension array
private Color[][] cells;
//RandomColors across the given board size.
public TestPane() {
cells=new Color[ROWS][COLS];
for (int i=0;i<cells.length;i++) {
for (int j=0;j<cells[i].length;j++) {
int randomColor = (int) (Math.random() * availableColors.length);
cells[i][j]=availableColors[randomColor];
}
}
//Here the mouse listener, we only need to manage click events
//so I use a MouseAdapter to not implement the complete MouseListener interface
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
onClick(e);
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(COLS * BOX_SIZE, ROWS * BOX_SIZE);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int xOffset = (getWidth() - (COLS * BOX_SIZE)) / 2;
int yOffset = (getHeight() - (ROWS * BOX_SIZE)) / 2;
System.out.println("...");
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
g2d.setColor(cells[row][col]);
g2d.fillRect(xOffset + (col * BOX_SIZE), yOffset + (row * BOX_SIZE), BOX_SIZE, BOX_SIZE);
}
}
g2d.dispose();
}
//Finally the click handler
protected void onClick(MouseEvent e) {
//Convert mouse x,y (that are relative to the panel) to row and col
int xOffset = (getWidth() - (COLS * BOX_SIZE)) / 2;
int yOffset = (getHeight() - (ROWS * BOX_SIZE)) / 2;
int row=(e.getY()-yOffset)/BOX_SIZE;
int col=(e.getX()-xOffset)/BOX_SIZE;
//Check that we are in the grid
if (row>=0&&row<ROWS&&col>=0&&col<COLS) {
//Set new color
cells[row][col]=Color.white;
//Repaint, only the changed region
repaint(xOffset + (col * BOX_SIZE), yOffset + (row * BOX_SIZE), BOX_SIZE, BOX_SIZE);
}
}
}
}
You could use GridPane layout with a custom class for representing the squares
I have a working example here if you want to check
All squares handle their own painting
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
public class ColoredBoxes {
//Selected Colors
private Color[] availableColors = new Color[]{Color.YELLOW, Color.RED, Color.BLUE, Color.GREEN};
public ColoredBoxes() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Collapse");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static void main(String[] args) {
new ColoredBoxes();
}
public class TestPane extends JPanel {
//Size of the board
protected static final int ROWS = 25;
protected static final int COLS = 25;
protected static final int BOX_SIZE = 25;
private List<Square> colors; // List of the representation of the Squares
//RandomColors across the given board size.
public TestPane() {
int length = ROWS * COLS;
GridLayout gridLayout = new GridLayout(ROWS, HEIGHT, 0, 0);
this.setLayout(gridLayout);
colors = new ArrayList<>();
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
int randomColor = (int) (Math.random() * availableColors.length);
Square temp = new Square(availableColors[randomColor], row, col);
colors.add(temp);
this.add(temp);
}
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(COLS * BOX_SIZE, ROWS * BOX_SIZE);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int xOffset = (getWidth() - (COLS * BOX_SIZE)) / 2;
int yOffset = (getHeight() - (ROWS * BOX_SIZE)) / 2;
System.out.println("...");
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
int index = (row * COLS) + col;
g2d.setColor(colors.get(index).getColor());
g2d.fillRect(xOffset + (col * BOX_SIZE), yOffset + (row * BOX_SIZE), BOX_SIZE, BOX_SIZE);
}
}
g2d.dispose();
}
}
public class Square extends JPanel {
private Color color;
private boolean clicked = false;
private int row;
private int col;
public Square(Color color, int row, int col) {
this.row = row;
this.col = col;
this.color = color;
this.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
if (!clicked) {
//do stuff
Square source = (Square) e.getSource();
source.setColor(Color.white);
repaint();//Dont forget the repaint method
clicked = true;
}
}
#Override
public void mousePressed(MouseEvent e) {
if (!clicked) {
//do stuff
Square source = (Square) e.getSource();
source.setColor(Color.white);
repaint();//Dont forget the repaint method
clicked = true;
}
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
g.fillRect(0, 0, getWidth(), getHeight());
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
}
}
** Here i created only one moving object ,i want to create more objects which falls down and has random X coordinate .i know i should implement runnable and i should create squres then store them in a collection but its really hard for me to merge everything.i also might have done some mistakes btw . Could you help me some ? **
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Random;
public class Project3 extends JFrame {
public Project3(){
super("Game");
setSize(600,600);
add(new Game(600,600));
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new Project3());
}
class Squares{
public int x;
public int y;
public Squares(int x, int y) {
this.x = x;
this.y = y;
}
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;
}
}
class Game extends JPanel implements ActionListener {
private int score;
private java.util.List<Squares> shapeList=new ArrayList<>();
private boolean play ;
private int X=50;
private int Y=0;
Timer timer=new Timer(10,this);
public Game(int w , int h){
Dimension d = new Dimension(w, h);
setBackground(Color.BLUE);
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.fillRect(X,Y,60,60);
timer.start();
}
#Override
public void actionPerformed(ActionEvent e) {
Y=Y+5;
repaint();
if(Y==600){
Random random=new Random();
Y=0;
X=random.nextInt(600-60);
}
}
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
public class Project3 extends JFrame {
public Project3() {
super("Game");
setSize(600, 600);
add(new Game(600,600));
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new Project3());
}
class Square {
public int squareX;
public int squareY;
int squareW = 25;
int squareH = 25;
public Square(int X, int Y) {
this.squareX = X;
this.squareY = Y;
}
public int getSquareX() {
return squareX;
}
public void setSquareX(int X) {
this.squareX = X;
}
public int getSquareY() {
return squareY;
}
public void setSquareY(int Y) {
this.squareY = Y;
}
}
class Game extends JPanel implements ActionListener ,Runnable,MouseListener {
public int score;
private java.util.List<Square> shapeList = new ArrayList<>();
Timer timer = new Timer(10, this);
private boolean play= true;
public Game(int w, int h) {
Dimension d = new Dimension(600, 600);
setBackground(Color.BLUE);
add(new Label("SCORE...."),BorderLayout.PAGE_END);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.YELLOW);
for (Square s:shapeList) {
g.fillRect(s.squareX,s.squareY,25,25);
}
}
#Override
public void actionPerformed(ActionEvent e) {
for (Square k : shapeList) {
k.setSquareY(k.getSquareY() + 5);
repaint();
}
}
public void stop() {
play = false;
}
#Override
public void run() {
while(play){
int randomNumber=(int)(Math.random()*600)+1;
shapeList.add(new Square(randomNumber,0));
for (Square k : shapeList) {
if (k.getSquareY()== 600) {
stop();
}try {
Thread.sleep(500);
} catch (InterruptedException ignored) {
}
}
}
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
int mouseX=e.getX();
int mouseY=e.getY();
for (Square s:shapeList){
if ((mouseX > s.squareX) && (mouseX < s.squareX + s.squareW) && (mouseY > s.squareY) && (mouseY < s.squareY + s.squareH)) {
shapeList.remove(s);
score++;
}
}
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
}
This code produces three layers of 'snow flakes' which drift towards the bottom of the screen.
Have a look over it, for tips:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.util.Random;
public class AnimatedSnowFall {
private JComponent ui = null;
AnimatedSnowFall() {
initUI();
}
public final void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
ui.add(new SnowFall());
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = () -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
AnimatedSnowFall o = new AnimatedSnowFall();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
};
SwingUtilities.invokeLater(r);
}
}
class SnowFall extends JPanel implements ActionListener {
Dimension prefSize = new Dimension(1600, 900);
SnowFlake[] farFlakes = new SnowFlake[200];
SnowFlake[] midFlakes = new SnowFlake[150];
SnowFlake[] closeFlakes = new SnowFlake[75];
Color farColor = new Color(100,100,255);
Color midColor = new Color(150,150,255);
Color closeColor = new Color(255,255,255);
SnowFall() {
setBackground(Color.BLACK);
for (int ii = 0; ii < farFlakes.length; ii++) {
farFlakes[ii] = new SnowFlake(prefSize.width, prefSize.height, 2, 4);
}
for (int ii = 0; ii < midFlakes.length; ii++) {
midFlakes[ii] = new SnowFlake(prefSize.width, prefSize.height, 3, 6);
}
for (int ii = 0; ii < closeFlakes.length; ii++) {
closeFlakes[ii] = new SnowFlake(prefSize.width, prefSize.height, 4, 8);
}
Timer timer = new Timer(50, this);
timer.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(farColor);
for (SnowFlake snowFlake : farFlakes) {
snowFlake.draw(g);
}
g.setColor(midColor);
for (SnowFlake snowFlake : midFlakes) {
snowFlake.draw(g);
}
g.setColor(closeColor);
for (SnowFlake snowFlake : closeFlakes) {
snowFlake.draw(g);
}
}
#Override
public Dimension getPreferredSize() {
return prefSize;
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
}
class SnowFlake {
int w;
int h;
int x;
int y;
int size;
int speed;
static Random r = new Random();
SnowFlake(int w, int h, int size, int speed) {
this.w = w;
this.h = h;
x = r.nextInt(w);
y = r.nextInt(h);
this.size = size;
this.speed = speed;
}
public void draw(Graphics g) {
y += speed;
if (y > h) {
x = r.nextInt(w);
y = 0;
}
g.fillOval(x, y, size, size);
}
}
So I'm new at java and need some help with my breakout game. My JFrame is just blank and i don't know how to fix it?
So I have a ball class, paddle class, canvas class and a brick class as well as a main class. In my canvas class I set all functions the ball, paddle and bricks has etc. In brick class I draw the bricks. And in my main I do the JFrame but it's blank
Main class :
public class Main {
public static void main(String[] args){
JFrame frame = new JFrame();
Canvas c = new Canvas();
frame.add(c);
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I expect the JFrame to show the game instead of just blank window
package breakout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.KeyEvent;
import breakout.Bricks.Type;
public class Canvas extends JPanel implements ActionListener, MouseMotionListener, MouseListener, KeyListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private static final int HEIGHT = 600;
public static final int WIDTH = 720;
private int horizontalCount;
private BufferedImage image;
private Graphics2D bufferedGraphics;
private Timer time;
private static final Font endFont = new Font(Font.SANS_SERIF, Font.BOLD, 20);
private static final Font scoreFont = new Font(Font.SANS_SERIF, Font.BOLD, 15);
private Paddle player;
private Ball ball;
ArrayList<ArrayList<Bricks>> bricks;
public Canvas() {
super();
setPreferredSize( new Dimension(WIDTH, HEIGHT));
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
bufferedGraphics = image.createGraphics();
time = new Timer (15, this);
player = new Paddle((WIDTH/2)-(Paddle.PADDLE_WIDTH/2));
ball = new Ball (((player.getX() + (Paddle.PADDLE_WIDTH / 2 )) - (Ball.DIAMETER / 2)), (Paddle.Y_POS - (Ball.DIAMETER + 10 )), -5, -5);
bricks = new ArrayList<ArrayList<Bricks>>();
horizontalCount = WIDTH / Bricks.BRICK_WIDTH;
for(int i = 0; i < 8; ++i) {
ArrayList<Bricks> temp = new ArrayList<Bricks>();
#SuppressWarnings("unused")
Type rowColor = null;
switch(i) {
case 0 :
case 2:
rowColor = Type.LOW;
break;
case 1 :
case 3 :
case 5 :
rowColor = Type.MEDIUM;
break;
case 4 :
case 6 :
rowColor = Type.HIGH;
break;
case 7 :
default :
rowColor = Type.ULTRA;
break;
}
for(int j = 0; j < horizontalCount; ++j) {
Bricks tempBrick = new Bricks();
temp.add(tempBrick);
}
bricks.add(temp);
addMouseMotionListener(this);
addMouseListener(this);
addKeyListener(this);
requestFocus();
}
}
public void actionPerformed(ActionEvent e) {
checkCollisions();
ball.Move();
for(int i = 0; i < bricks.size(); ++i) {
ArrayList<Bricks> al = bricks.get(i);
for(int j = 0; j < al.size(); ++j) {
Bricks b = al.get(j);
if(b.dead()) {
al.remove(b);
}
}
}
repaint();
}
private void checkCollisions() {
if(player.hitPaddle(ball)) {
ball.setDY(ball.getDY() * -1);
return;
}
if(ball.getX() >= (WIDTH - Ball.DIAMETER) || ball.getX() <= 0) {
ball.setDX(ball.getDX() * -1);
}
if(ball.getY() > (Paddle.Y_POS + Paddle.PADDLE_HEIGHT + 10)) {
resetBall();
}
if(ball.getY() <= 0) {
ball.setDY(ball.getDY() * -1);
}
int brickRowActive = 0;
for(ArrayList<Bricks> alb : bricks) {
if(alb.size() == horizontalCount) {
++brickRowActive;
}
}
for(int i = (brickRowActive==0) ? 0 : (brickRowActive - 1); i < bricks.size(); ++i) {
for(Bricks b : bricks.get(i)) {
if(b.hitBy(ball)) {
player.setScore(player.getScore() + b.getBrickType().getPoints());
b.decrementType();
}
}
}
}
private void resetBall() {
if(gameOver()) {
time.stop();
return;
}
ball.setX(WIDTH/2);
ball.setDY((HEIGHT/2) + 80);
player.setLives(player.getLives() -1);
player.setScore(player.getScore() <= 1);
}
private boolean gameOver() {
if(player.getLives() <= 1) {
return true;
}
return false;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
bufferedGraphics.clearRect(0, 0, WIDTH, HEIGHT);
player.drawPaddle(bufferedGraphics);
player.drawBall(bufferedGraphics);
for(ArrayList<Bricks> row : bricks) {
for(Bricks b : row) {
b.drawBrick(bufferedGraphics);
}
}
bufferedGraphics.setFont(scoreFont);
bufferedGraphics.drawString("Score: " + player.getScore(), 10, 25);
if(gameOver() && ball.getY() >= HEIGHT) {
bufferedGraphics.setColor(Color.black);
bufferedGraphics.setFont(endFont);
bufferedGraphics.drawString("Game Over Score: " + player.getScore(), (WIDTH /2) -85, (HEIGHT/2));
}
if(empty()) {
bufferedGraphics.setColor(Color.black);
bufferedGraphics.setFont(endFont);
bufferedGraphics.drawString("You won. Score: " + player.getScore(), (WIDTH /2) -85, (HEIGHT /2));
time.stop();
}
g.drawImage(image, 0, 0, this);
Toolkit.getDefaultToolkit().sync();
}
private boolean empty() {
for(ArrayList<Bricks> al : bricks) {
if(al.size() != 0) {
return false;
}
}
return true;
}
#Override
public void mouseMoved(MouseEvent e) {
player.setX(e.getX() - (Paddle.PADDLE_WIDTH / 2));
}
#Override
public void mouseClicked(MouseEvent e) {
if(time.isRunning()) {
return;
}
time.start();
}
#Override
public void mouseDragged(MouseEvent e) { }
#Override
public void mouseEntered(MouseEvent arg0) {}
#Override
public void mouseExited(MouseEvent arg0) {}
#Override
public void mousePressed(MouseEvent arg0) {}
#Override
public void mouseReleased(MouseEvent arg0) {}
#Override
public void keyPressed(KeyEvent arg0) {}
#Override
public void keyReleased(KeyEvent arg0) {}
#Override
public void keyTyped(KeyEvent arg0) {}
}
Preparing an MCVE, as required in SO, not only it makes helping much easier.
In many case, while preparing one, you are likely to find the problem, so it is a good debugging tool.
To answer "why is my JFrame blank ?" you could create the minimal code example like the following (copy-paste the entire code into GameBoard.java and run):
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GameBoard extends JPanel {
static final int HEIGHT = 600, WIDTH = 720, BRICK_ROWS = 8;
private final int horizontalCount;
private static final Font scoreFont = new Font(Font.SANS_SERIF, Font.BOLD, 15);
private final Paddle player;
private final Ball ball;
ArrayList<ArrayList<Brick>> bricks;
public GameBoard() {
super();
setPreferredSize( new Dimension(WIDTH, HEIGHT));
player = new Paddle(WIDTH/2-Paddle.PADDLE_WIDTH/2);
ball = new Ball (player.getX() + Paddle.PADDLE_WIDTH / 2 - Ball.DIAMETER / 2,
Paddle.Y_POS - (Ball.DIAMETER + 10 ));
bricks = new ArrayList<>();
horizontalCount = WIDTH / Brick.BRICK_WIDTH;
for(int i = 0; i < BRICK_ROWS; ++i) {
ArrayList<Brick> temp = new ArrayList<>();
for(int j = 0; j < horizontalCount; ++j) {
Brick tempBrick = new Brick(j*Brick.BRICK_WIDTH , Brick.BRICK_YPOS + i*Brick.BRICK_HEIGHT);
temp.add(tempBrick);
}
bricks.add(temp);
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D)g;
g2D.clearRect(0, 0, WIDTH, HEIGHT);
player.drawPaddle(g2D);
ball.drawBall(g2D);
for(ArrayList<Brick> row : bricks) {
for(Brick b : row) {
b.drawBrick(g2D);
}
}
g2D.setFont(scoreFont);
g2D.drawString("Score: " + player.getScore(), 10, 25);
}
}
class Paddle{
public final static int PADDLE_WIDTH = 100, PADDLE_HEIGHT= 30, Y_POS = GameBoard.HEIGHT - 2* PADDLE_HEIGHT;
private int xPos, score;
Paddle(int xPos) {
this.xPos = xPos;
}
void setX(int xPos) {this.xPos = xPos;}
int getX() {return xPos;}
String getScore() {
return String.valueOf(score);
}
void drawPaddle(Graphics2D g2D) {
g2D.setColor(Color.GREEN);
g2D.fillRect(xPos, Y_POS, PADDLE_WIDTH, PADDLE_HEIGHT);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(400,250);
frame.add(new GameBoard());
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
}
}
class Brick{
final static int BRICK_WIDTH = 80, BRICK_HEIGHT = 15, BRICK_YPOS = 50;
int xPos, yPos;
Brick(int xPos, int yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
void drawBrick(Graphics2D g2D) {
g2D.setColor(Color.RED);
g2D.fillRect(xPos, yPos, BRICK_WIDTH, BRICK_HEIGHT);
g2D.setColor(Color.BLACK);
g2D.drawRect(xPos, yPos, BRICK_WIDTH, BRICK_HEIGHT);
}
}
class Ball{
final static int DIAMETER = 40;
int xPos, yPos;
Ball(int xPos, int yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
void drawBall(Graphics2D g2D) {
g2D.setColor(Color.BLUE);
g2D.fillOval(xPos, yPos, DIAMETER, DIAMETER);
}
}
This produces the following result, which I believe can serve as the basis of what you wanted to achieve:
Now start adding the missing functionality and see what breaks it.
To be frank i have not the slightest clue how to fix this whats so ever. It works until you get to the part that only 1 brick shows and its kinda frustrating... If anyone could help me i would appreciate it. I did look up how to fix this but i didn't even find anyone that had this problem. Google searching isn't really that good. Oh and i used Eclipse for this program.
Board Class
package Final;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JPanel;
public class Board extends JPanel implements Commons {
private Timer timer;
private String message = "Your Fired";
private Ball ball;
private Paddle paddle;
private Brick bricks[];
private boolean ingame = true;
public Board() {
initBoard();
}
private void initBoard() {
addKeyListener(new TAdapter());
setFocusable(true);
bricks = new Brick[N_OF_BRICKS];
setDoubleBuffered(true);
timer = new Timer();
timer.scheduleAtFixedRate(new ScheduleTask(), DELAY, PERIOD);
}
#Override
public void addNotify() {
super.addNotify();
gameInit();
}
private void gameInit() {
ball = new Ball();
paddle = new Paddle();
int k = 0;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 6; j++) {
bricks[k] = new Brick(j * 40 + 30, i * 10 + 50);
k++;
}
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
if (ingame) {
drawObjects(g2d);
} else {
gameFinished(g2d);
}
Toolkit.getDefaultToolkit().sync();
}
private void drawObjects(Graphics2D g2d) {
g2d.drawImage(ball.getImage(), ball.getX(), ball.getY(),
ball.getWidth(), ball.getHeight(), this);
g2d.drawImage(paddle.getImage(), paddle.getX(), paddle.getY(),
paddle.getWidth(), paddle.getHeight(), this);
for (int i = 0; i < N_OF_BRICKS; i++) {
if (!bricks[i].isDestroyed()) {
g2d.drawImage(bricks[i].getImage(), bricks[i].getX(),
bricks[i].getY(), bricks[i].getWidth(),
bricks[i].getHeight(), this);
}
}
}
private void gameFinished(Graphics2D g2d) {
Font font = new Font("Verdana", Font.BOLD, 18);
FontMetrics metr = this.getFontMetrics(font);
g2d.setColor(Color.BLACK);
g2d.setFont(font);
g2d.drawString(message,
(Commons.WIDTH - metr.stringWidth(message)) / 2,
Commons.WIDTH / 2);
}
private class TAdapter extends KeyAdapter {
#Override
public void keyReleased(KeyEvent e) {
paddle.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
paddle.keyPressed(e);
}
}
private class ScheduleTask extends TimerTask {
#Override
public void run() {
ball.move();
paddle.move();
checkCollision();
repaint();
}
}
private void stopGame() {
ingame = false;
timer.cancel();
}
private void checkCollision() {
if (ball.getRect().getMaxY() > Commons.BOTTOM_EDGE) {
stopGame();
}
for (int i = 0, j = 0; i < N_OF_BRICKS; i++) {
if (bricks[i].isDestroyed()) {
j++;
}
if (j == N_OF_BRICKS) {
message = "Pay Day";
stopGame();
}
}
if ((ball.getRect()).intersects(paddle.getRect())) {
int paddleLPos = (int) paddle.getRect().getMinX();
int ballLPos = (int) ball.getRect().getMinX();
int first = paddleLPos + 8;
int second = paddleLPos + 16;
int third = paddleLPos + 24;
int fourth = paddleLPos + 32;
if (ballLPos < first) {
ball.setXDir(-1);
ball.setYDir(-1);
}
if (ballLPos >= first && ballLPos < second) {
ball.setXDir(-1);
ball.setYDir(-1 * ball.getYDir());
}
if (ballLPos >= second && ballLPos < third) {
ball.setXDir(0);
ball.setYDir(-1);
}
if (ballLPos >= third && ballLPos < fourth) {
ball.setXDir(1);
ball.setYDir(-1 * ball.getYDir());
}
if (ballLPos > fourth) {
ball.setXDir(1);
ball.setYDir(-1);
}
}
for (int i = 0; i < N_OF_BRICKS; i++) {
if ((ball.getRect()).intersects(bricks[i].getRect())) {
int ballLeft = (int) ball.getRect().getMinX();
int ballHeight = (int) ball.getRect().getHeight();
int ballWidth = (int) ball.getRect().getWidth();
int ballTop = (int) ball.getRect().getMinY();
Point pointRight = new Point(ballLeft + ballWidth + 1, ballTop);
Point pointLeft = new Point(ballLeft - 1, ballTop);
Point pointTop = new Point(ballLeft, ballTop - 1);
Point pointBottom = new Point(ballLeft, ballTop + ballHeight + 1);
if (!bricks[i].isDestroyed()) {
if (bricks[i].getRect().contains(pointRight)) {
ball.setXDir(-1);
} else if (bricks[i].getRect().contains(pointLeft)) {
ball.setXDir(1);
}
if (bricks[i].getRect().contains(pointTop)) {
ball.setYDir(1);
} else if (bricks[i].getRect().contains(pointBottom)) {
ball.setYDir(-1);
}
bricks[i].setDestroyed(true);
}
}
}
}
}
Brick Class
package Final;
import javax.swing.ImageIcon;
public class Brick extends Sprite {
private boolean destroyed;
public Brick(int x, int y) {
ImageIcon ii = new ImageIcon("images/bricks.png");
image = ii.getImage();
i_width = image.getWidth(null);
i_heigth = image.getHeight(null);
destroyed = false;
}
public boolean isDestroyed() {
return destroyed;
}
public void setDestroyed(boolean val) {
destroyed = val;
}
}
Commons Class
package Final;
public interface Commons {
public static final int WIDTH = 300;
public static final int HEIGTH = 400;
public static final int BOTTOM_EDGE = 390;
public static final int N_OF_BRICKS = 30;
public static final int INIT_PADDLE_X = 200;
public static final int INIT_PADDLE_Y = 360;
public static final int INIT_BALL_X = 230;
public static final int INIT_BALL_Y = 355;
public static final int DELAY = 1000;
public static final int PERIOD = 10;
}
Sprite Class
package Final;
import java.awt.Image;
import java.awt.Rectangle;
public class Sprite {
protected int x;
protected int y;
protected int i_width;
protected int i_heigth;
protected Image image;
public void setX(int x) {
this.x = x;
}
public int getX() {
return x;
}
public void setY(int y) {
this.y = y;
}
public int getY() {
return y;
}
public int getWidth() {
return i_width;
}
public int getHeight() {
return i_heigth;
}
Image getImage() {
return image;
}
Rectangle getRect() {
return new Rectangle(x, y,
image.getWidth(null), image.getHeight(null));
}
}
Breakout Class
package Final;
import java.awt.EventQueue;
import javax.swing.JFrame;
public class Breakout extends JFrame {
public Breakout() {
initUI();
}
private void initUI() {
add(new Board());
setTitle("Lord Carl's Demolition Job");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(Commons.WIDTH, Commons.HEIGTH);
setLocationRelativeTo(null);
setResizable(false);
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Breakout game = new Breakout();
game.setVisible(true);
}
});
}
}
The problem is in checkCollision(). Inside the loop, j will never equal N_OF_BRICKS because of the loop condition. You could change to:
private void checkCollision() {
if (ball.getRect().getMaxY() > Commons.BOTTOM_EDGE) {
stopGame();
}
int j = 0;
for (int i = 0; i < N_OF_BRICKS; i++) {
if (bricks[i].isDestroyed()) {
j++;
}
}
if (j == N_OF_BRICKS) {
message = "Pay Day";
stopGame();
}
}
Also, in the Brick class you neglect to store the x,y coords:
public class Brick extends Sprite {
....
public Brick(int x, int y) {
ImageIcon ii = new ImageIcon("images/bricks.png");
image = ii.getImage();
i_width = image.getWidth(null);
i_heigth = image.getHeight(null);
destroyed = false;
// Save these
this.x = x;
this.y = y
}
....
}
Or, add a constructor to the Sprite class and call that from the Brick constructor:
public class Sprite {
....
public Sprite(int x, int y) {
this.x = x;
this.y = y;
}
....
}
public class Brick extends Sprite {
....
public Brick(int x, int y) {
// Call the sprite constructor
super(x, y);
ImageIcon ii = new ImageIcon("images/bricks.png");
image = ii.getImage();
i_width = image.getWidth(null);
i_heigth = image.getHeight(null);
destroyed = false;
}
....
}
EDIT: I've found that the following code works. It appears there was a slip-up with the earlier code. However, I still have the burning question, of whether this code is good practice? Is this an acceptable method to share the model data underlying the Swing objects between the main application thread and the Swing event dispatch thread?
package com.guitest;
import java.awt.*;
import java.util.*;
import javax.swing.*;
public class Test {
public static void main(String[] args) {
new Test().run();
}
public void run() {
Board board = new Board();
board.createBoard();
board.setTileValue(2, 2, 3);
board.revalidate();
board.repaint();
}
#SuppressWarnings("serial")
public class Board extends JFrame {
final int tileSize = 100;
final int numberOfRows = 2;
final int numberOfCols = 3;
private final Map<Integer, Integer> _tiles;
public Board() {
_tiles = Collections.synchronizedMap(new HashMap<Integer, Integer>(numberOfRows*numberOfCols));
for (int row = 0; row < numberOfRows; row++) {
for (int col = 1; col <= numberOfCols; col++) {
_tiles.put(row*numberOfCols+col, 1);
}
}
}
public void setTileValue(int row, int col, int value) {
_tiles.put(row*(numberOfCols-1)+col, value);
}
public void createBoard() {
SwingUtilities.invokeLater(new Runnable() {
#Override public void run() {
setLayout(new GridLayout(numberOfRows, numberOfCols, 0, 0));
for (int row = 0; row < numberOfRows; row++) {
for (int col = 1; col <= numberOfCols; col++) {
add(createPanelFor(row, col));
}
}
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(numberOfCols*tileSize, numberOfRows*tileSize);
setVisible(true);
}
});
}
public JPanel createPanelFor(final int row, final int col) {
return new JPanel() {
#Override protected void paintComponent(Graphics g) {
g.setColor((col % 2 == 0) == (row % 2 == 0) ? Color.BLACK : Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
String string = String.valueOf(_tiles.get(row*numberOfCols+col));
g.setColor(Color.RED);
g.drawString(string, getHeight() / 2, getWidth() / 2);
}
};
}
}
}