As the question says, here's the code.
What I want to do basically is I have a list of array, says "myArray". This array contains stored time points in millisecond. Next thing is I want to call a method based on those time points. So, I need to run a time counter from 0 while the music is playing, compare the time counter with the time points in the array progressively (from first array index until finished).
The first method "timeCounter" is a method to start a time counter while a music is playing through MediaPlayer.
public void timeCounter(){
Runnable myRunnable = new Runnable(){
#Override
public void run(){
while(musicPlaying){
startCounter(arrayPos);
}
}
};
Thread musicPlayer = new Thread(myRunnable);
musicPlayer.start();
}
This is where the comparison of time counter and time in the array takes place.
public void startCounter(List<Long> array){
elapsedTime = System.currentTimeMillis() - timeStart;
if(elapsedTime == array.get(arrayPos)){
arrayPos += 1; //Continue comparing with the next number in the array
Log.v("DEBUG", "TIME MATCHES!");
if(arrayPos>= array.size()){
arrayPos= 0; //Prevent out of array index
}
}
}
I have the code running correctly and the result from the LogCat is correct.
Now the problem is sometimes the Thread is not running until the music finished playing (I have set onCompletionListener and set "musicPlaying" to false when music finished). The stopping point is totally random, sometimes when it's just started, or around 50%, or even when it's near to completion. Sometimes it doesn't even start!
I've been trying to figure out why but I couldn't find any info about Thread stopping halfway or such in anywhere. Thanks in advance! =)
If musicPlaying is modified and read between threads, make sure it is declared volatile.
I suspect your if(elapsedTime == array.get(arrayPos)) should be if(elapsedTime >= array.get(arrayPos)).
You need to remember that the millisecond timer does not necessarily have a one millisecond tick. On Windows, for example, the returned value will only change every 15 ms or so. You may therefore completely miss a particular time and therefore never get past that entry in your list.
Related
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.
I'm new to java and I'm trying to constantly add "zombie" entity to my game after a delay, and then shortening the delay as time goes on.
In my PlayState class I've got the code to spawn the entities in a position when my update(); method is run (which houses getInput(); and such. Not shown for clarity.)
public void update(long elapsed) {
this.entities.add(new Zombie(-535));
}
How would i make a delay that shortens? I'm guessing I would make the delay and then use a multiplier which i have getting smaller every 10 seconds or so, but how would I do this?
Now, I don't know much about the finer workings of your class, but this might give you a general idea of what I mean:
int counter = 50;
for(int i = 100; i >= 0; i--)
{
if(i == counter)
{
counter = counter / 2;
this.entities.add(new Zombie(-535));
}
}
Suppose i is the the total run-time of the game, and counter represents a percent of the game when you want to add a zombie.
If you want to add a zombie after 50% of the run-time (here, 100 seconds), then as the time reduces, you check if the time has come to add a zombie (Here, 50 seconds).
What I've done here is reduce the delay to half, and continue checking if the time has come to add a zombie.
Maybe you could call sleep on your thread of execution:
int sleepInMs = 5000
Thread.sleep(sleepInMs);
sleepInMs+=1000; //Then of course handle the case when sleepInMs == 0
Really need more information about your implementation.
For a simple delay, use "delay ms;"
Edit ms for the number of milliseconds you want. 1000 milliseconds is one second
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);
}
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.
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)