2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

XInput + x360ceの使用

Posted at

#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;
}
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?