Creating graphics with programming languages can seem a little strange; how do these commands we write possibly become that nice picture on the screen? How can that nice picture be animated?
Today I’m going to show you a really simple 2D example of how to do it in Java.

Do we need special packages?

None that don’t already come in the Java build that you are using. We will be drawing the image onto the Graphics object in a JPanel. The Graphics object is from the AWT library and the JPanel is from the Swing library – simply import java.awt.*; and import javax.swing.*;
To make our lives simple we are going to take advantage of the Object Oriented nature of Java so that we are Manipulating objects and then drawing them to screen – this helps to separate logic from view and if you’ve already read my MVC with Java tutorial, you’ll realise that means we are going to do this using the Model View Controller architecture. If you don’t know what that is or haven’t really used it before, go and have a read now because I will assume in this tutorial that you are an MVC whizz-kid.

So, let’s get started!

What are we making?

A really simple example of animated 2D graphics is a Mouse-Trail application – a fading coloured line follows the mouse wherever it goes. This example is really simple and is only intended to get you familiar with the idea, and get you thinking about what you can create yourself. It is created by ticking a timer and at each tick taking the old mouse position and the new mouse position and creating a line between them. The fading part is done by then manipulating that line object – no need for fancy tricks or filters!
We are going to have quite a few classes, but most of them are only really to fulfil the MVC requirement which may seem a bit like overkill for this example, but will soon come into its own for a more detailed project.

  • Model.java – This is the model, it stores details of all the lines in the drawing and sends notifications to the observers.
  • View.java – This is the UI – in this case incredibly simple as it just makes a frame and puts a customised JPanel (canvas.java) in it. It is an observer to Model and will repaint the canvas. It also deals with the Timer.
  • Controller.java – Unlike the MVC tutorial we actually have something for the controller to do here; it deals with working out the position of the mouse and telling the model.
  • Canvas.java – This is where things are drawn! It extends JPanel and re-writes the repaint methods.
  • Line.java – This is a line object, which stores where it should be stored and the transparency level.

Show us the code!

I’ll start off with the Line class because it is the building block that we need.

private int x1, y1, x2, y2;
private float transparency;
private Color colour;
private Model model;

These are the variables we will need. We store the start and end points as integers because this is what the Graphics object will draw a line with – floats and doubles etc. are useless to it.
The value of the transparency is stored as a float as it will be a ‘percentage’ of 1. I’ve also included a Color variable which will allow you to alter the colour that the line is drawn in. Finally, there is a Model variable so that the Line knows where it is being stored – this will also allow it to remove itself from the Model once it has full transparency (i.e. can’t be seen!).

public Line(int nx1, int ny1, int nx2, int ny2, Color c, Model m)
{
	x1 = nx1;
	y1 = ny1;
	x2 = nx2;
	y2 = ny2;
	transparency = 1;
	colour = c;
	model = m;
}

This is the constructor – nothing fancy, just setting all the variables to those given and setting the transparency to 1.
The rest of this class is given up to Get and Set methods which I won’t bother writing into the tutorial, but obviously they are in the sample code at the bottom of the page. The only one which is altered from the standard return method is the setTransparency method.

public void setTransparency(float transparency) 
{
	this.transparency = transparency;
	if(this.transparency<=0)
	{
		model.remove(this);
		return;
	}
}

This method sets the value and then checks if the transparency has gone equal to or below 0. If it has, it removes itself from the model containing it.

Next we will look at the Canvas class because it is what draws the lines.

private View parent;

This is the only variable we need for this class because it is very simple. If you are going to implement some custom Double Buffering, you will need to have a few more variables but that is outside of the scope of this tutorial.

public Canvas(View v)
{
	super();
	parent = v;
}

There is only a very simple constructor, just calling the super constructor and setting our only variable to the one given.

public void paint(Graphics g)
{	
	Graphics2D canvas = (Graphics2D)g;
	canvas.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
 
	Dimension d = getSize();
	g.setColor(Color.black);
	g.fillRect(0, 0, d.width, d.height);
	Vector<Line> lines = parent.getLines();
	for(int i=0; i<lines.size(); i++)
	{
		canvas.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, lines.elementAt(i).getTransparency()));
		canvas.setColor(lines.elementAt(i).getColour());
		canvas.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
		canvas.drawLine(lines.elementAt(i).getX1(), lines.elementAt(i).getY1(), lines.elementAt(i).getX2(), lines.elementAt(i).getY2());
lines.elementAt(i).setTransparency((float)(lines.elementAt(i).getTransparency()-0.02));
	}
}

This is the all-new paint method which will over-write the native one. Its job is very simple – draw a big black rectangle over the whole screen, then draw each line in the Model. We cast the Graphics object to a Graphics2D object to allow us to use Transparency and alter the stroke (thickness and style). We then make the changes we want to and then use the drawline method to draw it! Finally, we change the transparency of the line by a pre-set amount.

Next up we’ll make the Model class so that the View and the Controller will have something to communicate with.

private Vector<Line> lines;

This is the only variable in the Model and is just a container to store the Line objects. I have used a Vector but you can use anything you like as long as the size isn’t too constrictive – an array is bad because it really needs the size to be specified at the beginning.

public Model()
{
	lines = new Vector<Line>();
}

A simple constructor is all that is needed, and it just initializes our container for Lines.

public void update()
{
	this.setChanged();
	this.notifyObservers(lines);
}

This is the update method that is required for the class to fulfil its purpose as an Observable in the MVC architecture. It just sends the lines container to any observers.

public void remove(Line l)
{
	if(lines.contains(l))
		lines.remove(l);
}
 
public void add(int x1, int y1, int x2, int y2, Color c)
{
	lines.add(new Line(x1, y1, x2, y2, c, this));
}

These are the remaining methods in the class and deal with creating and removing lines. They are fairly self explanatory, and the only item of note is that the remove method ensures that the given line exists to avoid any errors.

Now that we have the Model we can create the Controller which sends all the information about the mouse location to the Model. It implements Observer so that it can be an observer to the Model.

public class Controller implements Observer, ActionListener, MouseMotionListener

This is the class declaration line, and as shown we implement Observer, ActionListener and MouseMotionListener. You may also wish to implement some others, for example a KeyListener or a MouseListener.

private Model model;
private int prevx, prevy;

The variables we need for the Controller are an instance of the Model so that data about events can be sent, and also the ‘old’ positions of the mouse in order to create start and end points for the line.

public Controller(Model m)
{
model = m;
	model.addObserver(this); // Register this class with the Model.
	prevx = -1;
	prevy = -1;
}

Again this is a very simple constructor, where the Model is set to the one given, and registers this Controller as being an observer. We also set the previous mouse values to -1 as this is an impossible number for the screen position to register and we can identify the first movement. If we didn’t do this, we would start off with a big ugly line from the top right corner (0, 0) to where the mouse is.

There are several methods we need to allow us to have the implementations of the class (Observer etc.) but most of them aren’t used. For this example we are only going to use ActionPerformed() and MouseMoved()

public void actionPerformed(ActionEvent e) 
{
	model.update();
}

Basically this method will be fired every time the timer in the View ticks, so all we want to do is update the model.

public void mouseMoved(MouseEvent arg0) 
{
	if(prevx>-1 && prevy>-1)
	{
		model.add(prevx, prevy, arg0.getX()-7, arg0.getY()-25, Color.GREEN);
	}
	prevx = arg0.getX()-7;
	prevy = arg0.getY()-25;
}

This is the section where we work out where the mouse is on the screen. As you will see we have the condition for checking our first-move values (prevx and prevy are set to -1 before the first move and changed after it). I’m also making a slight adjustment to the location of -7 on the x value and -25 on the y value to make it look like the line is being drawn from the tip of the mouse pointer. If you are using a different pointer, you may need to alter these values.

That’s the Controller done, so let’s move on to the final class – the View.

public class View extends JFrame implements Observer

In the class declaration we simply extend JFrame and implement Observer to allow this class to hold and show a JPanel as well as register as an observer to the Model.

private Model model;
private Controller controller;
private Canvas canvas;
private Vector<Line> lines;

The variables we need are basically just instances of everything else. We need a Model to register with, a Controller to deal with Timer ticks, a Canvas to show everything on and a Vector of lines to store the update from the Model for the Canvas to get a hold of and display.

public View(Model m)
{
	super("Mouse Trail Tutorial"); // Properly instatiate the Superclass JFrame.
	MakeThis(); // Set up the GUI stuff.
	model = m;
	model.addObserver(this); // Register this class with the Model
	controller = new Controller(model); // Make the Controller using the same Model
	Timer timer = new Timer(10, controller); // Make the timer use the Controller
	timer.start(); // ...and start it
	lines = new Vector<Line>();
	this.addMouseMotionListener(controller);
}

A fairly detailed constructor for the View, but it is fairly simple and is just about registering this with everything else and starting the Timer. Note that I’m adding the MouseMotionListener available through the Controller to the View instead of the Canvas – strictly it should be the Canvas but as we are only showing the Canvas it’s a bit neater to do it this way. There will be no difference to how it shows, it is just slightly less efficient if you were to have other objects in the Frame.

public void MakeThis()
{
	canvas = new Canvas(this);
	this.getContentPane().add(canvas);
	this.pack();
	this.setVisible(true);
	this.setLocation(250, 250);
	this.setSize(500, 500);
 
	this.addWindowListener(new WindowAdapter() 
	{
		public void windowClosing(WindowEvent e) 
		{
			System.exit(0);
		}
	});
}

This is a fairly straightforward method to create and show the View. It initiates the Canvas variable to be linked with this View, then adds it to the contentPane and sets the size and location of the View. It also sets the View to be visible and adds a window listener to close it properly when the ‘x’ at the corner of the screen is clicked.

public void update(Observable arg0, Object arg1)
{
	if(arg1!=null)
	{
		try
		{
			Vector<Line> temp = (Vector<Line>)arg1;
			lines = temp;
			canvas.repaint();
		}
		catch(Exception e)
		{
			System.out.println("Error; Invalid update object");
		}
	}
}

The update method is required to allow the View to be an observer, and this allows the Model to send data to it on update.
In this example, the data being sent is a Vector of Line objects so we attempt to parse the Vector from the update Object and then tell the Canvas to repaint using the new lines.

And that’s it, done!

Conclusion

Today we’ve made a very simple example that is very probably useless to you at this point in time, but it does introduce a few key concepts of making 2D Graphics in Java – in particular the idea of using objects to represent items on the drawing which can then be individually modified, and also using the Graphics2D object to give a bit more freedom in the techniques you can achieve.
If you are wondering what the point is in learning this kind of stuff, I’ve used these basic concepts to create a 2D graphics engine driving a full and extended version of Asteroids, an extension of the 2D graphics engine to produce a 3D mesh with Fractal composition, and a separate project to create a detailed and rather graphics-happy extension of Pinball.

I hope you’ve enjoyed reading this and it’s inspired you to try and create something of your own. I’d love to hear of any projects you use these concepts for!

Remember to head over to our forum if you have any problems or just want to talk about everything Programming!

Download the ZIP file

Related Posts

More?

If you enjoyed this post, please consider promoting it.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Design Float
  • Reddit
  • Mixx
  • Technorati

Remeber to subscribe to the feed and get future articles delivered to your feed reader.

If you want to discuss this tutorial or any other thoughts you have then you can do so over on our fourm.

Comments


No comments yet...

Leave a Comment

(required)

(required)