I am making a Java game. It's intended target platform is NOT Windows, but I'm still going to write it in Java. So, I have a pretty basic question, but there's a few different rather complicated answers.

My question is this: How can I make the most efficient engine, or main loop, which ticks and does gameplay action (moves character, enemies, etc.), while also dealing with repainting? There are a few different ways to do so.

Method A:Put delay in the tick() method. Here, the game loop logic, and the repainting, is done on the same thread. If the game processing and drawing takes longer than the delay, then the game will simply slow down. I'll have to code efficiently!

Method B:Calculate the time delta in the tick() method, and move enemies and other game logic according to how much time has passed. The game will always appear to run at the same speed, although the FPS will go higher or lower depending on the processing load of the game actions and drawing.

In the above logic, you see that enemies will move depending on the time taken. So, if it took 50ms, they'll move by 10 pixels, or if it took 25ms, they'll move by 5 pixels.

The problem with this method, is that in-game logic timing becomes hard. What if a gun is supposed to fire 3 times a second? If the processing theoretically took a total of 1 second, I would have to fire the gun 3 times in the same tick(), which is bad because what if you'd want a back and forth between two entities (A interacts with B, B interacts with A, etc., instead of A interacts with B x 3, and THEN B interacts with A x 3). Or, in some cases where the logic just fails, the gun would only fire once when it was supposed to fire three times.

Interesting, my code does the inverse. But then, I never wrote a serious game.

Riven, I do it the same as you. Rendering gets second priority, whereas logic tries to be smooth. Probably depends on the game. The reason why rendering gets left out is because I need fidelity of input (thus I need to capture it frequently) whereas FPS are not so important, as long as the user can't really observe any graphical hiccups. Also, rendering in my games usually ends up taking much longer than the logic, so it makes sense to let the logic run free and reign in the rendering instead. I imagine Markus's games don't often suffer from these problems because he so often has very complicated game algorithms but very low res textures (like Minecraft as a good example).

I have most of my games run at a game logic of about 30-40 hz, while rendering the game as fast as possible, interpolating the state between the last two ticks.

Same here.

@DemonpantsThe same approach Markus_Persson described can be used to run the logic at any fixed speed. This means you can place the input checks in the logic. Letting your simulation run at whatever speed it can means if that speed is very slow, everything explodes. Not prioritizing rendering means that objects may not move smoothly. Markus_Persson's games don't have problems because his time step approach solves them all.

It's not about prioritizing framerate over game feel at all. It's actually about making sure the game plays exactly the same on all computers (see the link Nate posted). The fact that the framerate gets as smooth as possible on any given computer is just a nice side effect.

There are a couple of downsides to this approach:

* If game logic takes a long time, every n'th frame will render slower than the rest, causing stuttering graphics* The game visuals will always lag behind by 1/game_logic_hz seconds because of the interpolation. (Of course, this has the upside of putting the graphics more in synch with the audio if you tweak it right)* If a game logic step takes more than 1/game_logic_hz seconds on a computer, the game will never catch up and the game won't be playable on that computer.

Hey, don't knock it! A lot of my "smaller" games (ludum dare, 4k) use fixed 60 hz logic.A major advantage of that system is that each frame takes about as long to process and render, so there's not as much uneven framerate.A downside is playing a 60hz game on a monitor running anything other than 60 hz (except perhaps 30 or 120 hz) WILL get choppy.

@DemonpantsThe same approach Markus_Persson described can be used to run the logic at any fixed speed. This means you can place the input checks in the logic. Letting your simulation run at whatever speed it can means if that speed is very slow, everything explodes. Not prioritizing rendering means that objects may not move smoothly. Markus_Persson's games don't have problems because his time step approach solves them all.

Hm, interesting. I've always just used a delta to make up for stutters - if it has been a long time since the last step then everything will move a little bit further. But I suppose it makes sense in most settings to try to fix things around the graphics, if I really think about it. Having the logic stutter is not nearly as observable as having the graphics stutter.

Usually I make it so that updates happen about 3 times per render. And obviously it goes as fast as it possibly can. Problem with this obviously is that it uses up your whole processor no matter what. I've been using the iPhone lately so this doesn't matter, but usually when deving in Java I just use the sync() method in LWJGL so I don't have to bother with it. Also, the reason I render less often on the iPhone is because long renders will lock receiving touch input which can cause very annoying control. So I update much more often. In Java I guess this isn't a problem typically because input is usually handled in another Thread anyway. Although I'd imagine with LWJGL you might want to do this so you can poll the keyboard more often.

It's very important to have a fixed tickrate, to keep your game deterministic, which is a requirement for any (serious) networked game.

update(delta) is the root of all evil, unless delta is a constant

Yeah I guess I never spent enough time thinking about it. The first time I put a custom loop in the game (I had been using java.util.Timer previously, which is even worse), I was using an example that Kev made (Space Invaders) that attempts to achieve a constant FPS but allows fluctuation to happen. Or so I thought when I originally looked it. Since then I've been doing my own bastardized method.

So say you're trying to get 60 fps but the game is only able to get 40 fps. Doesn't that mean that you should be passing in a delta of 60 / 40 - moving everything a bit extra to make it all appear like it's working the same? Or should you just do like Markus suggested and go for a low easy to achieve logic frame rate (around 30 hz) and let the rendering take as much time as it needs? I guess really what should happen is you force the logic to maintain its 60 hz as best you can, sucking away from rendering frequency if you're having trouble meeting your desired hz. Yes/no?

I think I'm honestly going to go and adjust some of my game loops now, because this makes a lot of sense to me now that I'm actually thinking about it.

I'm attempting to get frame interpolation in my game working (just messing around with different types of game loops), and the result is very twitchy entities. I'm not sure if I'm doing this right.

So here it is distilled a bit:

In the update for the entity, it will add its acceleration to its velocity, then its position will be position + velocity.In the draw for the entity, it will be drawn at position + velocity * interpolation.

In the update for the entity, it will add its acceleration to its velocity, then its position will be position + velocity.In the draw for the entity, it will be drawn at position + velocity * interpolation.

It sounds like you are doing extrapolation. You don't want to guess where the object will be next frame, then sudden movements can render your guess incorrect and the movement will jump around. I recommend the link I posted earlier.

Snapshot the state of the game before each fixed logic step. Now you have the previousState and the currentState. Since you did a fixed logic step, you may have stepped < the delta. Do alpha = 1 - timeRemaining / fixedTimeStep to get a number between 0 and 1. Interpolate by rendering at the previousState + ((currentState - previousState) * alpha). This introduces one frame of latency, but no guessing is involved.

Note the accumulator is int. The fixed steps are 16ms (60hz). Because I know the logic will always happen in 16ms increments, I base all my speeds on this (note I don't even bother passing the step to integrate()). Eg, if I move an object each logic step by 20 * 0.016, then it will move at a speed of 20 pixels per second. By doing this, in the above code I can use speed = 1 for normal speed or I can do slow (speed < 1) or fast (speed > 1) motion without ruining the simulation.

if you want smooth interpolation (that take care in a certain manner of acceleration) try cubic interpolation

That has one MAJOR flaw. If a ball is moving towards a wall at 100 mph at tick n, and hits the wall one tenth of the way between tick n and n+1, the renderer will interpolate the ball as moving into the wall and back out.

I always use linear interpolation. It's fast and it works well.For things like pinball and such where collisions are important, I build a list of all collision points during a tick, then interpolate (linearely) between those when rendering.

That has one MAJOR flaw. If a ball is moving towards a wall at 100 mph at tick n, and hits the wall one tenth of the way between tick n and n+1, the renderer will interpolate the ball as moving into the wall and back out.

I always use linear interpolation. It's fast and it works well.For things like pinball and such where collisions are important, I build a list of all collision points during a tick, then interpolate (linearely) between those when rendering.

I also usually use linear interpolation, but as Demon talk about acceleration cubic interpolation fit better. this is only a flow if you use it "brut force" and only interpolate position without doing anything else (you can handle such case pretty easily),

also in the case your mention (as I understand it).... linear interpolation will just make the ball never touch the wall like if a magnetic field keep it away, it is as false than going throught.... :p

the advantage of Cubic vs linear is that you can subsampling it into smaller linear part and compute real collision(avoid the MAJOR flaw), subsampling linear will have no effect and will stay as false.

Thanks for all that, guys. I'm definitely going to go with the state approach as mentioned above - I've already got previousPosition and position stored, so all I need to add is previousRotation and it'll work fine. I wasn't really seeing it as being 1 frame behind which is what my original problem was, I think.

I'll let you all know how this works.

EDIT - Doing it via state looks great. Very stable and not twitchy. Thanks everyone. I'll definitely make my loops like this in the future. It's a lot nicer to not have to worry about a delta variable all the time, too.

also in the case your mention (as I understand it).... linear interpolation will just make the ball never touch the wall like if a magnetic field keep it away, it is as false than going throught.... :p

I find it much less jarring with linear interpolation than cubic, and the overhead of doing a "clever" (ie world aware) cubic interpolation is probably a LOT bigger than you assume. I'd rather list all collisions within a tick and interpolate linearely between those.

Including acceleration in the interpolation, however, is a very good idea if you manage to do it right, but it'll only matter in games where things change direction a lot.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org