Java - getBounds2D, Ellipse Rectangle Collision - java

I've just started Java and we have been asked to produce pong (or a twist on it). I am currently working on the collision between the ball and the players bat. I've got this code.
Rectangle2D.Double player;
Ellipse2D.Double ball;
public void drawActualPicture( Graphics2D g )
{
// Players Bat
g.setPaint( Color.green ); // Paint Colour
player = new Rectangle2D.Double( playerX, playerY, PW, PH );
g.fill(player);
// The ball at the current x, y position (width, height)
g.setPaint( Color.red );
ball = new Ellipse2D.Double( x-HALF_BALL_SIZE, y-HALF_BALL_SIZE, BALL_SIZE, BALL_SIZE );
g.fill( ball );
}
Some irrelevant code has been removed.
Then to detect my collision I've used
if ( ball.getBounds2D() == player.getBounds2D() )
{
System.out.println("true");
//x_inc = -1*ballS;
}
When the code is used the game simple freezes. When commented out the game runs fine.
Any ideas? Am I using the correct method in the correct way? Would it be better to use intersects?
Thanks
EDIT: It appears that anything involving .getBounds2D(); causes the game to crash. Any ideas?
EDIT2: Adding all of code-completly not needed parts
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
/*
* Note If you change S (Speed) collision detection will be more complex
* as the ball edge may be within the bat.
* Ignores concurrency issues (x,y access)
*/
class Main
{
public static void main( String args[] ) //
{ //
System.out.println("Application");
Application app = new Application();
app.setVisible(true);
app.run();
} //
}
class Application extends JFrame // So graphical
{
private static final int H = 600; // Height of window
private static final int W = 800; // Width of window
public Application()
{
setSize( W, H ); // Size of application
addKeyListener( new Transaction() ); // Called when key press
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void update( Graphics g ) // Called by repaint
{ //
drawPicture( (Graphics2D) g ); // Draw Picture
}
public void paint( Graphics g ) // When 'Window' is first
{ // shown or damaged
drawPicture( (Graphics2D) g ); // Draw Picture
}
private Dimension theAD; // Alternate Dimension
private BufferedImage theAI; // Alternate Image
private Graphics2D theAG; // Alternate Graphics
public void drawPicture( Graphics2D g ) // Double buffer
{ // allow re-size
Dimension d = getSize(); // Size of curr. image
if ( ( theAG == null ) ||
( d.width != theAD.width ) ||
( d.height != theAD.height ) )
{ // New size
theAD = d;
theAI = (BufferedImage) createImage( d.width, d.height );
theAG = theAI.createGraphics();
AffineTransform at = new AffineTransform();
at.setToIdentity();
at.scale( ((double)d.width)/W, ((double)d.height)/H );
theAG.transform(at);
}
drawActualPicture( theAG ); // Draw Actual Picture
g.drawImage( theAI, 0, 0, this ); // Display on screen
}
// The ball position and how to increment to next position
private int x = W/2, x_inc = 1;
private int y = H/2, y_inc = 1;
// The bat position and how to increment to next position
private int playerX = 60;
private int playerY = PH/2, playerY_inc = 1;
double count = 0.00;
// Called on key press
class Transaction implements KeyListener // When character typed
{
public void keyPressed(KeyEvent e) // Obey this method
{
// Key typed includes specials
switch ( e.getKeyCode() ) // Character is
{
/*
case KeyEvent.VK_LEFT: // Left Arrow
x_inc = -1;
break;
case KeyEvent.VK_RIGHT: // Right arrow
x_inc = 1;
break;
*/
case KeyEvent.VK_UP: // Up arrow
playerY_inc = -1;
break;
case KeyEvent.VK_DOWN: // Down arrow
playerY_inc = 1;
break;
}
// x,y could send to a server instead of calling
repaint(); // Call update method
}
public void keyReleased(KeyEvent e)
{
switch ( e.getKeyCode() ) // Character is
{
/*
case KeyEvent.VK_UP: // Up arrow
playerY_inc = playerY_inc;
break;
case KeyEvent.VK_DOWN: // Down arrow
playerY_inc = playerY_inc;
break;
*/
}
}
public void keyTyped(KeyEvent e)
{
// Normal key typed
char c = e.getKeyChar(); // Typed
repaint(); // Redraw screen
}
}
private static final int B = 6; // Border offset
private static final int M = 26; // Menu offset
private static final int BALL_SIZE = 10; // Ball diameter
private static final int HALF_BALL_SIZE = BALL_SIZE/2;
//Players Bat
private static final int PW = 20;
private static final int PH = 100;
private static final int HALF_PLAYER = PH/2;
// Code called to draw the current state of the game
Rectangle2D.Double player;
Ellipse2D.Double ball;
public void drawActualPicture( Graphics2D g )
{
// White background
g.setPaint( Color.white );
g.fill( new Rectangle2D.Double( 0, 0, W, H ) );
Font font = new Font("Monospaced",Font.PLAIN,24);
g.setFont( font );
// Blue playing border
g.setPaint( Color.blue ); // Paint Colour
g.draw( new Rectangle2D.Double( B, M, W-B*2, H-M-B ) );
// Players Bat
g.setPaint( Color.green ); // Paint Colour
player = new Rectangle2D.Double( playerX, playerY, PW, PH );
g.fill(player);
// Display state of game
g.setPaint( Color.blue );
FontMetrics fm = getFontMetrics( font );
String fmt = "Score/ Time lasted = %3f";
String text = String.format( fmt, count );
g.drawString( text, W/2-fm.stringWidth(text)/2, M*2 );
// The ball at the current x, y position (width, height)
g.setPaint( Color.red );
ball = new Ellipse2D.Double( x-HALF_BALL_SIZE, y-HALF_BALL_SIZE, BALL_SIZE, BALL_SIZE );
g.fill( ball );
}
// Main program loop
public void run()
{
int ballS = 1; // Speed 1 - 5
int playerS = 1;
try
{
while ( true )
{
count = count + 0.015;
//Ball hitting walls
//Right wall
if ( x >= W-B-HALF_BALL_SIZE )
{
x_inc = -1*ballS;
}
//Left wall
if ( x <= 0+B+HALF_BALL_SIZE )
{
count = count;
break;
}
//Bottom Wall
if ( y >= H-B-HALF_BALL_SIZE )
{
y_inc = -1*ballS;
}
//Top Wall
if ( y <= 0+M+HALF_BALL_SIZE )
{
y_inc = 1*ballS;
}
//Player Hiting Wall
//Bottom Wall
if ( playerY >= H-B-100 )
{
playerY_inc = -1*playerS;
}
//Top Wall
if ( playerY <= 0+M )
{
playerY_inc = 1*playerS;
}
//Player
Rectangle2D ballB = ball.getBounds2D();
if ( ball.getBounds2D().intersects(player.getBounds2D() ))
{
System.out.println("true");
//x_inc = -1*ballS;
}
//Wall
x += x_inc;
y += y_inc;
playerY += playerY_inc;
repaint(); // Now display
Thread.sleep( 10 ); // 100 Hz
}
} catch ( Exception e ) {};
}
}
Edit: Solved it, I used math and x-y coords to work out if it was inside the other shape. Thanks the help.

ball.getBounds2D() == player.getBounds2D()
Is a reference check as they are objects; not primitives. You are checking if the Rectangle2D returned by both the game objects are one in the same (which they aren't).
To check if a Rectangle2D object intersects another Rectangle2D object you should do:
ball.getBounds2D().intersects(player.getBounds2D())

Related

Drawing lines to create a Cell in Java

I am trying to create a DFS generated maze. I started by making a Cell object that has 4 lines (Top, Right, Bottom and Left). I then drew these lines on to a Maze JPanel. My problem is that most of the cells look fine but the left and top side of the JPanel have thick lines and I can't figure out how to make it just a regular grid.
Here is my Cell where I create the lines:
boolean[] walls = {true, true, true, true};
// Draw the lines of one cell with w width and h height
void drawCell(Graphics g, int w, int h){
// Set the color of the lines to white
g.setColor(Color.WHITE);
// If the top wall exists draw a top line
if (walls[0]) {
g.drawLine(TopLeftX(), TopLeftY(), TopRightX(w), TopRightY());
}
// If a right wall exists draw a right line
if (walls[1]) {
g.drawLine(TopRightX(w), TopRightY(), BotRightX(w), BotRightY(h));
}
// If a bottom wall exists draw a bottom line
if (walls[2]) {
g.drawLine(BotRightX(w), BotRightY(h), BotLeftX(), BotLeftY(h));
}
// If a left wall exists draw a left line
if (walls[3]) {
g.drawLine(BotLeftX(), BotLeftY(h), TopLeftX(), TopLeftY());
}
}
// Set each coordinate for the lines, these will make a square that
// is w wide and h high
private int TopLeftX() { return i; }
private int TopLeftY() { return j; }
private int TopRightX(int w){ return i * w; }
private int TopRightY() { return j; }
private int BotRightX(int w){ return i * w; }
private int BotRightY(int h){ return j * h; }
private int BotLeftX() { return i; }
private int BotLeftY(int h) { return j * h; }
w is the width of a cell and h is the height.
And here is my MazeView JPanel where I draw the lines:
class MazeView extends JPanel{
private Cell grid[][];
private Cell cell;
private int row;
private int col;
private int width = 600;
private int height = 580;
// Create a maze view JPanel that is rows tall and cols wide
MazeView(int rows, int cols){
super.setBackground(Color.BLACK);
super.setLayout(new GridLayout(rows, cols));
newGrid(rows, cols);
}
// Paint all the cells
public void paintComponent(Graphics g){
super.paintComponent(g);
// Get the height and width of each cell
int h = height / getRows();
int w = width / getCols();
// Loop to draw each cell
for (int i = 0; i <= getRows(); i++){
for (int j = 0; j <= getCols(); j++){
grid[i][j].drawCell(g, w, h);
}
}
}
}
I appreciate any help I can get.
When this is run my grid looks like this:
Have a look at g.drawLine(TopLeftX(), TopLeftY(), TopRightX(w), TopRightY()); - resolving the values of those methods you get coordinates i, j, i*w, j. Assuming that i and j are the cell positions you'll draw a line
for cell 0/0 from 0/0 to 0/0
for cell 1/0 from 1/0 to w/0
for cell 0/1 from 0/1 to 0/1
for cell 2/2 from 2/2 to 2*w/2
etc.
Thus you'll want to correct your coordinate calculation for all 4 draw commands.
Assuming i andj are the cell's grid coordinates and w and h are the dimensions of the cell the coordinates for the top left corner would then be i * w and j * h and for the bottom right corner (i + 1) * w and (j + 1) * h.
Example:
0 3 6 9
--------------> x
0 | +---+---+---+
| |0/0|1/0|2/0|
3 | +---+---+---+
| |0/1|1/1|2/1|
6 | +---o---+---+
| |0/2|1/2|2/2|
9 | +---+---O---+
V
y
Let's assume each cell has a width and hight of 3 pixels. Thus the coordinates for the bottom center cell are:
top left (o): x = i * w = 1 * 3 = 3 and y = j * h = 2 * 3 = 6
bottom right (O): x = (i + 1) * w = (1 + 1) * 3 = 6 and y = (j + 1) * h = (2 + 1) * 3 = 9.
Well it isn't a maze yet. Im starting by drawing each cell
Don't fully grasp what you are attempting, but I would think a cell needs to be different colors, not lines. So for example a white cell is a place a player can move to. A black cell is a wall. I'm not sure how drawing individual line will make a maze?
I am trying to create a DFS generated maze.
Don't know what that is, but here is some old code that might give you some ideas.
This is designed to be a maze and you paint icons (instead of colors as I suggested above) for each cell. In this basic implementation you only have two types of icons:
a floor
a wall
A file containing 0/1 is used to identify each cell and therefore the icon of the cell
You then have a playing piece that can move from floor to floor and is blocked when it hits a wall.
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class SmallWorld extends JPanel implements KeyListener, ActionListener
{
//WORLD
String[][] worldArray = new String[30][30];
//Block colors
private static Color redBlock = new Color(255,0,0,255);
private static Color whiteBlock = new Color(255,255,255,255);
private static Color blackBlock = new Color(0,0,0,150);
//World images
// JLabel wall = new JLabel( new ImageIcon("wall.gif") );
// JLabel floor = new JLabel( new ImageIcon("floor.gif") );
ImageIcon wallIcon = new ImageIcon("dukewavered.gif");
ImageIcon floorIcon = new ImageIcon("copy16.gif");
//Starting coordinates
int blockPositionX = 1;
int blockPositionY = 1;
//Typing area to capture keyEvent
JTextField typingArea;
//Viewable area
JViewport viewable;
String type = "";
JLayeredPane layeredPane;
JPanel worldBack;
JPanel panel;
JPanel player;
Dimension worldSize = new Dimension(1500, 1500);
public SmallWorld() {
super( );
createWorld();
layeredPane = new JLayeredPane();
add(layeredPane);
layeredPane.setPreferredSize( worldSize );
worldBack = new JPanel();
layeredPane.add(worldBack, JLayeredPane.DEFAULT_LAYER);
worldBack.setLayout( new GridLayout(30, 30) );
worldBack.setPreferredSize( worldSize );
worldBack.setBounds(0, 0, worldSize.width, worldSize.height);
worldBack.setBackground( whiteBlock );
for (int i = 0; i < 30; i++) {
for (int j = 0; j < 30; j++) {
JPanel square = new JPanel( new BorderLayout() );
worldBack.add( square );
type = worldArray[i][j];
if ( type.equals("1") )
{
square.add( new JLabel(wallIcon) );
}
else
{
square.add( new JLabel(floorIcon) );
}
}
}
//Draw the player
player = new JPanel();
player.setBounds(50, 50, 50, 50);
player.setBackground( Color.black );
player.setLocation(50, 50);
layeredPane.add(player, JLayeredPane.DRAG_LAYER);
//set where the player starts
// panel = (JPanel)worldBack.getComponent( 31 );
// panel.add( player );
//Create the typing area with keyListener, add to window
typingArea = new JTextField(20);
typingArea.addKeyListener(this);
typingArea.setEditable( false );
add(typingArea);
}
//Get the world from the DAT file and translate it into
//a 2d array to be used by paintComponent
public void createWorld() {
String getData = null;
int countRow = 0;
try {
//Get file
FileReader fr = new FileReader("world.dat");
BufferedReader br = new BufferedReader(fr);
getData = new String();
//read each line from file, store to 2d array
while ((getData = br.readLine()) != null) {
if(countRow < 30) {
for (int i = 0; i < 30; i++) {
String temp = "" + getData.charAt(i);
worldArray[countRow][i] = temp;
}
countRow++;
}
}
} catch (IOException e) {
System.out.println("Uh oh, got an IOException error!");
e.printStackTrace();
}
}
//Move Block around the world
public void moveBlock() {
Point pt = new Point();
pt.x = blockPositionX * 50;
pt.y = blockPositionY * 50;
int x = Math.max(0, pt.x - 250);
int y = Math.max(0, pt.y - 250);
Rectangle r = new Rectangle(x, y, 550, 550);
scrollRectToVisible( r );
}
//check for collisions with blocks
public boolean checkCollision(int row, int col) {
if ( worldArray[col][row].equals("1") ) {
return true;
}
else {
return false;
}
}
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
updateView( e );
e.consume();
}
public void keyReleased(KeyEvent e) {
}
public void actionPerformed(ActionEvent e) {
}
//Update the view of the window based on which button is pressed
protected void updateView( KeyEvent e ) {
//if UP
if ( e.getKeyCode() == 38 ) {
if ( checkCollision( blockPositionX, blockPositionY - 1 ) == false ) {
blockPositionY = blockPositionY - 1;
moveBlock();
player.setLocation(blockPositionX *50, blockPositionY*50);
}
}
//if DOWN
if ( e.getKeyCode() == 40 ) {
if ( checkCollision( blockPositionX, blockPositionY + 1 ) == false ) {
blockPositionY = blockPositionY + 1;
moveBlock();
player.setLocation(blockPositionX *50, blockPositionY*50);
}
}
//if LEFT
if ( e.getKeyCode() == 37 ) {
if ( checkCollision( blockPositionX - 1, blockPositionY ) == false ) {
blockPositionX = blockPositionX - 1;
moveBlock();
player.setLocation(blockPositionX *50, blockPositionY*50);
}
}
//if RIGHT
if ( e.getKeyCode() == 39 ) {
if ( checkCollision( blockPositionX + 1, blockPositionY ) == false ) {
blockPositionX = blockPositionX + 1;
moveBlock();
player.setLocation(blockPositionX *50, blockPositionY*50);
}
}
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("SmallWorld");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane = new SmallWorld();
newContentPane.setPreferredSize( new Dimension(1500, 1500) );
JScrollPane scrollPane = new JScrollPane( newContentPane );
scrollPane.setPreferredSize( new Dimension(568, 568) );
frame.getContentPane().add( scrollPane );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setResizable( false );
//frame.setSize(500,520);
frame.setVisible( true );
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater( new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
You will need a couple of small icons to represent the floor/wall.
You will also need a file to represent the maze. Here is an example "world.dat" file:
111111111111111111111111111111
100010001010001000101000100011
100010001010001000101000100011
100011101010000000001000000001
100010000010000000001000000001
100110000010000000001000000001
100000000010000000001000000001
111100011110000000001000000001
100000000110001110111000111011
100000000000001110111000111011
100000000000000000000000000001
100010001110000000000000000001
100010001110001110111000111011
100011101100000000000000000011
100010000110001110111000111011
100110000100000000000000000011
100000000110000000001000000001
111100011100000000000000000011
100000000100000000000000000011
100000000010000000000000000001
100000000010000000000000000001
100010000000000000000000000001
100010000000001110111000111011
100011101110000000011000000001
100010000110000000011000000001
100110000110000000001000000001
100000000110001110111000111011
111100011110000000011000000001
100000000110000000011000000001
111111111111111111111111111111

Painting an arbitrary collection of points quickly

I am writing a darts application, and have implemented a Dartboard which is painted as a BufferedImage.
When rendering the dartboard, I first iterate over the co-ordinates of the BufferedImage and calculate the 'segment' that it resides in. I wrap this up into a DartboardSegment, which is basically just a collection of points with a small amount of extra structure (what number on the board it corresponds to, etc).
Currently, to actually render the dartboard I paint each point individually, like the following:
for (Point pt : allPoints)
{
DartboardSegment segment = getSegmentForPoint(pt);
Color colour = DartboardUtil.getColourForSegment(segment);
int rgb = colour.getRGB();
int x = (int)pt.getX();
int y = (int)pt.getY();
dartboardImage.setRGB(x, y, rgb);
}
Obviously this takes some time. It's not an intolerable amount (~2-3s to paint a 500x500 area), but I'd like to eliminate this 'lag' if I can. In other areas of my application I have encountered alternate methods (such as Graphics.fillRect()) which are much faster.
I've seen that there is a fillPolgyon() method on the Graphics class, however I don't think I can easily convert my segments into polygons because their shapes vary (e.g. the shape of a triple, a circle for the bullseye...). Is there a faster way in java to paint an arbitrary array of Points at once, rather than looping through and painting individually?
The code that I want to write is something like:
for (DartboardSegment segment : allSegments)
{
Color colour = DartboardUtil.getColourForSegment(segment);
Polgyon poly = segment.toPolygon();
Graphics gfx = dartboardImage.getGraphics();
gfx.setColor(colour);
gfx.fillPolygon(poly);
}
I don't think I can easily convert my segments into polygons because their shapes vary (e.g. the shape of a triple, a circle for the bullseye...)
Here is something that may give you some ideas.
You can create Shape objects to represent each area of the dartboard:
import java.awt.*;
import java.util.*;
import javax.swing.*;
import java.awt.geom.*;
public class Dartboard extends JPanel
{
private ArrayList<DartboardSegment> segments = new ArrayList<DartboardSegment>();
private int size = 500;
private int radius = size / 2;
private int border = 25;
private int doubleSize = size - (2 * border);
private int tripleSize = size / 2;
private int thickness = 10;
public Dartboard()
{
createSegmentWedges();
int innerRadius = size - (2 * border);
Shape outer = new Ellipse2D.Double(0, 0, size, size);
Shape inner = new Ellipse2D.Double(border, border, innerRadius, innerRadius);
Area circle = new Area( outer );
circle.subtract( new Area(inner) );
segments.add( new DartboardSegment(circle, Color.BLACK) );
createBullsEye();
}
private void createSegmentWedges()
{
int angle = -99;
for (int i = 0; i < 20; i++)
{
// Create the wedge shape
GeneralPath path = new GeneralPath();
path.moveTo(250, 250);
double radians1 = Math.toRadians( angle );
double x1 = Math.cos(radians1) * radius;
double y1 = Math.sin(radians1) * radius;
path.lineTo(x1 + 250, y1 + 250);
angle += 18;
double radians2 = Math.toRadians( angle );
double x2 = Math.cos(radians2) * radius;
double y2 = Math.sin(radians2) * radius;
path.lineTo(x2 + 250, y2 + 250);
path.closePath();
Color wedgeColor = (i % 2 == 0) ? Color.BLACK : Color.WHITE;
segments.add( new DartboardSegment(path, wedgeColor) );
// Create the double/triple shapes
Color color = (i % 2 == 0) ? Color.RED : Color.GREEN;
createShape(doubleSize, path, color);
createShape(tripleSize, path, color);
}
}
private void createShape(int outerSize, GeneralPath path, Color color)
{
int outerOffset = (size - outerSize) / 2;
int innerSize = outerSize - (2 * thickness);
int innerOffset = (size - innerSize) / 2;
Shape outer = new Ellipse2D.Double(outerOffset, outerOffset, outerSize, outerSize);
Shape inner = new Ellipse2D.Double(innerOffset, innerOffset, innerSize, innerSize);
Area circle = new Area( outer );
circle.subtract( new Area(inner) );
circle.intersect( new Area(path) );
segments.add( new DartboardSegment(circle, color) );
}
private void createBullsEye()
{
int radius1 = 40;
int offset1 = (size - radius1) / 2;
Ellipse2D.Double bullsEye1 = new Ellipse2D.Double(offset1, offset1, radius1, radius1);
segments.add( new DartboardSegment(bullsEye1, Color.GREEN) );
int radius2 = 20;
int offset2 = (size - radius2) / 2;
Ellipse2D.Double bullsEye2 = new Ellipse2D.Double(offset2, offset2, radius2, radius2);
segments.add( new DartboardSegment(bullsEye2, Color.RED) );
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g.create();
for (DartboardSegment segment: segments)
{
g2d.setColor( segment.getColor() );
g2d.fill( segment.getShape() );
}
}
#Override
public Dimension getPreferredSize()
{
return new Dimension(500, 500);
}
class DartboardSegment
{
private Shape shape;
private Color color;
public DartboardSegment(Shape shape, Color color)
{
this.shape = shape;
this.color = color;
}
public Shape getShape()
{
return shape;
}
public Color getColor()
{
return color;
}
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("DartBoard");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Dartboard());
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
After a bit more digging, I think one solution to this is to do the following. It's not the neatest, but I think it will work:
int i = 0;
for (int y=0; y<height; y++)
{
for (int x=0; x<width; x++)
{
Point pt = new Point(x, y);
DartboardSegment segment = getSegmentForPoint(pt);
Color colour = DartboardUtil.getColourForSegment(segment);
pixels[i] = colorToUse.getRGB();
i++;
}
}
dartboardImage.setRGB(0, 0, width, height, pixels, 0, width);
I am open to better suggestions, however!

Why are my images not drawing on the JPanel?

I'm trying to make a hex board with hex images (720x835 GIF) on a scroll-able JPanel. I've overridden the paintComponent method to draw the tiles at different specific locations and used a timer to call repaint at each tick.
When repaint() is called, doDrawing is called. When doDrawing is called, choseTile is called to draw the tiles with drawImage.
For some reason, the tiles are not being drawn and I'm left with an empty black panel. Why are my images not being drawn? Is it because the images are too large? The panel is too large?
public class MapPanel extends JPanel {
// Images for the tiles
Image tile1;
Image tile2;
//etc
// measurements for the tiles
int tileX = 720;
int tileY = 835;
int dimensionX = 14760;
int dimensionY = 14613;
//Use this to keep track of which tiles goes where on a 20x20 board
public int[][] hexer;
/**
* Create the panel.
*/
public MapPanel(int[][] hexMap) {
hexer = hexMap;
setPreferredSize(new Dimension(dimensionX, dimensionY));
setBackground(Color.black);
setFocusable(true);
loadImages();
Timer timer = new Timer(140, animatorTask);
timer.start();
}
//getting the images for the tiles
private void loadImages() {
// Setting the images for the tiles
ImageIcon iid1 = new ImageIcon("/Images/tiles/tile1.gif");
tile1 = iid1.getImage();
ImageIcon iid2 = new ImageIcon("/Images/tiles/tile2.gif");
tile2 = iid2.getImage();
//etc
}
// Drawing tiles
private void choseTile(Graphics g, int x, int y, int id) {
switch (id) {
case 1:
g.drawImage(tile1, x, y, this);
break;
case 2:
g.drawImage(tile2, x, y, this);
break;
//etc
}
}
// repainting stuff
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
private void doDrawing(Graphics g) {
int actualX;
int actualY;
//set the painting coordinates and image ID then call the method to draw
for (int x = 0; x < 20; x++) {
for (int y = 0; y < 20; y++) {
if ((y + 1) % 2 == 0) {
actualX = x * tileX + 720;
} else {
actualX = x * tileX + 360;
}
if((x + 1) % 2 == 0){
actualY = (y/2) * 1253 + 418;
}else{
actualY = (y+1)/2 * 1253 + 1044;
}
if(hexer[x][y] != 0)
choseTile(g, actualX, actualY, hexer[x][y]);
}
}
}
private ActionListener animatorTask = new ActionListener() {
public void actionPerformed(ActionEvent e) {
repaint();
}
};
}
Edit: I've already checked to make sure the images aren't null.
Following Andrew Thompson's suggestion; I used ImageIO. I was able to figure out that the way I was accessing the image files was faulty thanks to thrown errors by ImageIO.

AffineTransform.rotate() - how do I xlate, rotate, and scale at the same time?

I have the following code which does (the first part of) what I want drawing a chessboard with some pieces on it.
Image pieceImage = getImage(currentPiece);
int pieceHeight = pieceImage.getHeight(null);
double scale = (double)side/(double)pieceHeight;
AffineTransform transform = new AffineTransform();
transform.setToTranslation(xPos, yPos);
transform.scale(scale, scale);
realGraphics.drawImage(pieceImage, transform, this);
that is, it gets a chess piece's image and the image's height, it translates the drawing of that image to the square the piece is on and scales the image to the size of the square.
Llet's say I want to rotate the black pieces 180 degrees. Somewhere I expect to have something like:
transform.rotate(Math.toRadians(180) /* ?, ? */);
But I can't figure out what to put in as X and Y. If I put nothing, the image is nicely rotated around the 0,0 point of its chessboard square, putting the piece upside down in the square to the northeast of where it is supposed to be. I've guessed at various other combinations of x,y, with no luck yet.
I am already using translation to put the piece in the right square, the rotation transform wants another x,y around which to rotate things, but I don't know how to tell the transform to rotate the piece around one x,y and write the image to a different x,y. Can someone help me with the rotation parameters, or point me to something that explains how these things work? I've found examples of things that don't explain how they work, and so far I haven't figured out how to alter them to my situation...
Major edit: addition of working code. Sorry, I don't know how to post images, please substitute your own.
When I run the following I get a 2x2 chess board with a rook at the top left and a knight at the bottom right.
If I go into SmallChessboardComponent and take the comment delims off the first rotation transform statement, I get the rook in its original place upside down and the knight does not appear. If I instead take the comment delims off the second transform statement, neither piece appears at all.
I am looking for a way to turn the pieces upside down on the square on which they would appear anyway. I want to draw each piece onto the board; I don't want code that flips the board.
main program:
package main;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import directredraw.SmallChessboardComponent;
public class SmallChessboardMain
{
private static void dbg (String message) { System.out.println(message); }
public static void main(String[] args)
{
//Create the top-level container and add contents to it.
final JFrame frame = new JFrame("Small Chessboard");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// create the chessboard itself and set it in the component
SmallChessboard chessboard = new SmallChessboard();
// create the GUI component that will contain the chessboard
SmallChessboardComponent chessboardComponent = new SmallChessboardComponent();
chessboardComponent.setBoard (chessboard);
frame.getContentPane().add(chessboardComponent, BorderLayout.CENTER);
// pack and display all this
frame.pack();
frame.setVisible(true);
}
}
chessboard class:
package main;
public class SmallChessboard
{
Piece [][] squares = new Piece[2][2];
public SmallChessboard()
{
squares[0][0] = new Piece(Piece.WHITECOLOR, Piece.ROOK);
squares[1][1] = new Piece(Piece.WHITECOLOR, Piece.KNIGHT);
}
/**
* get the piece at the given rank and file; null if
* no piece exists there.
*/
public Piece getPiece(int rank, int file)
{
if (0 > rank || rank > 2 || 0 > file || file > 2) { return null; }
else { return squares[rank][file]; }
}
}
chessboard component class:
package directredraw;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import javax.swing.JPanel;
import main.Piece;
import main.PieceImages;
import main.SmallChessboard;
public class SmallChessboardComponent extends JPanel
{
private static final long serialVersionUID = 1L;
Color whiteSquareColor = Color.yellow;
Color blackSquareColor = Color.blue;
private static void dbg (String msg) { System.out.println(msg); }
private SmallChessboard chessboard = null;
// currently playing with rotating images; this affine transform
// should help
AffineTransform rotationTransform = null;
private final int DEFAULT_PREFERRED_SIDE = 400;
int wholeSide = DEFAULT_PREFERRED_SIDE;
int side = DEFAULT_PREFERRED_SIDE / 8;
public void setBoard (SmallChessboard givenBoard)
{ chessboard = givenBoard;
}
/**
* set either or both colors for this chessboard; if either of
* the arguments are null, they do not change the existing color
* setting.
*/
public void setColors (Color darkSquare, Color lightSquare)
{
if (darkSquare != null) { blackSquareColor = darkSquare; }
if (lightSquare != null) { whiteSquareColor = lightSquare; }
}
/**
* return the preferred size for this component.s
*/
public Dimension getPreferredSize()
{ return new Dimension(wholeSide, wholeSide);
}
/*
* return the image object for the given piece
*/
private Image getImage(Piece piece)
{ return PieceImages.getPieceImage(this, piece);
}
public void paintComponent (Graphics graphics)
{
Graphics2D realGraphics = (Graphics2D) graphics;
// the image container might have been stretched.
// calculate the largest square held by the current container,
// and then 1/2 of that size for an individual square.
int wholeWidth = this.getWidth();
int wholeHeight = this.getHeight();
wholeSide = (wholeWidth / 2) * 2;
if (wholeHeight < wholeWidth) { wholeSide = (wholeHeight / 2) * 2; }
side = wholeSide / 2;
Rectangle clip = realGraphics.getClipBounds();
boolean firstColumnWhite = false;
// for each file on the board:
// set whether top square is white
// set background color according to white/black square
//
for (int fileIndex=0; fileIndex<8; fileIndex++)
{ boolean currentColorWhite = firstColumnWhite;
firstColumnWhite = !firstColumnWhite;
// draw the board and all the pieces
int rankIndex = 2;
for (rankIndex=2; rankIndex>=0; rankIndex--)
{
currentColorWhite = !currentColorWhite;
// x and y position of the top left corner of the square we're drawing,
// and rect becomes the dimensions and position of the square itself.
int xPos = fileIndex * side;
int yPos = rankIndex * side;
Rectangle rect = new Rectangle(xPos, yPos, side, side);
// if this square intersects the clipping rectangle we're drawing,
// then we'll draw the square and the piece on the square.
if (rect.intersects(clip))
{
// this puts down the correct color of square
if (currentColorWhite) { realGraphics.setColor(whiteSquareColor); }
else { realGraphics.setColor(blackSquareColor); }
realGraphics.fillRect(xPos, yPos, side, side);
// if there is a piece on this square and it isn't selected at the
// moment, then draw it.
Piece currentPiece = chessboard.getPiece(rankIndex, fileIndex);
if (currentPiece != null)
{
Image pieceImage = getImage(currentPiece);
int pieceHeight = pieceImage.getHeight(null);
double scalePiece = (double)side/(double)pieceHeight;
AffineTransform transform = new AffineTransform();
// transform.setToRotation(Math.toRadians(180));
transform.setToRotation(Math.toRadians(180), side/2, side/2);
transform.scale(scalePiece, scalePiece);
transform.translate(xPos/scalePiece, yPos/scalePiece);
// if (currentPiece.isBlack())
// {
// transform.translate(xPos + (side+2), yPos + (side+2));
// transform.rotate(Math.toRadians(180) /*, ,*/ );
// }
// else
// {
// transform.translate(xPos, yPos);
// }
realGraphics.drawImage(pieceImage, transform, this);
}
}
}
}
}
}
Piece.java
package main;
public class Piece
{
// piece types; the sum of the piece type and the
// color gives a number unique to both type and color,
// which is used for things like image indices.
public static final int PAWN = 0;
public static final int KNIGHT = 1;
public static final int BISHOP = 2;
public static final int ROOK = 3;
public static final int QUEEN = 4;
public static final int KING = 5;
// one of these is the color of the current piece
public static final int NOCOLOR = -1;
// the sum of the piece type and the
// color gives a number unique to both type and color,
// which is used for things like image indices.
public static final int BLACKCOLOR = 0;
public static final int WHITECOLOR = 6;
int color = NOCOLOR;
int imageIndex;
public Piece(int color, int pieceType)
{
// dbg -- all pieces are white rooks for now...
this.color = color;
imageIndex = color + pieceType;
}
/**
* return the integer associated with this piece's color;
*/
int getPieceColor()
{ return color;
}
/**
* return true if the piece is black
*/
public boolean isBlack()
{
return (color == BLACKCOLOR);
}
/**
* set the color associated with this piece; constants
* found in this class.
*/
public void setPieceColor(int givenColor)
{ color = givenColor;
}
/**
* return the integer designated for the image used for this piece.
*/
int getImageIndex()
{ return imageIndex;
}
}
and PieceImages.java
package main;
import java.awt.Component;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.net.URL;
public class PieceImages
{ static Image images[] = null;
private static void dbg (String msg) { System.out.println(msg); }
public static Image getPieceImage (Component target, Piece piece)
{
if (images == null)
try
{
MediaTracker tracker = new MediaTracker(target);
images = new Image[12];
images[Piece.BLACKCOLOR + Piece.PAWN] = getImage(tracker, "bPawn.gif");
images[Piece.BLACKCOLOR + Piece.KNIGHT] = getImage(tracker, "bKnight.gif");
images[Piece.BLACKCOLOR + Piece.BISHOP] = getImage(tracker, "bBishop.gif");
images[Piece.BLACKCOLOR + Piece.ROOK] = getImage(tracker, "bRook.gif");
images[Piece.BLACKCOLOR + Piece.QUEEN] = getImage(tracker, "bQueen.gif");
images[Piece.BLACKCOLOR + Piece.KING] = getImage(tracker, "bKing.gif");
images[Piece.WHITECOLOR + Piece.PAWN] = getImage(tracker, "wPawn.gif");
images[Piece.WHITECOLOR + Piece.KNIGHT] = getImage(tracker, "wKnight.gif");
images[Piece.WHITECOLOR + Piece.BISHOP] = getImage(tracker, "wBishop.gif");
images[Piece.WHITECOLOR + Piece.ROOK] = getImage(tracker, "wRook.gif");
images[Piece.WHITECOLOR + Piece.QUEEN] = getImage(tracker, "wQueen.gif");
images[Piece.WHITECOLOR + Piece.KING] = getImage(tracker, "wKing.gif");
if (!tracker.waitForAll(10000))
{ System.out.println("ERROR: not all piece main.images loaded");
}
dbg("piece images loaded");
}
catch (Exception xcp)
{ System.out.println("Error loading images");
xcp.printStackTrace();
}
return images[piece.getImageIndex()];
}
private static Image getImage(MediaTracker tracker, String file)
{
URL url = PieceImages.class.getResource("images/" + file);
Image image = Toolkit.getDefaultToolkit().getImage(url);
tracker.addImage(image, 1);
return image;
}
}
Okay, this is a little slight of hand. The example code will only work for 90 degree increments (it was only designed this way), to do smaller increments you to use some trig to calculate the image width and height (there's a answer somewhere for that to ;))
public class ImagePane extends JPanel {
private BufferedImage masterImage;
private BufferedImage renderedImage;
public ImagePane(BufferedImage image) {
masterImage = image;
applyRotation(0);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(renderedImage.getWidth(), renderedImage.getHeight());
}
#Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
protected int getVirtualAngle(int angle) {
float fRotations = (float) angle / 360f;
int rotations = (int) (fRotations - (fRotations / 1000));
int virtual = angle - (rotations * 360);
if (virtual < 0) {
virtual = 360 + virtual;
}
return virtual;
}
public void applyRotation(int angle) {
// This will only work for angles of 90 degrees...
// Normalize the angle to make sure it's only between 0-360 degrees
int virtualAngle = getVirtualAngle(angle);
Dimension size = new Dimension(masterImage.getWidth(), masterImage.getHeight());
int masterWidth = masterImage.getWidth();
int masterHeight = masterImage.getHeight();
double x = 0; //masterWidth / 2.0;
double y = 0; //masterHeight / 2.0;
switch (virtualAngle) {
case 0:
break;
case 180:
break;
case 90:
case 270:
size = new Dimension(masterImage.getHeight(), masterImage.getWidth());
x = (masterHeight - masterWidth) / 2.0;
y = (masterWidth - masterHeight) / 2.0;
break;
}
renderedImage = new BufferedImage(size.width, size.height, masterImage.getTransparency());
Graphics2D g2d = renderedImage.createGraphics();
AffineTransform at = AffineTransform.getTranslateInstance(x, y);
at.rotate(Math.toRadians(virtualAngle), masterWidth / 2.0, masterHeight / 2.0);
g2d.drawImage(masterImage, at, null);
g2d.dispose();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
int width = getWidth() - 1;
int height = getHeight() - 1;
int x = (width - renderedImage.getWidth()) / 2;
int y = (height - renderedImage.getHeight()) / 2;
g2d.drawImage(renderedImage, x, y, this);
}
}
Now, you could simply "flip" the image vertically, if that works better for you
public class FlipPane extends JPanel {
private BufferedImage masterImage;
private BufferedImage renderedImage;
public FlipPane(BufferedImage image) {
masterImage = image;
flipMaster();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(renderedImage.getWidth(), renderedImage.getHeight());
}
#Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
protected void flipMaster() {
renderedImage = new BufferedImage(masterImage.getWidth(), masterImage.getHeight(), masterImage.getTransparency());
Graphics2D g2d = renderedImage.createGraphics();
g2d.setTransform(AffineTransform.getScaleInstance(1, -1));
g2d.drawImage(masterImage, 0, -masterImage.getHeight(), this);
g2d.dispose();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
int width = getWidth() - 1;
int height = getHeight() - 1;
int x = (width - renderedImage.getWidth()) / 2;
int y = (height - renderedImage.getHeight()) / 2;
g2d.drawImage(renderedImage, x, y, this);
}
}
This basically results in:
Original | 180 degree rotation | Vertical inversion...
Now, if you change the flipMaster method to read:
g2d.setTransform(AffineTransform.getScaleInstance(-1, -1));
g2d.drawImage(masterImage, -masterImage.getWidth(), -masterImage.getHeight(), this);
You'll get the same effect as the 180 rotation ;)
Try performing the rotation before translating it into the correct position. Simply reorder the transformations so that first you scale, then you rotate (around the center point of the image), and then you translate:
transform.scale(scale, scale);
transform.rotate(Math.PI, pieceWidth / 2, pieceHeight /2);
transform.translation(xPos, yPos);
By the way, the black pieces on a chess board usually aren't rotated. :)
Update
In what way does it not work? The solution I provided also also differs from your code in that scaling is performed before translating. You can try the rotating, translating, and then scaling.
I strongly suggest that you modify your code so that you can perform the translation last. If you do this, everything will become a lot less complicated. Once you have done so, you only have to scale once to automatically take care of the rotation.
transform.scale(scale, scale); // or transform.scale(scale, -scale); to rotate
transform.translate(xPos, yPos);

Creating a Checkers Board in Java

I'm begining a little project to create a simple checkers game. However it's been a long time since I've used the java GUI tools. The goal of the code at this point is to draw the initial board (red pieces at top, black at bottom). However all I get when I run the code is a blank frame. I'm also a little uncertain if my circle drawing code will do what I want (ie create solid red or black circles inside certain squares) Here is the code. Thanks in advance for any help/suggestions
EDIT: I should probably alternate drawing blue and gray squares or else the thing will probably just be a giant blue blob, however I'll settle for a giant blue blob at this point :p
import javax.swing.*;
import java.awt.*;
public class CheckersServer
{
public static class Board
{
private JFrame frame = new JFrame();
private JPanel backBoard = new JPanel();
Board()
{
frame.setSize(905,905);
backBoard.setSize(900,900);
frame.setTitle("Checkers");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
backBoard.setVisible(true);
boardSquare bs;
String type = null;
//Filling in Red Side
for (int i = 0; i <=1; i++)
{
for(int j = 0; j < 9; j++)
{
if(j % 2 == 0)
{
type = "Red";
}
else
{
type = "Blank";
}
bs = new boardSquare(100*j,100*i,type);
backBoard.add(bs);
}
}
//Filling in empty middle
type = "Blank";
for (int i = 2; i < 7; i++)
{
for(int j = 0; j < 9; j++)
{
bs = new boardSquare(100*j,100*i,type);
backBoard.add(bs);
}
}
//Filling in Black side
for (int i = 7; i < 9; i++)
{
for(int j = 0; j < 9; j++)
{
if(j % 2 != 0)
{
type = "Black";
}
else
{
type = "Blank";
}
bs = new boardSquare(100*j,100*i,type);
backBoard.add(bs);
}
}
backBoard.repaint();
frame.add(backBoard);
frame.repaint();
}
private class boardSquare extends JComponent
{
private int x; //x position of the rectangle measured from top left corner
private int y; //y position of the rectangle measured from top left corner
private boolean isBlack = false;
private boolean isRed = false;
public boardSquare(int p, int q, String type)
{
x = p;
y = q;
if (type.equals("Black"))
{
isBlack = true;
isRed = false;
}
else if (type.equals("Red"))
{
isRed = true;
isBlack = false;
}
else if (type.equals("Blank"))
{
isBlack = false;
isRed = false;
}
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Rectangle box = new Rectangle(x,y,100,100);
g2.draw(box);
g2.setPaint(Color.BLUE);
g2.fill(box);
if(isBlack)
{
g2.fillOval(x, y,100 ,100 );
g2.setColor(Color.black);
g2.drawOval(x, y, 100, 100);
}
else if(isRed)
{
g2.fillOval(x, y,100 ,100 );
g2.setColor(Color.red);
g2.drawOval(x, y, 100, 100);
}
}
}
}
public static void main(String[] args)
{
Board game = new Board();
}
}
You have several issues.
Java UI is layout-based, which means that when you add a component to a parent, the parent's layout determines where the child component will be placed. You don't have any code to set up the layout, and so your application is using the defaults (FlowLayout is the default, and this may work in your case, as long as your JFrame and children are the appropriate size).
The bigger problems are in your boardSquare class. By default, JPanels have a dimension of 10x10. You aren't specifying the size, and so all your squares are 10x10. You need to tell the squares how big they are. You can do this in the boardSquare constructor:
setPreferredSize(new Dimension(100, 100));
Finally, in your drawing code, you are doing an offset of x,y when drawing the squares and circles. This is an offset from the top-left corner of the component. Your components (after setting the size) will be 100x100 pixels. But if your x,y are greater than these values, you will be drawing outside of the bounds of the component. Instead, these values should be set to 0,0 because that is the top-left corner of the component you are drawing in.
By just setting the preferred size of the squares and setting x,y to 0, I was able to get the squares drawing in the frame, though it wasn't pretty. You will need to work on setting the correct layout before it will be laid out correctly.
Here are some hints:
Your BoardSquares have dimension 0x0. Not a good size for something you want to be visible to the user.
To help visualize what's going on, cause each BoardSquare to be 100x100 pixels in size, and give them a border. Now you can see where they are showing up in your GUI. Your GUI code still needs significant changes, but this will at least let you start seeing what you're dealing with.
public BoardSquare(int p, int q, String type)
{
this.setBorder(new LineBorder(Color.CYAN, 2));
this.setPreferredSize(new Dimension(100, 100));
// ... etc ...
BoardSquare seems to be coded to draw its contents based on coordinates from the absolute topmost leftmost point in the window, but they should be coded to draw themselves from the topmost leftmost point of the BoardSquare itself. That is, components should only draw within their own boundaries, and they should use coordinates that assume 0,0 designates the top,left of the component, not of the window.
If you want to use BoardSquares (JComponents) and add them to the frame, you probably should use a different layout manager, like GridLayout. FlowLayout won't give you the kind of precise positioning you want.
import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.*;
public class CheckersServer2
{
public static String type_BLANK = "BLANK";
public static String type_RED = "RED";
public static String type_BLACK = "BLACK";
public static int width = 100;
public static int height = 100;
public static class Board
{
private JFrame frame = new JFrame();
private JPanel backBoard = new JPanel();
Board()
{
int numRows = 8;
int numCols = 8;
frame.setSize(905,905);
backBoard.setSize(900,900);
frame.setTitle("Checkers");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
backBoard.setVisible(true);
String type;
for(int r=0; r<numRows; r++){
for(int c=0; c<numCols; c++){
//
type = type_BLANK;
if(c%2==0){
if(r==0 || r==2) {
type = type_RED;
}else if(r==6){
type = type_BLACK;
}
}else{
if(r==1){
type = type_RED;
} else if(r==5 || r==7) {
type = type_BLACK;
}
}
backBoard.add(new BoardSquare(r,c,type));
}
}
backBoard.repaint();
frame.add(backBoard);
frame.repaint();
}
private class BoardSquare extends JComponent
{
/**
*
*/
private static final long serialVersionUID = 1L;
private int x; //x position of the rectangle measured from top left corner
private int y; //y position of the rectangle measured from top left corner
private boolean isBlack = false;
private boolean isRed = false;
public BoardSquare(int p, int q, String type)
{
//this.setBorder(new LineBorder(Color.CYAN, 2));
this.setPreferredSize(new Dimension(width, height));
x = p;
y = q;
if (type.equals(type_BLACK))
{
isBlack = true;
isRed = false;
}
else if (type.equals(type_RED))
{
isRed = true;
isBlack = false;
}
else if (type.equals(type_BLANK))
{
isBlack = false;
isRed = false;
}
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Rectangle box = new Rectangle(x,y,width,height);
g2.draw(box);
g2.setPaint(Color.BLUE);
g2.fill(box);
int ovalWidth = width - 15;
int ovalHeight = ovalWidth;
if(isBlack)
{
g2.setColor(Color.black);
g2.fillOval(x, y, ovalWidth, ovalHeight);
g2.drawOval(x, y, ovalWidth, ovalHeight);
}
else if(isRed)
{
g2.setColor(Color.red);
g2.fillOval(x, y, ovalWidth, ovalHeight);
g2.drawOval(x, y, ovalWidth, ovalHeight);
}
}
}
}
public static void main(String[] args)
{
Board game = new Board();
}
}

Categories

Resources