Problem: Sometimes, when my fighter's running in one direction (because Im'm holding direction button like A,D,Left or Right), and I quicly release button for that direction and press button for opposite direction, the fighter continues to run in the first mentioned direction. This doesn't happen all the time, it's "random". Also, this has nothing to do with jumping/falling, because it doesn't matter if fighter's in air or not.
I have 4 classes in which fighter movement is regulated in update methods:
Input class, just some functions
public static void UpdateNew(GameTime gt)
{
// fires before any other update is called (before player/level/fighter update...)
frameTime = (float)gt.ElapsedGameTime.TotalSeconds;
ksNew = Keyboard.GetState();
msNew = Mouse.GetState();
}
public static void UpdateOld()
{
// fires after every other update is called (after player/level/fighter update...)
ksOld = ksNew;
msOld = msNew;
scrollValue = msOld.ScrollWheelValue;
}
public static bool Down(Keys k)
{ return ksNew.IsKeyDown(k); }
Player class:
Fighter fighter; //set in constructor, it's not null
public void Update()
{
fighter.RunDirection = Input.Down(rightK).ToInt() - Input.Down(leftK).ToInt();
fighter.Jump = Input.Down(jumpK);
fighter.Punch = Input.Clicked(punchK);
}
// where .ToInt() converts bool to 1 if it's true, and to 0 if it's not true
Fighter class
public int RunDirection
{ set { runMultiplier = MathHelper.Clamp(value, -1, 1); } }
public override void Update (float elTime, List<Entity> entities)
{
// region: checks for jump, works fine
AddForce(
// X - Horizontal Force
((Math.Abs(Force.X) < runSpeed) ? runMultiplier * runSpeed * 5 * elTime : 0) // movement controls
+ ((runMultiplier == 0) ? -Force.X.Sign() * runSpeed * 5 * elTime : 0) // traction when not moving
,
// Y - Vertical Force
((!canJump) ? 900 * elTime : 0) // gravity
- jumpDecreasingSpeed * elTime // jump
);
// region: Check collision and puts force.X or force.Y to 0 when it's colliding with other
// entities and put's player next to that entity
//set bool that stores last direction of looking (left/right)
if (runMultiplier != 0) lookingRight = runMultiplier > 0;
//checks if animation should be changed (idle, running, jumping or falling)
CheckAnimation();
//update currently playing animation
currentAnim.Update(elTime);
//stop fighters horisontal movement if it's small enough
if (Math.Abs(Force.X) < 1) AddForce(-Force.X, 0);
// after all calculations, move fighter by the force that is currently imacting him.
Position += Force * elTime;
}
Level class
public void Update (float elTime)
{
// PLAYERS
p1.Update(); // updates only controls, as mentioned above, not the fighter itself.
p2.Update();
// update ENTITIES, player's fighters, and walls (their update method is empty)
// player's fighters are added to maps "entities" list.
for (int i = 0; i < map.entities.Count; i++)
map.entities[i].Update(elTime, map.entities.Where(q => q != map.entities[i]).ToList());
}
Brief update order for each frame
GameMainUpdate
---Input.UpdateNew
---Level.Update
------Player.Update
------Fighter.Update
---------Check if player want's you to move, and add force (velocity)
---------Check collision, set force to 0 moving if colliding
---------when all calculations are done, add force to current position
---Input.UpdateOld
Question: Why is this happening? Why is it so "random"? I understand that it happends for a reason, but I can't put my finger on it.
One possible scenario that causes it is when Math.Abs(Force.X) >= runSpeed
then you add 0 force.
If Force.X >= runSpeed then 0
runMultiplier == 0 (false due to immediate switch) then 0
AddForce(0+0)
// X - Horizontal Force
((Math.Abs(Force.X) < runSpeed) ? runMultiplier * runSpeed * 5 * elTime : 0) // movement controls
+ ((runMultiplier == 0) ? -Force.X.Sign() * runSpeed * 5 * elTime : 0) // traction when not moving
Then this will never be executed because Math.Abs(Force.X) >= 1
(I assume runspeed is >= 1).
//stop fighters horisontal movement if it's small enough
if (Math.Abs(Force.X) < 1) AddForce(-Force.X, 0);
This is a possible reason why switching keys within a 1 frame buffer where the one direction is immediately replaced by the other can net you a force of 0; which would cause the fighter to continue in the previous direction.