Exiting from a loop on a runnable and move to next screen - java

I am almost a beginner on android. I am sort of stuck at a point. In the following code I am running a while loop for 30 times and runnable post delay is 3 seconds, means loop will run for 90 seconds(which is not important yet). It does so, thats fine. But in the runnable, when I call rangeofRouter0() function,the value in the textView changes to "You have reached the turn" when it goes into "else if" condition of rangeofRouter0() function and it must remove the callbacks as defined and move to next activity, exitiing from the while loop whether it has completed 90 seconds or not but program doesn't reach in if(textView.getText.equals....) part. And if I put this condition directly into "else if", callbacks are (I think) not removed and next screen is called again and again. I want that when code goes into else if, it should simply move to next screen and previous activity(means this activity), should simply be forgotten
int i = 1;
while (i<30)
{
myRunnable =new Runnable() {
public void run() {
scanWifiList();
rangeofRouter0();
}
};
handler1.postDelayed(myRunnable, i * 3000);
i++;
if(textView.getText().toString.equals("You have reached the turn")){
///this text gets in textView in "else if" condition
handler1.removeCallbacks(myRunnable);
Intent intent = new Intent(getApplicationContext(), FrontScreen.class);
// finish();
startActivity(intent);
break;
}
}//While loop ended
private void scanWifiList() {
mainWifi.startScan();
wifiList = mainWifi.getScanResults();
textView5.setText("" + firstRouterDistance());
}
public void rangeofRouter0(){
if(firstRouterDistance() >= 30 &&
firstRouterDistance() <= 70 && ((degree>0 && degree <60)||(degree>300 && degree <360)))
{
textView.setText("Move left");
speakOut(textView.getText().toString());
}
else if(firstRouterDistance() >= 3 &&
firstRouterDistance() <= 20 &&
secondRouterDistance() >= 7 &&
secondRouterDistance() <= 60 && degree>220 && degree <250)
{
textView.setText("You have reached the turn");
counter++;
}
else{
textView.setText("Not before dining hall");
}
}

You first need to understand how postDelayed() works exactly.
When you assign a runnable to the Handler's postDelayed(), that means you are scheduling a task to get executed at a particular time interval from the current time.
Now what you are doing is running a while loop 29 times and each time scheduling the task - total 29 tasks to run at 3,6,9... seconds respectively.
At this point you only scheduled the task and it's not started running yet.
And you while loop finishes after iterating for 29 times.
Your rangeofRouter0() never gets called during the while loop iterations since it took only a few milliseconds and hence counter is never greater than 0.
Note - If you want the loop to run for 30 times you should change it to while (i<=30).
So, you need to change your logic to achieve what you want. If you want to read more about Handler. Check this.

Related

How to set a delayed in Android

I'm aware or the Thread.sleep() and postDelayed() function in java/androidStudio.
But here is the issue, I'm creating a replicate of Simon says game.
I created a generateSequence() function that puts number of 1-9 randomly into an array called sequence. After that, I need to display these sequence, which basically changes the background of a textView for a second and then back to its original background using the postDelayed() function.
Here is my code:
private void displaySequence(){
for(int i = 0; i < sequence.size(); i++) {
if(sequence.get(i) == 1) {
viewCard11.setBackgroundResource(R.drawable.text_view_circle4);
proceed = false;
handler.postDelayed(() -> {
viewCard11.setBackgroundResource(R.drawable.text_view_circle3);
proceed = true;
}, 1000);
}
else if(sequence.get(i) == 2) {}
else if(sequence.get(i) == 3) {}
else if(sequence.get(i) == 4) {}
else if(sequence.get(i) == 5) {}
else if(sequence.get(i) == 6) {}
else if(sequence.get(i) == 7) {}
else if(sequence.get(i) == 8) {}
else if(sequence.get(i) == 9) {}
while(!proceed) {}
}
}
But the problem with postDelayed() is that only whatever is inside the function is delayed. Meaning if this sequence had 2 element, it will simultaneously blink the background. The for loop doesn't wait for the postDelayed to finish whatever it is suppose to do, but instead it increments and proceed to put the next postDelayed.
To solve this issue, I tried to use a proceed boolean variable as a delay. What I do is that, before we call the postDelayed, I set proceed as false. Since it will not wait for postDelayed(), it will go to the next line of code which is the while loop.
By setting the proceed as false, I use it to create a infinite loop. But this infinite loop will be broken by the completed postDelayed() as proceed will be set to true in it, then the code can continues the for loop.
But I not sure why it simply doesn't work. When I run the code, it just displayed a blank screen. It seemed like the problem resides within the infitine while loop and postDelayed() can't update the proceed variable.
I tried using Thread.sleep(1000) as a replacement of postDelayed, but during startup, the program simply shows a white background for however long the parameter is passed to Thread.sleep()
I have exhausted my option and I hope someone has a better idea.
Thank you.
The loop does not wait for the postDelayed because what's inside the postDelayed happens async. This means that it works independently from the UI thread, on a second thread. What you want to accomplish is to make the UIthread wait for a period of time, and not start another thread after a specific period.
You could try to use the handler in this way:
Handler handler=new Handler()
{
public void handleMessage(Message msg)
{
if(msg.what==0)
{
viewCard11.setBackgroundResource(R.drawable.text_view_circle3);
proceed = true;
}
}
};
and then you may use the handler like this:
handler.postDelayed(() ->
{
//does nothing just waits 1 second and then send empty message
handler.sendEmptyMessage(0)
}, 1000);

Android Studio Delay inside Loop

I want to make a loop, the times the user wants but with a delay of 3 seconds.
This is the code:
for (i = 0;i < n1; i++){
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Toast.makeText(KeyMapCreator.this, "Try number " + i,Toast.LENGTH_SHORT).show(); ActionIwantToDo();
}
},3000);
}
The variable i is the one that the user sets.
The problem is that the toast doesn't show up every 3 seconds, it just do like a normal loop without delay. I thought it was because of the time of the toast but if i set the time to 20 secs still being the same.
Someone knows how to make a proper delay inside a loop???
The problem you have is that your loop creates many handlers at once that delay for 3 seconds and then show a toast. They do not wait for each other, and because they are created within milliseconds of each other they will show the toast at the same time.
I'm not sure what you are trying to accomplish, and a loop is probably not what you want. However this is a way to get the toast to display after 3 seconds and every 3 seconds after for a number of times.
For this we will use recursion because it will make it so that you are not blocked on the main thread.
Call doSomething (the recursive function) from where you need the function to start (remember that the second variable is the number of times you want it to run, and 0 is just required as a counter)
doSomething(0, 3)
create doSomething
private void doSomething(int i, int n) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (i < n) {
Toast.makeText(KeyMapCreator.this, "Try number " + i,Toast.LENGTH_SHORT).show();
actionIWantToDo();
doSomething(i+1, n);
}
}
}, 3000);
}
A Handler just schedules some work for later execution. It doesn't actually block the current thread. All you're doing is scheduling n1 items of work to execute three seconds later, which will all execute in sequence on that exact delay.
You don't really ever want to write code to block the main thread. Ever. It will make your app appear to be unresponsive.

LibGDX Do Something One Time During Update Method

I'm a bit new to Java and LibGDX, and I'm working on a point based game. A problem I'm facing is that the update method constantly runs something that I want to run on a timely manner. In my update method, I have the code to increment the score if a point is earned, and to make a lose state come up when the player lost. Without going into much detail, here's the pseudo code I have:
protected void update(float dt){
for(Thing x : a list) {
x.update(dt);
//continue
if (you complete the objective of the game) {
score++;
//do other stuff
}
//lost
if (you fail to complete the objective){
make lose state come up
}
}
//I want something like this to run:
if(score >=0 && score <=10){
do something ONCE(ie. print to console once)
}
if(score >= 11 && score <=15){
do something once
}
if(ect...){
do something else once
}
.
.
.
The problem here is that, if the IF condition is met, I notice the IF block gets executed multiple times very quickly(ie. printing to the console a lot). I have enclosed the details of the code that relies on the score in a separate class, I just want to be able to call the method from this update method and have it run once depending on the score conditions (ie. run it again if the score satisfies another IF statement)
I had the same problem, but I solved it by using following method. In Libgdx the update method runs in 1/60 second. That is the reason the method is rendering continously and the if condition will be executing various times.
To solve this problem, just declare an integer variable, say count, in your create method.
public static int count;
public static void create()
{
count =0;
// do other stuffs
}
protected void update(float dt){
// just increment this count value in your update method
for(Thing x : a list) {
count++
x.update(dt);
//continue
if (you complete the objective of the game) {
score++;
//do other stuff
}
//lost
if (you fail to complete the objective){
make lose state come up
}
}
// and make a small condition to run the if condition only once by using the declared variable "count".
if(count%60==0){
// here the condition only executes when the count%60==0.that is only once in 1/60 frames.
if(score >=0 && score <=10){
}
if(score >= 11 && score <=15){
}
if(ect...){
}
}
.
.
. This is how I solved the same issue.
The update() method is called every frame, multiple times very quickly(usually 60 times per second) in an infinite loop. This is not only specific in libGDX, but in any game engine. And when some condition of your if block evaluates to true, that if block is executed every frame until that condition becomes false again. But you want to execute the block only once after the condition changed.
Just declare a variable named isLastScoreUnder10 or whatever, and update it after the if block. Like this:
private boolean isLastScoreUnder10 = false;
protected void update(float dt){
if(!isLastScoreUnder10 && score >=0 && score <=10){
isLastScoreUnder10 = true;
// ..do something
} else {
isLastScoreUnder10 = false;
}
}

Java - add time delay to a cycle flow

I need to add time delay between cycle flow like this:
public boolean timeDelay(int seconds) {
// 1000000000 ns = 1 s
if (/* some system method to start calculate time in seconds*/ == seconds) {
return true;
} else {
return false;
}
}
public void renderEnemies() {
for (int w = 0; w < wave.size(); w++) {
while(timeDelay(2)){
(wave.get(w)).render();
}
}
}
Maybe my thinking isn't good, but I need to do like this...
wave --> ArrayList of enemies in my game
Render enemies is in game loop after pressing button "NextWave" and I need to spawn them with delay between them like a --> 2s * 2s * 2s * 2s * 2s *
where * is enemy...
Can you help me?
Try:
Thread.sleep(1000);
and use a try-catch.
You should probably thread it and use sleep as #curiosu mentions.
However, if you don't want to use sleeps/multiple threads but do want it to be pseudo real time (not turn based) you'll need a driving loop at the top of your game like so:
boolean keepPlaying = true;
while(keepPlaying) {
doNpcStep()
doPlayerStep()
keepPlaying = !isGameOver()
}
Each of these steps needs to run in a very small time slice, then in the doNpcStep function you get the current time, find the offset from a start time and run any action that should happen by now.
You could, for example, do this by keeping a min priority queue where priority is equal to the time they should execute by (in ms since start of java epoch). Then take all elements off the queue that are less than or equal to current time and run them, placing new occurrences onto the queue as necessary.
In essence this is a simulation of running a player and npc thread, where you are in charge of how much time each gets to run for.
try putting an infinite while loop
while(1)
{
if(/*method to calc time*/ == seconds)
return true;
}
return false;
I'm assuming that you want to start spawning enemies after 'seconds' time, so always a 'true' should be returned after 'seconds' time has passed. Your method should keep track from what time it has to start counting the seconds. You can call that function when 'NextWave' button is pressed where a variable can increment itself in multiples of 'seconds' so that you can keep track of elapsed time.
Hope this helps.

set a delay in libgdx game

i have a game(like super jumper, this game is a jumping game) that our character has life. after collision with enemies, his life reduce. and i want to after 1 sec , calculate the collisions. i mean in this 1 sec, if my character contact with enemies , nothing happen and he continue his way.
for this , i define a boolean variable in my GameScreen class, name "collision" and another in Wolrd class, name "collBirds". after one contact with enemy collision and collBirds change to true. but i want after 1 sec collistion change to false. i use several things like System.currentTimeMillis() and "for loop",and nothing happen. i'm not so good in java.
this is my condition:
if(World.collBirds == true && collition == false){
life -= 1;
lifeString = "Life : " + life;
World.collBirds = false;
collition = true;
for (??? "need to stay here for 1 sec" ???) {
collition = false;
}
}
In some cases you could also want to use com.badlogic.gdx.utils.Timer
Example usage:
float delay = 1; // seconds
Timer.schedule(new Task(){
#Override
public void run() {
// Do your work
}
}, delay);
When the first collision occurs, set a float timeSinceCollision = 0;
Then each loop, you will need to add the time since last check to the variable, and check if it's more than a second.
timeSinceCollision += deltaTime;
if(timeSinceCollision > 1.0f) {
// do collision stuff
} else {
// ignore the collision
}
If you want to do this in same thread than you can use Thread.sleep(). But in this case your current thread will freeze and if this is single thread game, than your whole game will freeze. If you don't want your game to freeze for 1 second, than you should spawn the thread and in that thread call the sleep and after sleep, change the flag

Categories