2012-07-04 20:56:44Morris

[JAVA][Eclipse] Diamond Dash 外掛

Demo 影片 http://www.youtube.com/watch?v=5Tjwk8dfXMU
Learn from http://annimon119.blogspot.tw/2011/09/blog-post.html

此次學習重點 :
1. Robot 的操作
2. 由於要判定圖形是否相同, 加入容錯處理, 為解決速度上的問題, 並不使用多次 robot.getPixelColor(), 速度過於緩慢, 用截取圖片替代, 速度明題明顯

操作要點:
按下 A 進行開始
並且在執行前, 確認 startx, starty 的值, 採用絕對位置方便操作, 如果電腦不同, 請自行找出左上角的操作點,
最左上角黑色區塊的角落



import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JButton;

import java.awt.AWTException;
import java.awt.image.BufferedImage;
import java.awt.Rectangle;
import java.awt.Font;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.MouseInfo;
import java.awt.Robot;
import java.awt.Color;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.event.InputEvent;

public class Game2 extends JFrame implements KeyListener {
    public final int BRICK_SIZE = 40;
    public final int COLOR_TOLERANCE = 130;
    public final int startx = 521, starty = 405;
    public static Robot robot;
    public int[][] brickID = new int[9][10];
    private static final int[][][] good = {
        { {0, 1}, {2, 1} },
        { {1, 0}, {1, 2} },
     
        { {0, 0}, {0, 1} },
        { {1, 0}, {2, 0} },
        { {2, 1}, {2, 2} },
        { {1, 2}, {0, 2} },
     
        { {0, 1}, {0, 2} },
        { {1, 2}, {2, 2} },
        { {2, 0}, {2, 1} },
        { {0, 0}, {1, 0} }
    };
    private JLabel text = new JLabel("Diamond Dash");
    private JLabel state = new JLabel("Ready");
    public Game2() throws AWTException {
        setTitle("Diamond Dash");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(null);
        setSize(200, 200);
        setResizable(false);
        setAlwaysOnTop(true);
       
        text.setFont(new Font("Arial", Font.ITALIC, 18));
        text.setBounds(35, 15, 150, 30);
        add(text);
       
        state.setFont(new Font("Arial", Font.ITALIC, 18));
        state.setBounds(70, 50, 150, 30);
        add(state);
       
        addKeyListener(this);
        robot = new Robot();
    }

    private void clickBlock(int xClick, int yClick) {
        xClick = startx + xClick * BRICK_SIZE + BRICK_SIZE / 2;
        yClick = starty + yClick * BRICK_SIZE + BRICK_SIZE / 2;
        robot.mouseMove(xClick, yClick);
        robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
        robot.delay(15);
        robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
    }

    public BufferedImage getImage(int x, int y, int width, int height) {
        return robot.createScreenCapture(new Rectangle(x, y, width, height));
    }

    public int[][] getBricksID(BufferedImage image) {
        int[] brickColors = new int[] { 0xFF0000, // RED
                0x00FF00, // GREEN
                0x0000FF, // BLUE
                0xFFFF00, // YELLOW
                0xFF00FF, // MAGENTA
        };
        for (int y = 0; y < brickID.length; y++) {
            for (int x = 0; x < brickID[0].length; x++) {
                int color = image.getRGB(x * BRICK_SIZE + BRICK_SIZE / 2
                        + BRICK_SIZE / 4, y * BRICK_SIZE + BRICK_SIZE / 4);
                brickID[y][x] = 0;
                for(int id = 0; id < brickColors.length; id++) {
                    if(isEquals(color, brickColors[id], COLOR_TOLERANCE)) {
                        brickID[y][x] = id+1;
                        break;
                    }
                }
            }
        }
        return brickID;
    }
    private boolean isEquals(int color1, int color2, int tolerance) {
        int r1, r2, g1, g2, b1, b2;
        r1 = (color1>>16) & 0xff;
        g1 = (color1>>8) & 0xff;
        b1 = color1 & 0xff;
        r2 = (color2>>16) & 0xff;
        g2 = (color2>>8) & 0xff;
        b2 = color2 & 0xff;
        return  (Math.abs(r1 - r2) <= tolerance) &&
                (Math.abs(g1 - g2) <= tolerance) &&
                (Math.abs(b1 - b2) <= tolerance);
    }
    public int getId(int x, int y) {
        if(x < 0 || x >= 10 || y < 0 || y >= 9)
            return 0;
        return brickID[y][x];
    }
    private boolean searchArea(int x, int y) {
        int curID = getId(x, y);
        if (curID == 0) return false;
        boolean[][] indexEquals = {
            { getId(x-1, y-1) == curID, getId(x, y-1) == curID, getId(x+1, y-1) == curID },
            { getId(x-1, y) == curID, true, getId(x+1, y) == curID },
            { getId(x-1, y+1) == curID, getId(x, y+1) == curID, getId(x+1, y+1) == curID }
        };
        for (int i = 0; i < good.length; i++) {
            if ( (indexEquals[ good[i][0][0] ][ good[i][0][1] ]) &&
                 (indexEquals[ good[i][1][0] ][ good[i][1][1] ])) {
                return true;
            }
        }
     
        return false;
    }
    public void click() {
        for(int y = 0; y < brickID.length; y++) {
            BufferedImage screen = getImage(startx, starty, 10 * BRICK_SIZE, 9 * BRICK_SIZE);
            brickID = getBricksID(screen);
            for (int x = brickID[0].length-1 ; x >= 0; x--) {
                //System.out.print(getId(x, y));
                if( ((getId(x, y) != 0) && searchArea(x, y))) {
                    clickBlock(x, y);
                }
            }
            //System.out.println("");
        }     
    }
    public void keyPressed(KeyEvent e) {
        switch(e.getKeyCode()) {
            case KeyEvent.VK_A:
                state.setText("Running !!");
                int cnt = 160;
                while(cnt-- != 0)
                    click();
                state.setText("Ready");
        }
    }
    public void keyReleased(KeyEvent e) {}
    public void keyTyped(KeyEvent e) {}
}