I like Java 2D. 3D engines seem overwhelming for me at the moment despite the fact that the pros say OpenGL or an OpenGL wrapper is the way to go. I'm a firm believer that 2D art still rocks hard with the right artist. The "Mona Lisa" was not tossed out of the museum when "The Thinker" statue was added to the collection. The question is can I do a large screen implementation that is fast enough for most computers. I have my doubts that it will be fast enough but I'll let the numbers decide.
Goal:
- 100 FPS with a reasonable animation smoothing delay of 10 ms.
- Screen size 1024 x 768 and greater, hopefully 1900x1200.
- 32x32 tiles with multiple layers.
- One background
- 2 Parallax backgrounds.
- Mode: Windowed. If Linux supports fullscreen, I'll test that as well.
- Do a little bit of alpha blending
Ideas for improvement:
- Force OpenGL and D3d Pipelines
- Test Timers
- Test VolatileImage
- Optimize Code
- Try different blitting techniques.
- Try different art formats, png, jpg, bmp, gif with different depths.
Test Environments
a) Desktop Radeon 3800 with 512mb of ram. 2 gigs memory. Windows xp pro.
b) Laptop Intel Chip set. 1 gig of ram Windows xp pro.
Another
I need to sleep my game loop for time than the processing time of the game loop.
Changing of my original goal of 100 FPS was quite surprising to me. Over the years, several gaming buddies and I have had silly competitions about who gets the most FPS out the game we play. Basically, FPS is not a true
representation of how smooth the graphics really are.
Problems
Jitter
System.currentTime() & nanoTime not accurate on Windows
Thread.sleep() not accurate on Windows, probably related to above.
Third Party timers inaccurte.
Bugs in Java
Jitter: Jitter is basically the varying time lag between paints. It is caused by several things, bugs, poor resolution of timers, Windows issues, and implementation.
I was System.currentTimeMillis() for my timer, thinking it really doesn't matter that much. I began playing with it and noticed if I set my delay between 5-13 milliseconds I saw no change. Weird. I then moved the delay to 14 and presto my FPS went from 65 to 70. I assume what this means is the inaccuracy of the timer was causing a delay in display. To test this I'm going to add a third party timer.
I tried using the GAGETimer a free timer. With the same resolutions of delay, I was getting about 1% improvement. Ok that is a bit strange, maybe a math difference.
Then I plugged in the number 10 a few times. I got totally random results.
I'm using the standard Kevin Glass setup with a delta with non-recommended System.currentTimeMillis
try { Thread.sleep(loopTime+10-System.currentTimeMillis()); } catch (Exception e) {}
Results
1) Framerate changes drastically everytime I run the test even though all I'm doing is drawing tiles and backgrounds. Sometimes it is 65 fps and others 94.
2) For some reason setting the delay between 9-12 seems to have little effect on the frame rates.
Question: Why does the frame rate vary everytime I run it?
Okay so now I throw out the System.currentTimeMillis and go to the Gage timer.
try { Thread.sleep(loopTime+10-SystemTimer.getTime()); } catch (Exception e) {}
I still get random results but I got a slight improvement by not using 10. 9 gave me an awesome frame rate. 105! woot this was the number i wanted. Even 11 gave me frame rates in the high 80s. 10 gave me 65.
Lets see if I can do better with the nanotimer.
Test number 1:
import java.awt.Canvas; import java.awt.Color; import java.awt.Graphics2D; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.image.BufferStrategy; import javax.swing.JFrame; import javax.swing.JPanel; /** * * @author Darrin Adams */ public class Speed extends Canvas{ private BufferStrategy bsStrategy; // fast flips private boolean bRunning = true; // main loop private static final int CANVAS_X = 1024; private static final int CANVAS_Y = 768; public Speed (){ // Frame Setup JFrame frame = new JFrame("Speed Test"); frame.setBounds(0, 0, CANVAS_X, CANVAS_Y); frame.setLayout(null); frame.setLocationRelativeTo(null); frame.setResizable(false); frame.setVisible(true); frame.addWindowListener(new WindowAdapter() { // a new way to close @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); // Panel added JPanel pane = new JPanel(); pane.setBounds(0, 0, CANVAS_X, CANVAS_Y); pane.setLayout(null); frame.add(pane); // this Canvas added setBounds(pane.getBounds()); pane.add(this); setIgnoreRepaint(true); // active painting only on canvas, does this apply to swing? requestFocus(); // get focus for keys // make it fast with this strat createBufferStrategy(2); bsStrategy = getBufferStrategy(); } public void loopGame(){ // Timer and FPS long loopTime = System.currentTimeMillis(); int fps=0; int frames=0; long startTime = System.currentTimeMillis(); // TODO remove this external timer for weapons long shotTime = System.currentTimeMillis(); while (bRunning) { long timeLapse = System.currentTimeMillis() - loopTime; // used to move objects smoothly loopTime = System.currentTimeMillis(); Graphics2D g2d = (Graphics2D) bsStrategy.getDrawGraphics(); // Wipe g2d.setColor(Color.black); g2d.fillRect(0, 0, CANVAS_X, CANVAS_Y); // fps counter if ((System.currentTimeMillis() - startTime) > 1000){ startTime = System.currentTimeMillis(); fps = frames; frames = 0; } ++frames; g2d.setColor(Color.green); g2d.drawString("fps: " + fps, 5, 30); // finally, we've completed drawing so clear up the graphics // and flip the buffer over g2d.dispose(); bsStrategy.show(); // Attempt to sleep for a consistant time. Smooths out bumps in processing. try { Thread.sleep(loopTime+10-System.currentTimeMillis()); } catch (Exception e) {} } } /** * @param args the command line arguments */ public static void main(String[] args) { Speed game = new Speed(); game.loopGame(); } }
Reference:
2d tests using pixel draws not quite what I'm doing but a good start
http://www.yov408.com/javagraphics/javagraphics.html
How to open the Opengl Pipe and logs. Also include D3d.
http://java.sun.com/j2se/1.5.0/docs/guide/2d/flags.html
http://weblogs.java.net/blog/campbell/archive/2004/11/behind_the_grap.html
Explanation of VolitileImages
http://www.javalobby.org/forums/thread.jspa?threadID=16840&tstart=0
Ibm's example of frame double buffered
http://www.ibm.com/developerworks/java/library/j-mer04293.html
Thank you for the nice article here. Really nice and keep update to explore more gaming tips and ideas.
ReplyDeleteGame Testing Services Companies
Video Game Testing
Functionality QA Testing
Game QA Testing Company
Really nice topics you had discussed above. I am much impressed. Thank you for providing this nice information here.
ReplyDeleteSelenium Training in Chennai | Certification | Online Training Course | Selenium Training in Bangalore | Certification | Online Training Course | Selenium Training in Hyderabad | Certification | Online Training Course | Selenium Training in Coimbatore | Certification | Online Training Course | Selenium Training in Online | Certification | Online Training Course