[Pygame]ゲームコントローラ(JC-U3912T)の制御スクリプト

## はじめに

電気屋で見つけたコントローラをPygameで制御するスクリプトを作成します。
購入したのは ELECOM製の `JC-U3912T` というPC用のゲームコントローラです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/6dd9ef57-f1eb-dada-e28d-cc680aeb6dd8.png)

## 環境

コントローラ制御スクリプトは、Windows10で実行しました。

```powershell
PS C:\> python -V
Python 3.9.5
PS C:\> pip list | Select-String -Pattern "pygame"

pygame                2.0.1

PS C:\>
```

## Pygameのインストール

Pygameのインストールコマンドです。

- windows10
    - `pip install pygame`

## コントローラの制御スクリプト

コントローラの操作に応じて標準出力に情報を出力するスクリプトです。

```python:コントローラ(JC-U3912T)制御スクリプト
import pygame
from pygame.locals import *

pygame.init()
pygame.joystick.init()
try:
   joystick = pygame.joystick.Joystick(0)
   joystick.init()
   print('ジョイスティックの名前:', joystick.get_name())
   print('ボタン数 :', joystick.get_numbuttons())
except pygame.error:
   print('ジョイスティックが接続されていません')

active = True
while active:
   for e in pygame.event.get():
        if e.type == QUIT:
            active = False

        if e.type == pygame.locals.JOYHATMOTION:
            if e.value[0] == 0:
                if e.value[1] == 1:
                    print("十字キー：上")
                elif e.value[1] == 0:
                    print("十字キー：ー")
                else:
                    print("十字キー：下")
            elif e.value[0] == 1:
                if e.value[1] == 0:
                    print("十字キー：右")
                elif e.value[1] == 1:
                    print("十字キー：右上")
                else:
                    print("十字キー：右下")
            else:
                if e.value[1] == 0:
                    print("十字キー：左")
                elif e.value[1] == 1:
                    print("十字キー：左上")
                else:
                    print("十字キー：左下")

        elif e.type == pygame.locals.JOYAXISMOTION:
            if e.axis == 0 or e.axis == 1:
                if e.value == 0.0 or e.value == 1.0 or e.value == -1.0:
                    print('ジョイスティック(左) ー {0} {1}'.format(e.axis, e.value))
                else:
                    print('ジョイスティック(左)  {0} {1}'.format(e.axis, e.value))
            elif  e.axis == 2 or e.axis == 3:
                if e.value == 0.0 or e.value == 1.0 or e.value == -1.0:
                    print('ジョイスティック(右) ー {0} {1}'.format(e.axis, e.value))
                else:
                    print('ジョイスティック(右)  {0} {1}'.format(e.axis, e.value))
            else:
                print('ジョイスティック(ー)')
        elif e.type == pygame.locals.JOYBUTTONDOWN:
            print('ボタン押す {0}'.format(e.button))
        elif e.type == pygame.locals.JOYBUTTONUP:
            print('ボタン離す {0}'.format(e.button))
```

---

## コントローラの調査スクリプト

前述のスクリプトを作成するために、コントローラ操作時にどのような情報が出力されるか確認するため`信号確認スクリプト`を作成しました。

### 信号確認スクリプト
[こちらのスクリプト](https://note.com/npaka/n/n7b799597e706) を参考にして、信号を確認するスクリプトを作成しました。

```python:信号確認スクリプト
import pygame
from pygame.locals import *

pygame.joystick.init()
try:
   joystick = pygame.joystick.Joystick(0)
   joystick.init()
   print('ジョイスティックの名前:', joystick.get_name())
   print('ボタン数 :', joystick.get_numbuttons())
except pygame.error:
   print('ジョイスティックが接続されていません')

pygame.init()

active = True
while active:
   for e in pygame.event.get():
        if e.type == QUIT:
            active = False
        print('|'+str(e))
```

### 信号の確認結果

**十字キー**

|方向|スクリプト結果|
|---|---|
|↑　|Event(1538-JoyHatMotion {'joy': 0, 'instance_id': 0, 'hat': 0, 'value': (0, 1)})|
|↓　|Event(1538-JoyHatMotion {'joy': 0, 'instance_id': 0, 'hat': 0, 'value': (0, -1)})|
|←　|Event(1538-JoyHatMotion {'joy': 0, 'instance_id': 0, 'hat': 0, 'value': (-1, 0)})|
|→　|Event(1538-JoyHatMotion {'joy': 0, 'instance_id': 0, 'hat': 0, 'value': (1, 0)})|


**左スティック**

|方向|スクリプト結果|
|---|---|
|↑ |Event(1536-JoyAxisMotion {'joy': 0, 'instance_id': 0, 'axis': 1, 'value': -1.0})|
|↓ |Event(1536-JoyAxisMotion {'joy': 0, 'instance_id': 0, 'axis': 1, 'value': 1.0})|
|← |Event(1536-JoyAxisMotion {'joy': 0, 'instance_id': 0, 'axis': 0, 'value': -1.0})|
|→ |Event(1536-JoyAxisMotion {'joy': 0, 'instance_id': 0, 'axis': 0, 'value': 1.0})|

**右スティック**

|方向|スクリプト結果|
|---|---|
|↑ |Event(1536-JoyAxisMotion {'joy': 0, 'instance_id': 0, 'axis': 2, 'value': -1.0})|
|↓ |Event(1536-JoyAxisMotion {'joy': 0, 'instance_id': 0, 'axis': 2, 'value': 1.0})|
|← |Event(1536-JoyAxisMotion {'joy': 0, 'instance_id': 0, 'axis': 3, 'value': -1.0})|
|→ |Event(1536-JoyAxisMotion {'joy': 0, 'instance_id': 0, 'axis': 3, 'value': 1.0})|

※後述しますがスティック制御は難しそうです

**ボタン**

|番号|スクリプト結果|
|---|---|
|　１ |Event(1539-JoyButtonDown {'joy': 0, 'instance_id': 0, 'button': 0})|
|　２ |Event(1539-JoyButtonDown {'joy': 0, 'instance_id': 0, 'button': 1})|
|　３ |Event(1539-JoyButtonDown {'joy': 0, 'instance_id': 0, 'button': 2})|
|　４ |Event(1539-JoyButtonDown {'joy': 0, 'instance_id': 0, 'button': 3})|
|　５ |Event(1539-JoyButtonDown {'joy': 0, 'instance_id': 0, 'button': 4})|
|　６ |Event(1539-JoyButtonDown {'joy': 0, 'instance_id': 0, 'button': 5})|
|　７ |Event(1539-JoyButtonDown {'joy': 0, 'instance_id': 0, 'button': 6})|
|　８ |Event(1539-JoyButtonDown {'joy': 0, 'instance_id': 0, 'button': 7})|
|　９ (左スティック)|Event(1539-JoyButtonDown {'joy': 0, 'instance_id': 0, 'button': 8})|
|１０ (右スティック)|Event(1539-JoyButtonDown {'joy': 0, 'instance_id': 0, 'button': 9})|
|１１ |Event(1539-JoyButtonDown {'joy': 0, 'instance_id': 0, 'button': 10})|
|１２ |Event(1539-JoyButtonDown {'joy': 0, 'instance_id': 0, 'button': 11})|
|AUTO|信号なさそう|

## スティックの制御は難しそう

コントローラの調査スクリプトでスティック操作時の信号を調べた結果Pygameでの制御は難しいかもと思っています。スティックの位置が同じでも、スティックの操作によって `e.value` の値が変わるようです。第3のパラメータがあればと思いPygameのドキュメントを確認しましたが見つけられず。。とりあえず、スティック制御は保留にしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/b3390d48-839e-c04c-2d5a-f13e1682c394.png)