30

Frame based simulations will experience errors when updates fail to compensate for non-linear rates of change. For example consider an object starting with position and velocity values of zero experiencing a constant acceleration of one. If we apply this update logic: velocity += acceleration * elapsedTime position += velocity * elapsedTime We can expect ...


19

Your main problem is likely this: final int skipTicks = 1000 / ticksPerSecond; Dividing an int by an int returns an int (the value is rounded down if needed), so skipTicks evaluates to 16. 1000 / 16 is 62.5 so you get around this many ticks per second. To solve this the easiest solution would be to use a millisecondsPerTick variable (what you are calling ...


9

You could restart your time value every 2pi: if(time > 2*pi) time -= 2*pi; If is still okay to increase your time variable infinitely but the input for the sine is to large, just use fmod(time, 2*pi).


7

Alex's answer seems sufficient, but you say you want more detail, so here goes. First, why does the gameloop from http://www.koonsolo.com/news/dewitters-gameloop/ deliver its desired frame rate while your version doesn't? Because their integer division works out exactly: const int FRAMES_PER_SECOND = 25; const int SKIP_TICKS = 1000 / FRAMES_PER_SECOND; ...


6

It depends on where you're calling your step from. If you're calling it from Update, your movement will indeed be framerate independent if you scale with Time.deltaTime, but if you're calling it from FixedUpdate, you need to scale with Time.fixedDeltaTime. I figure you're calling your step from FixedUpdate, but scaling with Time.deltaTime, which would result ...


6

Get rid of the Sleep call. Sleep is fine for reducing CPU usage, but it is not fine for controlling framerate, and these two are not the same thing. Sleep can have poor precision, in the order of ~16 milliseconds. Sleep guarantees that the thread will resume at some arbitrary time after the Sleep interval has elapsed, not at the exact Sleep interval. ...


6

Yes, you need to keep Time.deltaTime into account when you use Input.GetAxis, because the values it returns are also deltaTime-adjusted. You can read this in the documentation: This is frame-rate independent; you do not need to be concerned about varying frame-rates when using this value. The example code in the documentation makes it clear that ...


6

I've done some tests simulating low framerate conditions, and empirically confirmed that the deltaTime value for each FixedUpdate step does indeed stay consistent. For example, using the default Fixed TimeStep of 0.02 (50 Hz) and Maximum Allowed Timestep of 0.3333333 (as set in Edit -> Project Settings -> Time)... At 60 fps we get 0-1 physics & ...


5

I most often encounter this in the context of Unity, which has the following attributes: Input is checked once per displayed frame, before any of that frame's fixed/variable timestep updates Input is interpreted as one flat state for the entirety of the current display frame, not a queue of events Each logical button has three independent boolean states: ...


5

Games inherited this term from animation, film, and video. There, a "frame" is one still image in the sequence. By playing lots of frames in rapid succession, we create the illusion of motion. See this strip of 35 mm film from the Museum of Obsolete Media. In it, we can see three consecutive frames of a Spider-Man movie. The framerate of a piece ...


4

You will unfortunately never get a behaviour that is 100% consistent across framerates, but it’s worth trying to approximate. Here is my suggested solution and the explanation of the maths behind it. Consider what happens to distance after your update: it becomes distance * (1 - factor) since the camera moved by distance * factor. If the player wasn’t ...


4

It’s because, in general, jumping involves applying an impulse instead of a force. You apply forces when the interaction is expected to last for at least some time. For instance, gravity is a force: it lasts more or less forever. Pushing a door is applying a force, too: you keep pushing while the door opens. You apply impulses when the interaction should ...


4

So I have struggled to get this right and this is what I currently use. The point is to have a friction value that is dependent on time and therefor works on low and hi end devices similarly. //*** Set friction value friction = 5f; //*** Calculate Fiction decay xRatio = 1 / (1 + (Time.deltaTime * friction)); //*** Decay velocity velocity *= xRatio; //*** ...


4

I think you need to rethink what you're trying to do. Look at the last lines in your example move forward code var scalar = //**IDK what goes here something that considers the fps**// player.position.x += units * scalar; Now look at the normal movement scaled by time code player.position.x += 1 * dt Notice the similarity? I understand that you have ...


4

I'd go with something like this (pseudo-code): spawnProbability = 0.001 // Your original probability at fixed timestep spawnAtThisFrequency = 1/30 // The original fixed timestep dt dtAcc = 0 // An accumulator that will accumulate the variable dt update( dt ) { dtAcc += dt; // Accumulate while( dtAcc >= spawnAtThisFrequency ) ...


4

On some platforms the game actually starts running before the splash screen is gone. So this may give the illusion of a defective timer if you test it right at the start. Another issue on slow devices is that your first frame of timer activation may have a very large deltaTime if other things happen at the same time. For example if it takes 2 seconds to ...


4

Your lerps and slerps are backwards: lerp(current, previous, alpha) should be lerp(previous, current, alpha) ie. increasing alpha (more time accumulated since the last update) should move us toward the future, not toward the past. This could account for at least some of the choppiness you perceive. There could be additional judder coming from the player ...


4

But how does this get setup to begin with? The client connects to the server, the server starts a game... does the client jump ahead of it's own accord? (Server says "game is starting, I'm at tick 0", and the client is like "okay, well, based on my ping I'm going to be tick 20 then") No. Once the connection is established, the client ...


3

If my assumption that you want your speed to lose 2% of its value every second, then this is a perfect opportunity to use the exponential rate of decay expression, which looks like this: A=Pe^(rt) A is the final amount you want (so, after 1 second, .98(vx)) and P is the initial amount. t is just time, so since you want the velocity to only be 98% of its ...


3

I assume GetTicks() is standard SDL. In which case when I look at the documentation is says "Get the number of milliseconds since the SDL library initialization." However all your calculations seems to be in seconds. So if you treat the output from GetTicks() as being seconds you are gonna effectively be running 1000 times faster. Or you would if it weren't ...


3

Ok, think I got an answer for you. The short version: compute the friction force F = friction * velocity before you start the loop and apply it in do Physics() like this: v -= F * deltaTime. Long version: the assumption you're making that it should work independent of frame time only works with constant acceleration, like the one you're applying in ...


3

I share the skepticism @Estharon expresses about whether players will enjoy a 30-minute non-interactive battle, but I'll answer as if it's a given that these will be interesting events. Unless there's a compelling reason for this to take exactly 30 minutes, I would make a sequence of smaller fixed or randomized decisions (balanced around a target duration) ...


3

Expanding on Stormwind's lead, I'd be curious whether your application needs a windowed average with equal weights per unit of time, or if an exponential moving average may suffice. The latter is very simple to implement, and can be adapted to a variable framerate like so: float weight = 1 - pow(1 - responsiveness, dT * referenceFPS); smoothedValue += (...


3

JavaScript On the browser For code running in the browser, I would strongly advice to use requestAnimationFrame as game loop. See availability. Example: function update(timestamp) { // ... window.requestAnimationFrame(update); } window.requestAnimationFrame(update); requestAnimationFrame takes a callback that will be called once per frame, ...


2

deltaTime = (float)(currentTime - previousTick) / 1000000.f It's a simple floating point bug. When you divide an integer by another integer it returns an integer. This truncates all your decimal detail.


2

As Sean says you are really just using the accumulator to enforce a fixed time step, this is likely to look very jumpy in comparison with the rest of your game. This would be one approach that applies movement on each update: class Camera { const float factor = /* low values for "tight" movement */; void update (float timeElapsed) { ...


2

The fix is simple, integrate position in the middle of integrating velocity. (As in, add half of the force, update, then add the other half.) Here is a more in-depth explanation: http://www.niksula.hut.fi/~hkankaan/Homepages/gravity.html


2

I would still use GameTime to track the passage of time (no sense reinventing that wheel), but I would not bother storing it in your MyTime object and you certainly shouldn't try to subclass GameTime. Just create your own type with whatever fields you want and then use the GameTime provided to the Game class to update your instance however you want, applying ...


2

The approach by Narrateur du chaos is commonly called the delta-t approach. But there is also another approach, the game-tick approach. In this approach you keep track of how long the game is running in real-time and how much time the game-world has processed. After each graphics frame you check how far the game world lacks behind the real world and do ...


2

Considering how the ratio is calculated, the culprit seems to be the delta time (time step). It is the only variable that depends on unknown factors in the context of the calculation. The issue described is likely caused by a variable time step. In that case, the counter would not increment uniformly, but faster or slower depending on arbitrary conditions. ...


Only top voted, non community-wiki answers of a minimum length are eligible