Difference between revisions of "User:Nfwu/Painter"

From Robowiki
Jump to navigation Jump to search
m (New page: Something new I wrote to help with my debugging. Feel free to use, with or without giving credit. <pre>package nfwu; import robocode.*; import java.util.Vector; import java.util.Iterator...)
 
m (Nav)
Line 1: Line 1:
 +
{{User:Nfwu/Nav}}
 +
 
Something new I wrote to help with my debugging.
 
Something new I wrote to help with my debugging.
 
Feel free to use, with or without giving credit.
 
Feel free to use, with or without giving credit.
 +
 +
== Credit ==
 +
To [[David Alves]] for the basic structure, which was from [[DrawingBot]].
 +
 +
== Usage ==
 +
 +
Has to be initalized before being used, as so:
 +
<pre>
 +
public void run(){
 +
//I want 2 layers
 +
Painter.init(2);
 +
//Register first layer to key '1'
 +
Painter.setupLayer(0, "Enemy Position", java.awt.event.KeyEvent.VK_1);
 +
//Register second layer to key 'w'
 +
Painter.setupLayer(1, "Waves", java.awt.event.KeyEvent.VK_W);
 +
 +
//other stuff...
 +
 +
}
 +
</pre>
 +
 +
Event handlers to call from bot:
 +
<pre>
 +
public void onKeyPressed(java.awt.event.KeyEvent e){
 +
if (Painter.onKeyPressed(e)) return;
 +
// other stuff
 +
}
 +
public void onKeyReleased(java.awt.event.KeyEvent e){
 +
if (Painter.onKeyReleased(e)) return;
 +
// other stuff
 +
}
 +
public void onPaint(java.awt.Graphics2D g){ Painter.onPaint(g); }
 +
</pre>
 +
 +
Interactive Display Controls:
 +
* Holding "key" displays the relevant layer until the key is released.
 +
* Typing Shift+"key" toggles permanent display of a layer.
 +
* Holding "H" shows a list of layer names and their keycodes.
 +
 +
More complex graphics can be drawn by extending Painter.Renderable.
 +
 +
== Full Source Code ==
  
 
<pre>package nfwu;
 
<pre>package nfwu;
 +
 +
  
 
import robocode.*;
 
import robocode.*;
 +
 
import java.util.Vector;
 
import java.util.Vector;
 +
 
import java.util.Iterator;
 
import java.util.Iterator;
 +
 
import java.awt.Color;
 
import java.awt.Color;
 +
 
import java.awt.Graphics2D;
 
import java.awt.Graphics2D;
 +
 
import java.awt.event.KeyEvent;
 
import java.awt.event.KeyEvent;
 +
 +
  
 
// Credit goes to David Alves for basic structure from DrawingBot.
 
// Credit goes to David Alves for basic structure from DrawingBot.
 +
 
// Added multiple layers for drawing on.
 
// Added multiple layers for drawing on.
 +
 
//Event Handlers to call from bot...
 
//Event Handlers to call from bot...
  
Line 20: Line 75:
 
Painter.init(2);
 
Painter.init(2);
 
//Register first layer to key '1'
 
//Register first layer to key '1'
 +
 
Painter.setupLayer(0, "Enemy Position", java.awt.event.KeyEvent.VK_1);  
 
Painter.setupLayer(0, "Enemy Position", java.awt.event.KeyEvent.VK_1);  
 
//Register second layer to key 'w'
 
//Register second layer to key 'w'
 +
 
Painter.setupLayer(1, "Waves", java.awt.event.KeyEvent.VK_W);
 
Painter.setupLayer(1, "Waves", java.awt.event.KeyEvent.VK_W);
 +
 
//other stuff
 
//other stuff
 +
 
}
 
}
  
 
public void onKeyPressed(java.awt.event.KeyEvent e){
 
public void onKeyPressed(java.awt.event.KeyEvent e){
 +
 
if (Painter.onKeyPressed(e)) return;
 
if (Painter.onKeyPressed(e)) return;
 +
 
// other stuff
 
// other stuff
 +
 
}
 
}
  
 
public void onKeyReleased(java.awt.event.KeyEvent e){
 
public void onKeyReleased(java.awt.event.KeyEvent e){
 +
 
if (Painter.onKeyReleased(e)) return;
 
if (Painter.onKeyReleased(e)) return;
 +
 
// other stuff
 
// other stuff
 +
 
}
 
}
  
Line 41: Line 106:
  
 
// Interactive Display Controls:
 
// Interactive Display Controls:
 +
 
//  Holding "key" displays the relevant layer until the key is released.
 
//  Holding "key" displays the relevant layer until the key is released.
 +
 
//  Typing Shift+"key" toggles permanent display of a layer.
 
//  Typing Shift+"key" toggles permanent display of a layer.
 +
 
//  Holding "H" shows a list of layer names and their keycodes.
 
//  Holding "H" shows a list of layer names and their keycodes.
 +
 +
  
 
public class Painter {
 
public class Painter {
 +
 
public final static int HELP_KEY = KeyEvent.VK_H; //The 'h' key.
 
public final static int HELP_KEY = KeyEvent.VK_H; //The 'h' key.
public final static float MAGIC_FONT_HEIGHT_VALUE = 12.0f;
+
 
static boolean isDisplayingHelpMessage = true;
+
public final static float TEXT_HEIGHT = 12.0f;
static boolean isDisplayingLayersList = false;
+
 
static boolean isShiftPressed = false;
+
static boolean isDisplayingHelpMessage;
 +
 
 +
static boolean isDisplayingLayersList;
 +
 
 +
static boolean isShiftPressed;
 +
 
 +
 
  
 
//Setup stuff
 
//Setup stuff
 +
 
public static void init(int numberOfLayers){//Call before every round
 
public static void init(int numberOfLayers){//Call before every round
 +
 
System.out.println("This bot has debugging graphics.");
 
System.out.println("This bot has debugging graphics.");
 +
 
System.out.println("Hold the '"+KeyEvent.getKeyText(HELP_KEY)+"' key with Paint enabled for help.");
 
System.out.println("Hold the '"+KeyEvent.getKeyText(HELP_KEY)+"' key with Paint enabled for help.");
 +
 
overlays = new DebugOverlay[numberOfLayers];
 
overlays = new DebugOverlay[numberOfLayers];
 +
 +
isDisplayingHelpMessage = true;
 +
 
isDisplayingLayersList = false;
 
isDisplayingLayersList = false;
 +
 
isShiftPressed = false;
 
isShiftPressed = false;
 +
 
}
 
}
  
 
public static void setupLayer(int oid, String name, int key, boolean defaultDisp){ //key must be a valid VK_ code!!!
 
public static void setupLayer(int oid, String name, int key, boolean defaultDisp){ //key must be a valid VK_ code!!!
 +
 
overlays[oid] = new DebugOverlay(name, key, defaultDisp);
 
overlays[oid] = new DebugOverlay(name, key, defaultDisp);
 +
 
}
 
}
  
 
public static void setupLayer(int oid, String name, int key){
 
public static void setupLayer(int oid, String name, int key){
 +
 
setupLayer(oid, name, key, false);
 
setupLayer(oid, name, key, false);
 +
 
}
 
}
 +
 +
  
 
//Draw Stuff (oid = the layer id)
 
//Draw Stuff (oid = the layer id)
 +
 
public static void drawObject(int oid, Renderable r){
 
public static void drawObject(int oid, Renderable r){
 +
 
overlays[oid].renderables.add(r);
 
overlays[oid].renderables.add(r);
 +
 
}
 
}
 +
 +
  
 
public static void drawLineRect(int oid, Color color, double x1, double y1, double x2, double y2){ //Rectangular Coords as input
 
public static void drawLineRect(int oid, Color color, double x1, double y1, double x2, double y2){ //Rectangular Coords as input
 +
 
drawObject(oid, new Line(x1, y1, x2, y2, color));  
 
drawObject(oid, new Line(x1, y1, x2, y2, color));  
 +
 
}
 
}
 +
 +
  
 
public static void drawLinePol(int oid, Color color, double x1, double y1, double len, double ang){ //Relative polar Coords as input
 
public static void drawLinePol(int oid, Color color, double x1, double y1, double len, double ang){ //Relative polar Coords as input
 +
 
double x2 = x1 + Math.sin(ang) * len; //NOTE: Robocode Angles... www
 
double x2 = x1 + Math.sin(ang) * len; //NOTE: Robocode Angles... www
 +
 
double y2 = y1 + Math.cos(ang) * len;  
 
double y2 = y1 + Math.cos(ang) * len;  
 +
 
drawObject(oid, new Line(x1, y1, x2, y2, color));
 
drawObject(oid, new Line(x1, y1, x2, y2, color));
}
+
 
 +
}
 +
 
 +
  
 
public static void drawCircle(int oid, Color color, double x, double y, double radius){
 
public static void drawCircle(int oid, Color color, double x, double y, double radius){
 +
 
drawObject(oid, new Circle(x, y, radius, color));
 
drawObject(oid, new Circle(x, y, radius, color));
 +
 
}
 
}
 +
 +
  
 
public static void drawPoint(int oid, Color color, double x, double y){
 
public static void drawPoint(int oid, Color color, double x, double y){
 +
 
drawObject(oid, new Dot(x, y, color));
 
drawObject(oid, new Dot(x, y, color));
 +
 
}
 
}
 +
 +
  
 
public static void drawText(int oid, Color color, double x, double y, String text){
 
public static void drawText(int oid, Color color, double x, double y, String text){
 +
 
drawObject(oid, new Text(text, x, y, color));
 
drawObject(oid, new Text(text, x, y, color));
 +
 
}
 
}
  
 +
//Event Handlers
  
//Handler Stuff
 
 
public static boolean onKeyPressed(KeyEvent e) {
 
public static boolean onKeyPressed(KeyEvent e) {
 +
 
switch (e.getKeyCode()) {
 
switch (e.getKeyCode()) {
 +
 
case KeyEvent.VK_SHIFT:
 
case KeyEvent.VK_SHIFT:
 +
 
isShiftPressed = true;
 
isShiftPressed = true;
 +
 
return true;
 
return true;
 +
 
case HELP_KEY:
 
case HELP_KEY:
 +
 
if (isShiftPressed) isDisplayingHelpMessage = false;
 
if (isShiftPressed) isDisplayingHelpMessage = false;
 +
 
else isDisplayingLayersList = true;
 
else isDisplayingLayersList = true;
 +
 
return true;
 
return true;
 +
 
}
 
}
  
 
if (isShiftPressed) return false;
 
if (isShiftPressed) return false;
 +
 
for (int i=0;i<overlays.length;++i){
 
for (int i=0;i<overlays.length;++i){
 +
 
if (overlays[i].key == e.getKeyCode()){
 
if (overlays[i].key == e.getKeyCode()){
 +
 
overlays[i].displayed = true;
 
overlays[i].displayed = true;
 +
 
return true;
 
return true;
 +
 
}
 
}
 +
 
}
 
}
  
 
return false;
 
return false;
 +
 
}
 
}
  
Line 123: Line 256:
  
 
public static boolean onKeyReleased(KeyEvent e) {
 
public static boolean onKeyReleased(KeyEvent e) {
 +
 
switch (e.getKeyCode()) {
 
switch (e.getKeyCode()) {
 +
 
case KeyEvent.VK_SHIFT:
 
case KeyEvent.VK_SHIFT:
 +
 
isShiftPressed = false;
 
isShiftPressed = false;
 +
 
return true;
 
return true;
 +
 
case HELP_KEY:
 
case HELP_KEY:
 +
 
if (isShiftPressed) isDisplayingHelpMessage = false;
 
if (isShiftPressed) isDisplayingHelpMessage = false;
 +
 
else isDisplayingLayersList = false;
 
else isDisplayingLayersList = false;
 +
 
return true;
 
return true;
 +
 
}
 
}
  
 
//Toggle whether or not shift is pressed
 
//Toggle whether or not shift is pressed
 +
 
for (int i=0;i<overlays.length;++i){
 
for (int i=0;i<overlays.length;++i){
 +
 
if (overlays[i].key == e.getKeyCode()){
 
if (overlays[i].key == e.getKeyCode()){
 +
 
overlays[i].displayed = !overlays[i].displayed;
 
overlays[i].displayed = !overlays[i].displayed;
 +
 
return true;
 
return true;
 +
 
}
 
}
 +
 
}
 
}
  
 
return false;
 
return false;
 +
 
}
 
}
  
Line 147: Line 296:
  
 
public static void onPaint(Graphics2D g){
 
public static void onPaint(Graphics2D g){
 +
 
g.setColor(Color.WHITE);
 
g.setColor(Color.WHITE);
 +
 
if (isDisplayingHelpMessage) g.drawString("Hold the '"+KeyEvent.getKeyText(HELP_KEY)+"' key for help.", 0.0f, 0.0f);
 
if (isDisplayingHelpMessage) g.drawString("Hold the '"+KeyEvent.getKeyText(HELP_KEY)+"' key for help.", 0.0f, 0.0f);
 +
 
else if (isDisplayingLayersList) g.drawString("List of avaliable debug graphics layers:", 0.0f, 0.0f);
 
else if (isDisplayingLayersList) g.drawString("List of avaliable debug graphics layers:", 0.0f, 0.0f);
  
 
for (int j=0;j<overlays.length;++j){
 
for (int j=0;j<overlays.length;++j){
 +
 
if (isDisplayingLayersList){
 
if (isDisplayingLayersList){
 +
 
g.setColor(Color.WHITE);
 
g.setColor(Color.WHITE);
g.drawString((overlays[j].displayed?"*":" ")+"["+KeyEvent.getKeyText(overlays[j].key)+"]: "+overlays[j].name, 0.0f, (j+1)*MAGIC_FONT_HEIGHT_VALUE);
+
 
 +
g.drawString((overlays[j].displayed?"*":" ")+"["+KeyEvent.getKeyText(overlays[j].key)+"]: "+overlays[j].name, 0.0f, (j+1)*TEXT_HEIGHT);
 +
 
 
}
 
}
  
 
if (!overlays[j].displayed) continue;
 
if (!overlays[j].displayed) continue;
 +
 
Iterator i = overlays[j].renderables.iterator();
 
Iterator i = overlays[j].renderables.iterator();
 +
 
while(i.hasNext()){
 
while(i.hasNext()){
 +
 
Renderable r = (Renderable) i.next();
 
Renderable r = (Renderable) i.next();
 +
 
r.render(g);
 
r.render(g);
 +
 
}
 
}
 +
 
overlays[j].renderables.clear();
 
overlays[j].renderables.clear();
 +
 
}
 
}
  
 
if (isDisplayingLayersList){
 
if (isDisplayingLayersList){
 +
 
g.setColor(Color.WHITE);
 
g.setColor(Color.WHITE);
g.drawString("Holding the key in brackets displays the layer", 0.0f, (overlays.length+1)*MAGIC_FONT_HEIGHT_VALUE);
+
 
g.drawString("Typing Shift+key toggles permanent display of a layer", 0.0f, (overlays.length+2)*MAGIC_FONT_HEIGHT_VALUE);
+
g.drawString("Holding the key in brackets displays the layer", 0.0f, (overlays.length+1)*TEXT_HEIGHT);
 +
 
 +
g.drawString("Typing Shift+key toggles permanent display of a layer", 0.0f, (overlays.length+2)*TEXT_HEIGHT);
 +
 
 
}
 
}
 +
 
}
 
}
  
Line 178: Line 346:
  
 
static DebugOverlay[] overlays;
 
static DebugOverlay[] overlays;
 +
 +
 +
 
private static class DebugOverlay {
 
private static class DebugOverlay {
 +
 
DebugOverlay(String name, int key, boolean defaultDisp){
 
DebugOverlay(String name, int key, boolean defaultDisp){
 +
 
this.name = name;
 
this.name = name;
 +
 
this.key = key;
 
this.key = key;
 +
 
this.displayed = defaultDisp;
 
this.displayed = defaultDisp;
 +
 
}
 
}
 +
 
Vector renderables = new Vector();
 
Vector renderables = new Vector();
 +
 
boolean displayed;
 
boolean displayed;
 +
 
int key; //Keycode to toggle display mode
 
int key; //Keycode to toggle display mode
 +
 
String name;
 
String name;
 +
 
}
 
}
  
Line 193: Line 374:
  
 
public static abstract class Renderable {
 
public static abstract class Renderable {
 +
 
public abstract void render(Graphics2D g);
 
public abstract void render(Graphics2D g);
 +
 
}
 
}
  
Line 199: Line 382:
  
 
private static class Circle extends Renderable {
 
private static class Circle extends Renderable {
 +
 
double x, y, radius;
 
double x, y, radius;
 +
 
Color color;
 
Color color;
 +
 
public Circle(double x, double y, double radius, Color color){
 
public Circle(double x, double y, double radius, Color color){
 +
 
this.x = x; this.y = y; this.radius = radius;
 
this.x = x; this.y = y; this.radius = radius;
 +
 
this.color = color;
 
this.color = color;
 +
 
}
 
}
 +
 
public void render(Graphics2D g) {
 
public void render(Graphics2D g) {
 +
 
g.setColor(color);
 
g.setColor(color);
 +
 
g.drawOval((int)Math.round(x - radius), (int)Math.round(y - radius),
 
g.drawOval((int)Math.round(x - radius), (int)Math.round(y - radius),
 +
 
  (int)Math.round(2 * radius), (int)Math.round(2 * radius));
 
  (int)Math.round(2 * radius), (int)Math.round(2 * radius));
 +
 
}
 
}
 +
 
}
 
}
  
Line 215: Line 410:
  
 
private static class Dot extends Circle {
 
private static class Dot extends Circle {
 +
 
public Dot(double x, double y, Color color){
 
public Dot(double x, double y, Color color){
 +
 
super(x, y, 2, color); //super(x, y, 2, colour);
 
super(x, y, 2, color); //super(x, y, 2, colour);
 +
 
}
 
}
 +
 
}
 
}
  
Line 223: Line 422:
  
 
private static class Line extends Renderable {
 
private static class Line extends Renderable {
 +
 
double x1, y1, x2, y2;
 
double x1, y1, x2, y2;
 +
 
Color color;
 
Color color;
 +
 
public Line(double x1, double y1, double x2, double y2, Color color){
 
public Line(double x1, double y1, double x2, double y2, Color color){
 +
 
this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2;
 
this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2;
 +
 
this.color = color;
 
this.color = color;
 +
 
}
 
}
 +
 
public void render(Graphics2D g) {
 
public void render(Graphics2D g) {
 +
 
g.setColor(color);
 
g.setColor(color);
 +
 
g.drawLine((int)Math.round(x1), (int)Math.round(y1), (int)Math.round(x2), (int)Math.round(y2));
 
g.drawLine((int)Math.round(x1), (int)Math.round(y1), (int)Math.round(x2), (int)Math.round(y2));
 +
 
}
 
}
 +
 
}
 
}
  
Line 238: Line 448:
  
 
private static class Text extends Renderable {
 
private static class Text extends Renderable {
 +
 
String text;
 
String text;
 +
 
double x, y;
 
double x, y;
 +
 
Color color;
 
Color color;
 +
 
public Text(String text, double x, double y, Color color){
 
public Text(String text, double x, double y, Color color){
 +
 
this.text = text;
 
this.text = text;
 +
 
this.x = x; this.y = y;
 
this.x = x; this.y = y;
 +
 
this.color = color;
 
this.color = color;
 +
 
}
 
}
  
 
public void render(Graphics2D g) {
 
public void render(Graphics2D g) {
 +
 
g.setColor(color);
 
g.setColor(color);
 +
 
g.drawString(text, (float)x, (float)y);
 
g.drawString(text, (float)x, (float)y);
  
 
}
 
}
 +
 
}
 
}
 +
 
}
 
}
 +
 +
 +
 
</pre>
 
</pre>
 +
 +
__NOTOC__
 +
[[Category:Code Snippets]]
 +
[[Category:Source Code]]

Revision as of 10:23, 6 September 2008

Nfwu's User Pages
Free Code · ELO Sim · Debug Gfx
Tools · LRP · RR@H Uploads

Nfwu · User Talk · Contributions

Something new I wrote to help with my debugging. Feel free to use, with or without giving credit.

Credit

To David Alves for the basic structure, which was from DrawingBot.

Usage

Has to be initalized before being used, as so:

	public void run(){
		//I want 2 layers
		Painter.init(2);
		//Register first layer to key '1'
		Painter.setupLayer(0, "Enemy Position", java.awt.event.KeyEvent.VK_1); 
		//Register second layer to key 'w'
		Painter.setupLayer(1, "Waves", java.awt.event.KeyEvent.VK_W);
	
		//other stuff...

	}

Event handlers to call from bot:

	public void onKeyPressed(java.awt.event.KeyEvent e){
		if (Painter.onKeyPressed(e)) return;
		// other stuff
	}
	public void onKeyReleased(java.awt.event.KeyEvent e){
		if (Painter.onKeyReleased(e)) return;
		// other stuff
	}
	public void onPaint(java.awt.Graphics2D g){ Painter.onPaint(g); }

Interactive Display Controls:

  • Holding "key" displays the relevant layer until the key is released.
  • Typing Shift+"key" toggles permanent display of a layer.
  • Holding "H" shows a list of layer names and their keycodes.

More complex graphics can be drawn by extending Painter.Renderable.

Full Source Code

package nfwu;



import robocode.*;

import java.util.Vector;

import java.util.Iterator;

import java.awt.Color;

import java.awt.Graphics2D;

import java.awt.event.KeyEvent;



// Credit goes to David Alves for basic structure from DrawingBot.

// Added multiple layers for drawing on.

//Event Handlers to call from bot...

/*
	public void run(){
		//I want 2 layers
		Painter.init(2);
		//Register first layer to key '1'

		Painter.setupLayer(0, "Enemy Position", java.awt.event.KeyEvent.VK_1); 
		//Register second layer to key 'w'

		Painter.setupLayer(1, "Waves", java.awt.event.KeyEvent.VK_W);

	//other stuff

	}

	public void onKeyPressed(java.awt.event.KeyEvent e){

		if (Painter.onKeyPressed(e)) return;

		// other stuff

	}

	public void onKeyReleased(java.awt.event.KeyEvent e){

		if (Painter.onKeyReleased(e)) return;

		// other stuff

	}

	public void onPaint(java.awt.Graphics2D g){ Painter.onPaint(g); }

*/

// Interactive Display Controls:

//   Holding "key" displays the relevant layer until the key is released.

//   Typing Shift+"key" toggles permanent display of a layer.

//   Holding "H" shows a list of layer names and their keycodes.



public class Painter {

	public final static int HELP_KEY = KeyEvent.VK_H; //The 'h' key.

	public final static float TEXT_HEIGHT = 12.0f;

	static boolean isDisplayingHelpMessage;

	static boolean isDisplayingLayersList;

	static boolean isShiftPressed;



//Setup stuff

	public static void init(int numberOfLayers){//Call before every round

		System.out.println("This bot has debugging graphics.");

		System.out.println("Hold the '"+KeyEvent.getKeyText(HELP_KEY)+"' key with Paint enabled for help.");

		overlays = new DebugOverlay[numberOfLayers];

		isDisplayingHelpMessage = true;

		isDisplayingLayersList = false;

		isShiftPressed = false;

	}

	public static void setupLayer(int oid, String name, int key, boolean defaultDisp){ //key must be a valid VK_ code!!!

		overlays[oid] = new DebugOverlay(name, key, defaultDisp);

	}

	public static void setupLayer(int oid, String name, int key){

		setupLayer(oid, name, key, false);

	}



//Draw Stuff (oid = the layer id)

	public static void drawObject(int oid, Renderable r){

		overlays[oid].renderables.add(r);

	}



	public static void drawLineRect(int oid, Color color, double x1, double y1, double x2, double y2){ //Rectangular Coords as input

		drawObject(oid, new Line(x1, y1, x2, y2, color)); 

	}



	public static void drawLinePol(int oid, Color color, double x1, double y1, double len, double ang){ //Relative polar Coords as input

		double x2 = x1 + Math.sin(ang) * len; //NOTE: Robocode Angles... www

		double y2 = y1 + Math.cos(ang) * len; 

		drawObject(oid, new Line(x1, y1, x2, y2, color));

	}

	

	public static void drawCircle(int oid, Color color, double x, double y, double radius){

		drawObject(oid, new Circle(x, y, radius, color));

	}

	

	public static void drawPoint(int oid, Color color, double x, double y){

		drawObject(oid, new Dot(x, y, color));

	}

	

	public static void drawText(int oid, Color color, double x, double y, String text){

		drawObject(oid, new Text(text, x, y, color));

	}

//Event Handlers

	public static boolean onKeyPressed(KeyEvent e) {

		switch (e.getKeyCode()) {

		case KeyEvent.VK_SHIFT:

			isShiftPressed = true;

			return true;

		case HELP_KEY:

			if (isShiftPressed) isDisplayingHelpMessage = false;

			else isDisplayingLayersList = true;

			return true;

		}

		if (isShiftPressed) return false;

		for (int i=0;i<overlays.length;++i){

			if (overlays[i].key == e.getKeyCode()){

				overlays[i].displayed = true;

				return true;

			}

		}

		return false;

	}



	public static boolean onKeyReleased(KeyEvent e) {

		switch (e.getKeyCode()) {

		case KeyEvent.VK_SHIFT:

			isShiftPressed = false;

			return true;

		case HELP_KEY:

			if (isShiftPressed) isDisplayingHelpMessage = false;

			else isDisplayingLayersList = false;

			return true;

		}

		//Toggle whether or not shift is pressed

		for (int i=0;i<overlays.length;++i){

			if (overlays[i].key == e.getKeyCode()){

				overlays[i].displayed = !overlays[i].displayed;

				return true;

			}

		}

		return false;

	}



	public static void onPaint(Graphics2D g){

		g.setColor(Color.WHITE);

		if (isDisplayingHelpMessage) g.drawString("Hold the '"+KeyEvent.getKeyText(HELP_KEY)+"' key for help.", 0.0f, 0.0f);

		else if (isDisplayingLayersList) g.drawString("List of avaliable debug graphics layers:", 0.0f, 0.0f);

		for (int j=0;j<overlays.length;++j){

			if (isDisplayingLayersList){

				g.setColor(Color.WHITE);

				g.drawString((overlays[j].displayed?"*":" ")+"["+KeyEvent.getKeyText(overlays[j].key)+"]: "+overlays[j].name, 0.0f, (j+1)*TEXT_HEIGHT);

			}

			if (!overlays[j].displayed) continue;

			Iterator i = overlays[j].renderables.iterator();

			while(i.hasNext()){

				Renderable r = (Renderable) i.next();

				r.render(g);

			}

			overlays[j].renderables.clear();

		}

		if (isDisplayingLayersList){

			g.setColor(Color.WHITE);

			g.drawString("Holding the key in brackets displays the layer", 0.0f, (overlays.length+1)*TEXT_HEIGHT);

			g.drawString("Typing Shift+key toggles permanent display of a layer", 0.0f, (overlays.length+2)*TEXT_HEIGHT);

		}

	}



//Implementation

	static DebugOverlay[] overlays;



	private static class DebugOverlay {

		DebugOverlay(String name, int key, boolean defaultDisp){

			this.name = name;

			this.key = key;

			this.displayed = defaultDisp;

		}

		Vector renderables = new Vector();

		boolean displayed;

		int key; //Keycode to toggle display mode

		String name;

	}



	public static abstract class Renderable {

		public abstract void render(Graphics2D g);

	}

	

	private static class Circle extends Renderable {

		double x, y, radius;

		Color color;

		public Circle(double x, double y, double radius, Color color){

			this.x = x; this.y = y; this.radius = radius;

			this.color = color;

		}

		public void render(Graphics2D g) {

			g.setColor(color);

			g.drawOval((int)Math.round(x - radius), (int)Math.round(y - radius),

				   (int)Math.round(2 * radius), (int)Math.round(2 * radius));

		}

	}

	

	private static class Dot extends Circle {

		public Dot(double x, double y, Color color){

			super(x, y, 2, color); //super(x, y, 2, colour);

		}

	}

	

	private static class Line extends Renderable {

		double x1, y1, x2, y2;

		Color color;

		public Line(double x1, double y1, double x2, double y2, Color color){

			this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2;

			this.color = color;

		}

		public void render(Graphics2D g) {

			g.setColor(color);

			g.drawLine((int)Math.round(x1), (int)Math.round(y1), (int)Math.round(x2), (int)Math.round(y2));

		}

	}

	

	private static class Text extends Renderable {

		String text;

		double x, y;

		Color color;

		public Text(String text, double x, double y, Color color){

			this.text = text;

			this.x = x; this.y = y;

			this.color = color;

		}

		public void render(Graphics2D g) {

			g.setColor(color);

			g.drawString(text, (float)x, (float)y);

		}

	}

}