I am making an Image Detection bot using the Sikuli API and I was wondering if anyone knows how I can make it constantly scan for an image, then click on it? At the moment it will scan then click, but I want it to be constantly scanning.
how about:
int mil = MaxMillis;
boolean flagIsFound = false;
while (mil > 0 && flagIsFound != true)
{
Thread.sleep(1000);
mil -= 1000;
System.out.println("wait for the image a sec");
if (screen.exists(image) != null)
{
// found
flagIsFound = true;
}
}
if(flagIsFound == false)
{
throw new SikuliException(image + " not found for " + MaxMillis + " milliseconds");
}
Do you need it to scan until it appears and then click on the image, or will the image recur, and you need it to click on the image every time it pops up? Either way, I think your solution is simple--
For scanning until it pops up, then clicking on it once, then no more scanning--
while not exists(yourImage):
wait(1) #can also use sleep()
click(yourImage)
for continuing to scan and click again and again, wrap it in another 'while' statement, for example--
while True:
while not exists(yourImage):
wait(1)
click(yourImage)
if (someConditionIsMet):
break
Related
I'm trying to create something like an info screen that just scrolls through images (and maybe one day pdfs) that are uploaded with a small managment app I wrote.
After some reading I think I understand why I should NOT have Thread.sleep in my for loop. I read some posts on stackoverflow and other pages that teached me not to do it.
Apparently I'm supposed to use ExecutorService for something like this, but I can't wrap my head around it.
So after preparing my GUI and everything else I finally call my showImages and stay in this while loop.
After each loop I reload the records from the file systems, so any changes are represented on the screen.
I created a metafile containing the preferred delay for each image and just sleep for the amount of time.
private void showImages() {
//noinspection InfiniteLoopStatement
while (true) {
loadRecords();
for (ImageRecord record : records) {
System.out.println("Showing: " + record.getFilename());
imageLabel.setIcon(record.getIconForInfoScreen(screenWidth, screenHeight));
int delay = record.getDurationAsInt();
System.out.println("Waiting for " + delay + " milliseconds");
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
So if I understand correctly I could use something like
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
exec.scheduleAtFixedRate(showImage(),0, delay, TimeUnit.MILLISECONDS);
But this would trigger the showImage() every "delay" millisecond and I still need to increment some counter, to get to the next image in my records.
Could someone push me in the right direction? I'm kinda lost at the moment.
All the comments on my question can be considered good ideas an and one of them also lead me to my final result. But it in the end, the matter was, that I did not understand how to implement a timer into my loop.
Or in other words, the loops had to be gone and instead use a counter and set the delay for the follow up record inside the timer loop.
private void loopImages() {
loadRecords();
recordSize = records.size();
int delay = records.get(1).getDurationAsInt();
timer = new Timer(delay, e -> showImages());
timer.start();
}
private void showImages() {
if (recordIndex == recordSize) {
loadRecords();
recordSize = records.size();
recordIndex = 0;
}
ImageRecord record = records.get(recordIndex);
imageLabel.setIcon(record.getIconForInfoScreen(screenWidth, screenHeight));
recordIndex++;
if (recordIndex < recordSize) {
record = records.get(recordIndex);
int delay = record.getDurationAsInt();
timer.setDelay(delay);
}
}
My program is coded in Java. I have an IF() check in run() method (in a Thread). In the IF check, if the condition is satisfied, it shows a Window dialog (using JOptionPane.showMessageDialog) with OK button. However, it shows infinitely. When I click OK it pops up again and again. How can I end the if check after the user click OK. Or when the condition is met, it only shows once ?
This is my method()
public void danhHoiWumpus()
{
if ((GameScreen.bg[x[0] + 1][y[0]] == 2) || (GameScreen.bg[x[0] + 2][y[0]] == 2) || (GameScreen.bg[x[0] + 3][y[0]] == 2) || (GameScreen.bg[x[0]][y[0]+1] == 2) || (GameScreen.bg[x[0]][y[0]+2] == 2) || (GameScreen.bg[x[0]][y[0]+3] == 2))
{
JOptionPane.showMessageDialog(this, "Có mùi wumpus ! \n Bạn được học bổng 40%");
}
}
This is my run() method
public void run()
{
while(true)
{
hunter.update();
hunter.danhHoiWumpus();
// i++;
repaint();
// System.out.println("Gia tri cua y la " +i);
try {
thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The idea of this action is. When the RED square is going near the YELLOW square, it will pop up a dialog "I smell Wumpus". When the user click OK. They will choose to shot the wumpus (I will do this later).
And here is my full source code (for reference):
https://www.mediafire.com/?wkp6hyq32nq23mp
Thank you in advance.
Your code is executing in an infinite while loop
while(true)
// I am infinite
}
The term you are looking for is hit detection. There are a myriad of ways to achieve it. Look up hit detection in Java for some pointers.
What you have isn't necessarily wrong though.
while (true) // I'm not always bad!
is used in a lot of applications. However, while your code isn't completely posted, I don't see anywhere you break from this. You may be interested in the
java.util.Timer
and the
java.util.TimerTask
Both of those have wide application in Java game development
Your sleep time is too low (20 nanoseconds). Increase the time, otherwise it will happen too quick for you to understand it.
You are potentially triggering this if condition many many times.
You need some 'rising edge trigger' logic in order to only trigger when the new value goes from false to true, instead of triggering whenever it's true.
currentValue = bigLongLogicCheck;
if(!oldvalue&¤tValue) {alert()}
oldvalue = currentValue
I need to program a robot to drive at 50% speed when the 'a' button on a game controller is pressed and released, and then to drive at 100% when 'a' is pressed and released again, like a latched button. I have the following code that makes the robot drive a 50% when 'a' is held down constantly, and at 100% when 'a' is released, it works fine.
telemetry.addData("Status", "Running: " + runtime.toString());
if(gamepad1.a)
{
telemetry.addData("Status", "A pressed");
leftMotor.setPower(-gamepad1.left_stick_y*0.5);
rightMotor.setPower(-gamepad1.right_stick_y*0.5);
telemetry.addData("Status", "Running Slow");
}
else {
leftMotor.setPower(-gamepad1.left_stick_y);
rightMotor.setPower(-gamepad1.right_stick_y);
telemetry.addData("Status", "Running regular");
}
}
And this is the code I have for the latched button, it does not drive when running. I think it is just a matter of fixing the if and else statements, but I cant pinpoint the problem .
telemetry.addData("Status", "Running: " + runtime.toString());
if(gamepad1.a)
{
telemetry.addData("Status", "A pressed");
//if A was pressed
if(aPressed == false)
{
aPressed = true;
if(goingSlow)
{
leftMotor.setPower(-gamepad1.left_stick_y);
rightMotor.setPower(-gamepad1.right_stick_y);
telemetry.addData("Status", "Running Regular");
goingSlow = false;
}
else {
leftMotor.setPower(-gamepad1.left_stick_y*0.5);
rightMotor.setPower(-gamepad1.right_stick_y*0.5);
telemetry.addData("Status", "Running Slow");
goingSlow = true;
}
}
}
else
{
aPressed = false;
}
I think that you are trying to do too much inside the branches of the "if" statement. Moving some of the functionality to other methods should make things easier to understand.
It's difficult to know exactly what's going on, since you don't show the entire method, or provide any context about how you are notified of the button presses / releases, but you might want to try something like this, once you've dealt with the button presses and figured out whether you should be going slow or fast:
if(shouldGoFast) {
goFast();
} else {
goSlow();
}
public void goFast() {
leftMotor.setPower(-gamepad1.left_stick_y);
rightMotor.setPower(-gamepad1.right_stick_y);
telemetry.addData("Status", "Running Regular");
}
public void goSlow() {
leftMotor.setPower(-gamepad1.left_stick_y*0.5);
rightMotor.setPower(-gamepad1.right_stick_y*0.5);
telemetry.addData("Status", "Running Slow");
}
I'm assuming that you don't really need to keep track of whether you're currently going slow or fast, i.e. there's no problem if you execute goFast() when you're already going fast.
I am using AndEngine to develop my game, though I'm thinking this problem is unrelated to AndEngine.
I have two possible dialogs that fire if:
User touches down in an incorrect area or
Users lifts up from an incorrect area.
Unfortunately, if a user touches down in an incorrect area, when they lift up they are also satisfying error 2--lifting up from an incorrect area.
Here's my code in a nutshell:
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
float y = pSceneTouchEvent.getY();
int dialog_count = 0;
if (pSceneTouchEvent.isActionDown() && y < 1000) {
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
AlertDialog Code
..............
}
}
dialog_count ++;
Log.d("Dialog Count", "Count is " + dialog_count);
} else if (dialog_count < 1 && pSceneTouchEvent.isActionUp() && y > 105) {
Log.d("Dialog Count", "Count is still " + dialog_count);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
Second AlertDialog Code
.................
}
}
}
return false;
}
Now, my first log for dialog_count shows a value of 1. However when I lift up the second log shows a value of 0. Somehow this value is either getting reset or my Else statement just can't see the updated value of dialog_count because I get the second dialog popping on top of my first.
Any ideas?
Your code initializes
int dialog_count = 0;
each time it runs.
To keep the value you saw the last time, make dialog_count an instance variable in the class.
Notice that you will be seeing two events, one for "down" and one for "up".
If you want to show only one then you need to use a flag to check if the user has touched down and then if you want not to show the touch up dialog just check from the flag. But the Touch down will always follow the Touch Up. You can use the Touch Move method if you want to show the dialog when the user has moved a bit.
If I understand correctly, what you are trying to do
dialogCount is function local (garbage collected, after you exit the method). So it will be 0 on each new run of the method. (Make it private class variable).
If you are referring to your dialogCount in multiple threads, dialogCount must be thread safe, so use concurrent primitives - AtomicInteger
I am making a little game in Processing which is similar to those Guitar Hero style games and I am trying to do 2 things:
When the game loads, stop the time from moving
During the game, allow for Pause functionality
Now, I know I cant stop the time since the millis() returns the milliseconds since the application launched, so my timer will need to be millis() - millis() at the start to equal zero, so when the user presses START, they can obviously start at the start. The game reads a file at the start, similar to a subtitles file, that has the note to be played and the time in milliseconds that it should appear on screen.
My problem is, when I pause the game, the timer keeps going and when I unpause the game, all the notes get "bunched up" due to my logic, as you'll see from my code.
Can someone suggest a better algorithm than the one I'm using? Its late and I've been working on this all day and night. I think the problem is with the for() below:
public void draw()
{
if (gameInProgress)
{
currentTimerValue = millis(); // Update the timer with the current milliseconds
// Check to see if the note times falls between the current time, or since the last loop (difficult to match exact millisecond)
for(int i=0 ; i<songNotes.length ; i++)
{
if( songNotes[i].getStartTime() > previousTimerValue && songNotes[i].getStartTime() <=currentTimerValue)
notes.add(songNotes[i]);
}
noStroke();
textFont(f,18);
drawButtons(); //Draws coloured buttons relating to Button presses on the controller
drawHighScoreBox(); // Draws high score box up top right
drawLines(); // Draws the strings
moveNotes(); // Moves the notes across from right to left
//Now set the cutoff for oldest note to display
previousTimerValue=currentTimerValue; //Used everytime on the following loop
}
else
{
drawMenu(); // Draw the Main/Pause menu
}
}
NOTE: The boolean gameInProgress is set below when the users presses the pause button, eg "P", and songNotes is an array of objects of type Note that I wrote myself. It has 2 member variables, noteToBePlayed and timeToBePlayed. The method getStartTime()returns timeToBePlayed which is a millisecond value.
Any help is appreciated.
Thanks
How about having another integer to store time when you pause and use that to offset the game timer ?
So, in 'gameInProgress' mode you update currentTimerValue and previousTimerValue and in 'paused/menu' mode you update a pausedTimerValue, which you use to offset the 'currentTimerValue'. I hope this makes sense, it sounds more complicated in words, here's what I mean:
boolean gameInProgress = true;
int currentTimerValue,previousTimerValue,pausedTimerValue;
void setup(){
}
void draw(){
if(gameInProgress){
currentTimerValue = millis()-pausedTimerValue;
println("currentTimerValue: " + currentTimerValue + " previousTimerValue: " + previousTimerValue);
previousTimerValue=currentTimerValue;
}else{
pausedTimerValue = millis()-currentTimerValue;
}
}
void mousePressed(){
gameInProgress = !gameInProgress;
println("paused: " + (gameInProgress ? "NO" : "YES"));
}
Click the sketch to toggle modes and look in the console for times. You'll notice that you only loose a few millis between toggles, which is acceptable.
Use not system timer but special timer class with pause functionality. I'm sure it is not hard to implement such class by yourself. I know that java has Timer class but unfortunately it not support pause functionality.