I tried making a program that flips a coin(shows image of heads first and later shows image of tails) and I encountered problems trying to have the image of the coin viewed when I ran the problem; only a blank screen would show. I don't know whether this is from an improper saving method of the jpg images or from an error in the code. I also came across an error before again coding the program where I had the heads image show and tails image not show.
CoinTest.java runs coin runner and Coin.java is the class for the program.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CoinTest extends JPanel
implements ActionListener
{
private Coin coin;
public CoinTest ()
{
Image heads = (new ImageIcon("quarter-coin-head.jpg")).getImage();
Image tails = (new ImageIcon("Indiana-quarter.jpg")).getImage();
coin = new Coin(heads, tails);
Timer clock = new Timer(2000, this);
clock.start();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
int x = getWidth() / 2;
int y = getHeight() / 2;
coin.draw(g, x, y);
}
public void actionPerformed(ActionEvent e)
{
coin.flip();
repaint();
}
public static void main(String[] args)
{
JFrame w = new JFrame("Flipping coin");
w.setSize(300, 300);
w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
CoinTest panel = new CoinTest();
panel.setBackground(Color.WHITE);
Container c = w.getContentPane();
c.add(panel);
w.setVisible(true);
}
}
Now the actual Coin class.
import java.awt.Image;
import java.awt.Graphics;
public class Coin
{
private Image heads;
private Image tails;
private int side = 1;
public Coin(Image h, Image t)
{
heads = h;
tails = t;
}
//flips the coin
public void flip()
{
if (side == 1)
side = 0;
else
side = 1;
}
//draws the appropriate side of the coin - centered in the JFrame
public void draw(Graphics g, int x, int y)
{
if (side == 1)
g.drawImage(heads, heads.getWidth(null)/3, heads.getHeight(null)/3, null);
else
g.drawImage(heads, tails.getWidth(null)/3, tails.getHeight(null)/3, null);
}
}
Firstly, ensure that both images are in the correct location to load.
Secondly, you have a typo here:
if (side == 1)
g.drawImage(heads, heads.getWidth(null)/3, heads.getHeight(null)/3, null);
else
g.drawImage(heads, tails.getWidth(null)/3, tails.getHeight(null)/3, null);
^^^^
should be tails...
The width and height of the applet are coded in the tag. The code that draws the applet uses the two methods to get these values at run time. So now, different tags can ask for the same applet to paint different sized rectangles. The source code does not need to be recompiled for different sizes.
Related
I'm trying to draw squares to make grid system to make snake game in java but when i run my code i can't see any thing.
I made node class that has the square info like position, and grid class that has the data of all the squares and GUI class and i tried to use drawRect method but i have no result.
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.util.*;
import java.util.List;
public class SnakeGame {
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setSize(300,300);
frame.setLayout(null);
Grids grids = new Grids(300);
GUI gui = new GUI(grids.nodesList,grids.nodeSize);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(gui);
frame.setVisible(true);
}
public static class Node{
public float[] position = new float[2];
public Node(float[] Position){
//this is the x position
position[0] = Position[0];
//this is the y position
position[1] = Position[1];
}
}
public static class Grids{
public int nodesNum = 6;
public float screenSize;
public float nodeSize;
public float[] startNodePos = new float[2];
public List<Node> nodesList = new ArrayList<Node>();
public Grids(float ScreenSize){
screenSize = ScreenSize;
nodeSize = screenSize / nodesNum;
//set the start node position
//x
startNodePos[0] = nodeSize /2;
//y
startNodePos[1] = nodeSize /2;
//use for loop to create nodes
for (float X = startNodePos[0] ; X <= nodeSize * 5; X += nodeSize / 2) {
for (float Y = startNodePos[1]; Y <= nodeSize * 5; Y += nodeSize / 2) {
float[] Pos = {X, Y};
Node node = new Node(Pos);
nodesList.add(node);
}
}
}
}
public static class GUI extends JPanel{
public List<Node> nodes;
public float NodeSize;
public GUI(List<Node> Nodes,float nodeSize){
nodes = Nodes;
NodeSize = nodeSize;
}
#Override
public void paintComponents(Graphics g) {
super.paintComponents(g);
for(Node node : nodes){
g.setColor(Color.BLACK);
g.drawRect((int)node.position[0],(int)node.position[1],(int)NodeSize,(int)NodeSize);
}
}
}
}
There are two primary mistakes
First
frame.setLayout(null);
This means that you will become completely responsible for determine the location and size of all child components.
In this case, it's probably just easier to get rid of it and use the default BorderLayout
Second
You're overriding paintComponents, not paintComponent (not the s at the end)
public void paintComponents(Graphics g) {
//...
}
Since, there are no components to be painted, it's not getting called
Simple change it to paintComponent (and make sure you call it's super properly)
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (Node node : nodes) {
g.setColor(Color.BLACK);
g.drawRect((int) node.position[0], (int) node.position[1], (int) NodeSize, (int) NodeSize);
}
}
Observations
While running through the code, I note some ... interesting things, which might cause you issues in the long run.
The size of the view area is not the same as the size of the window. A window also needs to display the window decorations (title bar, borders, etc), which are inset into the window. This reduces the available viewable area. It's better to have the content provide a sizing hint and pack the window around, which brings me to...
The model seems to be taking into consideration view properties. You should aim to have the model and view be as agnostic as possible, meaning that the model should not be dictating display state to the view. Instead, the size of the cell's, and by extensions, the size of the panel, should be determined by the view.
I'm trying to write a simple program: a bouncing ball that appears and starts bouncing after you press the "Start" button on the screen. The program should be closed by pressing "X".
For some reason, it runs very slowly. The ball is blinking, and I have to wait for a long time after I press the "X" for program to close.
Here is the code:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;
public class Bounce
{
public static void main(String[] args)
{
JFrame frame = new BounceFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.show();
}
}
class BounceFrame extends JFrame
{
public BounceFrame()
{
setSize(WIDTH, HEIGHT);
setTitle("Bounce");
Container contentPane = getContentPane();
canvas = new BallCanvas();
contentPane.add(canvas, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
addButton(buttonPanel, "Start", new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
addBall();
}
});
contentPane.add(buttonPanel, BorderLayout.SOUTH);
}
public void addButton(Container c, String title, ActionListener listener)
{
JButton button = new JButton(title);
c.add(button);
button.addActionListener(listener);
}
public void addBall()
{
try
{
Ball b = new Ball(canvas);
canvas.add(b);
for (int i = 1; i <= 10000; i++)
{
b.move();
Thread.sleep(10);
}
}
catch (InterruptedException exception)
{
}
}
private BallCanvas canvas;
public static final int WIDTH = 300;
public static final int HEIGHT = 200;
}
class BallCanvas extends JPanel
{
public void add(Ball b)
{
balls.add(b);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
for (int i = 0; i < balls.size(); i++)
{
Ball b = (Ball)balls.get(i);
b.draw(g2);
}
}
private ArrayList balls = new ArrayList();
}
class Ball
{
public Ball(Component c) { canvas = c; }
public void draw(Graphics2D g2)
{
g2.fill(new Ellipse2D.Double(x, y, XSIZE, YSIZE));
}
public void move()
{
x += dx;
y += dy;
if (x < 0)
{
x = 0;
dx = -dx;
}
if (x + XSIZE >= canvas.getWidth())
{
x = canvas.getWidth() - XSIZE;
dx = -dx;
}
if (y < 0)
{
y = 0;
dy = -dy;
}
if (y + YSIZE >= canvas.getHeight())
{
y = canvas.getHeight() - YSIZE;
dy = -dy;
}
canvas.paint(canvas.getGraphics());
}
private Component canvas;
private static final int XSIZE = 15;
private static final int YSIZE = 15;
private int x = 0;
private int y = 0;
private int dx = 2;
private int dy = 2;
}
The slowness comes from two related problems, one simple and one more complex.
Problem #1: paint vs. repaint
From the
JComponent.paint docs:
Invoked by Swing to draw components.
Applications should not invoke paint directly, but should instead use the repaint method to schedule the component for redrawing.
So the canvas.paint() line at the end of Ball.move must go.
You want to call
Component.repaint
instead...
but just replacing the paint with repaint will reveal the second problem, which prevents the ball from even appearing.
Problem #2: Animating inside the ActionListener
The ideal ActionListener.actionPerformed method changes the program's state and returns as soon as possible, using lazy methods like repaint to let Swing schedule the actual work for whenever it's most convenient.
In contrast, your program does basically everything inside the actionPerformed method, including all the animation.
Solution: A Game Loop
A much more typical structure is to start a
javax.swing.Timer
when your GUI starts, and just let it run
"forever",
updating your simulation's state every tick of the clock.
public BounceFrame()
{
// Original code here.
// Then add:
new javax.swing.Timer(
10, // Your timeout from `addBall`.
new ActionListener()
{
public void actionPerformed(final ActionEvent ae)
{
canvas.moveBalls(); // See below for this method.
}
}
).start();
}
In your case, the most important
(and completely missing)
state is the
"Have we started yet?"
bit, which can be stored as a boolean in BallCanvas.
That's the class that should do all the animating, since it also owns the canvas and all the balls.
BallCanvas gains one field, isRunning:
private boolean isRunning = false; // new field
// Added generic type to `balls` --- see below.
private java.util.List<Ball> balls = new ArrayList<Ball>();
...and a setter method:
public void setRunning(boolean state)
{
this.isRunning = state;
}
Finally, BallCanvas.moveBalls is the new
"update all the things"
method called by the Timer:
public void moveBalls()
{
if (! this.isRunning)
{
return;
}
for (final Ball b : balls)
{
// Remember, `move` no longer calls `paint`... It just
// updates some numbers.
b.move();
}
// Now that the visible state has changed, ask Swing to
// schedule repainting the panel.
repaint();
}
(Note how much simpler iterating over the balls list is now that the list has a proper generic type.
The loop in paintComponent could be made just as straightforward.)
Now the BounceFrame.addBall method is easy:
public void addBall()
{
Ball b = new Ball(canvas);
canvas.add(b);
this.canvas.setRunning(true);
}
With this setup, each press of the space bar adds another ball to the simulation.
I was able to get over 100 balls bouncing around on my 2006 desktop without a hint of flicker.
Also, I could exit the application using the 'X' button or Alt-F4, neither of which responded in the original version.
If you find yourself needing more performance
(or if you just want a better understanding of how Swing painting works),
see
"Painting in AWT and Swing:
Good Painting Code Is the Key to App Performance"
by Amy Fowler.
I would suggest you to use 'Timer' class for running your gameloop.It runs infinitely and you can stop it whenever you want using timer.stop()
You can also set its speed accordingly.
I am trying to create a program in Java that is sort of like a board game. I have gameTiles, currently with only one color as I try to get the layout right. I want the tiles to appear about halfway of the width of the window and extend to the bottom, maybe anywhere from 9x9 or 11x11 different tiles. I have tried to use the grid layout to get these to be close together, not necessarily touching but close enough to look like a board game. However, no matter what I try, the tiles are space so far apart, and change shape when I resize window. I have been using the GridLayout manager to try to achieve this. Here is my code.
import java.awt.GridLayout;
import javax.swing.JFrame;
public class GameWindow extends JFrame {
public GameWindow(String title){
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(1200,400);
}
/**
* #param args
*/
public static void main(String[] args) {
GameWindow gameWindow = new GameWindow("Game");
gameWindow.setLayout(new GridLayout(0,2));
GameTile greenTile = new GameTile(0,true,0,10);
GameTile greenTile2 = new GameTile(0,true,0,10);
gameWindow.add(greenTile);
gameWindow.add(greenTile2);
gameWindow.setVisible(true);
}
}
This is the GameWindow.java file. The GameTile.java I have so far (which is still mainly not finished just for testing) is as follows:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
/**
* #author Zachary Parks
*
*/
public class GameTile extends JPanel {
private Color color;
private Color[] colors = {Color.BLUE, Color.YELLOW, Color.BLACK};
private int score, multiplier,initialX,initialY;
private boolean positiveEffect;
public GameTile(int colorTile, boolean effect, int initX, int initY){
color = colors[colorTile];
score = getScore(color);
multiplier = getMultiplier(color);
positiveEffect = effect;
initialX = initX;
initialY = initY;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Image image = null;
try {
image = ImageIO.read(new File("greentile.png"));
} catch (IOException e) {
e.printStackTrace();
}
g.drawImage(image,initialX,initialY,this);
}
private int getMultiplier(Color color2) {
return 0;
}
private int getScore(Color color2) {
return 0;
}
/**
* Method that returns the data from the tile in
* array of int. 0 index = added score, 1 index = tile effect score
* #return
*/
public int[] getData() {
int [] scoreData = null;
scoreData[0] = score*multiplier;
return null;
}
}
A lot of the code is still in progress, like the GameTile's properties, all I'm trying at this point is get the tiles next to each other.
This is what I am getting:
To add tiles like a grid. A tileSize variable is great to have. Let's say the image/tile is 32 pixels.
public static final tileSize = 32;
With this, we can now add tiles using a for loop:
for(int x = 0; x < SCREEN_WIDTH / GameTile.tileSize; x++) { // loop through as many tiles fit the x-axis.
for(int y = 0; y < SCREEN_HEIGHT / GameTile.tileSize; y++) { // do the same with y-axis
GameTile greenTile = new GameTile(0,true, x * GameTile.tileSize , y * GameTile.tileSize);
gameWindow.add(greenTile);
}
}
SCREEN_WIDTH and SCREEN_HEIGHT is the size of your JFrame.
Keep in mind this loops through the whole screen, you wanted the half but it's easily configurable.
Please format your code next time (tab in), much easier to read and help you.
I highly recommend moving image = ImageIO.read(new File("greentile.png")); into the constructor, right now you're loading the image every framerate for every gameTile which will cause performance drop.
Also do not have a JPanel for every GameTile. Instead keep it in your main drawing class and loop through all GameTiles using an ArrayList
public static ArrayList<GameTile> gameTiles = new ArrayList<GameTile>();
protected void paintComponent(Graphics g) {
for(int i = 0; i < gameTiles.size(); i++) {
gameTiles.get(i).draw(g);
}
So instead of adding a JPanel to the JFrame for every gameTile, we draw gameTiles at the specified coordinates. Good luck!
To answer your question in the comment field: the code will look similar to this
public class GameWindow extends JPanel {
public static ArrayList<GameTile> gameTiles = new ArrayList<GameTile>();
public static void main(String[] args) {
new GameWindow();
}
public GameWindow() {
JFrame frame = new JFrame();
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(this);
frame.setVisible(true);
// add all the tiles (I just use x and y as parameters here)
gameTiles.add(new GameTile(10, 10));
gameTiles.add(new GameTile(50, 10));
}
public void paintComponent(Graphics g) {
for(int i = 0; i < gameTiles.size(); i++) {
gameTiles.get(i).draw(g);
}
}
}
And inside your GameTile class, remove the extends JPanel. And rename the paintComponent as draw or something alike.
However, no matter what I try, the tiles are space so far apart, and change shape when I resize window
A GridLayout expands each cell to fill the space available to the component. If you only have two cells each cell will take up half the width of the frame.
So the solution is to wrap your tile panel into another panel that will respect the preferred size of the tiles. So don't set the layout of the frame, set the layout of a panel holding the tiles:
Something like:
JPanel tilePanel = new JPane( new GridLayout(0, 2, 5, 5) );
tilePanel.add( new GameTile(...) );
tilePanel.add( new GameTile(...) );
JPanel wrapper = new JPanel( new GridBagLayout() );
wrapper.add(tilePanel, new GridBagConstraints() );
frame.add(wrapper, BorderLayout.CENTER );
The above code will cause the tiles to be centered in the frame.
frame.add(wrapper, BorderLayout.LINE_END);
The above will cause the tiles to display on the right of the frame vertically centered.
I have a simple physics loop that does a calculation for a time interval, waits for the interval to pass, and then renders the results on the screen. It's very simple code (even though the timing is probably wrong, but that's exactly what I'm trying to learn about) and works well when I am moving the mouse around the screen.
package physicssim;
import java.awt.Graphics;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PhysicsSim extends JFrame {
private static class PhysicsObject {
public PhysicsObject(double x, double y, double v_x, double v_y) {
this.x = x;
this.y = y;
this.v_x = v_x;
this.v_y = v_y;
}
public double x;
public double y;
public double v_x;
public double v_y;
}
PhysicsObject particle;
boolean running = true;
DrawPane drawPane;
public PhysicsSim() {
particle = new PhysicsObject(10,10, .1, .2);
drawPane = new DrawPane(particle);
this.setSize(800,600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setContentPane(drawPane);
this.setVisible(true);
}
private static class DrawPane extends JPanel {
PhysicsObject p;
public DrawPane(PhysicsObject p) {
this.p = p;
}
#Override
public void paint(Graphics g) {
super.paint(g); //To change body of generated methods, choose Tools | Templates.
g.fillOval((int)p.x, (int) p.y, 10, 10);
}
}
public void start() {
int FPS = 60;
long TIME_BETWEEN_FRAMES_NS = 1000000000/FPS;
// Initial draw
drawPane.repaint();
long lastDrawTime = System.nanoTime();
while(running) {
// Update physics
particle.x+=particle.v_x*(TIME_BETWEEN_FRAMES_NS*.0000001);
particle.y+=particle.v_y*(TIME_BETWEEN_FRAMES_NS*.0000001);
// While there is time until the next draw wait
while(TIME_BETWEEN_FRAMES_NS > (System.nanoTime()-lastDrawTime)) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(PhysicsSim.class.getName()).log(Level.SEVERE, null, ex);
}
}
drawPane.repaint();
long currentTime = System.nanoTime();
System.out.println(currentTime - lastDrawTime);
lastDrawTime = currentTime;
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
PhysicsSim sim = new PhysicsSim();
sim.start();
}
}
The last bit about printing the time difference was just a sanity check to make sure that it was in fact calling around the requested interval. The results are fairly consistent so I don't see why there should be any choppiness.
As I mentioned above, this code works great if I a moving the mouse around the screen, everything is smooth.
If I am not moving the mouse it becomes very choppy until I start moving the mouse over the application.
I assume this is something simple, but I hope that you guys can help me. Thank you.
Alright, it looks like my problem was I was drawing directly to g in paint(). After replacing with the following everything worked correctly.
#Override
public void paint(Graphics g) {
BufferedImage img = new BufferedImage(800, 600, BufferedImage.TYPE_3BYTE_BGR);
img.getGraphics().fillOval((int) p.x, (int) p.y, 10, 10);
g.drawImage(img, 0, 0, null);
}
I was considering deleting this code snippet because it's rough and shameful, but maybe it will help someone else. Happy coding.
I have started developing Tetris Game. Everything is working fine but how to retain rectangles at the bottom?
This is the Comp1 class in which the random shape is retrieved and move down with the timer
package buildblock;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import buildblock.tetris;
public class Comp1 extends JPanel implements ActionListener {
int curx=10;
int cury=30;
int nx=0;
int ny=0;
int p=1;
Timer t;
boolean EndofLine=false;
JLabel l1=new JLabel("");
int value=0;
int coords[][][]=new int[3][3][2];
int shape[][][][]={
{{{0,0},{0,0},{0,0}},{{0,0},{0,0},{0,0}},{{0,0},{0,0},{0,0}}},
{{{0,0},{100,20},{0,0}},{{0,0},{100,40},{0,0}},{{80,60},{100,60},{0,0}}},
{{{0,0},{100,20},{0,0}},{{80,40},{100,40},{120,40}},{{0,0},{0,0},{0,0}}},
{{{0,0},{100,20},{0,0}},{{0,0},{100,40},{0,0}},{{0,0},{100,60},{0,0}}},
{{{80,20},{100,20},{0,0}},{{0,0},{100,40},{0,0}},{{0,0},{100,60},{0,0}}},
{{{0,0},{100,20},{0,0}},{{80,40},{100,40},{0,0}},{{80,60},{0,0},{0,0}}},
{{{80,20},{0,0},{0,0}},{{80,40},{100,40},{0,0}},{{0,0},{100,60},{0,0}}},
{{{80,20},{100,20},{0,0}},{{80,40},{100,40},{0,0}},{{0,0},{0,0},{0,0}}},
};
Comp1(tetris Parent)
{
setVisible(true);
setSize(400,900);
curx=(400-curx)/2;
setLayout(new BorderLayout());
timer();
}
public void getShape(int a)
{
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
for(int k=0;k<2;k++)
{
coords[i][j][k]=shape[a][i][j][k];
repaint();
}
}
}
}
public void paint(Graphics g)
{
super.paint(g);
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
for(int k=0;k<2;k++)
{
if(coords[i][j][k]!=0)
{
if(k==0)
{
curx=coords[i][j][k]+nx;
}
else
{
cury=coords[i][j][k]+ny;
drawRec(g,curx,cury,20,20);
}
}
}
}
}
}
public void drawRec(Graphics g,int newx,int newy,int w,int h)
{
g.drawRect(newx, newy, 20, 20);
g.drawLine(curx+1,cury+20-1,curx+20-1,cury+20-1);
}
public void timer()
{
t=new Timer(150,this);
t.start();
}
public int Random()
{
Random r=new Random();
int n=Math.abs(r.nextInt()%7+1);
return n;
}
public void lineDown()
{
ny=ny+10;
repaint();
}
public void actionPerformed(ActionEvent e)
{
if(value!=250&&!EndofLine)
{
value=value+5;
if(p==0)
{
p=Random();
}
getShape(p);
lineDown();
}
else
{
p=Random();
ny=0;
EndofLine=false;
value=0;
}
}
}
The shape is a 4 dimensional array from which the width and height of particular rectangle is retrieved which collectively form a desired shape.Through random function we choose the particular shape with getShape() method and using drawRect function we draw the Rectangles.
Now the lineDown function move down the particular shape with increment of 10,and after reaching at the last line the repaint() method is called and new Random shape is falling down from top,The Problem is now how to retain the particular shape at bottom so that next operations can be carried out.
I would create a List of "shapes" that have already fallen down to the bottom of the Tetris board. This List would be held within your Tetris class and when the current falling item hits the bottom of the board or one of the already falled shapes then it should be stopped and added to the fallen list.
Other general tips:
From personal experience, try to stay away from arrays of size > 2 unless its necessary; they are bloated, confusing and hard to maintain. In your case there's a perfect interface to use called Shape. Check out this code
// java.awt.geom.Path2D implements java.awt.Shape
java.awt.geom.Path2D path = new Path2D.Double();
path.moveTo(0, 0);
path.lineTo(2, 0);
path.lineTo(2, 2);
path.lineTo(2, 0);
path.closePath();
path.transform(AffineTransform.getScaleInstance(20, 20));
This creates a Shape that is your basic square! You then have access to great features that you wont have to implement yourself.
PS: As Andrew suggests in the comments, "Also look at Shape based collision detection. It uses Java 2D Area objects to test for intersection."