Last push

17 10 2010

Sorry about the delay but deadlines before blogs I guess; wow it’s been four days, where does the time fly?
Where was I?

Ah yes, velocity and acceleration. Well, the calling code for the RunningCore would probably look something like this:

if (InputDevice.IsPressed("Left"))
{ 
  mRunningCore.Accelerate(RunningCore.LEFT); 
}
.../*somewhere in an update function*/...
mRunningCore.Update(_deltaTime);

And from here users can query the CurrentVelocity and go on their merry ways; sort of. I’ve established what happens when users press “Left”, the problem is I’m still one question/answer short of proper communication. What happens when users stop pressing left?
At the moment, nothing, velocity will never change, users cannot slow down [they won’t reach lightspeed anymore but I bet even YOU will get tired after seven hours of straight running at maximum speed].

I’ve reach, you guessed it, another decision.
Should I add another function?

public function Decelerate(_friction:Number):void;

Or should the RunningCore class implicitly slow velocity when users aren’t pressing the movement buttons?

The answer in this case, as in many with programming, is – it depends.

I actually don’t have a hard and fast and right answer for this; I’ve tried implementing both ways and in various forms, each one with its own benefits and drawbacks. But code has to be written and choices have to be made, in this case I’ll use an implicit slowdown. The real problem here is that these physics are faked and faking things is harder because it involves hacking solutions which in turn mean hacked and tacked-on add-ons [it rhymes and is the truth, two for two].

But how do we signal the RunningCore its users have stopped wanting to accelerate?
My solution relies on the fact that when users call accelerate the RunningCore changes mCurrentAcceleration;

mCurrentAcceleration = mMaximumAcceleration * mDirection;

Using this I can augument the Update function in this manner:

public function Update(_deltaTime:number):void
{
  if (!IsVelocityAtMaximum())
  {
    mCurrentVelocity += mCurrentAcceleration * _deltaTime;
  }
  mCurrentAcceleration=0;
}

The logic behind reseting the mCurrentAcceleration is simple. I basically say, assume that users have not requested Accelerate() until proven otherwise. This solves the communication problem, but not the slowing down problem. RunningCore needs to slow its velocity by a certain amount when users aren’t requesting to accelerate.

public function Update(_friction:number, _deltaTime:number):void
{
  // mCurrentAcceleration will only be 0 if users have not called RunningCore::Accelerate
  if (mCurrentAcceleration == 0) { mCurrentAcceleration =_friction; }  
  if (!IsVelocityAtMaximum())
  {
    mCurrentVelocity += mCurrentAcceleration * _deltaTime;
  }
  mCurrentAcceleration=0;
}

The code still needs to be organized a bit here as well, because my previous decision concerning handling maximum speed is actually producing results which are wrong. So let’s refactor.

public function Update(_friction:number, _deltaTime:number):void
{
  if (!IsVelocityAtMaximum()) { CapVelocityToMaximum(); }
  
  // mCurrentAcceleration will only be 0 if users have not called RunningCore::Accelerate
  if (mCurrentAcceleration == 0) { mCurrentAcceleration =_friction; }
  
  mCurrentVelocity += mCurrentAcceleration * _deltaTime;
  mCurrentAcceleration=0;
}

Run it, test it, and you’ll see that this code doesn’t actually do what we need. The problem stems from not defining my new requirements. The question should now be what do I want from friction? And the answer… I want to use friction as an acceleration which works against the current direction of RunningCore’s velocity. Let’s revise the code.

public function Update(_friction:number, _deltaTime:number):void
{
  // assert(mVelocity>=0)
  if (!IsVelocityAtMaximum()) { CapVelocityToMaximum(); }
  
  // mCurrentAcceleration will only be 0 if users have not called RunningCore::Accelerate
  if (mCurrentAcceleration == 0)
  { 
    mCurrentAcceleration =_friction * -Tools.GetSign(mCurrentVelocity); 
  }
  
  mCurrentVelocity += mCurrentAcceleration * _deltaTime;
  mCurrentAcceleration=0;
}

Much better. But notice the new asserting check to make sure that _friction is positive [or at least zero] because the internal logic of Update() relies on that fact. Phew, nearly done. There’s just one more thing to complete this function, can you [if you aren’t me that is] spot it? Try running it, I wonder what would happen?

There’s probably one more post to do concerning RunningCore. But the truth of the matter is these posts aren’t really about physics [fake or real] or code at all, they’re about my workflow and how I approach programming [at the moment]. I wonder what it would look like in 10 years?

“Life is a lemon and I’d like my money back”

Advertisements

Actions

Information

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: