jezek2
|
 |
«
Reply #60 - Posted
2008-11-13 23:03:40 » |
|
Weirdly enough running his draw-a-block-and-move it is jerky here too.
If I implement a old school simplistic self coded double buffered approach, it's smooth. (image still jerks a bit, what double buffing was suppose to fix.) Then again under linux I have quite some paint issues progress bars don't draw too well either out of the box.
Try using Toolkit.getDefaultToolkit().sync(); just after you call show() of BufferStrategy.
|
|
|
|
|
Mr_Light
|
 |
«
Reply #61 - Posted
2008-11-13 23:18:05 » |
|
That makes a huge difference; on par with smoothness achieved with the self coded double buffered strategy - much less taxing on the cpu.
|
It's harder to read code than to write it. - it's even harder to write readable code.
The gospel of brother Riven: "The guarantee that all bugs are in *your* code is worth gold." Amen brother a-m-e-n.
|
|
|
erikd
|
 |
«
Reply #62 - Posted
2008-11-14 11:02:04 » |
|
Here's the output for my machine: 1 2 3 4
| failed, iteration 1, time 9961881ns failed, iteration 83, time 9998757ns failed, iteration 94, time 9968865ns failed, iteration 97, time 9989818ns |
Unpredictable as Hell, what a headache! Does anyone get a run of the code above with zero failures? --Mario Maybe I'm missing something, but I seriously don't know how you can call that 'Unpredictable as Hell'  Given that Thread.sleep() has a precision of 1ms, 9998757ns IS exactly the amount of time you intended to sleep, so your example just demonstrates that Thread.sleep() works as advertised and your code to report a failure is wrong. Which doesn't mean timing using the standard libraries isn't without it's problems, but my understanding is that nanoTime generally works fine except when you have some Dual core AMD system with outdated drivers. The LWJGL timer is the most reliable one afaik. System.currentTimeMillis is too unreliable when you want to measure with 1ms accuracy (esp. on Windows).
|
|
|
|
Games published by our own members! Check 'em out!
|
|
mgianota
Senior Newbie 
|
 |
«
Reply #63 - Posted
2008-11-14 23:44:20 » |
|
Try using Toolkit.getDefaultToolkit().sync(); just after you call show() of BufferStrategy.
That dramatically improves things. Interestingly, it causes Windows Vista to revert to what it calls a basic colour scheme: "The following program has performed an action that requires Windows to temporarily change the colour scheme to Windows Basic." The popup help hints at the fact that there is either: (i) insufficient memory to continue displaying Windows Aero (the default scheme on Windows Vista) translucent Windows. Which is unlikely, or (ii) the computer's hardware configuration or screen resolution was changed. Looks like a call to sync() triggers this behaviour on Windows Vista. Bu-ut, the frame rate is now more or less steady at 58-60 FPS. Thanks jezek2. --Mario
|
|
|
|
|
|
|
mgianota
Senior Newbie 
|
 |
«
Reply #65 - Posted
2008-11-15 00:25:21 » |
|
Maybe I'm missing something, but I seriously don't know how you can call that 'Unpredictable as Hell'  Given that Thread.sleep() has a precision of 1ms, 9998757ns IS exactly the amount of time you intended to sleep, so your example just demonstrates that Thread.sleep() works as advertised and your code to report a failure is wrong. ... Since when was 9998757ns ever equal to 10ms? Okay, it is close to 10ms but it is not exact. This thread is about why Java is not a good language for game development and the sample code which attempts to synchronize a main loop to 60fps clearly doesn't work properly on my machine (a reasonably well spec'd one) which is why I am investigating Java's timing abilities. A jerky screen update is a major reason for abandoning Java as a games development language. Here's some timer test code written by David Brackeen that shows the problem. He's already stated in a PM to me that he believes it to be a thread scheduling problem. When you execute it you should get no jumps forward. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| import static java.lang.System.out;
public class TimerTest implements Runnable {
long testLength = 10L * 1000 * 1000 * 1000; long iterations = 0; long jumpsForward = 0; long jumpsBackward = 0; boolean lastWasAJump = false; long firstTime = System.nanoTime(); long lastTime = firstTime;
public void run() { while (true) { Thread.yield(); long time = System.nanoTime(); if (time < lastTime) { out.println("Backwards by: " + ((lastTime - time) / 1000000.0f) + "ms"); lastWasAJump = true; jumpsBackward++; } else if (time >= lastTime + 1000 * 1000 * 10) { out.println("Large jump by: " + ((time - lastTime) / 1000000.0f) + "ms"); lastWasAJump = true; jumpsForward++; } else if (lastWasAJump) { out.println("Back to normal"); lastWasAJump = false; } lastTime = time; iterations++;
if (time >= firstTime + testLength) { break; } }
out.println(iterations + " iterations."); out.println(jumpsBackward + " jumps backwards"); out.println(jumpsForward + " jumps forwards"); out.println("Java " + System.getProperty("java.version")); }
public synchronized static void main(String[] args) { Thread t = new Thread(new TimerTest()); t.setPriority(Thread.MAX_PRIORITY); t.start(); } } |
--Mario
|
|
|
|
|
princec
|
 |
«
Reply #66 - Posted
2008-11-15 00:55:50 » |
|
What framerate do my games run at? (Assuming you've gotten some working GL drivers now?) Cas 
|
|
|
|
mgianota
Senior Newbie 
|
 |
«
Reply #67 - Posted
2008-11-15 01:28:18 » |
|
The installer for the newest graphics drivers from AMD fails to execute properly on my machine. Windows Vista notifies me with a "this program has stopped working" dialog. I think the installer wasn't tested on Windows Vista.  So, I can't update the drivers to run LWJGL code until AMD get around to fixing their installer to work with Vista.  --Mario
|
|
|
|
|
bosun
Senior Newbie 
|
 |
«
Reply #68 - Posted
2008-11-15 02:01:14 » |
|
The newest drivers installed just fine for me (vista64). But I saw some people mention a problem installing them on the support forums. You might want to look there for a solution.
|
|
|
|
|
mgianota
Senior Newbie 
|
 |
«
Reply #69 - Posted
2008-11-15 02:41:11 » |
|
Damn. Graphics card doesn't support OpenGL. I wanted to download and try the Puppy Games too.
--Mario
|
|
|
|
|
Games published by our own members! Check 'em out!
|
|
princec
|
 |
«
Reply #70 - Posted
2008-11-15 02:51:52 » |
|
|
|
|
|
bosun
Senior Newbie 
|
 |
«
Reply #71 - Posted
2008-11-15 02:57:39 » |
|
The xpress 1100 has very poor support for opengl. It's a hardware issue. If he feels like experimenting gldirect might help, but I am somewhat sceptical of it.
|
|
|
|
|
princec
|
 |
«
Reply #72 - Posted
2008-11-15 03:35:38 » |
|
I barely use any OpenGL whatsoever - I literally blit quads and draw lines. If it can't cope with that... Cas 
|
|
|
|
bosun
Senior Newbie 
|
 |
«
Reply #73 - Posted
2008-11-15 03:58:30 » |
|
We've gotten way off topic here, but official drivers often have to be modded to work on laptops. www.driverheaven.net should have information about how to modify the driver. Or http://www.omegadrivers.net/ might have drivers you can use. But yeah, seems like a really poor card. Lots of people complaining about it.
|
|
|
|
|
mgianota
Senior Newbie 
|
 |
«
Reply #74 - Posted
2008-11-15 04:30:53 » |
|
We've gotten way off topic here...
Yup. The thread is about reasons why Java should not be used for games writing. To bring the thread back on track I thought I'd post the updated test code I'm using. It is a physics based main loop and the physics update code is decoupled from the framerate with a fixed time step --quite groovy really. But it is still jerky, despite the addition of a call to synchronize with the display adapter. Recall from previous posts that the stuttering and lag is a major reason for saying no to using Java for writing games. It needs a bit of a clean-up because I've hacked about with it a bit but there is no reason I can think of why this code should produce a stuttering animation. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
| package gameloop;
import java.awt.*; import java.awt.event.KeyEvent; import java.awt.image.BufferStrategy; import java.awt.event.KeyListener; import java.awt.geom.Rectangle2D;
public class Main implements KeyListener { private static Color[] COLORS = new Color[] { Color.red, Color.blue, Color.green, Color.white, Color.black, Color.yellow, Color.gray, Color.cyan, Color.pink, Color.lightGray, Color.magenta, Color.orange, Color.darkGray }; Frame mainFrame; long lastTime; int fps; int frameCounter; long elapsedTime; double delayTime; float gameTime; float dt = 0.01f; float accumulator; double frameRate = (double)1000000000L/(double)60; Rectangle2D rect; public Main(GraphicsDevice device) { try { GraphicsConfiguration gc = device.getDefaultConfiguration(); mainFrame = new Frame(gc); mainFrame.setUndecorated(true); mainFrame.setIgnoreRepaint(true); mainFrame.setVisible(true); mainFrame.setSize(640, 480); mainFrame.setLocationRelativeTo(null); mainFrame.createBufferStrategy(3); mainFrame.addKeyListener(this); BufferStrategy bufferStrategy = mainFrame.getBufferStrategy(); rect = new Rectangle2D.Float(0,100,64,64); while(true) { long time = System.nanoTime(); calculateFramesPerSecond(); accumulator += (float)elapsedTime/(float)1000000000; while( accumulator >= dt ) { updateWorld(dt); gameTime += dt; accumulator -= dt; } Graphics g = bufferStrategy.getDrawGraphics(); drawScreen(g); g.dispose(); if( ! bufferStrategy.contentsLost() ) bufferStrategy.show(); Toolkit.getDefaultToolkit().sync(); elapsedTime = System.nanoTime() - time; delayTime = frameRate - (double)elapsedTime; time = System.nanoTime(); while( System.nanoTime() - time <= delayTime) Thread.yield(); } } catch (Exception e) { e.printStackTrace(); } finally { device.setFullScreenWindow(null); } }
private void updateWorld(float deltaTime) { rect.setRect(rect.getX() + 240*deltaTime, 100, 64, 64); if( rect.getX() > mainFrame.getWidth() ) rect.setRect(-rect.getWidth(), 100, 64, 64); } private void drawScreen(Graphics g) { g.setColor(COLORS[0]); g.fillRect(0, 0, mainFrame.getWidth(), mainFrame.getHeight()); g.setColor(COLORS[3]); g.drawString("FPS: "+ fps, 0, 17); g.drawString("Game time: " + gameTime, 0, 34); g.setColor(COLORS[1]); g.fillRect((int)rect.getX(), (int)rect.getY(), (int)rect.getWidth(), (int)rect.getHeight()); } private void calculateFramesPerSecond() { long time = System.nanoTime(); if( time - lastTime >= 1000000000L ) { fps = frameCounter; lastTime = time; frameCounter = 0; } frameCounter++; } public void keyPressed(KeyEvent e) { if( e.getKeyCode() == KeyEvent.VK_ESCAPE ) { System.exit(0); } } public void keyReleased(KeyEvent e) { } public void keyTyped(KeyEvent e) { } public static void main(String[] args) { try { GraphicsEnvironment env = GraphicsEnvironment. getLocalGraphicsEnvironment(); GraphicsDevice device = env.getDefaultScreenDevice(); new Main(device); } catch (Exception e) { e.printStackTrace(); } }
} |
I realize that many of you use LWJGL because of the performance hit, but I actually can't see the point of including native libraries with a Java program. When a Java program calls for native support I automatically reach for my C/C++ compiler. Once I'm in the C/C++ environment I'm reluctant to leave it to go back into Java as it just feels as though I'm creating a DLL for scripting purposes. I might as well stay in the C/C++ IDE and write the whole thing in C and then I don't have to concern myself with producing JNI interfaces. So-o, I want to write pure Java games without native support. --Mario
|
|
|
|
|
jezek2
|
 |
«
Reply #75 - Posted
2008-11-15 08:56:10 » |
|
I realize that many of you use LWJGL because of the performance hit, but I actually can't see the point of including native libraries with a Java program. When a Java program calls for native support I automatically reach for my C/C++ compiler. Once I'm in the C/C++ environment I'm reluctant to leave it to go back into Java as it just feels as though I'm creating a DLL for scripting purposes. I might as well stay in the C/C++ IDE and write the whole thing in C and then I don't have to concern myself with producing JNI interfaces. So-o, I want to write pure Java games without native support.
Native libraries for LWJGL are no issue, as they're already precompiled for all platforms and I just need to include few files in my projects. The rest is done in pure Java and it's huge saving to be able doing just one build for all platforms and code in sane programming language. And LWJGL is the only library where I need native access, everything other can be done in pure Java. Absolutely no need to touch any C/C++ at all.
|
|
|
|
|
mgianota
Senior Newbie 
|
 |
«
Reply #76 - Posted
2008-11-15 09:47:14 » |
|
LWJGL doesn't work on all systems. To run LWJGL code you must either have a graphics card plus drivers that support OpenGL, or a software OpenGL emulation layer. A lot of people out there simply will not be able to run your game. As soon as you include native libs like LWJGL you effectively reduce the portability of your code to people who have compatible hardware. Cas has already said that he doesn't really use much OpenGL code, all he does is blit quads and draw lines. If that's all then you might as well use Windows GDI and DirectDraw and your game will work on every Windows machine. I think now that if you're going to write games in Java, then for maximum portability you should stick to pure Java. But so far it looks as though pure Java isn't up to the job of managing a simple game loop.  --Mario
|
|
|
|
|
Eli Delventhal
|
 |
«
Reply #77 - Posted
2008-11-15 09:56:27 » |
|
and your game will work on every Windows machine.
Then what about Mac and Linux? OpenGL is much more prolific and cross platform than DirectX.
|
|
|
|
jezek2
|
 |
«
Reply #78 - Posted
2008-11-15 10:01:23 » |
|
LWJGL doesn't work on all systems. To run LWJGL code you must either have a graphics card plus drivers that support OpenGL, or a software OpenGL emulation layer. A lot of people out there simply will not be able to run your game.
Well that depends on your target audience. For example I'm aiming for cards that supports at least PS2.0a/b pixel shaders in an standalone (normal app) non-causal game. For causal games, you can use pure Java2D and tune your usage of it according to Java2D's software renderer (and have nice boost on 6u10 with D3D acceleration by default), or use own optimized software rendering by using either your own code or some existing pure Java libraries such as PulpCore, JPCT and others.
|
|
|
|
|
mgianota
Senior Newbie 
|
 |
«
Reply #79 - Posted
2008-11-15 10:06:58 » |
|
'Course you can, yeah. Bu-ut, the main game loop stutters and lags if you use pure Java. That is what this thread is currently about.
--Mario
|
|
|
|
|
jezek2
|
 |
«
Reply #80 - Posted
2008-11-15 10:18:12 » |
|
'Course you can, yeah. Bu-ut, the main game loop stutters and lags if you use pure Java. That is what this thread is currently about.
As I posted previously, it looks like as very specific problem of your machine. The most constructive approach is to try examining the root of problems and fix that if possible. Generally I see pretty bad pattern on people on various forums... when they have problem in Java they automatically blame whole Java without further examination. If they have problem in C/C++ they're finally looking for cause of problem. Isn't that weird?
|
|
|
|
|
mgianota
Senior Newbie 
|
 |
«
Reply #81 - Posted
2008-11-15 10:35:20 » |
|
Look, when I write the same code in C it works flawlessly with no stutter and no lag. When I write the code in Java there is stutter and lag. The problem is not my hardware, the problem is Java.  --Mario
|
|
|
|
|
Mr_Light
|
 |
«
Reply #82 - Posted
2008-11-15 11:55:14 » |
|
Ever figured the problem could be between the screen and the chair? your code stutters here too, I've added an adaptation of your original code that works smooth here. it also consumes a fraction of my cpu-time compared to yours. ps. I won't be handing out cookies for the obvious memory leak that's in there. 
|
It's harder to read code than to write it. - it's even harder to write readable code.
The gospel of brother Riven: "The guarantee that all bugs are in *your* code is worth gold." Amen brother a-m-e-n.
|
|
|
mgianota
Senior Newbie 
|
 |
«
Reply #83 - Posted
2008-11-15 22:39:45 » |
|
Ever figured the problem could be between the screen and the chair?
Frequently  your code stutters here too, I've added an adaptation of your original code that works smooth here. it also consumes a fraction of my cpu-time compared to yours. ps. I won't be handing out cookies for the obvious memory leak that's in there.  That's not fair, I'm a C programmer not a Java programmer, you have way more experience.  Are you just going to sit on the mod'd code without telling me what you've done? --Mario
|
|
|
|
|
kevglass
|
 |
«
Reply #84 - Posted
2008-11-15 22:50:34 » |
|
He attached it to his post.
Kev
|
|
|
|
mgianota
Senior Newbie 
|
 |
«
Reply #85 - Posted
2008-11-15 23:30:45 » |
|
@Mr_Light: Gosh, that was well written. It also runs smoothly.
Thanks for the lesson. That's me told. I consider myself spanked.
--Mario
|
|
|
|
|
brackeen
|
 |
«
Reply #86 - Posted
2008-11-15 23:49:30 » |
|
your code stutters here too, I've added an adaptation of your original code that works smooth here. it also consumes a fraction of my cpu-time compared to yours.
FYI - putting yield() in a tight loop like that uses 100% CPU on the Mac. If no other threads are doing anything, it's like a no-op. EDIT: oops sorry, I think I was looking at the wrong code. Looks like there's a couple different game loops in there.
|
|
|
|
|
ewjordan
|
 |
«
Reply #87 - Posted
2008-11-16 00:53:20 » |
|
your code stutters here too, I've added an adaptation of your original code that works smooth here. it also consumes a fraction of my cpu-time compared to yours. ps. I won't be handing out cookies for the obvious memory leak that's in there.  For the only-minorly-curious (by which I mean lazy, or - if you're feeling kind! - busy  ) among us that don't have the inclination to diff the jar source (assuming it's included) and the posted code (I'm not even entirely sure which version we're talking about here, there have been several game loops posted), what was the main problem with the original code? Just a memory leak, improper usage of something Java specific, or a logic problem? jezek2 wrote: Generally I see pretty bad pattern on people on various forums... when they have problem in Java they automatically blame whole Java without further examination. If they have problem in C/C++ they're finally looking for cause of problem. Isn't that weird? Well, the trouble is the same as Java's greatest strengths - first, you have a lot less explicit control over everything, which reduces complexity but increases the chance that there is a bottleneck or something similar outside your own code (though this is usually not the case, when you're dealing with graphics you've got to admit that there's a lot of bizarre stuff that you can accidentally do that will ruin performance, and a lot of it is not obviously "naughty"). Second, there is a large (massive, even) body of standard library code that everyone has to rely on, and it does have some quirks, especially performance related ones, which can bite you very easily if you don't know the ins and outs of how to use everything. Worse, if you look for tutorials on how to do these things "properly," you often find bad advice (or advice that may have been good in the 1.1 days but sucks now, or has been superseded by better methods - try searching around on Java optimization, most of the advice on the web will actually either do nothing or even slow down your code on a recent VM!). So the perception ends up being that it's all Java's problem, which is not true; the real problem is just that there are more ways to attempt the same thing in Java, and a lot of them lead to poor quality. A glut of choice, if you will, without many ways to guide you to the right one unless you happen to stumble upon the right answer or interact with someone that has (which is one reason why this forum is so fantastic!). In C/C++ the library code you rely to do simple things like this tends to be far less substantial because you're a lot closer to the hardware, and you don't need to know any details about how it works because each call does very little. If there's a performance problem, it's likely that you've directly caused it, not that you've called some library function that caused it. You also don't tend to have as many options once you've chosen a technology. In most cases you can just cut and paste a snippet from Nehe's tutorials and be up and running with no trouble, so it's perceived as a lot easier. Got to be honest - personally, I feel that stuff like this is far better left to a library if you can find one that suits your needs. I'd much prefer to add a dependency on Pulp Core and let David fight these things if best practices shift over time. He's far better at it than I would be.  I'm sure the same goes for jME and a lot of other game libraries, too, though I can't vouch personally in those cases for the quality of the results. All that said, since this does come up somewhat often, it occurs to me that it would be very useful to have a somewhat detailed and recent explanation of how to do a game loop the right way in Java, perhaps as a sticky. In particular, it would be great to hear the common pitfalls and a bit about why they cause trouble. Anyone up to the task?
|
|
|
|
|
jamongames
Senior Newbie 
|
 |
«
Reply #88 - Posted
2008-11-16 01:38:29 » |
|
it is very easy to blame java virtual machine. 90% of optimazation issues or bugs or something bad in my applet are my fault, no browser or JVM fault. but you realice it, when you find the solution, meanwhile you blame your JVM,browser,SO, the cat...
|
|
|
|
mgianota
Senior Newbie 
|
 |
«
Reply #89 - Posted
2008-11-16 02:33:49 » |
|
@Mr_Light: It still stutters on my machine --I didn't run your code for long enough to see the stuttering effect the first time. It is as if something is throttling the execution thread, slowing it down and then speeding it up.
The *reason* you don't see stuttering as bad with your example is that you are not updating the game objects inline with elapsed time, you just tick them forward a fixed increment at a time. That's why your example looks smoother even though the game objects are actually moving at a variable rate. My game needs physics and that means integrating values over an elapsed time period.
I need to think about this issue some more. Something in the JVM or in the OS is throttling the execution thread.
--Mario
|
|
|
|
|
|