Yes I hardcoded it, yes I could have used some sort of pixel/image scanning to find this point, if I ever decide to improve on this bot, I’d definitely change this.
Okay, we have our point of origin, awesome. But we need the location of each piece on the board. We will obtain this by:
X or Y coordinate = Point of Origin + (Length/2) + (Length * x or y)
Where x and y == the respective x or y piece on the board. We get this length the same way as we got the point of origin:
Great, looks like each square is 83 pixels long. RIGHT? RIGHT? WRONG! Upon closer examination, (using paint and the zoom tool) I found 82 pixels to be a better estimate. Although I tried 83, 81, and 80, each giving not-so-great results. In fact, these squares aren’t actually exactly 82 pixels long, they’re 81 point something-something-something. I’m not even sure if they’re perfect squares! Curse you PopCap!
Thinking I had the correct length, identifying colors seemed like it would be easy. I’d be grabbing the pixel at the exact center of each square, so I should be able to hard code these colors in right? Using the BufferedImage class, we will use the getRGB(int x, int y) function which returns an “integer pixel in the default RGB color model”.
With this approach, converting this integer value into its individual RGB values isn’t necessary. Alright, so we iterate through each square and fetch this integer value, and I can then hardcode these colors in and bam, we have color identification, EASY PEAZY, or so I thought.
You see, I mentioned earlier that these squares weren’t actually perfectly 82 pixels long. You can see why this would be problematic. After doing some comparisons, I found that this method still gave mostly correct answers. So, lazy me, I thought I could just get away with storing a few variants of each color into a set, and then checking that set for a color match. Oh, lazy me does stupid things sometimes. This leads to a myriad of other problems. For example the fire gems casting a glow on nearby gems, and the fact that it would take A LOT of test runs to get a perfect Set for each color. I did this for like 5 minutes before realizing how dumb this idea was.
After giving up on my first plan, I gave in and decided to convert the integer value into its individual RGB values. Enter Java’s Color class.
I would then use a series of if-statements to check these values and then try to identify the color that way. By using relational operators, I can check for a range of colors. This quickly turned into a mess of spaghetti code and not-so-accurate color identification, especially since the yellow and orange were giving nearly the exact same RGB values. Add in the fire gem and orange/yellow becomes white etc etc.
At this point I was starting to get a little frustrated. Finally, I decided to convert the color to the HSB (Hue, Saturation, Brightness) format.
This returns a float containing the hue, saturation, and brightness.
I then used this HSL color picker as a reference point and built my if statements based on this. Being able to check for brightness/saturation is a huge benefit when trying to identify the color white. I then just built my own ranges of hue values to determine the other colors. Orange/Yellow gave similar values, but they were different enough to work with. I’m quite happy with the accuracy of it:
Now that we have the color values, the majority of the work is done. We loop through all the board locations, find matches, and then apply these matches using Java’s Robot Class (I will definitely cover this class in a later post), which is very straightforward. If I ever do another screen-based bot, I’ll be sure to focus more on the other aspects next time around, but this post is already getting long enough! I leave you with the final product:
It’s far from perfect, as it takes screenshots of the board to determine the pieces, and sometimes it will take these screenshots as the gems are still falling, which obviously throws off the colors. Also, the fiery gems still throws things off a bit. Not too shabby for a day’s work though! I’m not sure if I will continue to work on it, but I might work on a Java library to make color identification easier for the purposes of making screen bots. So expect a post on that when it’s complete.
Please ignore my friend complaining about NCIX :).