30/Distance = force

Hello rubber ducky.
I'm writing a game that runs at 60fps.
I'm trying to come up with a way to push one object harder if they are closer to the pushing object than if they are further apart.
(if player is next to explosive punch, fly out of bounds. If player is 20 pixels away, toss them at half speed. If player is barely within range then do a couple pixels of knock-back).
My initial thought looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void player::shove(item * other)
{
    // all member variables are floats
    float distance = posX - other->posX;
    if(dist > 0.003f || distance < -0.003f)
    {
        this->speedX = 30.0f/distance;
    }
    else
    {
        this->speedX = 30.0f;
    }


}

My goal is to avoid the division operation.
Having written the above description, I realize I could do this as a piecewise function with 3 or 4 if statements each checking range, but I don't see that being much faster than a single division operation (except where the first if operation is more likely than the last if).

So for today I'll wrap this in a big box-check to see if any objects are in range before getting into the slower calculations.

Edit 1:
How about concentric circles, adding more force for each one that they come into contact with. Can be used to get appropriate angle...
To get the angle we'd use sin and cos, and I was already concerned about division.
But if I take the number of enemies down a notch, then we can get the number of checks down as well. That will take some testing to get right, but I think anything less than a couple hundred enemies on screen should be fine. Again, doing the box-check to get that number down even further, and in all likelihood no more than 10 enemies will ever be in the explosion box range.

I think I've talked myself into using more expensive operations/functions and reducing the number of effected objects overall.
Last edited on
Conditions are a little costly, division is fairly cheap.
crossing an axis ... is that really useful for your code? If you kept your working area in the positive axis area only, its a little simpler.
this-> is an uglifier that is rarely necessary. just say speedX, and possibly pass other by reference instead of by pointer, just to generally clean it up.

anyway... exploit the known value of boolean expressions, which are 1 or 0, to cook up a no-condition expression.

float booler = (float)(!(dist > 0.003f || distance < -0.003f));
speedX = 30.0*booler + !booler*(30.0/distance);
//should be if your condition is false, 30*1 + 0*30/dist = 30
//if your condition is true, 30*0 + 1*30/dist
Last edited on
OK. You kind of just rocked my world there. Last time I ran any kind of speed testing, float division was a major bottleneck (about 26 clock cycles on the computer I tested on, though that was a low-end machine even when I bought it 6 years ago, Walmart discount priced).

I've got my research hat on now, and it's looking like fdiv is a single micro-op instruction? Wow, I'm feeling like a dinosaur. Super-scalar processing, out of order processing, branch predictions, etc.

Dang, being a cheapskate and hobby-programmer can bite yah in the rump sometimes. I'm going to have to change a lot of my coding strategies.
Last edited on
Topic archived. No new replies allowed.