65.9K
CodeProject 正在变化。 阅读更多。
Home

Managed DirectX 中的力反馈

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.54/5 (8投票s)

2008年3月16日

CPOL

3分钟阅读

viewsIcon

81440

downloadIcon

1490

一个在 Managed DirectX 中使用力反馈的 C# 示例。

引言

Managed DirectX 是使用 .NET 语言编写 DirectX 应用程序的好方法,并且大多数 Managed DX 库都有很好的文档记录,健壮性强,并且在 Internet 上有很多示例。 自 2002 年首次发布以来,我就一直在断断续续地编写 Managed DX 代码,但直到最近才接触力反馈。

令我惊讶的是,我发现所有公开的 C# 力反馈代码示例在使用我的游戏手柄(Logitech 2 Rumble)时都会报错。 许多其他人在各种 Internet 论坛上发布了关于 Managed DirectX 和其他游戏手柄的这个问题,因此这似乎是 Managed DirectInput 库中一个长期存在的错误。 尽管有很多人报告了这个问题,但我无法找到适合我的解决方案 - 所以这里是我自己的解决方案。

附件中的项目提供了如何创建和触发几种不同力的示例,因此如果您是 C# 力反馈的新手,这里有您开始所需的一切。

背景

如果您想查看 Microsoft 的标准示例(对我不起作用),请访问此链接

我最终找到的解决方案是独一无二的,但在一定程度上受到了Ayucar的一篇博客文章的启发。

Using the Code

附件中的项目包含所有代码,但如果您已经熟悉这些示例但仍然遇到“Value does not fall within expected range”错误,这里有一些(有些简化的)亮点。

基本设备初始化

Device Dev = null;
    
foreach ( DeviceInstance instance in Manager.GetDevices( DeviceClass.GameControl,
    EnumDevicesFlags.AttachedOnly ) )
{
    Dev = new Device( instance.InstanceGuid );
}
            
Dev.SetDataFormat( DeviceDataFormat.Joystick );
Dev.SetCooperativeLevel( Parent, CooperativeLevelFlags.Background |
    CooperativeLevelFlags.Exclusive );
Dev.Properties.AxisModeAbsolute = true;
Dev.Properties.AutoCenter = false;
Dev.Acquire();

以上是 DirectInput 示例的典型示例。 AutoCenter = false 行对于力反馈尤其重要。 SetDataFormat 行中的 Parent 变量必须是 System.Windows.Forms.Control

查找轴

int[] axis = null;

// Enumerate any axes
foreach ( DeviceObjectInstance doi in Dev.Objects )
{
    if ( ( doi.ObjectId & (int)DeviceObjectTypeFlags.Axis ) != 0 )
    {
        // We found an axis, set the range to a max of 10,000
        Dev.Properties.SetRange( ParameterHow.ById,
        doi.ObjectId, new InputRange( -5000, 5000 ) );
    }

    int[] temp;

    // Get info about first two FF axii on the device
    if ( ( doi.Flags & (int)ObjectInstanceFlags.Actuator ) != 0 )
    {
        if ( axis != null )
        {
            temp = new int[axis.Length + 1];
            axis.CopyTo( temp, 0 );
            axis = temp;
        }
        else
        {
            axis = new int[1];
        }
    
        // Store the offset of each axis.
        axis[axis.Length - 1] = doi.Offset;
        if ( axis.Length == 2 )
        {
            break;
        }
    }
}

在声明 int[] temp 之前的所有内容都是您的标准 DirectInput 轴初始化 - 无论您是否使用力反馈,都必须执行这些操作。 轴数组计算是力反馈特有的,并且全部直接取自 Microsoft 示例(我没有在那里添加任何新内容)。

创建力

InitializeForce( Dev, EffectType.ConstantForce, axis,
    10000, EffectFlags.ObjectOffsets | EffectFlags.Spherical, 250000 ) );
        
public static EffectObject InitializeForce( Device Dev, EffectType Type,
int[] Axis, int Magnitude, EffectFlags Flags, int Duration )
{
    EffectObject eo = null;
    Effect e;

    foreach ( EffectInformation ei in Dev.GetEffects( EffectType.All ) )
    {
        if ( DInputHelper.GetTypeCode( ei.EffectType ) == (int)Type )
        {
            e = new Effect();
            e.SetDirection( new int[Axis.Length] );
            e.SetAxes( new int[1] );

            e.EffectType = Type;
            e.ConditionStruct = new Condition[Axis.Length];
            e.Duration = Duration;
            e.Gain = 10000;
            e.Constant = new ConstantForce();
            e.Constant.Magnitude = Magnitude;
            e.SamplePeriod = 0;
            e.TriggerButton = (int)Microsoft.DirectX.DirectInput.Button.NoTrigger;
            e.TriggerRepeatInterval = (int)DI.Infinite;
            e.Flags = Flags;
            e.UsesEnvelope = false;

            // Create the effect, using the passed in guid.
            eo = new EffectObject( ei.EffectGuid, e, Dev );
        }
    }

    return eo;
}

这是我的解决方案的用武之地。 通常出错的行是 e.SetAxes(new int[Axis.Length]); 它通常会抛出一个异常“Value does not fall within expected range”,这显然是 Managed DirectX 中的一个错误(至少影响某些游戏手柄)。 更改该行,使其始终初始化长度为 1 的轴数组,而不是长度为 2 的轴数组(如 Microsoft 示例所示),可以解决此问题,而且似乎对性能或功能没有任何其他副作用。

我应该注意到,由于同样的问题,我无法在 Managed DirectX 中成功加载 FFE 文件。 据推测,从 FFE 加载时的内部初始化代码也在尝试加载两个轴。 据我所知,这个问题存在于所有版本的 Managed DirectX 中,至少在 2008 年 3 月编写本文时是这样。

关注点

力反馈在大多数 PC 游戏中未得到充分利用,可能是因为该技术直到最近才在低端游戏手柄中可用。 将力反馈功能添加到您的游戏中是提供更身临其境的体验的好方法,也是在 PC 游戏市场中脱颖而出的一种小方式。

历史

  • 版本 1:2008 年 3 月 16 日
© . All rights reserved.