-3
public class Main {

    public static void main(String[] args) {
        GUI gui = new GUI();
        GameHandler gameHandler = new GameHandler();
        while (!gui.shouldStop()) {
            while (gui.isRunning()) {
                gameHandler.run();
            }
        }
    }

}


import javax.swing.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

public class GUI extends JFrame implements KeyListener, WindowListener {

    private JLabel label;
    private boolean run = false;
    private boolean stop = false;

    public GUI() {
        label = new JLabel("Not running.");
        JPanel panel = new JPanel();
        panel.setSize(300, 200);
        panel.add(label);
        setSize(300, 200);
        add(panel);
        addKeyListener(this);
        addWindowListener(this);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setResizable(false);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    public boolean isRunning() {
        return run;
    }

    public boolean shouldStop() {
        return stop;
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
            String text = label.getText().equalsIgnoreCase("Not running.") ? "Running!" : "Not running.";
            label.setText(text);
            run = !run;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }

    @Override
    public void windowOpened(WindowEvent e) {
    }

    @Override
    public void windowClosing(WindowEvent e) {
        stop = true;
    }

    @Override
    public void windowClosed(WindowEvent e) {
        stop = true;
    }

    @Override
    public void windowIconified(WindowEvent e) {
    }

    @Override
    public void windowDeiconified(WindowEvent e) {
    }

    @Override
    public void windowActivated(WindowEvent e) {
    }

    @Override
    public void windowDeactivated(WindowEvent e) {
    }
}


import java.awt.*;

public class GameHandler {

    private Elektra elektra;
    private Button popupExitButton;

    public GameHandler() {
        elektra = new Elektra();
        popupExitButton = new Button(Button.EXIT_POPUP_IMAGE_PATH);
    }

    public void run() {
        if (elektra.isAlive()) {
            try {
                new Robot().mouseMove(20, 90);
            } catch (AWTException e) {
                e.printStackTrace();
            }
        } else if (popupExitButton.isVisible()) {
            try {
                new Robot().mouseMove(90, 90);
            } catch (AWTException e) {
                e.printStackTrace();
            }
        }
    }

}

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class Button {

    BufferedImage image;

    public Button(String fileName) {
        try {
            image = ImageIO.read(ClassLoader.getSystemResourceAsStream(fileName));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public boolean isVisible() {
        try {
            return new ImageSearcher(new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()))).containsSubImage(image);
        } catch (AWTException e) {
            e.printStackTrace();
        }
        return false;
    }

    public static final String EXIT_POPUP_IMAGE_PATH = "images/exitPopupButton.png";

}

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class Elektra {

    String imagePath = "images/elektra.png";
    BufferedImage image;

    public Elektra() {
        try {
            image = ImageIO.read(ClassLoader.getSystemResourceAsStream(imagePath));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public boolean isAlive() {
        try {
            return new ImageSearcher(new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()))).containsSubImage(image);
        } catch (AWTException e) {
            e.printStackTrace();
        }
        return false;
    }

}

My program is supposed to check the screen for a certain image, and if it finds it it should move the mouse. The problem is, it never works unless I am logging messages. I do not know why.

If I add in System.out.println("blah"); in each of the while loops in the main class, it works. But if I don't include them, it doesn't. Can someone explain this...? It makes no sense to me why this happens. This also happens when I use a debugger..it works while debugging but doesn't work when running it.

Example of when it works:

public class Main {

    public static void main(String[] args) {
        GUI gui = new GUI();
        GameHandler gameHandler = new GameHandler();
        while (!gui.shouldStop()) {
            System.out.println("..");
            while (gui.isRunning()) {
                System.out.println("..");
                gameHandler.run();
            }
        }
    }

}

3 Answers3

2

Does this MSCCE behave more as you expect? (I must admit I'm not entirely clear as to what it should do. Seems as useful as a glug-glug box.)

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

class Main {

    public static void main(String[] args) {
        GameHandler gameHandler = new GameHandler();
        GUI gui = new GUI(gameHandler);
        gameHandler.run();
    }
}

class GUI extends JFrame implements KeyListener {

    private JLabel label;
    private boolean run = false;
    private boolean stop = false;
    GameHandler gameHandler;

    public GUI(GameHandler gameHandler) {
        this.gameHandler = gameHandler;
        label = new JLabel("Not running.");
        JPanel panel = new JPanel();
        panel.setSize(300, 200);
        panel.add(label);
        setSize(300, 200);
        add(panel);
        addKeyListener(this);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setResizable(false);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    public boolean isRunning() {
        return run;
    }

    public boolean shouldStop() {
        return stop;
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
            String text = label.getText().equalsIgnoreCase("Not running.") ? "Running!" : "Not running.";
            label.setText(text);
            run = !run;
            if (run) {
                gameHandler.run();
            } else {
                gameHandler.stop();
            }
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }
}

class GameHandler {

    private Elektra elektra;
    private Button popupExitButton;
    Timer timer;

    public GameHandler() {
        elektra = new Elektra();
        popupExitButton = new Button("Button.EXIT_POPUP_IMAGE_PATH");
        timer = new Timer(400, listener);
    }

    public void run() {
        timer.start();
    }

    public void stop() {
        timer.stop();
    }

    ActionListener listener = new ActionListener() {
        public void actionPerformed(ActionEvent ae) {
            System.out.println("elektra.isAlive(): " + elektra.isAlive());
            if (elektra.isAlive()) {
                try {
                    new Robot().mouseMove(20, 90);
                } catch (AWTException e) {
                    e.printStackTrace();
                }
            } else if (popupExitButton.isVisible()) {
                try {
                    new Robot().mouseMove(90, 90);
                } catch (AWTException e) {
                    e.printStackTrace();
                }
            }
        }
    };

}

class Button {

    BufferedImage image;

    public Button(String fileName) {
        try {
            //image = ImageIO.read(ClassLoader.getSystemResourceAsStream(fileName));
            image = new Robot().createScreenCapture(new Rectangle(0,0,200,200));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public boolean isVisible() {
        try {
            return new ImageSearcher(new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()))).containsSubImage(image);
        } catch (AWTException e) {
            e.printStackTrace();
        }
        return false;
    }

}

class Elektra {

    BufferedImage image;

    public Elektra() {
        try {
            image = new Robot().createScreenCapture(new Rectangle(0,0,200,50));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public boolean isAlive() {
        try {
            return new ImageSearcher(
                new Robot().createScreenCapture(
                    new Rectangle(Toolkit.getDefaultToolkit().getScreenSize())))
                    .containsSubImage(image);
        } catch (AWTException e) {
            e.printStackTrace();
        }
        return false;
    }

}

class ImageSearcher {

    BufferedImage mainImage;

    public ImageSearcher(BufferedImage image) {
        mainImage = image;
    }

    public boolean containsSubImage(BufferedImage subImage) {
        int mainWidth = mainImage.getWidth();
        int mainHeight = mainImage.getHeight();
        int width = subImage.getWidth();
        int height = subImage.getHeight();
        for (int xOffset = 0; xOffset < mainWidth && xOffset + width < mainWidth; xOffset++) {
            for (int yOffset = 0; yOffset < mainHeight && yOffset + height < mainHeight; yOffset++) {
                if (picturesEquivalent(subImage, xOffset, yOffset)) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean picturesEquivalent(BufferedImage subImage, int xOffset, int yOffset) {
        int mainWidth = mainImage.getWidth();
        int mainHeight = mainImage.getHeight();
        int width = subImage.getWidth();
        int height = subImage.getHeight();
        for (int x = 0; x < width && xOffset + x < mainWidth; x++) {
            for (int y = 0; y < height && yOffset + y < mainHeight; y++) {
                int mainRGB = mainImage.getRGB(xOffset + x, yOffset + y);
                int subRGB = subImage.getRGB(x, y);
                if (mainRGB != subRGB) {
                    return false;
                }
            }
        }
        return true;
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
1

I'm having trouble finding anything on the internet to back this up specifically, but I think that your print statements slow down the program just enough to allow everything to run in the right order. Swing requests fire from a single thread, so it is easy for events to get tied up, as Hover put it, especially if you have lots of input events like KeyEvents and such. To solve this issue, you could try Thread.sleep, but it would be better to rewrite the program to either not use that while loop or not use swing.

0

Make your application properly multi-threaded.

Avoid working in the event dispatcher thread (google this!) as much as possible. It should only be used for making changes to the UI. Don't ever run a waiting loop in it, you might even deadlock your program.

Spend more time on planning when your application works and when (and how) it waits for things to happen. You don't want your application to waste 100% of your CPU.

Has QUIT--Anony-Mousse
  • 76,138
  • 12
  • 138
  • 194