I'm kinda stuck with the following code. My goal is to create multiple CountDownTimer objects and start them after each other. The method looks like that:
private CountDownTimer setUpCountdown(int duration, int tick) {
// when tick is not set, set it to default 1 second
tick = (tick == 0 ? 1 : tick);
// convert seconds to milliseconds and set up the timer
CountDownTimer timer = new CountDownTimer(duration*1000, tick*1000) {
public void onTick(long millisUntilFinished) {
if (countdown != null) {
int timeRemaining = (int) (millisUntilFinished / 1000);
countdown.setText(String.valueOf(timeRemaining));
}
}
public void onFinish() {
// hide the countdown button and remove it from baseLayout. set the background of baseLayout back to black
countdown.setVisibility(View.INVISIBLE);
baseLayout.removeView(countdown);
baseLayout.setBackgroundColor(Color.BLACK);
}
};
return timer;
}
Then I create two timers:
CountDownTimer timer1 = setUpCountdown(8,1);
timer1.start();
CountDownTimer timer2 = setUpCountdown(5,1);
timer2.start();
When running the code the output for those values is: 4..3..2..1..3 when it should be 7..6...1 4...1 When I'm using 10 and 5 seconds as duration I get a single Countdown on the android device that counts from 10 to 5. It looks like the objects I'm creating are not really independent from each other or (kind of) use the same variables. Do you see what I'm doing wrong?
You are starting two timer at same time and displaying their values in single textView so you are able to see the value of only second timer 4..1 then the remaining values of timer with 8 sec will be displayed as 3..1
timer 7 6 5 4 3 2 1
// timer 2 will reset the values in text view, then after 1, you will see 3 2 1
timer 4 3 2 1
You can use Toast to verify the behavior or you have to use different TextViews to achieve the desired result or to achieve desired behavior, you can create and start the second timer from onFinish()
Related
I'm trying to make a timer that goes from 15 minutes to 0 but my code doesn't work. Sorry if this is easy, I recently started learning.
package timer;
import java.util.Timer;
import java.util.TimerTask;
public class Timer {
int secondsLeft = 900;
int minutesLeft = secondsLeft/60;
int seconds2 = secondsLeft - minutesLeft * 60;
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
secondsLeft--;
System.out.println("Time left : " + minutesLeft + ":" + seconds2 );
}
};
public void start() {
timer.scheduleAtFixedRate(task, 1000, 1000);
}
public static void main(String[] args) {
Timer timer = new Timer();
timer.start();
}
}
Your program is mostly written correctly, but you are not printing any changes. When the seconds count down, you need to convert existing total seconds to minutes and seconds.
You can do it several ways.
Method 1: Like you are doing it now, by
maintaining a total number of seconds. It requires two operators.
The division operator /
The remainder operator %
To get the minutes remaining, simply divide total seconds by 60. (totalSeconds / 60)
To get the seconds remaining in the current minute take the remainder (totalSeconds % 60)
Method 2: By maintaining separate values for minutes and seconds, where seconds is the number of seconds within the current minute.
define a int minutes field initialized to 15
define a int seconds field initialized to 0
When the timer task runs, you need to update those fields correctly. When the seconds reach 0
decrement the minutes and set the seconds to 59. Otherwise, just decrement the seconds.
When they both reach 0, you're done. So this requires some if clauses on your part.
Additional Recommendations
To retain the leading zeroes of minutes and seconds, you can use the following formatted print statement.
System.out.printf("Time left : %02d:%02d%n",minutesLeft, secondsLeft);
The %02d is the field width and the 0 means keep leading zeroes to fill out that field. To learn more about formatted printing, check out the Formatter class in the Java API.
And finally, please call you class something other than Timer. You are using a Timer class by that name already and even though it is in the same package it can be confusing.
I am thinking about making an android app to support a game of mine, and I can't find info on how to do it. Here is an app explanation:
The app should have two timers (both set for x minutes). When first player starts his turn (by a button click) his time starts running out. when first player makes his move, he should click his time to stop it, and player two starts his turn.
NOW, the problem I can't find a solution for - When player one takes his turn, time that he loses should pass to the other player's timer.
Example: Both players start with a 5 minute timer. If player one takes 30 second for his turn, his time should go down to 04:30, at which time he clicked on his timer. During that time, for each second he lost, the other player gained time on his timer, so at the beginning of his turn, his time is 05:30. The time goes back and forth, and the player whose timer runs out loses the game.
Any idea how to do this?
I am still stuck to the idea on how to make it, so I have no code to share.
Thank you all for your answers, and effort in helping me, if you have a question I haven't covered, I will gladly answer it.
First, you will need to instantiate class of CountDownTimer everytime you click on button.
For reference check here: https://developer.android.com/reference/android/os/CountDownTimer.html
You have two parameters long millisInFuture, long countDownInterval
Before you start, you will need to create two global variables one for first player, and one for second player like this:
long firstPlayerRemainingTime = 5 * 60 * 1000; // start time 5 minutes
long secondPlayerRemainingTime = 5 * 60 * 1000;
long limitedTime = 30 * 1000; // 30 seconds
CountDownTimer mCountDownTimer;
Now we have came to the most important part and that is logic inside onClickListener method
I don't know if there are two buttons or one, but I will go with two buttons:
btnFirstPlayer.setTag(1); // start timer
btnFirstPlayer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (btnFirstPlayer.getTag() == 1) {
startTimer();
} else {
stopTimer();
}
});
private void startTimer() {
long startTime = firstPlayerRemainingTime;
btnFirstPlayer.setTag(2); // stop timer
btnFirstPlayer.setText("Stop");
mCountDownTimer = new CountDownTimer(firstPlayerRemainingTime, 1000) {
public void onTick(long millisUntilFinished) {
firstPlayerRemainingTime = millisUntilFinished;
tvPlayerOneTimer.setText("" + firstPlayerRemainingTime / 1000)
// Here you would like to check if 30 seconds has passed
if ((startTime / 1000) - (limitedTime / 1000)
== (firstPlayerRemainingTime / 1000)) {
stopTimer();
}
// Here you would like to increase the time of the second player
secondPlayerRemainingTime = ++1000;
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
}
}
private void stopTimer() {
btnFirstPlayer.setTag(1);
btnFirstPlayer.setText("Start");
mCountDownTimer.cancel();
// I guess here starts second player move
}
The same logic would go for second player. Let me know if this helped you or if I need to explain anything.
How can I get the time left in a util.Timer?
What I want to do is to add a progressbar that displays time left until the timer starts over.
This is what I've got this far:
int seconds = 8;
java.util.Timer timer = new Timer();
timer.schedule( new TimerTask(){
public void run(){
// Do something
// Add a progressbar that displays time left until the timer "starts over".
},0,(long) (seconds*1000));
You would need a second timer to refresh the gui in a specific interval.
Another way to achieve this, would be to activate a single timer every second and update the counting in the ui. If the time is up, call your specific action.
A simple expample with console output only:
TimerTask task = new TimerTask()
{
int seconds = 8;
int i = 0;
#Override
public void run()
{
i++;
if(i % seconds == 0)
System.out.println("Timer action!");
else
System.out.println("Time left:" + (seconds - (i %seconds)) );
}
};
Timer timer = new Timer();
timer.schedule(task, 0, 1000);
It's output would be:
Time left:7
Time left:6
Time left:5
Time left:4
Time left:3
Time left:2
Time left:1
Timer action!
Time left:7
Time left:6
Time left:5
Time left:4
Time left:3
Time left:2
Time left:1
Timer action!
Time left:7
Time left:6
...
Then simply change the System.out's with your code to update the progress bar. Remember: java.util.Timer starts its own Thread. Swing is not thread safe, so you need to put every gui changing code into SwingUtilities.invokeLater()!
If you're not doing any long running tasks, every time your timer reachs the 8 seconds mark, you may want to use javax.swing.Timer directly. It uses the EDT and not its own Thread, so you don't need to synchronize your calls to Swing components with SwingUtilities.invokeLater().
Also see:
javax.swing.Timer vs java.util.Timer inside of a Swing application
All you need to do is declare a long variable timeleft in your MainActivity.
long timeleft;
Then, when you create a new Timer, set the "onTick" override to update the timeleft variable each "onTick" (which in the following example is 1000 milliseconds )
timer = new CountDownTimer(time, 1000) {
#Override
public void onTick(long millisecondsUntilFinished) {
timeleft = millisecondsUntilFinished;
}
}
Your app can access then the variable timeleft every time you need to check how much time is left.
Why is this Code not working ?
This code should extend the Countdowntimer to 10 sec (everytime when point is 20 , 40 , 60) etc.But when I start it and my score is by 20 it shows in a TextView a right value of time.But then it is gone in 1 sec and the Countdowntimer got the old value and continue.Someone a idea ?
int bonus_time = 1 , sec = 10000 , point == 0;
points_timer =new CountDownTimer(sec,1000) {
#Override
public void onTick(long millisUntilFinished)
{
if ( point == (bonus_time * 20))
{
++bonus_time;
millisUntilFinished += 10000;
sec += 10000;
}
++point;
}
#Override
public void onFinish()
{
bonus_time = 1;
}
};
When you create a timer with the sec variable for its time, it does not magically connect the two so when the value of sec changes the timer's time changes, it just uses the value of sec once when you make the timer.
Same goes for changing millisUntilFinished, it's a parameter you got from a callback, by changing its value you are not doing anything.
The only way to change a timer's time is to create a new one. This is my suggestion:
// GLOBAL VARIABLES
CountDownTimer points_timer;
int bonus_time = 1 , sec = 10000 , point == 0;
public void createTimer()
{
points_timer =new CountDownTimer(sec,1000) {
#Override
public void onTick(long millisUntilFinished)
{
sec = millisUntilFinished;
if ( point == (bonus_time * 20))
{
++bonus_time;
//millisUntilFinished += 10000;
sec += 10000;
createTimer();
}
++point;
}
#Override
public void onFinish()
{
bonus_time = 1;
}
};
}
The creation of the timer is surrounded by a function, and that function is called each time the bonus is gained to recreate the timer with the new value of sec.
You should also call that method once in place of your previous code, to initially create the timer.
Hope this works..
There is no way to extend a CountDownTimer, no method in the class provides this.
Your attempt to add time to sec is useless, I even wonder how it can compile. Anyway, in Java integers are passed by value, so once you passed 1000, you passed it and can't change that value.
The only alernative is to re-create a new timer and use it instead of the old one. Or recode everything, a timer of your own that you can extend.
in
public void onTick(long millisUntilFinished)
you do
millisUntilFinished += 10000;
you can not assign to primitive parameter and expect that it changes anything outside of that method (eg. scope of millisUntilFinished is onTick method and nothing more)
I try to add time to my game that will increment every second.
How to fix that?
I add my code below
float timer;
timer += delta;
if(timer<=delta+1000)//every one sec
{
time = time+1;
timePoint.setSentence(""+time/100);
timer = 0f;
}
as your note, delta is Gdx.graphics.getDeltaTime().
'time' is string.
but looks like the time increment slowly. means that when time already run about 1,5 sec,
'time' still increase 1.
I divide by 100 because if not it will increase more faster/sec,
i also use TimeUtils class from libgdx but it produced similar result.
Thanks before.
This should work. Note that time/100 results in 0 for 0-99 and 1 for 100-199. That's probably not the effect you wanted.
float timer;
timer += delta;
if (timer >= 1) {
time++;
timePoint.setSentence(""+time);
timer -= 1;
}
The problem was that you set the timer back to 0. If it was 1.1f for example (because the last delta was 0.1f), then you basically lose 100ms. Don't reset the timer to 0f, but decrease it by 1f instead.
I would do it like this:
float time = 0f;
In render:
time += delta;
timePoint.setSentence(Integer.toString((int)time));
delta is giving the ellapsed time in seconds, so for 30FPS it is 1/30 seconds. So you only need to add it to your time. To print the difference (i guess the setSentence is printing the text) you only need to cast it to int, so that it cuts the fraction digits.
Hope it helps.
EDIT: If you need the timer and the time variable somewhere you need to store them in 2 different variables.
For that i would do it like this:
float timer = 0f;
int time = 0;
And in render:
timer+=delta;
if (timer >= 1f) {
time++;
timePoint.setSentence(Integer.toString(time));
timer-=1f;
}
By doing this you are not loosing the few milli seconds you would loose if you reset the timer.
This means, that if timer goes from 0.99f to 1.05f in one renderloop and you reset the timer to 0f, you loose 0.05 seconds. If this happens every second you loose 1 second every 20 seconds (if i am not wrong^^)
Like in pure java:
Timer timer = new Timer();
timer.schedule(new incrementYourValue(), 0, 1000); //1000 is time in mili sec
//0 is the time waited before the beginning.
Had similar problem but for me using delta time was kinda overkill. Instead I used Libgdx Timer that "Executes tasks in the future on the main loop thread". Using Timer from java.util may cause Concurrency problems in libgdx.
import com.badlogic.gdx.utils.Timer;
public class Scheduler {
public Scheduler(Runnable runnable, float periodInSeconds) {
Timer timer = new Timer();
timer.scheduleTask(new Timer.Task() {
#Override
public void run() {
runnable.run();
}
}, 0, periodInSeconds);
}}
And usage:
new Scheduler(() -> updateSth(), 1f);