sclass ShootLoop implements Runnable { BWImage screen; BufferedImage originalScreen; int screenWidth, screenHeight; ImageSurface isThumb; new L selections; S state = "Shooting & recognizing"; float precision = 1f; // how sharply to look at the screen bool showThumbnail; public void run() { while licensed { sleepSeconds(1); once(); } } // one step of the loop (shoot, recognize & print) void step { once(); } void once { long time = now(); // todo: switch to sysNow() (will need to change implementations of this class too) shoot(); recognizeEtc(time); } void recognizeEtc(long time) { recognize(); printState(time); if (showThumbnail) showThumbnail(); } // override me void recognize { } // override me void printState(long time) { done_always(time, state); } void shoot { setScreen(shootScreen2()); } void setScreen(BufferedImage img) { originalScreen = img; screenWidth = originalScreen.getWidth(); screenHeight = originalScreen.getHeight(); screen = new BWImage(originalScreen); } BWImage screen() { ret screen; } bool hasImageOnScreen(S imageID) { ret findImage(imageID) != null; } // Simple version - searches full screenshot Rect findImage(S imageID) { ret findImageSingle(screen(), imageID, precision); } Rect findImage(S imageID, float precision) { ret findImageSingle(screen(), imageID, precision); } L findImageAll(S... imageIDs) { ret main.findImagesAll(screen(), asList(imageIDs), precision); } L findImageAll(S imageID, float similarity) { ret main.findImageAll(screen(), imageID, similarity); } L findImageAllOnRow(S imageID, int row) { Rect r = new Rect(0, row, screenWidth, 1); ret main.findImageAllInPart(screen(), imageID, r, precision); } L findImageAllOnColumn(S imageID, int x) { Rect r = new Rect(x, 0, 1, screenHeight); ret main.findImageAllInPart(screen(), imageID, r, precision); } void showThumbnail() { BufferedImage thumb = shrinkScreenshot(originalScreen); double factor = thumb.getWidth()/(double) screenWidth; new L l; for (Rect r : selections) l.add(scaleRect(r, factor)); isThumb = showImageWithSelections(thumb, isThumb, l); } bool topRightCornerIs(S imageID) { BWImage pat = loadBWImage_cached(imageID); ret bwImageSectionsSimilar(screen(), pat, screenWidth-pat.getWidth(), 0, precision); } float topRightCornerSimilarity(S imageID) { BWImage pat = loadBWImage_cached(imageID); ret bwImageSectionsSimilarity2(screen(), pat, screenWidth-pat.getWidth(), 0, 0f); } void doSingle(BufferedImage screen) { setScreen(screen); long time = now(); recognizeEtc(time); } void setSelection(FoundImg fi) { selections = fi == null ? (L) ll() : ll(fi.r); } void runWithThumbnails() { set showThumbnail; this.run(); // "this." to soothe standard function adder } RGBImage rgb(Rect r) { ret new RGBImage(clipBufferedImage(originalScreen, r)); } }