Facebook RSS Feed
 

C#: USB Gamepad Bağlantısı (Direct Input)

Simulatör geliştirirken yada bazı elektronik projelerinde gamepad ile birşeyleri kontrol etmek isteyebiliriz. Bu projede bilgisayara bağlı bir gamepadin yön ve buton durumlarına C# ile ulaşıp ekranda yazdıracağız. Uygulamaya seri port dahil edip basit bir devre ile servo yada step motor kontrol etmeniz de mümkündür...

--

Ön Gereksinimler

Kodlamaya başlamadan önce Microsoft Download Center'dan DirectX SDK'yı indirip kurmanız gerekiyor. DirectX SDK ile gamepad cihazına erişim sağlayıp anlık pozisyon ve buton bilgilerini sorgulayacağız.

Daha sonra uygulamanın referanslarına
C:\Windows\Microsoft.NET\DirectX for Managed Code\1.0.2902.0\Microsoft.DirectX.dll
C:\Windows\Microsoft.NET\DirectX for Managed Code\1.0.2902.0\Microsoft.DirectX.DirectInput.dll
kütüpanelerini ekleyelim. Namespaceler arasına aşağıdaki satırları ekleyerek kodları yazmaya başlayabiliriz.

Uygulama Kodları

using Microsoft.DirectX;
using Microsoft.DirectX.DirectInput;

Global değişkenler:

Device joystick;              //Gamepad cihazı
JoystickState joystickState;  //Gamepad bilgisi güncellendiğinde o anki durumu saklayacak değişken
Byte[] joystickButtons;       //Gamepad butonlarının durumunu saklayacak byte dizisi
Int32[] jPOV0;                //Point of view'in pozisyonunu saklayacak int dizisi

Formun Load eventinde bilgisayara bağlı cihazları tarayıp bulduğumuz ilk gamepadi uygulamada kullanmak üzere atayacağız.

private void frmGamepad_Load(object sender, EventArgs e)
{
  //Bilgisayara bağlı cihazlar arasından GameControl cihazlarını bulalım:
  DeviceList gamepadListesi =
    Manager.GetDevices(DeviceClass.GameControl, EnumDevicesFlags.AttachedOnly);

  //Eğer 1 yada daha fazla gamepad bağlıysa, ilk cihazı seçelim:
  if (gamepadListesi.Count > 0)
  {
    foreach (DeviceInstance deviceInstance in gamepadListesi)
    {
      joystick = new Device(deviceInstance.InstanceGuid);
      joystick.SetCooperativeLevel(this,
        CooperativeLevelFlags.Background | CooperativeLevelFlags.NonExclusive);
      break;
    }

    //Uygulamamıza gelen verinin joystick türünde olduğunu bildirelim:
    joystick.SetDataFormat(DeviceDataFormat.Joystick);

    //Gamepadi uygulamamızda kullanmak üzere atayalım:
    joystick.Acquire();

    //Belirli aralıklarla gamepadi sorgulayacak bir timer oluşturalım. (Mesela saniyede 50 defa)
    Timer tmr = new Timer();
    tmr.Interval = 20;
    tmr.Enabled = true;
    tmr.Tick += new EventHandler(tmr_Tick);
    tmr.Start();
  }
}

Oluşturduğumuz timerın tick eventinde o anki gamepad durumunu (butonlar, vs...) sorgulatıp bu değerleri arayüzdeki labellara aktaralım:

void tmr_Tick(object sender, EventArgs e)
{
  //Gamepadin o anki durumunu sorgulayalım:
  joystick.Poll();

  //Sorgulattığımız veriyi oluşturduğumuz değişkenlere aktaralım:
  joystickState = joystick.CurrentJoystickState;
  joystickButtons = joystickState.GetButtons();
  jPOV0 = joystickState.GetPointOfView();

  //Axis - Rotation Bilgisi
  lblXAxis.Text = joystickState.X.ToString();
  lblYAxis.Text = joystickState.Y.ToString();
  lblZAxis.Text = joystickState.Z.ToString();
  lblXRotation.Text = joystickState.Rx.ToString();
  lblYRotation.Text = joystickState.Ry.ToString();

  //Buton Bilgisi
  lblBtn0.Text = joystickButtons[0].ToString();
  lblBtn1.Text = joystickButtons[1].ToString();
  lblBtn2.Text = joystickButtons[2].ToString();
  lblBtn3.Text = joystickButtons[3].ToString();
  lblBtn4.Text = joystickButtons[4].ToString();
  lblBtn5.Text = joystickButtons[5].ToString();
  lblBtn6.Text = joystickButtons[6].ToString();
  lblBtn7.Text = joystickButtons[7].ToString();
  lblBtn8.Text = joystickButtons[8].ToString();
  lblBtn9.Text = joystickButtons[9].ToString();
  lblBtn10.Text = joystickButtons[10].ToString();
  lblBtn11.Text = joystickButtons[11].ToString();

  //Point of View Bilgisi
  lblPOV0.Text = jPOV0[0].ToString();
}

Uygulama kapanırken gamepadi serbest bırakması için formun FormClosing eventine "joystick.Unacquire();" satırını da ekletelim:

private void frmGamepad_FormClosing(object sender, FormClosingEventArgs e)
{
  joystick.Unacquire();
}

.NET 4 Kullanıyorsanız...

Projede .NET 4 kullanuyorsanız uygulamayı çalıştırdığınızda
"Mixed mode assembly is built against version 'v1.1.4322' of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information."
hatasını alacaksınız. Bunun nedeni .NET 4'ün DirectX gibi mixed-mode assembly'leri birleştirirken kullandığı yöntemin değiştirilmiş olmasıdır. Uygulamayı uyumlu bir şekilde çalıştırmak için proje dosyalarımızın arasındaki app.config dosyasının içeriğini aşağıdaki gibi değiştirelim. (Önceki .NET sürümlerini kullanıyorsanız bu aşamayı atlayın.)

<?xml version="1.0"?>
<configuration>
  <startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0"/>
  </startup>
</configuration>

Projenizde app.config dosyası yoksa, Add > New Item'dan Application Configuration File ekleyebilirsiniz.
Uygulamayı çalıştırıp gamepadi kullandıkça değişkenlerin değiştiğini göreceksiniz.

-

X ve Y axis'i sol analog, X ve Y rotation'ı sağ analog ve Z axisi sağ ve sol pedalları temsil eder. POV ise dijital yön tuşlarıdır. POV orta konumdayken -1 değerini alır. Basılı durumdayken ise baktığı açıyı gösterir. (0 = yukarı, 9000 = 90 derece gibi) Butonlar ise serbestken 0, basılı konumdayken 128 değerini alır.

Kaynak kodlarını buradan indirebilirsiniz.




 
Hoşgeldiniz!
Son güncelleme: 25.12.2016
-
Yeni Teknik Yazılar
Latte Panda İncelemesi
Turta IoT HAT İncelemesi
USB Gamepad Kullanımı
GPIO Kullanımı
VEML6075 UV Sensör Kullan...
-
İlgili Gruplar
.NET MF ve Gadgeteer FB Grubu
İst. IoT & Wearables Meet-up
-
 

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.Copyright © 1999 - 2017, Umut Erkal. Bu materyal, "Creative Commons Public Licence" ile sunulmuştur.
Kaynak göstererek ve ücretsiz olarak, aynı şartlar altında paylaşabilir ve kullanabilirsiniz. | Kullanım Sözleşmesi