4 ms·
I implemented this in C++ for a commercial game engine many years ago. Both internally, and in the API used by games on top. We used Emacs-Lisp to generate a
by jlokier 7y ago
I implemented this in C++ for a commercial game engine many years ago. Both internally, and in the API used by games on top.
We used Emacs-Lisp to generate a collection of C++ classes with all of the arithmetic operaters that were allowed, and only those. "friend" is your friend for this in C++.
We mostly used floating point to represent values, but could also use integers with scale factors (automatically applied in the operators), which is nearly equivalent to fixed point.
For things where vectors made sense, 1d, 2d and 3d vector types were available. So Position2d and Position3d.
Absolute and relative values were distinguished: You could substract two absolutes to get a relative, but you couldn't add two absolutes. You could add a relative to an absolute to get an absolute.
And for time intervals we used wraparound arithmetic and comparisons, like the Linux kernel has the time_before() macro, so absolute times could continue "growing" without overflow in a running game.
Using the classes looked like a bit like this:
Position3d p1, p2;
Direction3d d = p2 - p1;
Absolute_Time t1, t2;
Time_Interval t = t2 - t1;
Velocity3d v;
object.set_position(p1 + t * v);
These types were used pervasively throughout all the game engine, gameplay logic, "AI" and so on.
The constraints provided great type-checking and effectively documented a lot of code as well.
This being a game engine, they had to be fast. So they were all inline methods, in classes containing just a number, or up to 3 numbers for vectors.
Using GNU C++ this compiled down to the same machine code as if we hand-coded the arithmetic in the traditional way; we checked. So there was no runtime cost.
It was very satisfying to use.