Game timer won't stop - java

I am trying to set a timer to randomly set the frame in the screen, but then, depending on the boolean, set it back to normal. I have already tried .cancel() but it doesn't work. How could I stop this timer?:
if(e.getSource()==impossible){
impossiblity=!impossiblity;
System.out.println(impossiblity);
if(!impossiblity){
new Timer().schedule(new TimerTask() {
public void run() {
int randWidth=(int)((dim.width-gameFrame.getSize().width) * Math.random());
int randHeight=(int)((dim.height-gameFrame.getSize().height) * Math.random());
gameFrame.setLocation(randWidth, randHeight);//sets location to center
}
}, 1000, 1000);
} else gameFrame.setLocation(dim.width/2-gameFrame.getSize().width/2, 0);//sets Location to center of screen
}
right now it does set the gameframe back to normal but then goes right back to randomizing

In general trying to cancel timers or other threads from outside the thread is a bad idea and leads to all sorts of problems.
Your best bet is to set some sort of flag or counter that the TimerTask checks when it comes to run.

Related

Using Timer to repaint in the fixed time then continuing calculation

Currently, I am making a Java program for graph visualization Prim's algorithm in finding minimum spanning tree.
Here is the image of my program's output
while(condition){
//Find the min vertex and min edges
Vertex vertex = findMinVertex();
Edge[] edges = findMinEdges();
//Then, for each vertex and edges I found, I will change the color of
//them and pause the program for 3 seconds, so user can see how
//algorithm works.
repaintAndPause(3000);
}
.
.
private void repaintAndPause(int time){
long start = System.currentTimeMillis();
long end = start + speed;
//Here is the timer for repainting.
Timer timer = new Timer(speed, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e){
GraphPanel.this.repaint();
}
});
timer.setRepeats(false);
timer.setDelay(0);
timer.start();
//And here is for pausing the program, a while loop without any commands.
while(System.currentTimeMillis() < end){}
}
However, I don't know why but the program doesn't work. Yes, there are the pauses of program but, all the edges and vertices are just changed the color at the end of program. They aren't changed every 3 seconds.
Could someone please tell me where I did wrong?
Thank you and hope you have a nice day!
Could someone please tell me where I did wrong?
Yes. You are putting a busy-loop in the Event Dispatching Thread.
while(System.currentTimeMillis() < end){}
You code reads:
do some calculation (busy)
when done, post a "repaint" message, to redraw the panel when not busy
continue being very busy doing nothing for 3 seconds
continue being busy by repeating steps 1 through 4.
The Event Dispatching Thread never finishes processing the first "event" until the end of the algorithm, after the while (condition) loop finally finishes.
You want:
Timer timer = new Timer(speed, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
/* Code to perform one step of Prim's algorithm here */
/* Change edge/vertex colour for step */
/* Call timer.stop(), once done */
GraphPanel.this.repaint();
}
});
timer.setRepeats(true);
timer.setDelay(3000);
timer.start();
On every tick of the timer (once every 3 seconds), one step of the algorithm is performed.
Note this means that each step of the algorithm must run with any partial results stored into class members, so the the next step will be able to retrieve all the information it needs to continue. Stack variables can only be used inside one step; they cannot be used to hold inter-step values.
You could rework the algorithm to use a SwingWorker to run the calculation in its own background thread, and publish intermediate results when computed. The EDT could then repaint as intermediate results are produced. With a Thread#sleep() call, this background thread could delay production of intermediate results to once per 3 seconds.
Alternately, you could run the algorithm, and store multiple copies of the output, once for each 'step'. Then your Panel timer could simply show the output of the next step.

java game programing enemy explosion

hi i am creating a small game as a project.
the game resembles chicken invader.
the game is run by a gameLoop which constantly calls the render(Graphics g) method to paint changes and the tick() method that changes the x,y coordinates of all moving objects.
i have attempted to make my chickens expload on impact (change their picture to an exploasion)..
my problem is the change happens so fast the user cannot see it.
i have attempted to use the following:
timer.schedule(new TimerTask() {
#Override
public void run() {
int temp = deleteExploasion;
exploasions.get(temp).setExplosion(false);
deleteExploasion++;
}
}, /*2*60*1000*/ 1500);
it sets a boolean on the chicken and in 1.5 seconds the chicken should in the next render method be painted back.
but i keep getting
Timer already cancelled.
at java.util.Timer.sched(Unknown Source)
and
Exception in thread "Timer-0" java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.LinkedList.checkElementIndex(Unknown Source)
would appreciate help or advice on how to implement such a thing.
Since you are already using a tick() method to update the game you should also use it to handle your timer.
Create an int called delay or timer or something and reduce it in the tick() method then check if the timer is done and call your explosion or remove method.
ok i have managed to solve this problem
i used this:
if(deleteExploasion == 0){
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
exploasions = new LinkedList<Chicken>();
}
}, 2000, 2000);
deleteExploasion++;
}
basicly i deleted the chickens.
then i created exploasions LinkedList containing all the explosions (Images with x,y)
and i start the time cycle once and reset it every few seconds.
thanks alot for help
and as was mentioned here this method is indeed in the render() method
(just like tick() it is also called constantly).
if anyone sees a problem with my implementation would appriciate a comment.

How to make my game stop after ten seconds in libgdx?

I'm almost done with my project to make a very simple game. The point of the game is to count how many times the user touches the screen and compare it to the number of times an object popped up on the screen to be touched. It's considered a win if number of touches = number of objects. All of this is to happen in 10 seconds, and I have no idea where to start on how to time the game? (It's supposed to be a veryyy very simple game just to learn how to use libgdx)
As of now, there's a start screen that the user touches to start and then the game starts where objects pop up to be touched. The problem is that it's basically an endless game right now... Here's how I make an object "randomly pop up":
if (Gdx.input.isTouched()) {
touchCount++;
Vector3 touchPos = new Vector3();
touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touchPos);
visual.x = MathUtils.random(10, 700);
visual.y = MathUtils.random(100, 400);
}
Do I have to put some built in timer function in this part of the code? And how to I go about tracking the touches to compare with the number of objects that popped up?
Thanks, any advice would be very appreciated!
System.currentTimeMillis() gives you current time in milliseconds
For example you can do something like this
private long time;
public void show(){
//...
time = System.currentTimeMillis();
}
public void draw(){
//...
if(System.currentTimeMillis()>time+10000){
System.out.println("after 10 seconds");
}
}
You may use old fashioned java way either:
Timer timer = new java.util.Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
// Pause your game or just close it...
Gdx.app.exit();
}
}, 10000L);
Of course it's better to use synchronous timer approach, but for fast debuging or prototyping needs its sometimes more convenient.
Use the delta value inside your render() method.
render(float delta){
// ......
if (yeni_oyun_mesaji_var_MI)// a boolean value to increment my time value only it is needed.
oyun_uyari_zamani_tutucu += delta;
if (oyun_uyari_zamani_tutucu > oyun_uyari_zaman_siniri) {// after some time (**oyun_uyari_zaman_siniri**) do what you need
oyun_uyari_zamani_tutucu = 0f;
oyun_durum_mesaji_str = "";
yeni_oyun_mesaji_var_MI = false;
Gdx.app.log(TAG, "Uyarı Kapatıldı!");
}
}

How can I create a JUnit test that runs until a certain condition is met?

I have a simple java snake game. I'm trying to test what happens when I press a lot of keys in a short interval.
Snake is my frame and Board is the JPanel where everything happens.
boolean stop=false;
Snake snake= new Snake();
KeyEvent key_right = new KeyEvent(snake.board, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0, KeyEvent.VK_RIGHT,'Z');
KeyEvent key_up = new KeyEvent(snake.board, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0, KeyEvent.VK_UP,'Z');
KeyEvent key_down = new KeyEvent(snake.board, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0, KeyEvent.VK_DOWN,'Z');
KeyEvent key_left = new KeyEvent(snake.board, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0, KeyEvent.VK_LEFT,'Z');
KeyEvent vect[]={key_right,key_down,key_left,key_up};
int i=0,nr=0;
Timer timer = new Timer();
#Test
public void StresTaste() {
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if(!stop){
snake.board.getKeyListeners()[0].keyPressed(vect[i]);
System.out.println(nr);
i++;nr++;
if(i==3) i=0;
if(nr==200){stop=true;}
}
}
}, 1, 1);
}
I create an array of keyEvents and loop over it using the i variable. I pass them to the keyListener of the JPanel.
Everything works fine.. but it stops at something over one hundred...not the same value everytime.
Please help. Is this even possible to implement?
A timer is a daemon thread, i.e. when one of them is around, that won't stop the VM from stopping.
So what happens is that you start the tests, create the timer and then stop the VM (because there are no more JUnit tests). The timer gets to process a couple of times but eventually, the termination of the VM kills it.
The solution is to add a lock to your code:
final Object lock = new Object();
timer.scheduleAtFixedRate(new TimerTask() { ...
if(stop) { synchronized(lock) { lock.notify(); }} // let test know that we're done
});
synchronized(lock) { lock.wait(); } // wait for timer to finish
That said, it's probably futile to test how many keypresses your code can process per second. The hardware, OS and human hands put a limit of about 215 words per minute.
Most often, the code doesn't care how fast it's being called but how often (memory leaks). So you can probably change your code to just loop over the key sequence and simply call snake.board.getKeyListeners() without a background thread (which, incidentally, will also give you hundreds of thousands of invocations per second).

Making moving motion with labels using threads in java

I'm having a problem I'm making a pool game and I need the ballos to react when I simulate a hit, the program works like this, you click the direction and power to hit the ball and the click go, the go button is in the GUI class where my labels are created, the button calls a method from my main class that recieves the parameter and then with a while in it, changes the X and Y of the ball till the power is reduced to 0 and then stops, the code is working, but the ball moves until the while stops. So the while works and when the power int is 0 the while goes out and then the new X,Y are painted.
This is the funcion that the button calls, the button sends all the parameters
public void golpe(int pbola, int pvelocidad, String pdireccion, JLabel[] listalabels) throws InterruptedException{
listabolas[pbola].setVelocidad(pvelocidad);
listabolas[pbola].setDireccion(pdireccion);
while (listabolas[pbola].getVelocidad() > 0) {
moverBola(pbola, listalabels);
//System.out.println(listabolas[pbola].getPosX());
//System.out.println(listabolas[pbola].getPosY());
Thread.sleep(500);
//This line is supposed to change the X and Y of the object over and over
//but only does it till the end
listalabels[pbola].setLocation(listabolas[pbola].getPosX(), listabolas[pbola].getPosY());
}
}
Here is the function moverbola(), only copied one "if" so that the code doesn't look to big
private void moverBola(int pbola, JLabel[] listalabels) {
if (listabolas[pbola].getDireccion().equals("SE")) {
int pposX = listabolas[pbola].getPosX();
listabolas[pbola].setPosX(pposX + 1);
int pposY = listabolas[pbola].getPosY();
listabolas[pbola].setPosY(pposY + 1);
}
Swing is a single threaded framework. That is, all interactions with UI are expected to occur from within a single thread, known as the Event Dispatching Thread.
Any action that blocks this thread, will prevent the EDT from updating the screen or processing any new events.
Your while-loop is blocking the EDT, preventing it from painting any updates until after the while-loop is completed.
Take a look at Concurrency in Swing for more details.
There are a number of approaches you could take...
You could use a Thread, but this causes problems as you need to ensure that any changes you make to the UI are re-synced back to the EDT and this can become messy...
For example
You could use a javax.swing.Timer that ticks at a regular interval and you would update any internal parameters from within it's assigned ActionListener. Because the tick events occur within the EDT, it is save to update the screen from within it.
For example
You could use a SwingWorker to run the task in the background. It has methods for re-syncing updates back to the EDT, but might be a little over kill for your purposes...
Updated with a possible Timer example
Caveat- It is very hard to produce a reasonable example with only a code snippet, but, something like this might work
public void golpe(final int pbola, int pvelocidad, String pdireccion, final JLabel[] listalabels) throws InterruptedException{
listabolas[pbola].setVelocidad(pvelocidad);
listabolas[pbola].setDireccion(pdireccion);
Timer timer = new Timer(40, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (listabolas[pbola].getVelocidad() == 0) {
((Timer)evt.getSource()).stop();
} else {
moverBola(pbola, listalabels);
}
}
});
timer.setRepeats(true);
timer.start();
}

Categories