Pausing Multiple Threads

Hello. First I’m sorry if my english sounds weird. I’m creating a small animation. There are multiple balls “bouncing” on Frame and if any of them hits a placed special ball, it will grow big and become another special ball (which means any of the rest ball can be special too by hitting any of two special things and repeat again). However a special ball’s lifespan is only 3 seconds. The Ball class extends Thread so it can call sleep(3000) and vanished after done. Ball isn’t the main class.

class Ball extends Thread{
public void run(){
			try{
				size = 100;
				isSpecial = true;
				this.sleep(3000);
				isDone = true; //tell main class to remove this "ball"
			}
			catch (InterruptedException e){
				System.err.println(e);
			}
		}
}

The main class puts every balls in an ArrayList. Main class uses Gudradrain’s template. Now I want to include Pause feature. When paused the canvas will draw another image and doesnt call update() method. The problem is the sleep(3000) on every ball is still counting so when we back to the animation, all special balls suddenly disappear. How to make all special balls sleep only on non-paused state? in other word, pause the ball’s sleep when enter pause state.

Thanks :smiley:

Don’t use threads for this type of thing.
To use the template you linked to, create another class that extends his Game class and overwrite the update and render functions with empty functions.

Then create your ball class and just give it 2 functions to start off with update(int) and render(Graphics2D).

Now create the ArrayList or whatever collection you want to use of Balls like you already do, possibly in your game class constructor.

Now fill in the update and render functions in your game class with a loop that iterates over the array of balls and calls the appropriate function.

Now to add pause just put the update loop in a conditional block.
It should look something like


protected void update(int deltaTime){
  if( !paused ){
    for(Ball ball: balls)
      ball.update(deltaTime);
  }
}

my current code goes like that with update() method updating position of the ball then checking for collision where if yes, start the 3seconds countdown and vanished. if no, nothing happen (still ‘common’ ball bouncing and waitting chance to hit the special). can you please give example code how the ball class wait for 3seconds before vanished but, that wait can be paused and resumed?

the rest as Game class and render() are already same approach like you said :smiley:

One way to have the ball vanish 3seconds after it is hit is to add a boolean and an int to the Ball class. Name the boolean something like fadeOut and the int fadeTimer.

Add some functions to the ball like this:


private final int THREE_SECONDS = 3000;

public void fade(){
  fadeOut = true;
  fadeTimer = THREE_SECONDS;
}

protected void update(int delta){
  if( fadeOut ){
    fadeTimer -= delta;
    alive = fadeTimer > 0;
  }
}

protected void render(Graphics2D g){
  if( !alive )
    return;
  // draw as normal
}

Because update isn’t called when the game is paused, the ball doesn’t fade while paused.

@zoto:
so I just need to call fade() when the collision is detected and let the update() method to start counting down by decrement. But in my sight, delta is always changing depends on how long time needed to update, sleep and render (based on template). how about the accuracy so it can vanish on exactly 3scnds?

anyway thanks for above solution. I try it :slight_smile:


Might be a good place to use a Timer to run the gameloop. Or, build in some controls to the gameloop so that the loop time remains steady.

Ah…in that case then my suggestions on using the Timer are moot.

[quote]so I just need to call fade() when the collision is detected and let the update() method to start counting down by decrement.
[/quote]
Yes, you also might want to check fadeOut in your collision detection so you can ignore fading circles.

[quote]But in my sight, delta is always changing depends on how long time needed to update, sleep and render (based on template). how about the accuracy so it can vanish on exactly 3scnds?
[/quote]
The delta variable is how many milliseconds have passed since the last update.
The counter will go a few milliseconds over 3 seconds depending how well the game is running, probably safe to ignore.

[quote]The delta variable is how many milliseconds have passed since the last update.
The counter will go a few milliseconds over 3 seconds depending how well the game is running, probably safe to ignore.
[/quote]
On small amount of balls it can be ignored but when I tried with 100 balls even I could sense the difference of fading time from 3scnds :slight_smile: it can be fixed if I turn off the AA (less update time) but player also can trigger this AA so time of update can be changed anytime. Should I remove this AA although the circles will look rough? :expressionless:

When on applet (java webstart), if the page lose focus (user see other window or tab), do all threads from the applet get paused automaticly or not?

That sounds promising. Just a guess because I can’t see your code but is your ball draw function just drawing an image or are you using Graphics2D.draw* or Graphics2D.fill*?
If you are not using an image I would advise you switch to either loading an image or draw it once in your code and reuse it.

The program jvisualvm comes with java and is very useful for debugging performance issues.

No code run on the client is safe from tampering.

I wouldn’t give up so fast, figure out what you want the computer to do then figure out how to make it do that.

This is something that has to be coded in, looking over the template it isn’t in there. My first place to look for java help is the JavaDoc.
You would probably just implement FocusListener on your game class,
add this line to the constructor,

canvas.addFocusListener( this );

and add something like this to the game class:


void focusLost(FocusEvent e){
  paused = true;
}

void focusGained(FocusEvent e){
  paused = false;
}

[quote]That sounds promising. Just a guess because I can’t see your code but is your ball draw function just drawing an image or are you using Graphics2D.draw* or Graphics2D.fill*?
[/quote]
I’m using Graphics2D.fillRect() because I only need circle.

[quote]If you are not using an image I would advise you switch to either loading an image or draw it once in your code and reuse it.
[/quote]
Sorry first but I really dont understand about “draw once”. They’re moving so they just need to be drawn every update right?

[quote]Sorry first but I really dont understand about “draw once”. They’re moving so they just need to be drawn every update right?
[/quote]
That was bad wording on my part.
What I was trying to explain is that Graphics2D.drawImage will perform better than a series of drawing commands. When I said draw once what I really meant to say was create the ball image once.

if that’s not clear or you don’t know how to do it maybe post your current Ball class.


class Ball extends Thread{

		private int x, y, dx, dy, value, size = 10;
		private Color color;
		private boolean die = false, idle = false;

		public Ball(){
			Random random = new Random();

			x = (int)(WIDTH * random.nextDouble());
			y = (int)(HEIGHT * random.nextDouble());
			//speed = 3
			dx = ((int)(3 * random.nextDouble()) - 1) * 3;
			dy = ((int)(3 * random.nextDouble()) - 1) * 3;
			if (dx == 0) dx = 3;
			if (dy == 0) dy = 3;

			color = new Color((int)(170 * random.nextDouble()) + 80,
				(int)(170 * random.nextDouble()) + 80,
				(int)(170 * random.nextDouble()) + 80);
		}

		public void setValue(int v){
			this.value = v;
		}

		public void updatePos(){
			this.x += dx;
			this.y += dy;
			if (x < 0){
				x = 0;
				dx = -dx;
			}
			if (x + size > WIDTH){
				x = WIDTH - size;
				dx = -dx;
			}
			if (y < 0){
				y = 0;
				dy = -dy;
			}
			if (y + size > HEIGHT){
				y = HEIGHT - size;
				dy = -dy;
			}
		}

		public void updateDraw(Graphics2D g){
			g.setColor(color);
			g.fillOval(x, y, size, size);
			if (isAlive()){
				g.setColor(Color.white);
				g.drawString(String.valueOf(value), x + 35, y + 55);
			}
		}

		public boolean checkColl(){
			int calc, dx, dy;
			boolean ret = false;
			if (big.size() > 0){
				for (Point bg : big){
					dx = (int)Math.abs(bg.getX() - x);
					dy = (int)Math.abs(bg.getY() - y);
					if (dx > RADIUS || dy > RADIUS){
						continue;
					}else{
						calc = (int)(Math.pow((dx - 5), 2) + Math.pow((dy - 5), 2));
						if (calc <= RADIUS){
							ret = true;
							break;
						}
					}
				}
			}
			return ret;
		}

		public void run(){
			try{
				size = 100;
				x -= 45;
				y -= 45;
				idle = true;
				this.sleep(3000);
				die = true;
			}
			catch (InterruptedException e){
				System.err.println("ball "+e);
			}
		}
	}

this is my current Ball class which work well by extending Thread (ofc no pause function until here). Dont mind the value variabel and method regarding it, they’re optional.

Ball size defaultly is 10 and 100 when become big (turn into special ball). I pass the Graphics2D to each Ball while on render() loop so each Ball can draw itself regarding their positions and color. checkColl() detects for collision to special balls. I save all special balls by their (x,y) of center only, not whole Ball class. That’s why I have ArrayList “big” to store all special ball but coordinat of the center only.

I hope this will make clear everything. On game class nothing special there.