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.
Related
I have a simple game where a player shoots some bullets. However, I want to make it so that the player can only shoot a bullet every x seconds. How would I do this?
I have tried to do it by taking the average time between bullets and saying that if average time is less than one second don't let the space bar (the control for shooting) work. However, I don't know how to make the space bar not work, AND that would mean a player could just not shoot for a wile and then shoot a lot of bullets at once.
The method for shooting looks something like this:
public void keyPressed(KeyEvent e) {
if (!keysDown.contains(e.getKeyCode()))
keysDown.add(new Integer(e.getKeyCode()));
This adds the integer of the key value to an array, which is then read here:
if (keysDown.contains(KeyEvent.VK_SPACE)) {
b = new Bullets(x);
bullCount.add(b);
System.out.println(bullCount.get(0).getY());
System.out.println ("There are " + bullCount.size() + "bullets alive.");
//elapsed = System.nanoTime() - start;
//if ((elapsed / bulletCount) < 1000000000) {
//this is where I would say 'no more bullets shot until
//average time in nanoseconds is more than 1 second!' but I don't know how
//}
Make a global variable ie: long lastShot.
When user shot, check if (System.currentTimeMilis()-lastShot>5000) before you allow him to shoot.
If it is ok to shoot, store the lastShot = System.currentTimeMilis(); and do the real shot. If not, don't allow him to shoot.
Here is an example in pseudo-code:
class SomeClass {
private long lastShot;
public void userPressedShot() {
if (System.currentTimeMillis()-lastShot>5000) {
lastShot = System.currentTimeMillis();
doTheRealShot();
}
// Ignored till 5000 miliseconds from last shot
}
}
One overkill option is to use the Guava's RateLimiter
final RateLimiter rateLimiter = RateLimiter.create(2.0); // rate is "2 permits per second"
while(true) {
rateLimiter.acquire();
shootSomething();
}
For this solution I assume that you use a Player Object.
It's very simple:
1.: add the field lastShot of the type long with the value 0 to your class.
2.: Whenever the player shoots, set lastShot to System.currentTimeMillis()
3.: Now, before you let him shoot, check if System.currentTimeMillis()-lastShot is smaller than your bullet delay in seconds.
This would be a MWE which has to be inserted in your player class:
Just call the Method player.shoot() to let him shoot - or not, if it's not possible.
private long lastShot = 0;
//return value is for you to check if the shot happened
public boolean shoot(){
//Did the last shot happen less than 1 second (1000 milliseconds) ago
if(System.currentTimeMillis()-lastShot <= 1000){
//If yes: return false, the shot can not happen
return false;
}else{
lastShot = System.currentTimeMillis();
//If no: insert your shooting code here to be executed
//return true, the shot happened
return true;
}
}
Try using a timer that resets every second the bullets count :
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
bullCount.clear();
}
}, 0, 1000); // 0 is the delay in milliseconds before it starts and 1000 is the time in milliseconds between successive task executions
Then when a player wants to shoot you just have to look at bullCount's size
I'm making fast forward button in my Mp3 player. I wrote already code for this, but have problem how to implement timer to jump 5% forward? I mean when I press button timer should jump 5% forward of total long song. This is my fastForward method.
public void FastForward(){
try {
//songTotalLength = fis.available();
fis.skip((long) ((songTotalLength * 0.05)));
} catch (IOException e) {
e.printStackTrace();
}
}
And here is the button method:
private void jButton3ActionPerformed(ActionEvent e) {
mp3.FastForward();
if(mp3.player.isComplete()){
bar = 100;
}
jProgressBar1.setValue((int)bar);
bar+=5;
}
And this one is for timer:
private void setTime(float t) {
int mili = (int) (t / 1000);
int sec = (mili / 1000) % 60;
int min = (mili / 1000) / 60;
start.set(Calendar.MINUTE, 0);
start.set(Calendar.SECOND, 0);
end.set(Calendar.MINUTE, 0 + min);
end.set(Calendar.SECOND, 0 + sec);
timer = new javax.swing.Timer(1000, new TimerListener());
percent = (float)100/(min*60+sec);
}
You're already redundantly tracking progress in two variables fis and bar. For the sake of good design, use one of those to determine elapsed time rather than using yet another variable for the same purpose.
but have problem how to implement timer to jump 5% forward?
You seem to have mistaken the purpose of a Timer. According to the Timer class documentation, it:
Fires one or more ActionEvents at specified intervals.
So the timer is not meant to keep track of how much time has elapsed. It will simply invoke the actionPerformed(ActionEvent) method of your TimerListener once per second (every 1000 milliseconds) as you have it configured.
For a more complete answer, please post the code for your TimerListener class.
Notes
It seems that your setTime(float) method is meant to be called repeatedly, so this method should not be initializing the timer variable. Rather initialize the timer once and leave it alone to do its job.
I'm assuming you intended the supplied float parameter t to represent microseconds.
The float data type has only 7 digits of precision. This could be fine since you're interested only in minutes and seconds, otherwise float is only good for up to about four months of seconds before losing accuracy.
It seems like you wanted your button click handler to do this (increment bar sooner):
private void jButton3ActionPerformed(ActionEvent e) {
mp3.FastForward();
bar+=5; // increment bar before checking complete, and before setting progress
if(mp3.player.isComplete()){
bar = 100;
}
jProgressBar1.setValue((int)bar);
}
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've looked everywhere for an answer but cannot find one for my situation. I have a couple problems and also wonder how to include millisecond countdown as well. I'm trying to get a countdown timer in the format 00.00 (seconds.milliseconds). A button is used to start the timer. The times I use depend on the button pressed, 5, 10, 15, 30, or 90 seconds. I'll just says its hard coded to 5000 ms to make simpler for now.
long timeSecs = 5000; // really timeSecs is dynamic but for the sake of simplicity
long countDownInterval = 1000; // this is a static value
TextView TVcountDown = (TextView)findViewById(R.id.TVcountDown);
public void createTimer() {
new CountDownTimer(timeSecs, countDownInterval) {
public void onTick(long millisUntilFinished) {
TVcountDown.setText(millisUntilFinished / 1000); // error here on
//.setText unless I cast to an int, which all values are long so I'm not sure why
}
#Override
public void onFinish() {
TVcountDown.setBackgroundColor(R.color.solid_red); // error here
TVcountDown.setTextColor(R.color.white); // error here
TVcountDown.setText("Expired"); // it will make it here
// It doesn't count down, just goes straight to onFinish() and displays "Expired"
}
}.start();
}
Thanks in advance. I've been beating my head against the desk for awhile now.
Try this.
For setText
TVcountDown.setText("" + (millisUntilFinished / 1000));
For the color
Resources res = getResources();
TVcountDown.setBackgroundColor(res.getcolor(R.color.solid_red));
TVcountDown.setTextColor(res.getcolor(R.color.white));
you should get color from the color resource before setting.
In android if a button is clicked i want a countdown to start from 30 and countdown to 0. I created a code with a basic countdown method but the problem is it doesn't continue to countdown if the activity or application closes.
What i want to do is for the activity or just the countdown to continue ticking down in the background until it hits 0 in which it'll change variable B to the value of 1.
I have expanded from my original model thinking i could compare dates times from when the button was clicked + 30 seconds to when the activity is called up upon again. But so far i have come to a stump in comparing two datetimes in android.
Any help?
What you likely want is an async task to run in the background. Something like:
private class JohnnysPollTask extends AsyncTask<Integer, Void, Integer> {
/**
* The system calls this to perform work in a worker thread and delivers
* it the parameters given to AsyncTask.execute()
*/
protected Integer doInBackground(Integer... millis) {
try {
int waited = 0;
int duration = 30000;
while (waited < duration) {
Thread.sleep(1000);
waited += 1000;
if (waited>=duration) {
b=1;
break;
}
}
} catch (InterruptedException e) {
// do nothing
}
return 1;
}
Implement CountDownTimer
inside service.
You could try using a service instead of an activity.