Given that you appear to allow position to end up non-integer why worry about exact pixel movement in the first place?
My C++ is rusty but given your code the following will step by 0.8 four times instead of 1 three times followed by 0.2
Make this small algorithm branchless ?
What about using the loop with the floored value, then always doing the else part after the loop?
yes - that is the traditional algo for "stepped" movement.
steps = amount div stepsize
remainder = amount mod stepsize
for i=0 i<steps i++
{
move(stepsize)
}
move(remainder)
Norm Barrows
Rockland Software Productions
"Building PC games since 1989"
PLAY CAVEMAN NOW!
http://rocklandsoftware.net/beta.php
Is there a specific reason that you're using double instead of float?
#define is evil for that usage; use an inline function - that's what they're for.
Your sign function is crazy inefficient (and in integer math!). How does that not produce compiler warnings? It translates to this:
inline int sign( double x )
{
int a = (x > 0.0) ? 1 : 0;
int b = (x < 0.0) ? 1 : 0;
return a - b; // integer result!
}
And then you add it to a double, so there's an implicit int->double conversion on top. There's a lot of trust there that the compiler will figure out what you mean and fix the code...
Also, unless you need the three-result version (-1,0,1), use a two-result version, and stay in float land instead of converting to int and back:
inline float sign_bit( float x )
{
return x >= 0.0f ? 1.0f : 0.0f;
}
The loop is bad:
for (int i = 0; i < ceil(fabs(X)); i++){
//note: X does not change within the loop.
//Don't make the compiler try to guess whether the loop body modifies the loop condition or not.
//Make it explicit, make the compiler's job easy:
for (int i = 0, end = (int)ceilf(fabsf(x)); i != end; ++i){
Likewise, these computations are used in the loop body, but are constant, move them before the for statement:
float absx = fabsf(x);
float signx = sign_bit(x);
The loop then reduces to:
float absx = fabsf(x), signx = sign_bit(x);
for (float i = 0, end = ceilf(fabsf(x)); i < end; ++i) {
float f = (absx-i < 1.0f) ? x-i : 1.0f; // you had an implicit int->float cast of 'i' here, may as well make the loop counter a float to avoid it
position += f*signx;
}
What is this algorithm anyway? I assume there's more to it, otherwise you'd just do something like: position += x; :lol:
. 22 Racing Series .
Wow thank you all for your answers ! I'm really not thinking the problems in the right way sometimes :D
Is there a specific reason that you're using double instead of float?
I use double after reading that they're a more native type for the CPU, having better performance (since floats have to be emulated) except if you have tons of them filling the cache then it'll be slower.
For the sign function i'm using pure C (no C++) and Visual Studio 2013, which unfortunately supports only C89 (yeah that sucks...) so inline doesn't work. Is #define still a good option or better use your sign_bit without making it inline ? (or just get a better compiler i know.. :D)
//note: X does not change within the loop.
//Don't make the compiler try to guess whether the loop body modifies the loop condition or not.
In fact, i change X within the loop... it may be a design issue though. I set X to zero when a collision occurs which stops the loop, but i also increase it sometimes when the player enters a slope. (its probably bad since the additionnal loop iterations will be processed within the same frame). Using breaks and never modifying a loop increment is a good practice I guess?
What is this algorithm anyway? I assume there's more to it, otherwise you'd just do something like: position += x; :lol:
It's the collision algorithm for my 2D platformer. It's not that straightforward since the ground is made of straight and angled tiles, the engine should handle good physics with all tiles combinations and high speeds (a bit like Sonic, but it won't be the same gameplay)
Given that you appear to allow position to end up non-integer why worry about exact pixel movement in the first place?
My C++ is rusty but given your code the following will step by 0.8 four times instead of 1 three times followed by 0.2
You are absolutely right ! I was too much thinking about pixels, having smaller increments is fine. I think i can also increment only the integer part, letting the floating part grow in an accumulator, the display is pixel-perfect so it should not matter. I have to carefully test how the physics are impacted though. I just tried and it seems to work well while staying simple :
static double xacc = 0;
xacc += xVelocityOfMyObject;
while(xacc <= -1 || xacc >= 1){
objXposition += sign(xacc);
xacc -= sign(xacc);
// other calculations here
}
Now i laugh at my first algo, uselessly complicated where this solution and yours are so much better :D