I'm making a battleship game using SWING. The program reads a file with the following data: height, length, matrix of positions populated with the number of boats. The problem is the matrix that the mouse captures is inverted in comparison with the one in the file and I don't know what to do. I will appreciate any help.
Below is the code:
Frame:
import Model.ArcMap;
import java.awt.BorderLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
public class GameFrame extends JFrame {
private GameCanvas canvas;
// CanvasThread updateScreenThread = new CanvasThread(canvas);
private ArcMap archive;
private int width;
private int hight;
public static final int AREA = 60;
public GameFrame(ArcMap archve) {
this.archive = archve;
this.width = archve.getArcWidth();
this.hight = archive.getArcHeight();
canvas = new GameCanvas(archive);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
setTitle("Stellar Battle");
add(BorderLayout.CENTER, canvas);
setResizable(false);
// Define largura e altura da janela principal
setSize(AREA * width, canvas.AREA * hight);
setLocationRelativeTo(null);
// setVisible(true);
// Inicia Thread com timer para redesenhar a tela.
// updateScreenThread.start();
canvas.addMouseListener(new MouseListener() {
#Override
public void mouseReleased(MouseEvent e) {
int x = e.getX();
int y = e.getY();
int x_pos = x / canvas.AREA;
int y_pos = y / canvas.AREA;
System.out.println(canvas.getShot(x_pos, y_pos);
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
});
}
}
Canvas:
import Model.ArcMap;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.nio.Buffer;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
public class GameCanvas extends Canvas {
public static final int AREA = 40;
private int margin = 0;
private int rows;
private int cols;
private ArcMap achive;
private int[][] explosionMatrix = new int[rows][cols];
public GameCanvas(ArcMap archive) {
this.achive = archive;
this.rows = archive.getArcHeight();
this.cols = archive.getArcWidth();
explosionMatrix = archive.getArcMatrix();
setSize(AREA * rows, AREA * cols);
}
//#Override
public void paint(Graphics g) {
int lenthI = rows;
int lenthJ = cols;
g.setColor(new Color(131, 209, 232));
g.fillRect(0, 0, cols * AREA, rows * AREA);
g.setColor(Color.white);
for (int i = 0; i < cols ; i++) {
g.drawLine(i * AREA, 0, i * AREA, AREA * rows);
for (int j = 0; j < rows; j++) {
g.drawLine(0, j * AREA, AREA * cols, j * AREA);
}
}
this.oque();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
System.out.print(explosionMatrix[i][j]);
}
System.out.println("");
}
// Prepare an ImageIcon
ImageIcon icon = new ImageIcon("images/ondas_1.jpg");
ImageIcon iconShot = new ImageIcon("images/explosion.png");
// Prepare an Image object to be used by drawImage()
final Image img = icon.getImage();
final Image imgShot = iconShot.getImage();
this.oque();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
g.drawImage(img, i * AREA, j * AREA, AREA, AREA, null);
if (explosionMatrix[i][j] == 1) {
g.drawImage(imgShot, i * AREA, j * AREA, AREA, AREA, null);
}
}
}
this.oque();
}
public void setShot(int x, int y) {
explosionMatrix[x][y] = 1;
}
public int getShot(int x, int y) {
return explosionMatrix[x][y];
}
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 int[][] getExplosionMatrix() {
return explosionMatrix;
}
public void setExplosionMatrix(int[][] explosionMatrix) {
this.explosionMatrix = explosionMatrix;
}
public void oque() {
System.out.println("");
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
System.out.print(explosionMatrix[i][j]);
}
System.out.println("");
}
}
}
Related
I am writing a space invaders clone for a school project, I am in the process of writing the aliens and their algorithm for movement with the use of an array.
My issue is a bunch of errors occur when I run the code but I can`t find why?
any help would be appreciated and bare in mind I am very inexperienced with game development and java
bellow is my GamePanel class, and then my Alien class
package Main;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
import entity.Alien;
import entity.Controller;
import entity.Player;
import entity.playerBullet;
public class GamePanel extends JPanel implements Runnable{
public final int screenHeight = 600;
public final int screenWidth = 800;
public final int playerSize = 48;
int fps = 60;
KeyHandler keyH = new KeyHandler();
Thread gameThread;
public Player player = new Player(this,keyH);
public CollisionChecker cChecker = new CollisionChecker(this);
private Controller c = new Controller(null);
Alien alien;
//player default position
int playerX = 100;
int playerY = 100;
int playerSpeed = 4;
public GamePanel() {
this.setPreferredSize(new Dimension (screenWidth, screenHeight));
this.setBackground(Color.black);
this.setDoubleBuffered(true);
this.addKeyListener(keyH);
this.setFocusable(true);
}
public void startGameThread() {
gameThread = new Thread (this);
gameThread.start();
alien.initAlien();
}
public void run() {
double drawInterval = 1000000000/fps; // 0.01666 seconds = 60 times per seconds
double nextDrawTime = System.nanoTime() + drawInterval;
while(gameThread != null) {
System.out.println("this game is runing");
// update information such as character positions
// draw the screen with the updated information
update();
repaint();
try {
double remainingTime = nextDrawTime - System.nanoTime();
remainingTime = remainingTime/1000000;
if(remainingTime<0) {
remainingTime = 0;
}
Thread.sleep ((long) remainingTime);
nextDrawTime += drawInterval;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void update() {
player.update();
c.tick();
alien.moveAliens();
}
public void paintComponent(Graphics g) {
// to draw something
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
player.draw(g2);
c.render(g );
g2.dispose();
alien.render(g );
}
}
Alien class
package entity;
import java.awt.Color;
import java.awt.Graphics;
public class Alien {
boolean isVisible;
boolean moveLeft;
boolean moveRight;
Alien[] a = new Alien[10];
private int x;
private int y;
int ax = 10;
int ay = 10;
public Alien(int x, int y) {
}
public void initAlien() {
for(int i=0;i<a.length; i++) {
a[i] = new Alien(ax,ay);
ax += 40;
if(i==4) {
ax=10;
ay+=40;
}
}
}
public void moveAliens() {
for(int i=0;i<a.length; i++) {
if (a[i].moveLeft ==true) {
a[i].x -=2;
}
if (a[i].moveRight ==true) {
a[i].x+=2;
}
for(int i1 = 0; i<a.length; ) {
if(a[i].x>600) {
for(int j =0;j<a.length; j++) {
a[j].moveLeft = true;
a[j].moveRight = false;
a[j].y += 5;
}
}
if(a[i].x<0) {
for(int j = 0; j< a.length; j++) {
a[j].moveLeft = false;
a[j].moveRight = true;
a[j].y += 5;
}
}
}
}
}
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;
}
}
}
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.");
}
}
Currently I'm working on an assignment about creating a version of "Game of Life". However my cells won't appear.
This is my Cell Class:
class Cell{
boolean alive; //true if cell is alive, false if cell is dead
int numNeighbors; //number of alive neightboring cells
//change alive/dead state of the cell
void setAlive(boolean state){
alive = state;
}
//return alive/dead state of the cell
boolean isAlive(){
return alive;
}
//set numNeightbors of the cell to n
void setNumNeighbors(int n){
numNeighbors = n;
}
//take the cell to the next generation
void update(){
if(numNeighbors <2 || numNeighbors >3){
alive = false;
} else if((numNeighbors == 2 || numNeighbors == 3) && alive == true){
alive = true;
} else if(numNeighbors == 3 && alive == false){
alive = true;
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor( Color.blue );
g.setOpaque(true);
for(int i = 0; i < row; i++){
for(int j = 0; j < col; j++){
if(grid[i][j].isAlive()){
g.setColor( Color.BLACK);
} else {
g.setColor ( Color.WHITE);
g.fillRect(50, 50, 50*i, 50*j);
}
}
}
}
And this is my GameOfLife Class
<pre>import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import java.io.*;
public class GameOfLife implements MouseListener{
Cell[][] grid; //contain grid of cells
String birthFilename = "birth.txt"; //text file where initial generation is stored
int row; //number of rows
int col; //number of columns
ActionListener actionListener = new ActionListener(){
javax.swing.Timer timer = new javax.swing.Timer(500, this); //new timer
#Override
public void actionPerformed(ActionEvent event){
}
};
public void buildIt() {
int width = 600;
int height = 600;
JFrame frame = new JFrame("Game of Life");
readInitial();
//adds button interface
JPanel buttonbar = new JPanel();
frame.add(buttonbar, BorderLayout.SOUTH);
JButton start = new JButton("Start");
JButton stop = new JButton("Stop");
JButton nextg = new JButton("Next Generation");
buttonbar.add(nextg);
buttonbar.add(start);
buttonbar.add(stop);
JPanel panel = new JPanel();
frame.add(panel);
panel.setPreferredSize(new Dimension(width, height));
panel.setLayout(new GridLayout(row, col, 4, 4));
frame.pack();
frame.setBackground(Color.WHITE);
frame.setVisible(true);
}
public void mousePressed( MouseEvent e) {
//add code to update x and y
}
public void mouseReleased( MouseEvent e) { }
public void mouseClicked( MouseEvent e) { }
public void mouseEntered( MouseEvent e) { }
public void mouseExited( MouseEvent e) { }
//calculate number of living neightbors of each cell and sets numNeighbors
//Does not update dead/live state of cells
void calculateNumNeighbors(){
int numNeighbors = 0;
for(int i = 1; i < row + 1; i++){
for(int j = 1; j < col + 1; j++){
for(int k = -1; k < 2; k++){
for(int m = -1; m < 2; m++){
if(grid[i+k][j+m].isAlive() && !(k == 0 && m == 0)){
numNeighbors++;
}
}
}
grid[i][j].setNumNeighbors(numNeighbors);
}
}
}
//create grid and read initial generation from file
void readInitial(){
try{
grid = new Cell[row + 2][col + 2]; //empty neighbors at corners, so + 2
File file = new File(birthFilename);
Scanner scanner = new Scanner( file );
row = scanner.nextInt();
col = scanner.nextInt();
for(int i = 0; i < row + 2; i++){
for (int j = 0; j < col + 2; j++){
grid[i][j] = new Cell();
}
}
for(int i = 1; i < row + 1; i++){
for (int j = 1; j < col + 1; j++){
if(scanner.next().equals(".")){
grid[i][j].setAlive(false);
} else if(scanner.next().equals("*")){
grid[i][j].setAlive(true);
}
}
}
for(int i = 0; i < row + 2; i++){
grid[0][i].setAlive(false);
grid[row+2][i].setAlive(false);
}
for(int j = 0; j < col + 2; j++){
grid[j][0].setAlive(false);
grid[j][col+2].setAlive(false);
}
} catch(FileNotFoundException e) {
grid = new Cell[12][12];
row = 10;
col = 10;
for(int i = 0; i < 12; i++){
for (int j = 0; j < 12; j++){
grid[i][j] = new Cell();
grid[i][j].setAlive(false);
}
}
}
}
//update grid to the next generation, using the values of numNeightbors in the cells
void nextGeneration(){
for(int i = 1; i < row + 1; i++){
for (int j = 1; j < col + 1; j++){
grid[i][j].update();
}
}
}
public static void main(String[] arg) {
(new GameOfLife()).buildIt();
}
I hope anyone can help me out to make this program work.
I don't see why anything should draw. You've got a Cell class that yes has a paintComponent method, but this method is meaningless since it's not part of a Swing component. Your JPanel, where you should do drawing -- does nothing. You've other problems with the Cell class too in that it appears to be trying to draw the whole grid and not just a single cell.
Get rid of Cell's paintComponent method
Instead give it a public void draw(Graphics g) method that allows it to draw itself.
Create a JPanel that holds a grid of cells
Have this JPanel do the drawing in its paintComponent override. It will call the draw(g) method of all the Cells that it holds within a for loop.
Always place an #Override annotation above any overridden method. If you had done this, above your paintComponent, the compiler would have warned you that something was wrong.
For example: here's a small program that does not do the Game of Life, but shows an example of a JPanel holding and displaying a grid of non-component cells. By "non-component" the SimpleCell class does not extend from a Swing component, does not have any Swing methods, but as suggested above, does have a draw(...) method and can use this to draw itself. It also has a public boolean contains(Point p) method that the main program can use in its MouseListener to decide if it's been clicked:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class SimpleCellGrid extends JPanel {
private static final int ROWS = 40;
private static final int COLS = 40;
private static final int CELL_WIDTH = 10;
private static final int PREF_W = CELL_WIDTH * COLS;
private static final int PREF_H = CELL_WIDTH * ROWS;
private SimpleCell[][] cellGrid = new SimpleCell[ROWS][COLS];
public SimpleCellGrid() {
MyMouse myMouse = new MyMouse();
addMouseListener(myMouse);
for (int row = 0; row < cellGrid.length; row++) {
for (int col = 0; col < cellGrid[row].length; col++) {
int x = col * CELL_WIDTH;
int y = row * CELL_WIDTH;
cellGrid[row][col] = new SimpleCell(x, y, CELL_WIDTH);
}
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for (SimpleCell[] cellRow : cellGrid) {
for (SimpleCell simpleCell : cellRow) {
simpleCell.draw(g2);
}
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class MyMouse extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
for (SimpleCell[] cellRow : cellGrid) {
for (SimpleCell simpleCell : cellRow) {
if (simpleCell.contains(e.getPoint())) {
simpleCell.setAlive(!simpleCell.isAlive());
}
}
}
repaint();
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("SimpleCellGrid");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new SimpleCellGrid());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
public class SimpleCell {
private static final Color CELL_COLOR = Color.RED;
private boolean alive = false;
private int x;
private int y;
private int width;
private Rectangle rectangle;
public SimpleCell(int x, int y, int width) {
this.x = x;
this.y = y;
this.width = width;
rectangle = new Rectangle(x, y, width, width);
}
public boolean isAlive() {
return alive;
}
public void setAlive(boolean alive) {
this.alive = alive;
}
public void draw(Graphics2D g2) {
if (alive) {
g2.setColor(CELL_COLOR);
g2.fill(rectangle);
}
}
public boolean contains(Point p) {
return rectangle.contains(p);
}
#Override
public String toString() {
return "SimpleCell [alive=" + alive + ", x=" + x + ", y=" + y + ", width=" + width + ", rectangle=" + rectangle
+ "]";
}
}
I am new to java 2d graphics and I have problem handling mouseclick event.
Is it possible for you to tell me why there is nothing going on after updating mouse status to clicked ?
What I want to do is to change the image in array at 0 2 to another image. Nothing happens tho. Thanks for your help in advance.
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.*;
import java.awt.*;
import javax.swing.ImageIcon;
import javax.swing.*;
public class Board extends JPanel implements MouseListener {
private static boolean[] keyboardState = new boolean[525];
private static boolean[] mouseState = new boolean[3];
private static Image[][] images;
Image house;
int w = 0;
int h = 0;
int xPos;
int yPos;
ImageIcon ii = new ImageIcon(this.getClass().getResource("house.gif"));
ImageIcon iii = new ImageIcon(this.getClass().getResource("house1.gif"));
public Board() {
house = ii.getImage();
h = house.getHeight(null);
w = house.getWidth(null);
images = new Image[10][10];
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 10; j++)
{
images[i][j] = house;
}
}
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 10; j++)
{
g2d.drawImage(images[i][j],w*i,h*j,null);
}
}
//g2d.drawImage(house,15,15,null);
}
public void checkMouse()
{
if(mouseState[0])
{
images[0][2] = iii.getImage();
repaint();
super.repaint();
}
}
#Override
public void mousePressed(MouseEvent e)
{
mouseKeyStatus(e, true);
checkMouse();
}
#Override
public void mouseReleased(MouseEvent e)
{
mouseKeyStatus(e, false);
repaint();
}
public static boolean mouseButtonState(int button)
{
return mouseState[button - 1];
}
private void mouseKeyStatus(MouseEvent e, boolean status)
{
if(e.getButton() == MouseEvent.BUTTON1)
mouseState[0] = status;
else if(e.getButton() == MouseEvent.BUTTON2)
mouseState[1] = status;
else if(e.getButton() == MouseEvent.BUTTON3)
mouseState[2] = status;
}
You need to register a MouseListener for your Board JPanel so that mouseKeyStatus can be called
addMouseListener(this);
Aside: Override paintComponent rather than paint when implementing custom painting in Swing and remember to invoke super.paintComponent(g).