Automated game of Doeo using Java Robot class

Now that pong is fully automated, it is time to optimize.

First I switched to the game Doeo. The goal of the game is to move your mouse as fast over Doeos as possible. A fun game to use as an example for automation.

I also made a small performance enhancement (10 to 15 percent) by not using getRGB () from BufferdImage, but reading directly from an array. It does take some time to get everything into an integer array, but if that’s done, the for-loop is a lot faster.

Demo video:

The optimized code:

import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
 
/*
 
©2010 Bobbie Smulders
 
RobotDoeo plays an automated game of Doeo.
Original game can be found here:
http://armorgames.com/play/1414/doeo
 
*/
 
public class RobotDoeo extends Thread{
 
	public Rectangle rect;
 
	public RobotDoeo(int x, int y, int width, int height) {
		rect = new Rectangle(x, y, width, height);
	}
 
	public void run() {
		try {
			Robot robot = new Robot();
 
			while(true){
				BufferedImage img = robot.createScreenCapture(rect);
				WritableRaster r=img.getRaster();
				DataBuffer db=r.getDataBuffer();
				DataBufferInt dbi=(DataBufferInt)db;
				int[] data=dbi.getData();            		
 
				for (int x_scale = 0; x_scale < rect.width; x_scale += 10) {
					for(int y_scale = 0; y_scale < rect.height; y_scale += 10) {
						int rgb = data[x_scale + rect.width * y_scale];
						if (rgb == -5381164 ||
							rgb == -13108 ||
							rgb == -2511443 ||
							rgb == -7093836 ||
							rgb == -1722441){
							robot.mouseMove(rect.x + x_scale, rect.y + y_scale);
						}
					}
				}
			}
		}
		catch(AWTException e) {
			e.printStackTrace();
		}
	}
 
	public static void main(String[] args) {
		new RobotDoeo(10, 100, 550, 430).start();
	}
}

5 thoughts on “Automated game of Doeo using Java Robot class

  1. Tuntuni

    Hey, great work but I don’t quite understand the comparing. Could you explain it to me a little? What’s a WriteableRaster, a DataBuffer, a DataBufferInt? You can also send me some links so I can read up a little bit. I’m also interested in your data array. Why did you do “data[x_scale + rect.width * y_scale];”? How are you comparing the colours, etc, what’s the principle? Thanks for your time, Tuntuni. Looking forward to your answer.

  2. Bobbie Smulders Post author

    Hi Tuntuni,

    The WritableRaster, DataBuffer and DataBufferint part is needed to get an integer array containing the raw pixel data. If you are interested in this part, you can check out the Java API at http://docs.oracle.com/javase/6/docs/api/.

    The data array containing the pixel data is two-dimensional data in a one-dimensional array. If you are interested in this method, you can check out this wikipedia article: http://en.wikipedia.org/wiki/Row-major_order

    Lastly, the colors, are plain simple integers. I grab the current color from the data array (which is an integer value) and compare it to several hardcoded colors. If the color matches, I move the mouse to this location.

    If you want to convert RGB to this integer type, you can create a new java.awt.Color object using red, green and blue floats and use toString to get the integer value. Internally, it uses bit shifting to create this integer, but that is something you don’t need to worry about.

  3. Tuntuni

    Hey, sorry for the late reply. Thanks a lot for your answer. I really appreciate it. Keep on rocking! =)

  4. Tuntuni

    Oh yes, one last question! Could you tell me how you got the colors of the doeos? Did you take a screenshot, got the RGB value and then converted it to a int? Thanks! =)

  5. Bobbie Smulders Post author

    Hi Tuntuni,

    I did indeed take a screenshot, got the RGB value and converted it to an integer (hash code to be precise).

    I’ve made a small application to demonstrate the conversion between RGB and the hash code Java uses on a screen capture. There are to ways to do this: Manually using bit-shifting, or automatically using the Java AWT Color object. The manual method is preferred when you want to use the code in multiple programming languages, the automatic method is preferred because it is more readable what’s happening.

    import java.awt.Color;
     
    public class ColorHash {
     
    	public static void main(String[] args) {
    		// Declarations
    		int r, g, b, rgb;
    		Color c;
     
    		// R+G+B to RGB hashcode, method A, using bit-shifting
    		r = 255;
    		g = 128;
    		b = 255;
    		rgb = 0xFF000000 + (r << 16) + (g << 8) + b;
     
    		System.out.println(rgb);
     
    		// R+G+B to RGB hashcode, method B, using the Color object
    		r = 255;
    		g = 128;
    		b = 255;
    		c = new Color(r, g, b);
    		rgb = c.hashCode();
     
    		System.out.println(rgb);
     
    		// RGB hashcode to R+G+B, method A, using bit-shifting
    		rgb = -32513;
    		r = (rgb & 0x00FF0000) >> 16;
    		g = (rgb & 0x0000FF00) >> 8;
    		b = (rgb & 0x000000FF);
     
    		System.out.println(r + ";" + g + ";" + b);
     
    		// RGB hashcode to R+G+B, method B, using the Color object
    		rgb = -32513;
    		c = new Color(rgb);
    		r = c.getRed();
    		g = c.getGreen();
    		b = c.getBlue();
     
    		System.out.println(r + ";" + g + ";" + b);
    	}
    }

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>