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?
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. >:(
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.
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?
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:
[quote]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?
[/quote]
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?
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…
@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.
For 2d using fixed time steps generally produces much better results (because as you’ve found variable steps can stutter and look bad). In fact even for 3d games fixed time steps have a whole bunch of advantages (determinism mainly). Depending on your game you may want to do fixed rate logic and rendering or fixed rate logic with variable rate rendering.
You’ve made a lot of fundamental mistakes over the course of this thread and have blamed the vm and java for your own mistakes. I suggest you do some proper background research and come back when you’ve got a better grasp of the basics.
I know how to write a game loop with a fixed time step, a variable time step and move objects in discrete increments and I know the benefits of these aproaches. I also know how to compensate for variable time step physics simulations by decoupling the physics update from the framerate and using an alpha blending approach to cope with any remainder problems. In short I know how the mathematics for game loops work. 8) Your comments are simply unfair.
Anyway, it still stutters regardless of whether you use a fixed, or variable time step. The C code doesn’t, which is strange because the JVM writers have access to the exact same C libraries that I do. If you write games in pure Java they stutter. I’m sorry but I think I’m correct, Java is not a good language for games development. Or more accurately, the JVM is not a good platform upon which to build a game.
If you use a native lib to do your graphics, input and sound then you might as well continue writing the game in C. At least in C you can synchronize the main loop properly. I think it is Java’s shortcomings in the timing and synchronization arena that you are attempting to vainly support (it is obviously inadequate) and that you’re just making excuses for Java’s stuttery, laggy games performance by pointing the finger at my coding errors which were Java specific and based upon lack of experience in Java. It isn’t fair to dismiss me as having made basic fundamental errors simply because I am new to Java. Let’s face it, the code that I posted was pretty simple stuff and it was a fair translation of how you implement a simple game loop. Works in C, doesn’t work in Java. Hmm… why not? That was the basis from which I approached the problem.
Why is it that Java games require a native library to handle the graphics & input in a satisfactory manner? Is it because pure Java simply sucks from a games development point of view? I think so. And it is obvious that others do too otherwise they wouldn’t need the native libs.
Here is my simplified loop (specific stuff taken out). At least I get decent accuracy and little stuttering using it. It doesnt differenciate logic and graphics, but that was a conscious choice on my part.
public void run()
{
long startTime = System.nanoTime();
int frameCount = 0;
cycleTime = 0.0;
// additional init stuff
while(isRunning)
{
// Update and render
if(drawable != null)
drawable.display();
// Increase frame count
frameCount++;
// Loop until our time is spent
while( ((cycleTime = System.nanoTime()-startTime) / aimedFPSFrame) < frameCount)
{
Thread.yield();
}
// convert to ms for loop values
cycleTime = cycleTime / 1000000.0;
// reset counters
startTime = System.nanoTime();
frameCount = 0;
}
// clean up
}
So if some basic stuff stutters using this, then I dont know what to say “It works here” ™
Hmm… You can’t do a Thread.yield() in your delay section as it will peg the CPU. It is better just to put the thread to sleep for the length of the delay time. Additionally, the AWT thread is running at a higher priority than your game thread so you don’t need code that gives it a chance to run. As far as I am aware, the only time you need to use yield is when you have a thread running at maximum priority and you need to give lower priority threads a chance to run.
I really want to get this stutter problem sorted out but I’m beginning to think that it is impossible.
Did you try it? I’ve had my share of Thread.Sleep loops, trust me. And it will only yield when you want it to, too. (And it won’t hog the cpu. Why dont you try it before you say these things
Anyway, it was a suggestion to you. I use it, it doesnt stutter, it doesnt hog the cpu, and it works well for me. If it doesnt work for you, then I dont think Java alone is to blame.
Edit: Ok, explanation. You will of course “hog” the cpu if you aim your fps low enough (to stabilize the loop cycle) and waste most of the cycles, but that’s basically the “fallback” mechanism. And as I use the EDT for I/O, I dont mind. Normally you’d be using most of these cycles though. Thread.Sleep is in my opinion waaay to unpredictable, and I find it very difficult to stabilize the loop with it alone (You can program your way around it by computing averages, but it seems like such a waste)
Greetings mgianota. I’m learning java and lwjgl as well. I’m still a novice really so i dunno if I am thinking correctly. :-\
I was just lurking around I thought we have a similar problem but it seems in your box program, there is something odd in your implementation of fixed time step.
If I interpret the first part of the article about Fix timestep correctly. You just let the render loop run and remember the elapsed time it took to make the loop. The accumulator in the render loop accumulates how many dt updates is possible within the time frame of the render loop. If the render took a long time, the update loop will run until the accumulater is less than the dt, if the render loop took a short amount of time, the update loop will wait till the next render loops if its time for another update.
Here is a portion of code in your render loop that i found odd:
// Delay for a period of time equal to 1/60th of a
// second minus the elapsed time
elapsedTime = System.nanoTime() - time; <----- also your elapsed time didnt account for the while loop below
delayTime = frameRate - (double)elapsedTime;
time = System.nanoTime();
while( System.nanoTime() - time <= delayTime)
Thread.yield();
your NOT suppose to control how long the render takes by stalling it based on specifying an exact time since Thread.sleep() and Timers have a slight inaccuracy anyway.
I suppose this way, If you want to limit the fps, you can add a Thread.sleep(var) in the renderloop since it wouldn’t matter if its accurate or not since elapsed time & accumulator will pick up on this.
Btw, guys, is this minor inaccuracy of thread.sleep() & timers the case in all Programming Langages? Whats the cause of this? CPU? Implimentation? OS?
That code is broken through too much hacking. Below is the code I’m currently using. It is based upon feedback from Mr_Light and it is better than my original version but it still stutters. BTW it is not true that Thread.sleep() is innacurate. The method has a resolution of 1 millisecond and it seems to sleep for exactly that length of time.
If you’re interested in this problem, here’s the current test code:
package gameloop;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferStrategy;
/**
* A basic game loop.
*
* @author Mario
*/
public class GameLoop implements KeyListener {
/*
* The display window
*/
Frame mainFrame;
/*
* Saves the time in nanos at which the last frame was drawn
*/
long lastFrameDrawn;
/*
* The frame rate cap. Set to 60 fps here as a default.
*/
long fpsLimit = 60;
/*
* Stores the frames per second.
*/
long fps;
/*
* Saves the last time we looked at the clock.
*/
long lastTime;
/*
* Saves a count of the number of frames drawn per 1 sec interval.
*/
long frameCounter;
/*
* Saves the elapsed time in nanos.
*/
long elapsedTime;
/*
* A rectangle to use as a basic game object to move
* around on screen.
*/
Rectangle2D rect;
/**
* Create a new GameLoop that will use the specified GraphicsDevice.
*
* @param device
*/
public GameLoop(GraphicsDevice device) {
try {
// Setup the frame
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(2);
mainFrame.addKeyListener(this);
// Uncomment this code if you want to see the game loop run full
// screen. Running in full screen will enable the buffer strategy's
// vertical retrace lock which should result in smoother animation.
//device.setDisplayMode(new DisplayMode(640,480,8,DisplayMode.REFRESH_RATE_UNKNOWN));
//device.setFullScreenWindow(mainFrame);
// Cache the buffer strategy and create a rectangle to move
BufferStrategy bufferStrategy = mainFrame.getBufferStrategy();
rect = new Rectangle2D.Float(0,100,64,64);
// Main loop
while(true) {
long time = System.nanoTime();
elapsedTime = System.nanoTime() - time;
updateWorld(elapsedTime);
// Draw
Graphics g = bufferStrategy.getDrawGraphics();
drawScreen(g);
g.dispose();
// Flip the buffer
if( ! bufferStrategy.contentsLost() )
bufferStrategy.show();
// Synchronise with the display hardware. Note that on
// Windows Vista this method may cause your screen to flash.
// If that bothers you, just comment it out.
Toolkit.getDefaultToolkit().sync();
yield();
calculateFramesPerSecond();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
device.setFullScreenWindow(null);
}
}
private void updateWorld(long elapsedTime) {
//double xMov = 0.001 * elapsedTime;
double xMov = 2.0;
rect.setRect(rect.getX() + xMov, 100, 64, 64);
if( rect.getX() > mainFrame.getWidth() )
rect.setRect(-rect.getWidth(), 100, 64, 64);
}
private void drawScreen(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, mainFrame.getWidth(), mainFrame.getHeight());
g.setColor(Color.WHITE);
g.drawString("FPS: "+ fps, 0, 17);
g.setColor(Color.RED);
g.fillRect((int)rect.getX(), (int)rect.getY(), (int)rect.getWidth(), (int)rect.getHeight());
}
protected void yield() throws InterruptedException {
long delayTime = 1000000000L/fpsLimit - (System.nanoTime() - lastFrameDrawn);
if(delayTime > 0) Thread.sleep(delayTime/1000000);
lastFrameDrawn = System.nanoTime();
}
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 GameLoop(device);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Euh yeah I also included the old code (Main.java), Game.java & co is the newer code.
Latest version he posted, but I worked of one of his earlier ones.
His fps limiter was off I think, it automaticly went away by pulling the code apart. And using sleep(); to actually un-schedule the thread. Adding sync() - Which as indicated before makes a huge difference.
Well that relates to why I stopped after 30 mins or so, I didn’t want to create another library while there are probably tons of better ones already out there.
Does the fps drop below 60? cause then all bets are off. - For single player gaming - well I’m against hard coding minimal specs, I’ve played red alert on a 386 and we had fun. For networked gaming it shouldn’t matter - to stay with red alert the game will go out of sync, so a minimum is enforced automatically.
Now you can trottle the game speed (even in network games, see supreme commander) based upon the available power. But game play shouldn’t be affected - so it will only work for some games. That and it needs to swift gracefully - small delta’s - else again it will effect gameplay.
To have anything reliable you just need a minimal fixed steps of your game logic being executed. For single player you might think well if I update logic and not draw it what’s the use. For multi-player it’s a bit different cause syncing take importance over a frame drop.
As for Laptops Pc’s and speed stepping / amd equvialent you have to counter that you need to facilitate that a bit I can make some comments on that but most likely someone else on this forum can elaborate on this better.
If you are above 60 frames everything should move at a fixed rate. - though the code should probably be refined to ensure this. Distribution of executing with a set small enough bock of time shouldn’t matter as it is not perceivable by human senses - and we are making games for humans right? With blocks of time made out of those small blocks with fixed executions we can guaranty linearity and fixture. Btw yield is probably even less predictable then sleep as sleep allows the scheduler to make a strategy for waking it up the closest possible by the scheduler to the specified time. If you’d want more precise you’d have to go beyond the sceduler(provided the sceduler is well written). - not something I advice, as inherently you will still have the same problem.
I am somewhat out of my comfort zone here, so do fact check if (large piles of) money is involved. :persecutioncomplex: - but then again you should probably do that with any information received from a public forum on the internet
I’m not sure what’s so wrong with using a library to achieve what you need to…? I mean it’s second nature to C programmers to use libraries right? And saying that if you use a native library you might as well just go C all the way is just crazy talk. The whole of Java is built with native libraries that interact with the OS! The LWJGL is just one that adds some extensions that make proper game development possible and easy. On their own, the Java standard libraries are not quite good enough.
There are some ideas i didn’t see discussed much. What would it take to make the Java platform better for making games?
First of all, i don’t think any of this would make it into the Sun JVM. The Java platform development direction is largely influenced by enterprise developers. Enterprise web applications are where Java rules, and where the money in Java is, not in games developed in Java. This means that all the decisions which RFE-s to implement is driven by needs of enterprise web applications, and not games.
The Sun JVM is open-source (OpenJDK), so in theory it would be possible to make a branch version of it, which is more focused on needs of games. The distribution of such a JVM is problematic, because it needs to be distributed with the games itself, so applets and JWS is ruled out, but at least there would be a better Java platform for desktop installable games.
What could this custom open JVM do better/differently than the Sun JVM?
A different native interface. The JNI has problems. It calls functions in dynamically linked library, with passing environment, object reference, and all access is going trough that. What it lacks very much is possibility to inline functions. The JIT compiles Java code to native code, but JNI function calls are going back to JVM and then to JNI. Why not have something as a “Java Driver Interface”? This interface would extend the JVM from the bottom, just like drivers are extending an operating system. These would be special function libraries, that can be called and functions even inlined (if designated so) by the JIT into the machine code compiled Java code. So for example, glDrawElements would be a call to OpenGL function library, with C call convention and if requested inlined into JIT compiled Java code. The binary format of these drivers would be proprietary, suited for tight integration into the JVM.
Manual control over object allocation. In my application i have different allocation scenarios. Some objects are allocated for the whole run time of the game, some are for the currently loaded level (geometry, textures), some are used for the duration of rendering one frame, and some are used for a single call (for example collision detection, stack allocation would fit for these). So the heap could be divided into segments based on allocation scenarios, and all the objects in a segment could be wiped out with a single call to a pointer reset when they are not needed any more. This requires more work from the programmer, than the automatic garbage collector. But every one who tried optimizing by using object pools and reusing objects, had to write code for that anyway.
More aggressive, and manual control over the optimization process. If the JIT is in doubt to eliminate an array bound check by itself, why not let the programmer hint it at his own responsibility (with a pragma for example)? Security is not guaranteed, but those who work with OpenGL have JVM crashes regularly anyway, which need to be eliminated by proper testing, and not by the JVM by default being safe but less performant.
Structs for Java. OpenMP for Java. Now!
The regular answer for ideas like these is: “use C++”. The C++ has its own problems, which in my eye are just as worrying as the suitability of Java for games.