wood burning stoves 2.0*
The moose likes Swing / AWT / SWT and the fly likes How to improve the performance of my animation? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "How to improve the performance of my animation?" Watch "How to improve the performance of my animation?" New topic
Author

How to improve the performance of my animation?

tom davies
Ranch Hand

Joined: Apr 27, 2012
Posts: 168
I have made a fairly basic animation. It is a single frame which holds a JPanel that displays my animation and another panel which holds my control buttons to add,start,pause etc.
My animation consists of a number of balls, each runs in their own thread and currently only bounce of the bounding box that they are within.
One ball is good and it animates well but as soon as i add another ball performance seems to almost be cut in half and both balls slow down a lot. With the addition of more balls it slows further and is not the smooth animation i had hoped for.
Just incase anyone was going to say a thread per ball is not the right approach for this program, its a requirement for this particular animation i am creating.

Here is my ball class:


In run() whenever balls panel.repaint() is called, it repaints my JPanel ballspanel within my JFrame.
Below is the paint component within my JPanel ballspanel. When a ball is added, it is added into a linked list. I then iterate through the list of balls and draw each one on the JPanel with their updated co ordinates
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4165
    
  21

I didn't do a thorough review of your code, but generally speaking having each ball be its own thread is not very efficient - it doesn't scale well. Instead you would have 1 thread which updates all ball positions - probably as a Timer or a single threaded scheduled executor. Each ball has task which, when triggered, updates its position then reschedules when the next update should take place. A ball controls its own speed by changing the delay for when the next update should take place.

Steve
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 37953
    
  22
It may be hazardous to use several threads to access a panel, anyway. Panels are not thread safe.

I shall move this discussion to our GUIs forum, where I think it would fit better.
tom davies
Ranch Hand

Joined: Apr 27, 2012
Posts: 168
I did create a basic version of the model i am trying to create using a timer. It just consisted of a single ball bouncing within a frame, and i can see why you would use a timer for this problem. However, as i mentioned in my first post, i have to use threads to control my ball. The requirement is as follows "Each ball must be controlled by its own thread or runnable."
Could thread.sleep() be used to help improve performance? when i tried this within my run method the balls just never appeared.
Jayesh A Lalwani
Bartender

Joined: Jan 17, 2008
Posts: 2272
    
  28

You might want to call repaint on a timer thread, and update the ball's posiiton in it's own thread. also, looking at the code that you have posted, aside from the repaint the balls should move so fast that you would freak. Can you remove the call to repaint and see how long it takes?
tom davies
Ranch Hand

Joined: Apr 27, 2012
Posts: 168
Jayesh A Lalwani wrote:You might want to call repaint on a timer thread, and update the ball's posiiton in it's own thread. also, looking at the code that you have posted, aside from the repaint the balls should move so fast that you would freak. Can you remove the call to repaint and see how long it takes?


Yes that was a problem at first, the ball speed is currently set at 0.00001 to let it move at a reasonable speed. This could also be a reason why it is running slowly. A timer thread sounds a good idea. Within that timer thread i would just have a normal timer, which repainted my JPanel at a set number of times per second? Then within my Ball threads i wouldn't need to call repaint i would just update the co ordinates?
Jayesh A Lalwani
Bartender

Joined: Jan 17, 2008
Posts: 2272
    
  28

Right exactly, and probably you would want your Ball thread to sleep inside the loop based on how fast you want the ball to move.
tom davies
Ranch Hand

Joined: Apr 27, 2012
Posts: 168
It runs using the timer to repaint. I have just used a timer class within my BallsPanel. It doesn't appear smooth though, probably because of a combination of the balls moving to fast and the panel repaints not keeping up with the balls co ordinates changes.
I have tried adding a sleep to my ball run method that you can see below. All that happens is i get the ball printed at its start co ordinate and nothing else . . .
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19651
    
  18

For a fluent movement you should have a frame rate of at least 24 frame per second. That's what's used in TV and film these days, because that's the rate at which the eye stops seeing separate images and starts seeing fluent motions. Note however that the movie makers are starting to switch to 48 fps; The Hobbit, coming out next month, will be one of the first movies filmed at 48 fps.

Of course, 24 fps is equivalent of a delay between calls of 1000 / 24 which is 41. Use 20 for a frame rate of 48 fps.


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
tom davies
Ranch Hand

Joined: Apr 27, 2012
Posts: 168
Rob Spoor wrote:For a fluent movement you should have a frame rate of at least 24 frame per second. That's what's used in TV and film these days, because that's the rate at which the eye stops seeing separate images and starts seeing fluent motions. Note however that the movie makers are starting to switch to 48 fps; The Hobbit, coming out next month, will be one of the first movies filmed at 48 fps.

Of course, 24 fps is equivalent of a delay between calls of 1000 / 24 which is 41. Use 20 for a frame rate of 48 fps.

Thank you, thats useful to know. HOwever i cant test out different frame rates and delays because of the reasons above. Does anyone know why when i put the thread to sleep it does not repaint?
Jayesh A Lalwani
Bartender

Joined: Jan 17, 2008
Posts: 2272
    
  28

A sleep of 100 ms shouldn't slow the loop that much. You should probably add some logs or debug the app. Or try to time the Thread without the UI. The Ball should go from start to end pretty fast.
tom davies
Ranch Hand

Joined: Apr 27, 2012
Posts: 168
I have found the problem. I still had the move values set at 0.00001 so it was moving just the smallest of margins it wasn't visible by eye. I have now changed to normal values of 1 and 2 and adjusted the frame rate using the timer and i get a good smooth animation now. I can now also add multiple balls and i keep the performance level the same
Now that has been sorted, i have some more questions relating to how i add,start and pause the animation.

I have buttons start, add, pause.
Start > start the animation and after a pause will continue the animation.
add > add a ball to the frame but will not start it.
pause > pause animation

Add uses this code to add the ball to my linkedlist and start the thread running. This should also add the static ball to the frame using the repaint method in run(). At the moment it appears to do nothing


Start and pause use the code below to set the boolean value of each ball in the linked list to either true or false. This controls the while(ball moving) loop within the run method.
When i press start before any balls are added it adds a new ball and starts its animation, even though it shouldn't be able to do this as there hasn't been a ball created yet? I can then pause the animation. when i press start again it will start all current balls on the frame and also add an extra one. Clearly something is not quite right there. Any ideas on these few problems i have? I can continue on the end of this topic or start a new one depending on which is best.

Jayesh A Lalwani
Bartender

Joined: Jan 17, 2008
Posts: 2272
    
  28

Probably, you defaulted ballMoving to true. So, as soon as the thread starts, your ball is moving.

You might want to has seperate UI functions for "addBall" and "start". If start is adding ball, it will always add a ball, even though you start it after the pause.
tom davies
Ranch Hand

Joined: Apr 27, 2012
Posts: 168
ballmoving is set by default to false, as the idea was that the animation start when the start button was pressed. Start sets the boolean value ballmoving to true to start the animation. But their shouldn't be a ball for it to move until add has been pressed and a new ball is added . . .
All start does is set the boolean value into this method. Which should check if there is a ball in the list and set the boolean value if there is.
Jayesh A Lalwani
Bartender

Joined: Jan 17, 2008
Posts: 2272
    
  28

Well, clearly start button is calling something besides controlAnimation that makes the control go to addBall first
tom davies
Ranch Hand

Joined: Apr 27, 2012
Posts: 168
Well that was embarrassing, out i added two actionlisteners to the start button instead of adding one of them to add.
Now add does what it is supposed to do and adds a ball to the frame. Start does not currently start the animation though so i will look at that tomorrow. Thanks for the help regarding the timer!
tom davies
Ranch Hand

Joined: Apr 27, 2012
Posts: 168
This problem is still confusing me. My Ball constructor looks like this. I have set the boolean ballMoving to false. I should be able to click my start button which will change this value within my run method to true and execute what is inside that loop. Currently if the boolean is set to false originally then the ball is displayed when add button is pressed but when you press start nothing happens. If i originally set this value to true, so the ball is moving then the animation runs whenever i add a new ball. I can then press the pause button and all the balls will stop. If i press the start button again to continue the animation they will not restart. It seems as though once the value is set to false within my run method it wont restart. The structure of my run method looks like this.

The thread will continuously run due to the outer while loop, but the inner loop will only run when the boolean ballMoving is true. Is there any reason why the thread wouldn't continue after ballmoving has been set to false and then true again?
I have added a slider which now controls the balls speed, so i am able to iterate through the balls and change the variables within them. Also the pause button does work it just does not seem to restart after i have changed the boolean to true again.


 
Don't get me started about those stupid light bulbs.
 
subject: How to improve the performance of my animation?
 
Similar Threads
keyboard arrow keys not working
Multiple threads with graphical components
Bouncing balls
Need help breaking up this code
First time with applets