从.net发送反馈/效果到操纵杆

时间:2014-05-28 14:30:28

标签: c# hid joystick sharpdx human-interface

感谢这个回答https://stackoverflow.com/a/13734766/637142我能够知道按下按钮的时间或旋转方向盘的时间。现在我的问题是如何将效果发送到设备?例如,当我正在玩游戏时,如果我发生碰撞,车轮会振动。我怎么能让方向盘振动?

我相信我需要做的是Start()效果(http://sharpdx.org/documentation/api/t-sharpdx-directinput-effect)。 SharpDX.DirectInput.Joystick类似乎没有一个方法可以返回所有效果。有一个名为GetEffects的方法,但该方法返回EffectInfo个对象的集合。游戏如何向操纵杆发送命令?

1 个答案:

答案 0 :(得分:5)

源代码是从here复制粘贴的。

要使用此来源,您需要一个“强制效果文件”( C:\ MyEffectFile.ffe ),以便在操纵杆上“播放”它。

根据this book创建“强制效果”文件,您需要使用DirectX SDK附带的“强制编辑器”。

(同一本书,或者说,你可以在代码中从头开始创建效果......在答案中,我发现另一段代码创建并起诉效果而不从文件中加载它: - ))

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using Microsoft.DirectX;
using Microsoft.DirectX.DirectInput;

namespace JoystickProject
{
    /// <summary>
    /// Summary description for Form1.
    /// </summary>
    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.Label label1;
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;
        private Device device = null;
        private bool running = true;
        private ArrayList effectList = new ArrayList();
        private bool button0pressed = false;
        private string joyState = "";

        public bool InitializeInput()
        {
            // Create our joystick device
            foreach(DeviceInstance di in Manager.GetDevices(DeviceClass.GameControl,
                EnumDevicesFlags.AttachedOnly | EnumDevicesFlags.ForceFeeback))
            {
                // Pick the first attached joystick we see
                device = new Device(di.InstanceGuid);
                break;
            }
            if (device == null) // We couldn't find a joystick
                return false;

            device.SetDataFormat(DeviceDataFormat.Joystick);
            device.SetCooperativeLevel(this, CooperativeLevelFlags.Exclusive | CooperativeLevelFlags.Background);
            device.Properties.AxisModeAbsolute = true;
            device.Properties.AutoCenter = false;
            device.Acquire();

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

            // Load our feedback file
            EffectList effects = null;
            effects = device.GetEffects(@"C:\MyEffectFile.ffe",
                FileEffectsFlags.ModifyIfNeeded);
            foreach(FileEffect fe in effects)
            {
                EffectObject myEffect = new EffectObject(fe.EffectGuid, fe.EffectStruct,
                    device);
                myEffect.Download();
                effectList.Add(myEffect);
            }

            while(running)
            {
                UpdateInputState();
                Application.DoEvents();
            }

            return true;
        }

        private void PlayEffects()
        {
                // See if our effects are playing.
                foreach(EffectObject myEffect in effectList)
                {
                    //if (button0pressed == true)
                    //{
                        //MessageBox.Show("Button Pressed.");
                    //  myEffect.Start(1, EffectStartFlags.NoDownload);
                    //}

                    if (!myEffect.EffectStatus.Playing)
                    {
                        // If not, play them
                        myEffect.Start(1, EffectStartFlags.NoDownload);
                    }
                }
                //button0pressed = true;
        }

        protected override void OnClosed(EventArgs e)
        {
            running = false;
        }

        private void UpdateInputState()
        {
            PlayEffects();

            // Check the joystick state
            JoystickState state = device.CurrentJoystickState;
            device.Poll();
            joyState = "Using JoystickState: \r\n";

            joyState += device.Properties.ProductName;
            joyState += "\n";
            joyState += device.ForceFeedbackState;
            joyState += "\n";
            joyState += state.ToString();

            byte[] buttons = state.GetButtons();
            for(int i = 0; i < buttons.Length; i++)
                joyState += string.Format("Button {0} {1}\r\n", i, buttons[i] != 0 ? "Pressed" : "Not Pressed");

            label1.Text = joyState;

            //if(buttons[0] != 0)
                //button0pressed = true;

        }

        public Form1()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            //
            // TODO: Add any constructor code after InitializeComponent call
            //
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null) 
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.label1 = new System.Windows.Forms.Label();
            this.SuspendLayout();
            // 
            // label1
            // 
            this.label1.BackColor = System.Drawing.SystemColors.ActiveCaptionText;
            this.label1.Location = new System.Drawing.Point(8, 8);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(272, 488);
            this.label1.TabIndex = 0;
            // 
            // Form1
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.BackColor = System.Drawing.SystemColors.ControlText;
            this.ClientSize = new System.Drawing.Size(288, 502);
            this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                          this.label1});
            this.Name = "Form1";
            this.Text = "Joystick Stuff";
            this.ResumeLayout(false);

        }
        #endregion

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() 
        {
            using (Form1 frm = new Form1())
            {
                frm.Show();
                if (!frm.InitializeInput())
                    MessageBox.Show("Couldn't find a joystick.");
            }
        }
    }
}

我刚刚发现here另一段可能有用的代码。 此示例似乎从头开始创建效果,因此您不需要“效果文件”。

   DeviceList xDeviceList = Manager.GetDevices(DeviceClass.GameControl, EnumDevicesFlags.AttachedOnly); 
            DeviceInstance someDeviceInstance; 
            foreach (DeviceInstance deviceInstance in xDeviceList) 
            { 
                someDeviceInstance = deviceInstance; 
                break; 
            } 

            Device someDevice = new Device(someDeviceInstance.InstanceGuid); 
            someDevice.SetCooperativeLevel(this.Handle, CooperativeLevelFlags.Exclusive | CooperativeLevelFlags.Background); 
            int[] axis = new int[0]; 
            foreach (DeviceObjectInstance doi in someDevice.Objects) 
            { 
                if((doi.Flags & (int)ObjectInstanceFlags.Actuator) != 0) 
                { 
                    axis = new int[axis.Length + 1]; 
                    axis[axis.Length - 1] = doi.Offset; 
                } 
            } 

            someDevice.Acquire(); 

            Effect effect = new Effect(); 
            effect.SetDirection(new int[axis.Length]); 
            effect.SetAxes(new int[axis.Length]); 
            effect.ConditionStruct = new Condition[axis.Length]; 

            effect.Flags = EffectFlags.Cartesian | EffectFlags.ObjectOffsets; 
            effect.Duration = int.MaxValue; 
            effect.SamplePeriod = 0; 
            effect.Gain = 10000; 
            effect.TriggerButton = (int)Microsoft.DirectX.DirectInput.Button.NoTrigger; 
            effect.TriggerRepeatInterval = 0; 
            effect.UsesEnvelope = false; 
            effect.EffectType = Microsoft.DirectX.DirectInput.EffectType.ConstantForce; 
            effect.StartDelay = 0; 
            effect.Constant = new Microsoft.DirectX.DirectInput.ConstantForce(); 
            effect.Constant.Magnitude = -5000; 
            EffectObject effectObject = null; 
            foreach (EffectInformation ei in someDevice.GetEffects(EffectType.ConstantForce)) 
            { 
                effectObject = new EffectObject(ei.EffectGuid, effect, someDevice); 
            } 

            effectObject.SetParameters(effect, EffectParameterFlags.Start ); 

这是另一个链接,然后可能有用Force feedback sample