How am I messing up my Java timer? - java

This Morning Class is supposed to create a new Morning, and at the beginning of each a rooster will crow. My rooster will crow once, wait five seconds, and crow again.. Then 5 seconds later it crows twice, and after that it crows non-stop. What could I be doing that makes it do that? I just want it to crow every 5 seconds. If I put a timer.restart() in ActionPerformed, it does nothing. Could someone please point out or give me a tip to what I'm doing wrong? Any help would be much appreciated.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.Timer;
public class Morning extends JFrame
implements ActionListener
{
private EasySound rooster;
public Timer timer;
public Morning()
{
super("Morning");
EasySound rooster = new EasySound("roost.wav");
rooster.play();
timer = new Timer(5000, this);
timer.start();
Container c = getContentPane();
c.setBackground(Color.WHITE);
//page 35
}
public void actionPerformed(ActionEvent e)
{
Morning morning = new Morning();
}
public static void main(String[] args)
{
Morning morning = new Morning();
morning.setSize(300, 150);
morning.setDefaultCloseOperation(EXIT_ON_CLOSE);
morning.setVisible(true);
}
}

You don't have an infinite loop but rather infinite recursion (albeit on the slow side). Don't recurse here -- don't create a new Morning in your Timer's actionPerformed. Instead just put in the method to make the crow sound heard.
Next time, please put your code in your post itself (as I've done for you). Don't make us go to other sites since if you're asking for free help, you want to make it as easy as possible for others to help you.
Edit
You're also shadowing the rooster variable declaring it twice, once int he class which is null and once in the constructor which is not null. Don't redeclare it so you initialize the class field not a local field.
Change this:
public Morning()
{
super("Morning");
EasySound rooster = new EasySound("roost.wav"); // this creates a *local* variable only
rooster.play();
to this:
public Morning()
{
super("Morning");
// EasySound rooster = new EasySound("roost.wav");
rooster = new EasySound("roost.wav");
rooster.play();

Looks to me like you have an infinite loop. You create a new Morning, which starts the timer. When then timer goes off you create a new Morning, which starts the time, etc, etc, etc. Seems like you should be using just a single Morning object that keeps track of how many times it has crowed.
I would suggest setting the Timer to repeat, in actionPerformed crow the appropriate number of times based on how many times it has crowed, and stop the timer when you are crowing forever. This however, assumes that you want exactly 5 seconds between the start of the crows. If you need 5 seconds between the end of a crow and the start of the next, do not repeat but restart the time after you are done crowing.

Instead of instantiating the Morning class each time the timer fires, put the rooster.play() to it (also don't forget to make rooster a class field instead of a local variable). In the constructor, also make sure to call 'timer.setRepeats(true)'

Related

How to create a single thread cooldown

I'm finding the way to make a Single thread cooldown but get stuck.
In the class who manages the cooldown I created a:
private HashMap<UUID,Integer> players = new HashMap<>();
//UUID = Player UUID
//Integer = Time in cooldown (Seconds)
public void run(){
for(UUID player : players){
//WHAT I NEED TO DO HERE?
if(//Time == 0){
players.remove(player);
}
}
}
Didn't use an IDE hopefully I didn't miss an error that eclipse would have picked up.
But how I can get the integer and save it with a second less?
TimeUnit is used for delaying a process, as it could be used as followed:
TimeUnit.SECONDS.sleep(1);
This will delay the current thread by one second.
I won't suggest using it, because your situation sounds more like a thread is working in the background and you want to wait till it has finished! Therefore use the new feature isAlive, which could be used in a (while) loop.
Edit
If you do want to delay a thread from another thread over the instance, then I'd suggest using the sleep method.
Example:
myThread.sleep(1000);
This will delay myThread by one second.
Edit #2
To change a value for a certain key of a HashMap, use the put and get method.
Example:
// Get the time of a player and subtract it by one
Integer value = players.get(player) - 1;
// Update the value
players.put(player, value);
// If the time runs out, than delete the player
if (value == 0){
players.remove(player);
}

Java Timer not working. Calling Multiple Timers at Once

I started making a game using Java. I am currently working on a basic enemy that will fire in range and when it fires I want it to wait for x seconds and fire 3 bullets at a rate of y.
So I decided to use a Timer to create this delay:
public class DelayFire
{
Toolkit toolkit;
Timer timer;
//The enemy firing
Enemy com;
public DelayFire(double seconds, Enemy e, boolean un)
{
toolkit = Toolkit.getDefaultToolkit();
timer = new Timer();
com = e;
timer.schedule(new FireTask(un), (int) seconds * 1000);
}
class FireTask extends TimerTask
{
public boolean unfire = false;
public FireTask (boolean x)
{
this.unfire = x;
}
public void run()
{
if(com.health>0)
{
com.charging = false;
com.fire();
if(unfire==true)
{
com.fire = false;
com.canFire = true;
}
this.cancel();
}
}
}
}
Then which I call in Enemy class it 3 times each with a different delay:
void spray()
{
new DelayFire(2.0,this,false);
new DelayFire(2.5,this,false);
new DelayFire(3.0,this,true);
}
This void is called when ever the player is in firing range (This is also in the Enemy class):
if(canFire==true && fire==false)
{
spray();
canFire = false;
fire = true;
}
Yet after all this work it will only create two bullets once I'm within range. Until I leave and re-enter the enemy's sight again.
Note: I only put the parts of my code where I would expect some mistake is made. Let me know if you need to see more code.
Are you absolutely sure only two bullets are fired? You can try inserting System.out.println("Hello, Bullet World!") in the run() method of FireTask. You might be surprised to find that the line will print three times.
What you're experiencing is the associativity of casts. Consider this part of your code:
(int) seconds * 1000
Since seconds is a double, and you want an int (or perhaps a long), it's natural that you'll want to cast it. However, the cast does not cast the entire expression seconds * 1000 to an int - just seconds. Next, consider your instantiations of your DelayFire class:
new DelayFire(2.0,this,false);
new DelayFire(2.5,this,false);
new DelayFire(3.0,this,true);
Here, you use the double values 2.0, 2.5, and 3.0. However, the 2.5 is casted to an int before the multiplication, causing it to become a flat 2. As a result, your program will schedule two bullets to be fired after 2 seconds, and one bullet to be fired after 3 seconds.
To get around this problem, stick some parentheses around the entire expression with the multiplication in it:
(int) (seconds * 1000)
This should result in the correct behavior. There may be other bugs in your code, though. But try that first.
Edit: As a side note, the conditions in your if-statements are overcomplicated. You are basically turning a boolean-valued expression into another boolean-valued expression by writing if (unfire == true). Since unfire is a boolean expression, there is no need for the == operator. You can simply write if (unfire). And instead of checking if the value is false, use the unary !-operator to negate the expression, if (!unfire).

Thread.sleep(); in Java

Whenever I use Thread.sleep(); in a do while loop, the hints tell me, "Invoking Thread.sleep in loop can cause performance problems." I have heard this from many other websites and books. What is something I can use instead?
Here's the code:
import javax.swing.*;
public class Delay {
public static void main(String[] args) throws Exception {
int difficulty;
difficulty = Integer.parseInt(JOptionPane
.showInputDialog("How good are you?\n" + "1 = evil genius...\n"
+ "10 = evil, but not a genius"));
boolean cont;
do {
cont = false;
System.out.println("12");
Thread.sleep(500);
String again = JOptionPane.showInputDialog("Play Again?");
if (again.equals("yes"))
cont = true;
} while (cont);
}
}
Try java.util.Timer and/or javax.swing.Timer. Play with them a bit, set initial delay, repetition period, etc. See what suits your needs.
Be sure to check differences between these two timers, for starters take a look at this question: Why are there two Timer classes in Java(one under javax.swing, one under java.util )?
Then try ScheduledExecutorService, as already suggested by #BoristheSpider.
Using Thread.sleep to do polling or similar update mechanism is ok approach. It's reasonable for instance if you want to repaint a canvas every 5 milliseconds, then you would use sleep(5). You could also use a hardware timer which will be more exact and relieve the CPU, but the usual approach is exactly Thread.sleep.

Processing P5 - Timer issue with millis()

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.

Problem related to variable persistence between threads in java

all. A thread in a Java program I am working on animates a random walk in space (or at least, it will once this problem is resolved). It contains the following two methods:
public void run() {
while(gw.checkBoundingBox()) {
if(!gw.pause) step();
}
}
public void step() {
Point3d p1, p2;
//get the last point, step, get the new point
p1 = new Point3d(gw.position);
gw.randomStep();
p2 = new Point3d(gw.position);
//create the Alpha that will do the animation, and wrap it in an AlphaControl,
//which will set this object's pause flag until the Alpha finishes
Alpha alpha = new Alpha();
alpha.setLoopCount(1);
if(alpha.finished()) System.out.println("DEBUG: I'm already dead.");
AlphaControl ac = new AlphaControl(alpha,gw);
ac.start();
//create a piece of the path, attach an interpolator to do the animation
PathCyl cyl = new PathCyl(p1,p2);
StretchInterpolator si = new StretchInterpolator(alpha, cyl.anchor);
si.setSchedulingBounds(new BoundingSphere(new Point3d(0,0,0),50));
cyl.anchor.addChild(si);
//put it all together
BranchGroup b = new BranchGroup();
b.addChild(cyl.tg);
trans.addChild(b);
}
So if the pause flag is not set, it runs step(). The only part of step() that you need to look at is the few lines about the Alpha object. (Alpha is an API class that produces a time-dependent function used for animating). So step() creates an Alpha object, which it then feeds to another thread called AlphaControl. AlphaControl tells the program to stop calculating points until this step is done animating. It does this by setting the pause flag that is checked in the run() method.
So what's the problem? Note that I added a debug line that immediately checks if the Alpha is finished after it is created. It seems like this line of code should never execute. Is the Alpha finished? Of course not, we just created it. But this line executes every time that the function is called AFTER the first time. Somehow it is hanging onto the same Alpha instance and using it over and over. I assume that this is because of the reference to the Alpha that is still alive in the AlphaControl thread.
So how do I fix this? I have tried several things. I created a huge array of Alphas, initialized them all before the walk even started, and tried to tell it to use a different alpha from the array at every step, but this had the same result. I also tried using the AlphaControl to set alpha to null before it closes, but this didn't work either. Is it possible to destroy this object? By the time the step() code gets back to running again, the AlphaControl that was created the first time around should be done and waiting for garbage collection.
Also, just in case it would be helpful to see it, here is the AlphaControl class.
public class AlphaControl extends Thread {
public Alpha alpha;
public GraphicalWalker gw;
public AlphaControl(GraphicalWalker gw, Alpha alpha) {
this.gw = gw;
this.alpha = alpha;
}
public void run() {
boolean stop = false;
boolean finished;
while(!stop) {
finished = alpha.finished();
if( !finished && !gw.pause ) gw.pause = true;
if( finished && gw.pause ) gw.pause = false;
if(finished) stop = true;
}
}
}
Thanks in advance for any help.
Jeff
I think key to understanding why your code fails is understanding what the Alpha class of the Java3D library does.
From your question it seems to me you do not understand it correctly. It does not loop. If you check the source code (http://www.java2s.com/Open-Source/Java/6.0-JDK-Modules/java-3d/javax/media/j3d/Alpha.java.htm) you will see it does not contain a single loop structure. What it does do, is define a function that maps a time value to a value in the range [0,1].
If you look at the source of the finished() method :
/**
* Query to test if this alpha object is past its activity window,
* that is, if it has finished looping.
* #return true if no longer looping, false otherwise
*/
public boolean finished() {
long currentTime = paused ? pauseTime : J3dClock.currentTimeMillis();
return ((loopCount != -1) &&
((float)(currentTime - startTime) * .001f > stopTime));
}
you notice that its value depends on when it is called.
And since you basically defined your alpha to have 1 loop of 1 millisecond, starting from the time of creation it will not be finished for 1 millisecond after you create that alpha, and finished ever after.
I hope this helps.
I'm not sure if I completely follow the intent of the program, but it seems like you have a race condition. When you call ac.start() on your AlphaControl object, there is no guarantee that gw.pause will be set prior to the next round of your loop executing. In fact, there's a fair chance that the loop will execute many times prior to gw.pause getting set.
Just for kicks, I suggest calling ac.run() instead of ac.start() on a run-through, as a shortcut to take threading out of the picture. If the intended behavior occurs, then I would look hard at your reason for doing this in multiple threads instead of a single one.
I think the problem is one of two issues:
Alpha's state is kept as a static variable, meaning that it's the same for all instances of Alpha, and you're likely not resetting it in the constructor (rightfully so).
Some part of your state isn't marked volatile, which breaks the semantics the compiler relies on to know that a marked field will always require a fresh value lookup (otherwise the compiler is free to cache the value)

Categories