Java实现碧蓝航线连续作战

一.实现功能

主线图作战结束到结算页自动点击再次前往

二.主要思路
  • 判断是否进入了结算界面:记录结算界面某个像素点的RGB值,每隔3秒对这个像素点进行比对
  • 移动鼠标点击再次前往:Java提供的Robot类
三.主要代码实现
  • MainFrame.java
    主要实现系统托盘的图标,右键菜单栏,菜单项的响应事件
    配置完像素位置,可以自动读取当前电脑页面的RGB至配置文件中
package com.simple.azurlane.view;

import com.simple.azurlane.auto.MainLine;
import com.simple.azurlane.util.PropertyUtil;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.util.List;
import java.util.*;

public class MainFrame {
    public MainFrame() {
        //系统托盘
        SystemTray systemTray = SystemTray.getSystemTray();
        //菜单栏
        PopupMenu pop = new PopupMenu();
        MenuItem control = new MenuItem("start");
        MenuItem config = new MenuItem("config");
        MenuItem loadColor = new MenuItem("loadColor");
        MenuItem exit = new MenuItem("exit");
        pop.add(control);
        pop.addSeparator();
        pop.add(config);
        pop.addSeparator();
        pop.add(loadColor);
        pop.addSeparator();
        pop.add(exit);

        control.addActionListener(e -> {
            if (control.getLabel().equals("start")) {
                MainLine.start();
                control.setLabel("stop");
            } else {
                MainLine.stop();
                control.setLabel("start");
            }
        });

        config.addActionListener(e -> {
            ConfigFrame frame = ConfigFrame.getFrame();
            frame.setVisible(true);
            frame.setExtendedState(Frame.NORMAL);
        });

        loadColor.addActionListener(e -> {
            int x;
            int y;
            try {
                x = PropertyUtil.getInt("x1");
                y = PropertyUtil.getInt("y1");
            } catch (NumberFormatException ex) {
                JOptionPane.showMessageDialog(null, "识别的像素坐标有误");
                return;
            }

            String r = PropertyUtil.getString("r");
            String g = PropertyUtil.getString("g");
            String b = PropertyUtil.getString("b");
            List<String> rl = Arrays.asList(r.split(","));
            List<String> gl = Arrays.asList(g.split(","));
            List<String> bl = Arrays.asList(b.split(","));
            Robot robot = MainLine.getRobot();
            Color pixelColor = robot.getPixelColor(x, y);
            if (MainLine.validatePixelColor(rl, gl, bl, pixelColor)) {
                return;
            }

            //刷新property的rgb属性
            Map<String, String> configMap = new HashMap<>();
            configMap.put("r", completion(r, String.valueOf(pixelColor.getRed())));
            configMap.put("g", completion(g, String.valueOf(pixelColor.getGreen())));
            configMap.put("b", completion(b, String.valueOf(pixelColor.getBlue())));
            PropertyUtil.alter(configMap);

            //刷新配置页的rgb属性
            if(ConfigFrame.frameCreated()){
                ConfigFrame frame = ConfigFrame.getFrame();
                frame.loadConfig();
            }
        });

        exit.addActionListener(e -> System.exit(0));

        try {
            TrayIcon trayIcon = new TrayIcon(ImageIO.read(Objects.requireNonNull(MainFrame.class.getClassLoader().getResourceAsStream("azurlane.jpg"))), "碧蓝航线", pop);
            trayIcon.setImageAutoSize(true);
            trayIcon.setToolTip("碧蓝航线");
            systemTray.add(trayIcon);
        } catch (IOException | AWTException e) {
            e.printStackTrace();
        }
    }

    private String completion(String oldColor, String newColor) {
        if (oldColor.trim().equals("")) {
            return newColor;
        }
        return oldColor + "," + newColor;
    }

    public static void main(String[] args) {
        new MainFrame();
    }
}

  • MainLine.java
    主要实现像素点的比对,自动移动鼠标点击
package com.simple.azurlane.auto;

import com.simple.azurlane.util.PropertyUtil;

import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class MainLine {
    private static ScheduledExecutorService scheduledService;

    private static Robot robot;

    static {
        try {
            robot = new Robot();
        } catch (AWTException e) {
            e.printStackTrace();
        }
    }

    private static void autoWork() {
        // load config from cache
        int x1;
        int y1;
        int x2;
        int y2;
        try {
            int z = PropertyUtil.getInt("z");
            x1 = PropertyUtil.getInt("x1");
            y1 = PropertyUtil.getInt("y1");
            x2 = PropertyUtil.getInt("x2") / z;
            y2 = PropertyUtil.getInt("y2") / z;
        } catch (NumberFormatException e) {
            return;
        }
        List<String> rl = Arrays.asList(PropertyUtil.getString("r").split(","));
        List<String> gl = Arrays.asList(PropertyUtil.getString("g").split(","));
        List<String> bl = Arrays.asList(PropertyUtil.getString("b").split(","));

        Color pixelColor = robot.getPixelColor(x1, y1);
        if (validatePixelColor(rl, gl, bl, pixelColor)) {
            robot.mouseMove(x2, y2);
            robot.mousePress(KeyEvent.BUTTON1_MASK);
            robot.delay(200);
            robot.mouseRelease(KeyEvent.BUTTON1_MASK);
            robot.delay(200);
            robot.mouseMove(0, 0);
        }
    }

    public static Robot getRobot() {
        return robot;
    }

    /**
     * 校验一组颜色是否与之指定像素点颜色匹配
     *
     * @param pixelColor 像素点颜色
     * @return true/false
     */
    public static boolean validatePixelColor(List<String> rl, List<String> gl, List<String> bl, Color pixelColor) {
        for (int i = 0; i < rl.size(); i++) {
            if (String.valueOf(pixelColor.getRed()).equals(rl.get(i)) && String.valueOf(pixelColor.getGreen()).equals(gl.get(i)) && String.valueOf(pixelColor.getBlue()).equals(bl.get(i))) {
                return true;
            }
        }
        return false;
    }

    public static void start() {
        scheduledService = Executors.newScheduledThreadPool(1);
        scheduledService.scheduleAtFixedRate(MainLine::autoWork, 0, 3, TimeUnit.SECONDS);
    }

    public static void stop() {
        scheduledService.shutdownNow();
        scheduledService = null;
        System.gc();
    }
}
  • ConfigFrame.java
    支持动态配置参数
package com.simple.azurlane.view;

import com.simple.azurlane.component.IButton;
import com.simple.azurlane.component.ILabel;
import com.simple.azurlane.component.IText;
import com.simple.azurlane.util.PropertyUtil;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class ConfigFrame extends JFrame {
    private final JLabel xl = new ILabel("X", 34, 30, 20, 20);
    private final JLabel yl = new ILabel("Y", 34, 90, 20, 20);
    private final JLabel rl = new ILabel("R", 34, 150, 24, 20);
    private final JLabel gl = new ILabel("G", 34, 210, 24, 20);
    private final JLabel bl = new ILabel("B", 34, 270, 24, 20);
    // x1
    private final JTextField x = new IText(100, 25, 160, 30);
    // y1
    private final JTextField y = new IText(100, 85, 160, 30);
    private final JTextField r = new IText(100, 145, 160, 30);
    private final JTextField g = new IText(100, 205, 160, 30);
    private final JTextField b = new IText(100, 265, 160, 30);
    public final JButton button1 = new IButton("Cancel", 34, 320, 96, 30);
    public final JButton button2 = new IButton("Apply", 164, 320, 96, 30);
    private volatile static ConfigFrame configFrame;

    private ConfigFrame() throws HeadlessException {
        setTitle("config");
        setSize(300, 400);
        setLocationRelativeTo(null);
        setLayout(null);
        setResizable(false);
        setFocusable(true);
        getContentPane().setBackground(new Color(255, 255, 255));
        try {
            setIconImage(ImageIO.read(Objects.requireNonNull(ConfigFrame.class.getClassLoader().getResourceAsStream("azurlane.jpg"))));
        } catch (IOException e) {
            e.printStackTrace();
        }
        loadConfig();
        loadComponent();
        setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                setVisible(false);
            }
        });
        setVisible(true);
    }

    private void loadComponent() {
        Container contentPane = getContentPane();
        contentPane.add(xl);
        contentPane.add(yl);
        contentPane.add(rl);
        contentPane.add(gl);
        contentPane.add(bl);
        contentPane.add(x);
        contentPane.add(y);
        contentPane.add(r);
        contentPane.add(g);
        contentPane.add(b);
        contentPane.add(b);
        contentPane.add(b);
        contentPane.add(button1);
        contentPane.add(button2);
    }

    public void loadConfig() {
        x.setText(PropertyUtil.getString("x1"));
        y.setText(PropertyUtil.getString("y1"));
        r.setText(PropertyUtil.getString("r"));
        g.setText(PropertyUtil.getString("g"));
        b.setText(PropertyUtil.getString("b"));
    }

    public static ConfigFrame getFrame() {
        if (configFrame == null) {
            configFrame = new ConfigFrame();
        }
        return configFrame;
    }

    public static boolean frameCreated(){
        return configFrame != null;
    }

    public void changeValue() {
        String xText = x.getText();
        String yText = y.getText();
        String rText = r.getText();
        String gText = g.getText();
        String bText = b.getText();
        if (!(x.getText().equals(PropertyUtil.getString("x1")) && y.getText().equals(PropertyUtil.getString("y1")) && r.getText().equals(PropertyUtil.getString("r")) && g.getText().equals(PropertyUtil.getString("g")) && b.getText().equals(PropertyUtil.getString("b")))) {
            Map<String, String> configMap = new HashMap<>(16);
            configMap.put("x1", xText.trim());
            configMap.put("y1", yText.trim());
            configMap.put("r", rText.trim());
            configMap.put("g", gText.trim());
            configMap.put("b", bText.trim());
            PropertyUtil.alter(configMap);
        }
    }
}
  • config.properties
#识别的像素点位置
x1=1600
y1=276
#鼠标点击位置
x2=1740
y2=1294
#匹配的rgb颜色
r=99,90,90
g=130,134,121
b=189,198,198
#分辨率-缩放比例
z=2
四.用exe4j生成.exe程序

具体参考我的这篇文章exe4j将jar包打成exe程序

五.最终效果

在这里插入图片描述
右键菜单栏
在这里插入图片描述
配置页
在这里插入图片描述

六.代码开源

所有代码已上传我的github仓库

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值