Meaningless Drivel is fun!*
The moose likes Game Development and the fly likes Occasional random pauses during game Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Game Development
Bookmark "Occasional random pauses during game" Watch "Occasional random pauses during game" New topic
Author

Occasional random pauses during game

Mich Robinson
Ranch Hand

Joined: Jun 28, 2009
Posts: 250
    
    1
I'm writing a retro shooter arcade game but it occasionally suffers from random pauses during play. I put some timings in and for the most part round the main loop it's taking around 15ms - must admit I was quite impressed by the performance of the language. Occasionally however there is a pause of around 1/2 second and this is very noticeable. It happens all the time on my sons old laptop while it only happens on my machine when I have a few other programs running.

I tried inserting a System.gc() call at the start of each new level etc but this doesn't seem to have much effect.

I'm guessing it's garbage collection but (I'm guessing here) the code doesn't really that much collected. Can I control this garbage collection any better? can I avoid doing things that require more garbage collection?

If it helps the gc output is shown below. The full collection takes over .1 sec which is probably enough to be noticed.
C:\Java\Game>appletviewer -J"-verbose:gc" index.html
[GC 896K->345K(5056K), 0.0098434 secs]
[GC 1225K->659K(5056K), 0.0079373 secs]
[Full GC 924K->872K(5056K), 0.0495242 secs]
[Full GC 901K->873K(5056K), 0.0491867 secs]
[GC 2875K->2285K(5056K), 0.0056996 secs]
[GC 3181K->2394K(5056K), 0.0028881 secs]
[GC 3287K->2485K(5056K), 0.0019653 secs]
[GC 3381K->2565K(5056K), 0.0022978 secs]
[GC 3461K->2627K(5056K), 0.0016812 secs]
[Full GC 3171K->2687K(5056K), 0.0557018 secs]
[Full GC 2816K->2555K(5440K), 0.0669809 secs]
[GC 3451K->2563K(5440K), 0.0014382 secs]
[Full GC 2809K->2563K(5440K), 0.0571131 secs]
[Full GC 2581K->2563K(5440K), 0.0564684 secs]


If you want to see what's happening then the applet is here. I can't guarantee that the problem will appear though. You can press "t" which will show the max time in milli sec in the main loop (anything over 45 milli is problematic). You can press "g" to reduce the graphics right down but this didn't have much effect on my machine.

Any ideas?

Mike


Arcade : Alien Swarm
Board : Chess - Checkers - Connect 4 - Othello
Anthony Hay
Greenhorn

Joined: Jan 08, 2010
Posts: 13
What are the specs to your computer?, I played the applet and it ran just fine, although it paused for a split second while loading the levels which is understandable.

I'm running an
AMD Athlon64 Dule core @ 2.7GHz
8GB system ram
NVidia 9600GSO with 1GB video ram

It would also help to have the code to the main loop.


Edit: I ran a test by playing your game and looking at my total CPU usage via task manager. I found that the game would slow down but CPU usage would stay around 3% and ram usage by the VM did not decrease as it would normally would during garbage collection.


Solving problems is a hobby of mine, specially java problems.
Mich Robinson
Ranch Hand

Joined: Jun 28, 2009
Posts: 250
    
    1
Mine's a Celeron 2.4 Ghz, 960MB ram - sometimes it plays fine and sometimes, especially when AVG is scanning, I get all the pauses. My son has an old (5 years) laptop and he says he gets a lot of pauses all the time. Oddly if I run the game on a little netbook then it plays perfectly with never a pause. If I press "t" then it shows the time taken to run the main loop (anywhere from 16ms to 30ms) and this seems fine but the pauses still occur somehow. I can reduce the graphics down by pressing "g" and the problems seem to go away but it doesn't look so pretty then.

Your info regards CPU and RAM usage is interesting - what else could create the pauses? I'm pretty much doing the same thing throughout the game but just altering various parameters to make things more difficult at the start of a level. Occasionally I'll add motherships and random bits of space junk onto the screen but the pauses don't seem to be linked to these. I could only think of garbage collection as being the culprit.

I could show the code but it's just a pretty basic loop moving aliens and bullets, then using keyDown etc to move the ship about. I obviously use double buffering. Perhaps I should just give a minimum spec to run the game? I was wondering if I could turn off garbage collection until the end of a level?

Mike

EDIT thank you for testing it
Anthony Hay
Greenhorn

Joined: Jan 08, 2010
Posts: 13
your welcome.

In a main loop we have to sleep at some point to keep the FPS from being out of control. I suspect that the code that handles the sleep timing is ether insufficient or has a bug in it. I would take your games logic and rendering code and put theme into separate methods so you only have to make a few method calls in your main loop. That will help keep your code clean. I would really like to see that main loop, it would shine lots of light on the problem. Also id like to see your double buffering and painting code, maybe there is some speed ups we can make there.

pete stein
Bartender

Joined: Feb 23, 2007
Posts: 1561
Need little game applet! Heck, I'd just like to see the code for my own educational benefit.
Mich Robinson
Ranch Hand

Joined: Jun 28, 2009
Posts: 250
    
    1
Well you guys wanted to see code so here's the main bits.

This is the main loop - I've cut a few bits out as they only get called during exceptions. It aims to take 50ms on each loop. It calculates how long to delay by timing each iteration and then seeing how much more time to sleep for to make up 50ms. If it's taken longer than 50ms then it doesn't sleep. I showed the time variables in case they are useful.


And this is the paint method - sorry it's a bit long but I have removed chunks that only get called during the splash screen etc. I showed the screen variables in case they are useful :


Any ideas?

Mike
Anthony Hay
Greenhorn

Joined: Jan 08, 2010
Posts: 13
I see many problems with this code. First the game logic is interlaced with drawing code, preventing you from separating updates from renderings. Second your calling repaint, which only places a request to redraw the applet. The time between you call repaint and the time it's actually redrawn is unpredictable at best, sometimes under heavy load or when lots of requests are made some of those requests are dropped, making the game appear choppy. Since you got your game logic interlaced with the drawing code the game only advances when paint is called, because your calling repaint in your main loop the call to paint is made at the determination of the VM and not your code. Fixing the game will involve major rewriting, that rewrite however will almost guarantee smoothness on all but the most paltry of systems.I recommend reading the first few chapters killer game programing in java, it will tell you alot you need to know when programing games and teach you how to write an effective main loop. A free online version can be found at the link below

http://fivedots.coe.psu.ac.th/~ad/jg/

Mich Robinson
Ranch Hand

Joined: Jun 28, 2009
Posts: 250
    
    1
I'm redoing the code now. I'll just have the draw routines within the paint method and the move and collision detection stuff called from the run method. I can see that this would be better structurally but I'm not sure how much difference it will make to the occasional stuttering on screen. I'd of thought the stuttering would be more frequent and regular if this was the issue but I don't have anything to back me up other than a gut feeling. I'll post the new code shortly.

Mike

PS The book looks interesting so I might get hold of that.
Mich Robinson
Ranch Hand

Joined: Jun 28, 2009
Posts: 250
    
    1
Ok - I've moved all the logic stuff out of the paint method and into methods called by the run method. I now just have relatively simple methods to initialise/move/draw each of the various items on screen ie aliens/bullets/mother ship/stars etc. The layout of the code is better but I still seem to be getting the same random pauses. Is there anything else I should try?

The paint method is now:


The run() method:


Thanks for looking.
Anthony Hay
Greenhorn

Joined: Jan 08, 2010
Posts: 13
So now the next step is to trash repaint, and call paint directly. your going to have to grab a graphics object directly by getting a graphics object from your applet and passing it into paint directly. This little code snippet should do, place this where your repaint is. If it still runs choppy after that theirs other things we can do to make your game appear to run faster when in fact it's not.

Mich Robinson
Ranch Hand

Joined: Jun 28, 2009
Posts: 250
    
    1
I found some collision logic within one of my draw methods - I've moved this logic out and things seemed to have improved. Things aren't perfect - on a slowish machine performing an AVG scan then everything gets very choppy but I guess that's fair enough. I couldn't get the paint to work directly as I kept getting null returned by the getGraphics method. I've uploaded the latest version of the game onto the web.

Were there other things should I look at as well?

Mike
Anthony Hay
Greenhorn

Joined: Jan 08, 2010
Posts: 13
Theirs not much more you can do without a direct call to paint.
Mich Robinson
Ranch Hand

Joined: Jun 28, 2009
Posts: 250
    
    1
I have the paint working directly now - things appear better but I'm still getting issues when the CPU is under load ie doing a full AVG scan in the background. So what else can I do?
Anthony Hay
Greenhorn

Joined: Jan 08, 2010
Posts: 13
Your game runs quite well even under even under heavy CPU usage, theirs one more tweak below but I really don't think it's necessary. And also a word of advice, virus scanners don't make very good load generators because they use tons of ram and Hard-disk access. Your game lagged on your computer probably because the AVG scan was hogging up all the ram and hard-disk usage time. Both of which are part of the life blood of any smooth running game. On my machine even notepad runs slow when a virus scan is underway, and I can run Crysis on high graphics with no lag.


The last thing now would be separating updates from rendering. So basically while the game runs we want to add up the overruns(frames that take longer to render then the allotted time) and do extra updates without rendering when necessary to catch up. Even though the frame rate will not be would it should be the update rate will stay really close to the desired FPS. So even though the graphics are running a little slow the game still advances at it's assigned pace. You should be careful not to let the code skip too many frames at once, otherwise the game will appear to jump forward.

so say we separate the updates from rendering.

so say we want 100FPS, this is fast in the gaming world but I'm just using it for the simplicity of the example.

Each frame should take 10ms (1000ms/100)

frame 1 takes 9ms, we have some time left so no overrun is added.

frame 2 takes 12ms, we went 2ms over the allotted time. we will add this to our overrun.
overrun = 2, since a frame should take 10ms and we only went over 2ms we don't need an extra update.

frame 3 takes 11 ms, we add one to our overrun and it now become 3.
again 3ms is not enough to warrant an extra update.

frame 4 takes 18ms, overrun = 18-10 + 3(from previous overruns)
overrun = 11ms

since our overrun is now grater then our allotted time we have lost at least one frames time, so now we do an extra update to cover that lost time,
we update without rendering.

overrun is now 1, we started with 11 and did one extra update wich covers our allotted time so we subtract our allotted time from the overruns.
Mich Robinson
Ranch Hand

Joined: Jun 28, 2009
Posts: 250
    
    1
I've implemented that idea and released it. One thing I noticed was that the pauses (when they came) were quite long. This meant that rather than roving the moveAllObjects() method once I might need to run it many times to get back into sync. This initially made it seem like you'd closed your eyes for a couple of seconds while playing! I changed that so it would only implement multiple moves a limited number of times. The end result seems quite reasonable now.

Thanks for your advice by the way - this is the first real time game I've implemented in Java and it's been an interesting learning curve.

Mike
Anthony Hay
Greenhorn

Joined: Jan 08, 2010
Posts: 13
Your welcome. I happy to help anytime.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Occasional random pauses during game