Robocode/Graphical Debugging

From Robowiki
Jump to navigation Jump to search
This article is in the process of being migrated from the old wiki by FlemmingLarsen.

This page will explain how to perform graphical debugging with Robocode using the onPaint method.

Classic Debugging

One classic way of debugging code is to use System.out.println() statements in your code and read the output in the console. This classic way of debugging is excelent in most cases, especially when you want to write out information about e.g. how many times you have hit another robot compared to how many times you have missed etc.

Another form of debugging is using a debug tool, e.g. the one that comes with Eclipse, where you are able to set breakpoints and create watch points etc. in your code to see how your robot behaves. With this kind of debugging you'll be able to get a "snapshot" of the current values contained by all field values of your robot.

Graphical Debugging

However, Robocode provides an additional and very powerful way of debugging your robot. That is graphical debugging, where you can paint graphics for you robot on top of the graphics that is being rendered on the battle view. In some cases, this kind of debugging provides you with better view of how your robot "sees" the world surrounding it.

Instead of printing out for example estimated future coordinates of your robots, you can paint these coordinates as dots (or similar) on the battlefield to see how well your robot is at tracking the enemies. Basically, the can paint whatever you want on the battlefield.

Enable Painting

NOTE: By default, the painting of all the robots is disabled. Why? Imagine 10 robots on the battlefield, who all wants to do their own paintings. The whole battle view would potentially be "poluted" with all kind of graphical stuff from each robot, which can be quite annoying, especially when you want to watch what is going on with your robot(s) on the battlefield. Therefore, you have to enable the painting of the robots, which you want to allow painting their graphics on the battlefield. However, you should expect that robots might "hide" their (debug) painting for the public, or have removed their code in order to keep the code size small.

The onPaint() method

In order to paint anything on the battlefield, you must override the public void onPaint(Graphics2D g) method. This method is automatically called by Robocode each time the battlefield is being rendered (and the painting is enabled). Basically, the painting is performed by calling methods on the Graphics2D object given a input parameter to the onPaint method. So you can for example set the color to paint with, draw circles, rectangles etc., which can be both filled out and not filled out.

Simple Example

So, here is an simple example of how to paint a red filled rectangle on the screen:

 import java.awt.Color;
 import java.awt.Graphics2D;
 public void onPaint(Graphics2D g) {
     // Set the paint color to red
     g.setColor(java.awt.Color.RED);
     // Paint a filled rectangle at (50,50) at size 100x150 pixels
     g.fillRect(50, 50, 100, 150);
 }

The Coordinate System

If you are used to the "normal" coordinate system used with Awt and Swing, you should know that the coordinate system is mirrored to fit the coordinate system used in Robocode. This mean that if your robot is located on coordinate (x1,y1), and you paint a dot on this location (e.g. by fillRect(x1, y1, 1, 1)), then this dot will be put exactly on top of your robot.

The debug.ScanAndPaint robot example

In the following a more advanced example is provided to give an idea of how the onPaint() method can be used. In this example we want to put a red square on top of the last scanned robot seen by our robot, and the robot does nothing else than just scanning and painting.

run() method

So first of all, we tell our robot to do nothing else than turning the robot for ever when it is run:

  // How to run our robot
  public void run() {
      // Rotate the radar for ever in order to detect robots
      while (true) {
          turnRadarRight(360);
      }
  }

onScannedRobot() method

Then we save the coordinates based on the last ScannedRobotEvent (via the e parameter) we receive whenever our robot scans another robot:

  // The coordinates of the last scanned robot
  int scannedX = Integer.MIN_VALUE;
  int scannedY = Integer.MIN_VALUE;

  // Called when we have scanned a robot
  public void onScannedRobot(ScannedRobotEvent e) {
      // Calculate the angle to the scanned robot
      double angle = Math.toRadians(getHeading() + e.getBearing()) % 360;

      // Calculate the coordinates of the robot
      scannedX = (int)(getX() + Math.sin(angle) * e.getDistance());
      scannedY = (int)(getY() + Math.cos(angle) * e.getDistance());
  }

onPaint() method

Okay, so now we just have to paint a red transparent square on top of the scanned robot:

  // Paint a transparent square on top of the last scanned robot
  public void onPaint(Graphics2D g) {
      // Set the paint color to a red half transparent color
      g.setColor(new Color(0xff, 0x00, 0x00, 0x80));

      // Draw a line from our robot to the scanned robot
      g.drawLine(scannedX, scannedY, (int)getX(), (int)getY());

      // Draw a filled square on top of the scanned robot that covers it
      g.fillRect(scannedX - 20, scannedY - 20, 40, 40);
  }

So now, whenever our robots scans a robot, it paints a red line from our robot to the scanned robot and also paints a red transparent square on top of it.

See Also

Links til side med wave-bullets m.v. evt. andre lign. sider Links til Eclipse + console debugging

References