So I'm trying to program a handheld electronic game, called Lights Out Cube, in Java using Eclipse Oxygen.2, and I decided to include a timer so that the player knows how much time was required by him to finish the game. When the player clicks on a button called "Start/Reset"(I change its text to "Reset" after clicking it once), which is where I activate the timer, the game starts. After every click I check if player has finished the game, and if he does, I stop the timer. If he wishes to play again, I want the timer to restart. Please help me out here:
//here i have a function called checkIfWinning() which does the checking; if there is a winner, the following code is executed to stop the timer
timer.cancel();
timer.purge();
//timer is a publicly declared java.util.Timer
//this is a code snippet for btnStart with "time" recording the time in seconds
time=0;
timer.schedule(new TimerTask()
{
#Override
public void run()
{
time++;
int hours = (int) time / 3600;
int remainder = (int) time - hours * 3600;
int mins = remainder / 60;
remainder = remainder - mins * 60;
int secs = remainder;
timeTaken.setText(String.format("%02d:%02d:%02d",hours,mins,secs));
}
}, 1000,1000);
Is there anyway this can be done? Or will I have to remove the timer entirely?
You can't reset when the TimerTask object will be activated, but in your specific case, you can reset the game time count without removing and recreating the timer.
Since your timer is fired every second, all you have to do is reset the time variable you are using, when the user clicks the reset button.
I am editing this answer based on Hulks and your comments:
Hulk is right, and you should use AtomicInteger for your time count. If you keep the timer running, there could be a bug some times where the value will not reset.
You can have an AtomicBoolean flag that lets the TimerTask know if the player is playing or not.
Here is a code example:
AtomicInteger time = new AtomicInteger();
//whenever you want to reset it:
time.set(0);
AtomicBoolean isPlaying = new AtomicBoolean();
//when user clicks "start":
isPlaying.set(true);
//when user wins or clicks "reset"
isPlaying.set(false);
//your timer task will look something like this:
public void run() {
if (isPlaying.get()) {
int currentTime = time.incrementAndGet();
int hours = (int) currentTime / 3600;
int remainder = (int) currentTime - hours * 3600;
int mins = remainder / 60;
remainder = remainder - mins * 60;
int secs = remainder;
timeTaken.setText(String.format("%02d:%02d:%02d",hours,mins,secs));
}
}
This might be clear.
You can't reset or pause the Timer in Java, but the functionality can be achieved by not running the Timer based on a boolean check.
As previously said by Hulk and Lev.M, AtomicInteger can be used in need of thread safety.
Whole logic in run() can be simplified using TimeUnit for converting seconds to the specified format,
time+=1000;
System.out.println(String.format("%02d:%02d:%02d", TimeUnit.SECONDS.toHours(time), TimeUnit.SECONDS.toMinutes(time), time%60));
import java.util.Timer;
import java.util.TimerTask;
public class Game
{
private static int time = 0;
private static Timer t = new Timer();
private static Game g;
private static boolean ispaused = false;
public static void main(String[] args)
{
t.schedule(new TimerTask() {
public void run()
{
if(ispaused)
{
return;
}
time++;
System.out.println(String.format("%02d:%02d:%02d", TimeUnit.SECONDS.toHours(time), TimeUnit.SECONDS.toMinutes(time), time%60));
}
}, 1000, 1000);
g = new Game();
try
{
System.out.println("Starting first game");
g.startGame(); Thread.sleep(5000); g.endGame();
System.out.println("Starting second game.");
g.startGame(); Thread.sleep(5000); g.endGame();
}
catch(Exception e)
{}
}
private void startGame()
{
time = 0;
ispaused = false;
System.out.println("Game Started");
}
private void endGame()
{
time = 0;
ispaused = true;
System.out.println("Game ended");
}
};
Related
I have developed a workout app. I've two timers on the screen one is for the total timer and one for exercise time also some tts and MediaPlayer sounds. When the screen is locked my exercise timer is stuck after 10 seconds but my total remaining time timer is still running. So confused about why is it happening, I've verified battery optimization permission on\off but the issue is still the same. I've set a toast in tick function and I turn off the screen when I come back toast is showing but my timer is stuck. Can anyone help to get out of this? Thanks in advance. Countdown works fines when the screen is opened or connected to the charger.
Exercise Timer code below...
excerciseCountDownTimer = new CountDownTimer(seconds * 1000, 1000) {
public void onTick(long millisUntilFinished) {
totalExcerciseSec = (int) (millisUntilFinished / 1000);
int currentMinute = totalExcerciseSec / 60;
int currentSecond = totalExcerciseSec % 60;
binding.workoutTimeTv.setText(String.format("%02d", currentMinute) + ":" + String.format("%02d", currentSecond));
if (totalExcerciseSec == 0) {
totalRemaingCountDownTimer.cancel();
onExerciseCompleteActions();
}
}
public void onFinish() {
}
}.start();
Total Remaining Timer code below...
totalRemaingCountDownTimer = new CountDownTimer(seconds * 1000, 1000) {
public void onTick(long millisUntilFinished) {
totalRemainingSecs = (int) (millisUntilFinished / 1000);
int minutes = totalRemainingSecs / 60;
int second = totalRemainingSecs % 60;
timerPlaying = true;
binding.totalRemainingTimeTv.setText(String.format("%02d", minutes) + ":" + String.format("%02d", second));
}
public void onFinish() {
}
}.start();
Your activity is getting stopped or destroyed and that's why your timer gets stuck.
To keep the timer running even if the app is closed or killed, see this way:-
You can use this technique to detect how long the user was inactive (even when the app is in the background).
Create a SharedPreference & its Editor object. Then declare 3 long variables such:
mMillisUntilFinished = pref.getLong("millisUntilFinished",60*1000); // Replace with your time
long userExitedMillis = pref.getLong("userExitedMillis",0);
long timeLeft = mMillisUntilFinished - (System.currentTimeMillis() - userExitedMillis);
Pass timeLeft as millisInFuture. Inside timer, assign millisUntilFinished to a public variable in every tick
new CountDownTimer(timeLeft,1000){
#Override
public void onTick(long millisUntilFinished) {
Log.d("TAG", "Time left : " + millisUntilFinished/1000 + " sec");
mMillisUntilFinished = millisUntilFinished;
}
#Override
public void onFinish() {
// Timer completed
}
}.start();
Save this mMillisUntilFinished variable & current time in shared preference at onStop().
#Override
protected void onStop() {
super.onStop();
editor.putLong("millisUntilFinished",mMillisUntilFinished);
editor.putLong("userExitedMillis",System.currentTimeMillis());
editor.apply();
}
Tip : If you subtract userExitedMillis from System.currentTimeMillis() then you will get the activity inactive time (in mili second).
I have used this class to solve my issue according to my requirements.
https://gist.github.com/Gautier/737759
I have a timer with a delay of 5 seconds. I am trying to change the label named lblTimer after a second passes to act as a countdown. I am having issues with it as currently it only works at 5 seconds. Do you have any suggestionsuggestions?
protected void Addition() {
//addition function
final int delay = 5000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
#SuppressWarnings("unused")
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
frame.getContentPane().setBackground(Color.red);
}
};
new Timer(delay, taskPerformer).start();
Random RandomNumber = new Random();
int number1 = RandomNumber.nextInt(12);
int number2 = RandomNumber.nextInt(12);
int number3 = RandomNumber.nextInt(12);
lblAnswer.setText("");
lblFirstNumber.setText(""+ number1);
lblfunction1.setText("+");
lblsecondNumber.setText(""+number2);
lblfunction2.setText("+");
lblthirdnumber.setText(""+number3);
lblequals.setText("=");
answer = number1+number2+number3;
if(delay <= 1000){
lblTimer.setText("1");
}
else if(delay == 2000){
lblTimer.setText("2");
}
else if(delay == 3000){
lblTimer.setText("3");
}
else if(delay == 4000){
lblTimer.setText("4");
}
else if (delay == 5000){
lblTimer.setText("5");
}
}
The answer to your question, that I assume is "why does this not work?", is that at no point do you recheck the elapsed time. The variable delay is always set at 5000, and never updated, also.
The stupid-ass solution:
lblTimer.setText("5");
Thread.sleep(1000)
lblTimer.setText("4");
Thread.sleep(1000)
lblTimer.setText("3");
Thread.sleep(1000)
lblTimer.setText("2");
Thread.sleep(1000)
lblTimer.setText("1");
Thread.sleep(1000)
lblTimer.setText("0");
Don't really do this, unless you need to satisfy your sick fetishes.
The four-liner
The same as above. Don't do this.
for (int i = secondsToWait; i >= 0; i--) {
lblTimer.setText(i + "");
Thread.sleep(1000);
}
The acceptable solution:
Use a Timer to schedule a task to be executed after a given period of time. You can use timers to also fire the same task multiple times at a given interval.
Timer timer = new Timer();
int secondsToWait = 5;
TimerTask task = new TimerTask() {
#Override
public void run() {
secondsToWait--;
lblTimer.setText(secondsToWait + "");
if (secondsToWait == 0) {
timer.cancel();
timer.purge();
}
}
};
lblTimer.setText(secondsToWait + "");
timer.scheduleAtFixedRate(task, 1000, 1000);
The best solution:
Instead of a timer, use a ScheduledExecutorService. This is better because of the way ScheduledExecutorService works with threads as opposed to Timer. Google it.
ScheduledExecutorService exec = Executors.newScheduledThreadPool(1);
int secondsToWait = 5;
Runnable task = new Runnable() {
#Override
public void run() {
secondsToWait--;
lblTimer.setText(secondsToWait + "");
if (secondsToWait == 0) {
exec.shutdown();
}
}
};
lblTimer.setText(secondsToWait + "");
exec.scheduleAtFixedRate(task, 1, 1, TimeUnit.SECONDS);
EDIT: As Stefan pointed out, for swing GUI applications a swing Timer would be the best pick.
It should look something like this:
1) create Timer
2) create TimerTask and implement run method (updating your count variable and check if counter is zero. if it is zero, stop the timer)
3) schedule the task to run every second
int count = [INITVALUE];
...
public void startMethod() {
final Timer timer = new Timer();
timer.shedule(new TimerTask() {
#Override
public void run() {
count--;
lblTimer.setText(count+"");
if (count == 0) {
timer.cancel();
timer.purge();
}
}
},1000);
}
Thumbs Up #Olavi Mustanoja your answer revealed an option I have never tried before now.
As he lastly suggested on his edit the javax.swing.Timer comes in very handy if you're work with GUI.
import javax.swing.Timer;
private int secondsToWait = 5000; //Time in milliseconds
private Timer timer;
....
//The following section should be inside a method member
timer = new Timer(secondsToWait, e -> {
if(secondsToWait == 0)
timer.stop();//Stop if secondsToWait is already zero
lblTimer.setText((secondsToWait/1000) + ""); //Update the label with the current sec
timer.setDelay(secondsToWait);
secondsToWait -= 1000; //Reduce time by 1sec each time
});
timer.start();
...
I am wondering the best way to keep a timer going in the background while a game is played.
I am programming a version of the HiLo game (in Java), which gives a user a certain amount of time to determine a number. If a guess is not correct, the game will tell the user whether the name is too high or too low.
I'm keeping track of time using System.currentTimeMillis() and seeing how much time has elapsed. This seems to work well, and so far I have been checking to see how much time has elapsed each time a new number is entered. For example, currently the app output looks like this:
Welcome to HiLo!
You have 10 seconds to guess a number I'm thinking of between 1 and 100.
> 67
Too high.
> 29
Too low.
Half of your time is gone! Only 5 seconds remains!
> 37
Too high.
> 33
Oops! Time is up - try again.
As you can see, currently, it can only check when I enter a new number how much time is passed.
I have tried creating a thread to start with a timer, however, when I start it, it keeps counting until the time is exhausted, without going on to the thread.run(int guess) which will be run when there is a new guess. I want to be able to still make guesses while the counter runs. Here is my attempt at a new implementation for thread.start():
public void start(int time_sent) throws InterruptedException {
time = time_sent;
startTime = (System.currentTimeMillis() / 1000);
while (1==1) {
long elapsed = ((System.currentTimeMillis() / 1000) - (startTime));
if (elapsed >= (time)) {
System.out.println("Oops! Time is up - try again.");
System.exit(0);
}
else if (elapsed >= (time/2) && !halfWarning) {
System.out.println("Half of your time is gone! Only " + (time/2) + " seconds remains!");
halfWarning = true;
}
}
}
How can I continue running this counter in the background?
This is one more approach:
public void game() {
Scanner scanner = new Scanner(System.in);
int time = 10; // sec
message("You have " + time + " seconds to guess...");
new Thread(new Background(System.currentTimeMillis() / 1000, time)).start();
while (true) {
String s = scanner.next();
if (s.equals("55")) {
message("You win");
System.exit(0);
} else {
message("try again...");
}
}
}
private void message(String str) {
System.out.println(str);
System.out.print("> "); // monit
}
You start 1 thread with behavior implemented in Background class. Next you enter while loop to capture user inputs. The Background thread works in background...
private class Background implements Runnable {
private long startTime;
private long time;
private boolean halfWarning;
private Background(long startTime, long time) {
this.startTime = startTime;
this.time = time;
}
#Override
public void run() {
while (true) {
long now = System.currentTimeMillis() / 1000;
long elapsed = now - startTime;
if (elapsed >= (time / 2) && !halfWarning) {
message("\n Half of your time is gone! Only " + (time / 2) + " seconds remains!");
halfWarning = true;
}
if (elapsed >= time) {
message("\n Oops! Time is up - try again.");
System.exit(0);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
//ignore
}
}
}
}
Use a ScheduledExecutorService to execute concurrent actions in the future:
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<?> half = ses.schedule(new Runnable() {
#Override
public void run() {
System.out.println("Half of your time is gone!");
}
}, time / 2, TimeUnit.SECONDS);
ScheduledFuture<?> full = ses.schedule(new Runnable() {
#Override
public void run() {
System.out.println("Oops! Time is up - try again.");
// System.exit(0) ?
}
}, time, TimeUnit.SECONDS);
// check
if (input == toGuess) {
half.cancel();
full.cancel();
}
You could have a Timer thread that prints out these messages and shuts down the listening program.
It might inspire you :
public static class Game extends TimerTask {
private long start;
private long end;
public Game(long end) {
super();
this.start = System.currentTimeMillis();
this.end = end;
}
#Override
public void run() {
while (System.currentTimeMillis() - start < end)
System.out.println(System.currentTimeMillis());
}
}
public static void main(String[] args) {
TimerTask task = new Game(10000);
Timer timer = new Timer();
timer.schedule(task,0);
}
I was just wondering for a quick question, what do you put in for delta exactly. The parameter double delta is (as the developer stated, in seconds of logic updates). If I wanted the loop to run 20 times a second, would I have it set to .2 or something like that? I am a bit confused on the logic updates (in seconds) part.
Anyways if you want to check any more of the game loops provided then check out the page here http://entropyinteractive.com/2011/02/game-engine-design-the-game-loop/
public abstract class GameLoop
{
private boolean runFlag = false;
/**
* Begin the game loop
* #param delta time between logic updates (in seconds)
*/
public void run(double delta)
{
runFlag = true;
startup();
// convert the time to seconds
double nextTime = (double)System.nanoTime() / 1000000000.0;
while(runFlag)
{
// convert the time to seconds
double currTime = (double)System.nanoTime() / 1000000000.0;
if(currTime >= nextTime)
{
// assign the time for the next update
nextTime += delta;
update();
draw();
}
else
{
// calculate the time to sleep
int sleepTime = (int)(1000.0 * (nextTime - currTime));
// sanity check
if(sleepTime > 0)
{
// sleep until the next update
try
{
Thread.sleep(sleepTime);
}
catch(InterruptedException e)
{
// do nothing
}
}
}
}
shutdown();
}
public void stop()
{
runFlag = false;
}
public abstract void startup();
public abstract void shutdown();
public abstract void update();
public abstract void draw();
}
You input the time in milliseconds that a single logic-loop should be based on.
If you want 20 times per second then 1/20 second is the number which is not 0.2 but 0.05.
You can write it more intuitively (IMO) by writing "1.0 / 20" then you don't have to convert back and forth and can just replace 20 with the frequency.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I found this stopwatch java code from somewhere on the Internet, but it does not seem to be working. I was wondering how to fix this code to make it work. It's supposed to have features to start, stop and reset, and should display the time as hours:minutes:seconds.milliseconds (example: 12:35:17.26). Please help me.
public class StopWatch {
private long startTime = 0;
private long stopTime = 0;
private boolean running = false;
public void start() {
this.startTime = System.currentTimeMillis();
this.running = true;
}
public void stop() {
this.stopTime = System.currentTimeMillis();
this.running = false;
}
//elaspsed time in milliseconds
public long getElapsedTime() {
long elapsed;
if (running) {
elapsed = (System.currentTimeMillis() - startTime);
}
else {
elapsed = (stopTime - startTime);
}
return elapsed;
}
//elaspsed time in seconds
public long getElapsedTimeSecs() {
long elapsed;
if (running) {
elapsed = ((System.currentTimeMillis() - startTime) / 1000);
}
else {
elapsed = ((stopTime - startTime) / 1000);
}
return elapsed;
}
//sample usage
public static void main(String[] args) {
StopWatch s = new StopWatch();
s.start();
//code you want to time goes here
s.stop();
System.out.println("elapsed time in milliseconds: " + s.getElapsedTime());
}
}
This example shows how to start and stop a javax.swing.Timer. Several approaches to formatting are shown here. Reset is left as an exercise.
By the level of your assignment, sounds like your professor wants you to use nested loops, which are not being used in the example you took from the web.
I won't give you the full answer, but it's fairly simple: outer-most loop is for hours, the one inside hours is for minutes, the one inside minutes for seconds, and the one inside seconds for milliseconds. The inner-most loop (milliseconds), is the one that prints the current time.
Something like this:
// 24 hours in a day
for(int hours = 0; hours < 24; hours++)
{
// 60 mins in an hours
for(int minutes = 0; minutes < 60; minutes++)
{
// 60 secs in a min
for(int seconds = 0; seconds < 60; seconds++)
{
// 1000 ms in a sec.
for(int ms = 0; ms < 1000; ms++)
{
System.out.println(hours + ":" + minutes + ":" + seconds + "." + ms);
}
}
}
}
Now make it pretty and add a 1-millisecond delay in the inner-most loop and you are done! :)
If you want to make a stopwatch you must make a Thread. The Java API states all of the functions of a thread. This is necessary, because otherwise you won't be able to pause the timer. This is because the system spends the full runtime on the counting.
Also, the script you provided is used for determining the amount of time a certain calculation took, it's not ment for timing itself.
I suggest you make 2 classes, 1 for the timer and 1 for the GUI. make the GUI with a label, a start-, stop- and reset-button.
Next, make sure the timer-class EXTENDS THREAD (or implements Runnable) and make it a thread. Next implement the functions to either stop the thread or start the thread (your start/stop buttons). The Reset should be easy after that (just set the timer back to 0).
The StopWatch-class could look like this:
public class Stopwatch extends Thread
{
private long startTime;
private boolean started;
public void startThread()
{
this.startTime = System.currentTimeMillis();
this.started = true;
this.start();
}
public void run()
{
while (started)
{
// empty code since currentTimeMillis increases by itself
}
}
public int[] getTime()
{
long milliTime = System.currentTimeMillis() - this.startTime;
int[] out = new int[]{0, 0, 0, 0};
out[0] = (int)(milliTime / 3600000 );
out[1] = (int)(milliTime / 60000 ) % 60;
out[2] = (int)(milliTime / 1000 ) % 60;
out[3] = (int)(milliTime) % 1000;
return out;
}
public void stopThread()
{
this.started = false;
}
}
In the GUI-class you would make start call the 'startThread', stop call the StopWatch.stop(); (which is a Thread-function) and make reset call the reset().
This should get you started with a basic stopwatch. A (bad) example for its useage:
public static void main(String[] args) throws InterruptedException
{
Stopwatch s = new Stopwatch();
s.startThread();
while (true)
{
int[] curTime = s.getTime();
System.out.println(curTime[0] + " : " + curTime[1] + " : " + curTime[2] + " : " + curTime[3]);
}
}
It would actually be more sensible to do the calculations on the currentTimeMillis outside of the threadclass.