So an object has a position, velocity, and is affected by gravity.
#include <simd/simd.h> // MacOS
struct Object {
vector_float3 Translation; // Units
vector_float3 Velocity; // Units per second
};
The game loop typically runs 60 times per second.
void ObjectUpdate(struct Object *obj) {
obj->Velocity.y -= 9.80655/60;
obj->Translation += obj->Velocity/60;
}
There are a couple problems with this approach:
- Lag exists, so the assumption of 60 updates per second being embedded in the code is not great.
- Floating point types are susceptible to precision errors at far distances from the origin, and are also more difficult to handle in some ways than integers.
I attempted to solve these with a fixed-point approach, and the use of clock()
as well as keeping track of the time of the last update.
struct Object {
vector_long3 Translation; // 65536ths of a unit
vector_long3 Velocity; // 65536ths of a unit per second
clock_t LastUpdate;
};
void UpdateObject(struct Object *obj) {
const clock_t current = clock();
const unsigned long delta = (unsigned long)((current-obj->LastUpdate)*(clock_t)65536/CLOCKS_PER_SEC); // Try to find the number of 65536ths of a second since the last update, in a way that it does not matter whether clock_t is integral or real
obj->LastUpdate = current;
obj->Velocity.y -= delta*642682>>16; // 642682 = 9.80655*65536
obj->Translation -= delta*obj->Velocity>>16;
}
However, this suffers from other problems, most notably, being extremely chunky and unreliable. If I simply add delta
to an accumulator and then print the accumulator, the value rises at an inconsistent rate, typically much slower than by 65536 per second.
How should I handle objects that need 'constant' updating and their updates are contingent on time?