使用 SlimDX 进行强制反馈?

问题描述 投票:0回答:3

我还没有找到任何文章或教程,可以吗? 它试图调用 Effect 类,但我得到的只是

E_INVALIDARG:向返回函数传递了无效参数(-2147024809)

代码

[TestClass]
public class ForceFeedbackTest
{
    [TestMethod]
    public void Test()
    {
        using (var form = new Form())
        {
            var directInput = new DirectInput();

            foreach (var device in directInput.GetDevices(DeviceClass.GameController, DeviceEnumerationFlags.AttachedOnly))
            {
                var controller = new Joystick(directInput, device.InstanceGuid);
                controller.SetCooperativeLevel(form.Handle, CooperativeLevel.Exclusive | CooperativeLevel.Background);
                controller.Acquire();

                int xAxisOffset = 0, yAxisOffset = 0;
                int nextOffset = 0;
                foreach (DeviceObjectInstance d in controller.GetObjects())
                {
                    if ((d.ObjectType & ObjectDeviceType.ForceFeedbackActuator)
                        != 0)
                    {
                        if (nextOffset == 0)
                            xAxisOffset = d.Offset;
                        else
                            yAxisOffset = d.Offset;
                        nextOffset++;
                    }
                }

                int[] offsets = new int[2];
                offsets[0] = xAxisOffset;
                offsets[1] = yAxisOffset;
                int[] coords = { 0, 0 };

                var info = controller.GetEffects(EffectType.All).First();

                var args = new EffectParameters();
                args.Flags = EffectFlags.ObjectOffsets | EffectFlags.Cartesian;
                var typeSpec = new ConstantForce();


                args.Duration = 1000;
                args.SamplePeriod = controller.Capabilities.ForceFeedbackSamplePeriod;
                args.Parameters = typeSpec;


                args.Gain = 5000;

                args.SetAxes(offsets, coords);

                args.StartDelay = 500;

                var effect = new Effect(controller, info.Guid);
                effect.SetParameters(args); //This is the line i get the error on.
                effect.Start();
            }
        }
    }
}
slimdx
3个回答
1
投票

您不能将从

DeviceObjectInstance
获得的偏移量用于
SetAxes
。 MSDN 提到了这一点,但有点粗略:

设备本机数据格式中的偏移。本机数据格式对应于原始设备数据。 dwOfs 成员不对应于该对象的设备常量,例如 DIJOFS_BUTTON0。

http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.dideviceobjectinstance(v=vs.85).aspx

您可以使用

EffectFlags.ObjectIds
代替
EffectFlags.ObjectOffsets
并从
ObjectType
传入
DeviceObjectInstance
来识别轴。

据我记得,如果您知道哪些轴有执行器,您还可以使用

JoystickObjects
类的静态成员之一作为
SetAxes
的偏移量。


0
投票

如果您使用的是 Xbox 360 控制器或任何支持 XInput 的控制器,我会使用它而不是 DirectInput。使用 IMO 更容易,而且强制反馈也很简单。查看 SlimDX.XInput。过去几年大多数较新的游戏手柄都支持 XInput。

VB.net 代码:

Dim player As Integer = 1 'Player can be 1-4
Dim gamePad As SlimDX.XInput.Controller = New SlimDX.XInput.Controller(player)

Public Sub VibrateController(ByVal rSpeed As Short, ByVal lSpeed As Short)
   Dim vibSettings As New SlimDX.XInput.Vibration()
   vibSettings.LeftMotorSpeed = lSpeed
   vibSettings.RightMotorSpeed = rSpeed
   gamePad.SetVibration(vibSettings)
End Sub

0
投票

对于像我一样想要使用它的人,我在 https://github.com/walbourn/directx-sdk-samples/blob/main/DirectInput/FFConst/ffconst.cpp

中找到了工作示例

这就是我如何让它在 C# 中工作:

var directInput = new DirectInput();
JoystickState joys = new JoystickState();
var joy = new Joystick(directInput, dev.InstanceGuid);
joy.SetCooperativeLevel(Process.GetCurrentProcess().MainWindowHandle, CooperativeLevel.Exclusive | CooperativeLevel.Background);
joy.Acquire();
joy.GetCurrentState(ref joys);
joy.Properties.SetRange(0, short.MaxValue);

int[] offsets = { 0 };
int[] coords = { 0 };
var info = joy.GetEffects(EffectType.ConstantForce).First();

var args = new EffectParameters();
args.Flags = EffectFlags.Cartesian | EffectFlags.ObjectOffsets;
args.Duration = -1;
args.SamplePeriod = 0;
args.Gain = 10000;
args.TriggerButton = -1;
args.TriggerRepeatInterval = 0;
args.Envelope = null;
args.SetAxes(offsets, coords);

var typeSpec = new ConstantForce();
typeSpec.Magnitude = 0;
args.Parameters = typeSpec;


var effect = new Effect(joy, info.Guid, args);
effect.Start(1, EffectPlayFlags.None);


while (true)
{
    var mouse = Cursor.Position;
    var x = mouse.X - 2560 / 2;
    args.Parameters = new ConstantForce() { Magnitude = x * 10 };
    effect.SetParameters(args, EffectParameterFlags.Start | EffectParameterFlags.TypeSpecificParameters | EffectParameterFlags.Direction);
    effect.Start(1, EffectPlayFlags.None);

    Thread.Sleep(10);
}
© www.soinside.com 2019 - 2024. All rights reserved.