Thursday, August 13, 2009

XNA Force Feedback Helper Class

This is a little helper class I whipped up to manage force feedback vibrations in XNA. The XNA libraries themselves just have a method you call to set the instantaneous left/right vibration force. In games, however, you generally want the feedback to last over a period of time, and you may have more than one force feedback event happening at the same time.

This code provides a "fire-and-forget" interface for triggering vibrations. Add a call to update the ForceFeedbackManager in your game's update code. Call AddVibration whenever you want to trigger force feedback.

Note: this code is not threadsafe - you must be triggering feedback from the same thread you call Update from.


public class Vibration
{
float leftMotor;
float rightMotor;
float msLeft;

public float LeftMotor
{
get { return leftMotor; }
set { leftMotor = value; }
}

public float RightMotor
{
get { return rightMotor; }
set { rightMotor = value; }
}

public float MSLeft
{
get { return msLeft; }
set { msLeft = value; }
}

public Vibration(float leftMotor, float rightMotor, float durationMS)
{
this.leftMotor = leftMotor;
this.rightMotor = rightMotor;
this.msLeft = durationMS;
}
}

public class ForceFeedbackManager
{
private PlayerIndex playerIndex;
List<Vibration> vibrations = new List<Vibration>();

public ForceFeedbackManager(PlayerIndex playerIndex)
{
this.playerIndex = playerIndex;
}

public void AddVibration(float leftMotor, float rightMotor, float durationMS)
{
vibrations.Add(new Vibration(leftMotor, rightMotor, durationMS));
}

public void Update(float msElapsed)
{
List<Vibration> toDelete = new List<Vibration>();

foreach (Vibration vibration in vibrations)
{
vibration.MSLeft -= msElapsed;

if (vibration.MSLeft < 0.0f)
{
toDelete.Add(vibration);
}
}

foreach (Vibration vibration in toDelete)
{
vibrations.Remove(vibration);
}

float leftMotor;
float rightMotor;

GetVibration(out leftMotor, out rightMotor);

GamePad.SetVibration(playerIndex, leftMotor, rightMotor);
}

public void GetVibration(out float leftMotor, out float rightMotor)
{
leftMotor = 0.0f;
rightMotor = 0.0f;

foreach (Vibration vibration in vibrations)
{
leftMotor = Math.Max(leftMotor, vibration.LeftMotor);
rightMotor = Math.Max(rightMotor, vibration.RightMotor);
}
}
}

2 comments:

  1. You like coding?
    I like your code ...
    clear, self explanatory, easy to follow!

    ReplyDelete
  2. Thanks, Peter - glad you found it useful!

    ReplyDelete