- Swing Timer: Java timers are notoriously inaccurate and actually do not bear a guarantee beyond "will not fire below a certain threshold". Thus, you still need a traditional gameloop-esque mechanism to account for deltas. Also, I would not use a timer for a game loop and would instead perform the update manually. You can - and is a reasonable idea - to use a Timer as your time base (e.g. per tick update some delta time value and grab that) as that helps mitigate cross-platform timing issues but relying on Java to manage your loop for you is asking for problems, particularly under the discretion of Swing. Furthermore, as mentioned in a couple of research discussions, if your rendering becomes complex the timer thread may get bogged down in events waiting for your render to complete (or, depending on what you're doing, it might just wig out for no reason). Furthermore, it is important to remember that the entire point of a BufferStrategy is for you to manually control the buffers; it doesn' t make a lot of sense to grab that manual control and then immediately hand it back off to Swing. You would be better off just using paint and pumping repaint events.
- Hardware acceleration: HA is a tricky subject with Java. Realistically, whether or not you get it is at the discretion of the JVM and the system you're using. To my knowledge, the only reliable way to accelerate a drawing context without using VolatileImage directly in Java2D is to use full-screen exclusive mode and remains the only way to do so on older systems, since FSEM reserves the drawing context for your application only. Newer systems shouldn' t have that issue but it still remains a difficult thing to guarantee on an end user.
Things to check:
- Check the value of the sun.java2d.opengl property. It will likely be null but it's still worth doing so.
- Check your buffer capabilities and ensure it supports page flipping and has multiple buffers. Grab both the front and back buffer capabilities and ensure they check out as well. E.g.
- [source lang="java"]// checkSystem.out.println("Page flipping: " + strategy.getCapabilities().isPageFlipping());System.out.println("Multiple Buffers: " + strategy.getCapabilities().isMultiBufferAvailable());System.out.println("FSEM Required: " + strategy.getCapabilities().isFullScreenRequired());System.out.println("Backbuffer accelerated: " + strategy.getCapabilities().getBackBufferCapabilities().isAccelerated());System.out.println("Frontbuffer accelerated: " + strategy.getCapabilities().getFrontBufferCapabilities().isAccelerated());[/source]
- As an example, the above on my system returns:
Things I would try:
- Lose the JScrollPane.
- Ensure your context is accelerated by checking the above. If FSEM returns true then you must enable fullscreen exclusive mode to be accelerated. If any of the others return abnormal results then, unfortunately, there's not a lot you can do to fix that manually other than playing Jeopardy! with various graphics configurations. If sun.java2d.opengl returns false (instead of null) then I would try passing that as a VM argument with the value of true and see if that improves anything.
- Ditch the timer. Use a while(true) loop and stagger your player updates yourself (use nanoTime()) and don't forget an event listener so you can kill your app. If you do not experience tearing then your problem is with Swing's EDT. I assure you that is a battle you will lose horribly so I would suggest reverting to a more traditional game-loop and moving on.
For what it's worth, this is why a lot of people prefer to use LWJGL or Slick2D over Java2D. You can still use simple draw commands without needing to battle AWT/Swing at the same time.