-1

I am trying to make a game involving the calcualtion of forces needed to perform some simple mathematical operations. I have a dx variable that represents both the speed and direction along the X-axis. Now I want to subtract friction but it would have to be an addition if the direction of dx is negative. Is there any way to subtract friction from dx using absolute values while returning a signed value? I was looking in to bitwise operators but I have no idea what the possibilities are...

What I could do (i think):

sign = ( dx >> 31 ) << 31;
dx = (dx << 1) >> 1;
dx = ( dx - friction ) & sign;

Not sure if this would work, just the idea... Any improvements?

Edit: this is what I did:

dxSign = Integer.signum(dx) * -1;
dySign = Integer.signum(dy) * -1;
dy = Math.abs(dy);
dx = Math.abs(dx);

fric = body.friction * mass;

dx = ( dx > fric ) ? dx - fric : 0;
dy = ( dy > fric ) ? dy - fric : 0;

dx = dx * absorption;
dy = dy * absorption;

dx *= dxSign;
dy *= dySign;
andand
  • 17,134
  • 11
  • 53
  • 79

5 Answers5

2

The safest option is to use a condition. You don't want fraction to change direction

dx = dx < -friction ? dx + friction : dx > friction ? dx - friction : 0
andand
  • 17,134
  • 11
  • 53
  • 79
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Right but it couldn't happen that dx > -friction or dx < friction, sorry for not writing that but it's not really what I asked for so I didn't expect it. Is using ternary however the most efficient way to pull this off? Seems strange to me... – Samuel Willems May 07 '14 at 12:56
  • @Val This used to be true, but if you look at JIT optimised code it often does a better job with `?:` than obscure mathematicaly coding. BTW I used to use such coding but found it is often slower. – Peter Lawrey May 07 '14 at 13:02
  • Well it appears to be performing best so this is what I'll use, thanks. – Samuel Willems May 07 '14 at 13:16
  • 1
    @SamuelWillems The JIT is getting smarter at handling common patterns which means that odd tricks don't work as well as they used to, which is almost disappointing ;) – Peter Lawrey May 07 '14 at 13:55
  • Hah, I guess. Shame, I really wanted to get into the bitwise stuff :p – Samuel Willems May 07 '14 at 14:06
  • 1
    @SamuelWillems I know what you mean. It used to be really useful for odd things like adding all the odd numbers in an array but I found using a condition in Java 8 was faster. :P – Peter Lawrey May 07 '14 at 14:07
1

Your code is incorrect, for two reasons:

  • dx = (dx << 1) >> 1; does not eliminate the sign. Moreover, it may incorrectly produce a "false positive" (i.e. a falsely negative number) when bit 31 is set to 1. Even if you replace >> with >>> you would not get an absolute value, because ints are stored in two's complement, not as a sign + value representation
  • sign will be either a 10000...00 or 00000..00 in binary representation, so ( dx - friction ) & sign will not merge the sign with the results of the other calculation.

You can change the addition for subtraction with the Integer.signum function, like this:

dx -= Integer.signum(dx) * friction;
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 2
    or use `int mult = Integer.signum(dx)` – slim May 07 '14 at 12:59
  • @slim Excellent comment! I was looking for `signum` in the wrong place (in the `java.lang.Math`) but it wasn't there. I stopped doing Java around the same time this function got introduced in 1.5. Thank you very much!!! – Sergey Kalinichenko May 07 '14 at 13:04
1

Just do it the obvious way: don't try to be clever unless this has performance issues.

if(dx >0 ) {
    dx -= friction;
} else {
    dx += friction;
}

If that seems a bit verbose, hide it in a method:

dx = applyFriction(dx,friction);

int applyFriction(int pos, int friction) {
     if(pos > 0) {
           return pos - friction;
     } else {
           return pos + friction;
     }
}

This has issues when abs(pos) < friction, and if you look into your physics, you'll find it's more likely that friction is simulated by multiplying - which removes your concern about sign.

slim
  • 40,215
  • 13
  • 94
  • 127
1

Use Math.abs when you want to ignore the sign. Be aware that optimization might result in your code becoming unreadable and difficult to maintain. So, for starters try to make your code as clean and possible and when you encounter performance issues, determine the source of your problem by benchmarking and optimize only the bottleneck of your code.

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
1

In physics, the sign of your direction doesn't really matter. I suggest using the fact that the kinetic friction is a force which is proportional to absolute velocity of the object in motion. That is, the object has some coefficient of friction μF in the range [0, 1]. The change in velocity is just δV = μFV∙δt where V is the initial velocity vector of your object, and δt is some span of time.

The new velocity V' is given by

V' = V - δV
   = V - μFV∙δt
   = V(1 - μF∙δt)

In this way, you don't need to deal with the sign at all, and it extends easily into higher dimensional cases.

As an aside, make sure δt is small enough that it doesn't introduce an oscillation in your model.

andand
  • 17,134
  • 11
  • 53
  • 79