#XInputの特徴とか
- 基本XBox 360のコントローラ用のライブラリ
- キーボードやマウスを取る場合はDirectInputやWin32APIを用いる
- デバイスが限定されている分、DirectInputと比べてかなり簡単に扱える
- XInputに対応してないコントローラもx360ceを用いることで使えるようになる
#x360ce
x360ce - XBOX 360 Controller emulator
XInput対応コントローラを持っていないため確認できないが、パススルーの設定もできるためDirectInput対応コントローラとXInput対応コントローラの共存は可能な模様
##使用方法
- x360ce Librariesと書かれたものダウンロードして中のxinput1_3.dllを実行ファイルから見えるディレクトリに配置
- XBOX 360 Controller emulatorと書かれたものをダウンロードして中のx360ce.exeを適当な場所に配置・起動してコントローラの設定を行い、作成されたx360ce.iniをxinput1_3.dllと同じディレクトリに配置
##注意点
- x360ce.exeから自動作成されるxinput1_3.dllをx360ce Librariesの代わりに用いると、デバッグ時にエラーを吐く
- x360ce.ini中のInstanceGuidはPC毎にも変わるため、環境ごとに編集する必要あり
- バイブレーションは対応してなさそう
#ラッパークラス
作ったものの正直必要ない気はする
Joypad.h
#pragma once
#include <complex>
#ifndef STRICT
#define STRICT
#endif
#include <windows.h>
#include <XInput.h>
inline void JoypadEnable(bool enable) { XInputEnable(enable); }
class Joypad{
public:
enum class Button{
A = XINPUT_GAMEPAD_A,
B = XINPUT_GAMEPAD_B,
X = XINPUT_GAMEPAD_X,
Y = XINPUT_GAMEPAD_Y,
Up = XINPUT_GAMEPAD_DPAD_UP,
Down = XINPUT_GAMEPAD_DPAD_DOWN,
Left = XINPUT_GAMEPAD_DPAD_LEFT,
Right = XINPUT_GAMEPAD_DPAD_RIGHT,
Start = XINPUT_GAMEPAD_START,
Back = XINPUT_GAMEPAD_BACK,
LThumb = XINPUT_GAMEPAD_LEFT_THUMB,
RThumb = XINPUT_GAMEPAD_RIGHT_THUMB,
LShoulder = XINPUT_GAMEPAD_LEFT_SHOULDER,
RShoulder = XINPUT_GAMEPAD_RIGHT_SHOULDER
};
Joypad(int userIndex) : m_UserIndex(userIndex) {}
bool update();
bool isPushed(Button button);
bool vibrate(double leftMotorSpeedByPercent, double rightMotorSpeedByPercent);
bool isConnected();
double getLTrigger(double thresholdByPercent = XINPUT_GAMEPAD_TRIGGER_THRESHOLD / (double)TriggerMax);
double getRTrigger(double thresholdByPercent = XINPUT_GAMEPAD_TRIGGER_THRESHOLD / (double)TriggerMax);
std::complex<double> getLStick(double thresholdByPercent = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE / (double)StickMax);
std::complex<double> getRStick(double thresholdByPercent = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE / (double)StickMax);
int getUserIndex();
private:
static const long TriggerMax = 255;
static const long MotorSpeedMax = 65535;
static const long StickMax = 32767;
int m_UserIndex;
XINPUT_STATE m_State;
bool m_Connected;
};
Joypad.cpp
#include "Joypad.h"
#include <algorithm>
#pragma comment(lib, "Xinput.lib")
bool Joypad::isPushed(Button button) {
return isConnected() && (m_State.Gamepad.wButtons & static_cast<int>(button));
}
bool Joypad::isConnected() {
return m_Connected;
}
bool Joypad::update() {
m_Connected = (XInputGetState(m_UserIndex, &m_State) == ERROR_SUCCESS);
return m_Connected;
}
int Joypad::getUserIndex() {
return m_UserIndex;
}
std::complex<double> Joypad::getLStick(double thresholdByPercent) {
if (!isConnected()) return std::complex<double>(0, 0);
auto y_abs = std::abs(m_State.Gamepad.sThumbLY) / (double)StickMax; // 負の割り算は処理系定義な為
auto y_sign = (m_State.Gamepad.sThumbLY < 0) ? -1 : 1;
auto x_abs = std::abs(m_State.Gamepad.sThumbLX) / (double)StickMax;
auto x_sign = (m_State.Gamepad.sThumbLX < 0) ? -1 : 1;
return std::complex<double>(
(x_abs < thresholdByPercent) ? 0 : x_abs * x_sign,
(y_abs < thresholdByPercent) ? 0 : y_abs * y_sign
);
}
std::complex<double> Joypad::getRStick(double thresholdByPercent) {
if (!isConnected()) return std::complex<double>(0, 0);
auto y_abs = std::abs(m_State.Gamepad.sThumbRY) / (double)StickMax;
auto y_sign = (m_State.Gamepad.sThumbRY < 0) ? -1 : 1;
auto x_abs = std::abs(m_State.Gamepad.sThumbRX) / (double)StickMax;
auto x_sign = (m_State.Gamepad.sThumbRX < 0) ? -1 : 1;
return std::complex<double>(
(x_abs < thresholdByPercent) ? 0 : x_abs * x_sign,
(y_abs < thresholdByPercent) ? 0 : y_abs * y_sign
);
}
double Joypad::getLTrigger(double thresholdByPercent) {
if (!isConnected()) return 0;
auto t = m_State.Gamepad.bLeftTrigger / (double)TriggerMax;
return (t < thresholdByPercent) ? 0 : t;
}
double Joypad::getRTrigger(double thresholdByPercent) {
if (!isConnected()) return 0;
auto t = m_State.Gamepad.bLeftTrigger / (double)TriggerMax;
return (t < thresholdByPercent) ? 0 : t;
}
bool Joypad::vibrate(double leftMotorSpeedByPercent, double rightMotorSpeedByPercent) {
XINPUT_VIBRATION vib;
vib.wLeftMotorSpeed = leftMotorSpeedByPercent * MotorSpeedMax;
vib.wRightMotorSpeed = rightMotorSpeedByPercent * MotorSpeedMax;
return XInputSetState(m_UserIndex, &vib) == ERROR_SUCCESS;
}