几个星期以来,我一直对制作一个显示XBOX控制器输入的程序感兴趣,而且我一直有很多问题。我正在使用Code :: Blocks,而XInput.h有SAL注释,我已经读过GNU GCC编译器,不知何故不熟悉。我坚持用Code :: Blcoks编码,所以我决定链接Visual Studio中的包含文件(我已经读过这将解决一些与SAL相关的问题)。现在我有了新的问题。我使用的代码来自https://lcmccauley.wordpress.com/2014/01/05/gamepad-input-tutorial/的教程,由于我也包含了新文件夹,我在第81行的vcruntime.h中遇到了错误。另一个错误是winnt.h,第2444行。我现在完全没有想法。
P.S:请不要因为没有注意到一些明显的解决方案而杀了我。我还是个初学者。谢谢!以下代码:
main.cpp中:
//------------------------------------------------------------
// C++ Xbox 360 gamepad Input using XInput
// Demo code by Lawrence M
//------------------------------------------------------------
// This is a demo program to demonstrate the 'Gamepad' class
// (based on the code from my 3-part tutorial).
//
// All code in this program (including 'Gamepad' class) was
// written and tested on a Windows 7 PC using Visual Studio
// 2013. A Microsoft (USB wired) Xbox 360 controller was used
// to test the gamepad code.
//------------------------------------------------------------
//#include <no_sal.h>
#include <iostream>
#include "Gamepad.h"
using namespace std;
bool running; // Used to break the loop
Gamepad gamepad; // Gamepad instance
// This example checks input on all gamepad buttons (Guide/logo
// button not supported). For example code on using the triggers
// and thumbsticks, please refer to the tutorial.
void TestGamepad()
{
// GetButtonDown only returns true on the frame it was first pressed.
if (gamepad.GetButtonDown(xButtons.A))
{
cout << " Button [A] pressed" << endl;
}
if (gamepad.GetButtonDown(xButtons.X))
{
cout << " Button [X] pressed" << endl;
}
// GetButtonPressed will keep returning true until the button is released.
if (gamepad.GetButtonPressed(xButtons.Y))
{
cout << " Button [Y] held, see how this doesn't appear just once?" << endl;
}
// Check the D-Pad buttons
if (gamepad.GetButtonDown(xButtons.DPad_Up))
{
cout << " Button [DPad Up] pressed" << endl;
}
if (gamepad.GetButtonDown(xButtons.DPad_Down))
{
cout << " Button [DPad Down] pressed" << endl;
}
if (gamepad.GetButtonDown(xButtons.DPad_Left))
{
cout << " Button [DPad Left] pressed" << endl;
}
if (gamepad.GetButtonDown(xButtons.DPad_Right))
{
cout << " Button [DPad Right] pressed" << endl;
}
// Check the Shoulder ('bumper') buttons
if (gamepad.GetButtonDown(xButtons.L_Shoulder))
{
cout << " Button [L Bumper] pressed" << endl;
}
if (gamepad.GetButtonDown(xButtons.R_Shoulder))
{
cout << " Button [R Bumper] pressed" << endl;
}
// Check the BACK and START buttons
if (gamepad.GetButtonDown(xButtons.Back))
{
cout << " Button [BACK] pressed" << endl;
}
if (gamepad.GetButtonDown(xButtons.Start))
{
cout << " Button [START] pressed" << endl;
}
// Check the Thumbstick buttons (press in the thumbstick)
if (gamepad.GetButtonDown(xButtons.L_Thumbstick))
{
cout << " Button [L STICK] pressed" << endl;
}
if (gamepad.GetButtonDown(xButtons.R_Thumbstick))
{
cout << " Button [R STICK] pressed" << endl;
}
}
int main()
{
// Set up
running = true;
gamepad = Gamepad(1); // Set gamepad ID to 1
cout << " --------------------------------------------" << endl;
cout << " Xbox 360 Gamepad INPUT TEST " << endl;
cout << " --------------------------------------------" << endl << endl;
cout << " Use gamepad buttons to test gamepad input." << endl;
cout << " To quit, press the [B] button." << endl;
cout << " --------------------------------------------" << endl << endl;
// Pretend game loop, repeat until 'B' is pressed
do
{
gamepad.Update(); // Update gamepad
if (gamepad.Connected())
{
// Run gamepad input test
TestGamepad();
// Pressing B quits the program
if (gamepad.GetButtonPressed(xButtons.B))
running = false;
}
gamepad.Refresh(); // Update gamepad for next cycle
}
while (running);
return 0;
}
Gamepad.cpp:
//------------------------------------------------------------
// C++ Xbox 360 gamepad Input using XInput
// Demo code by Lawrence M
//------------------------------------------------------------
// This code is based off my tutorial but I have dropped the
// notation style used in the tutorial to make the code easier
// to read.
//
// Some function and variable names may have changed. For
// more details on the Gamepad class and its features, please
// refer to the tutorial.
//------------------------------------------------------------
#include <no_sal.h>
#include "Gamepad.h"
// Link the 'XInput' library
// Note: For Visual Studio 2012 and above, XInput9_1_0 is the library
// required to make XInput work.
#pragma comment(lib, "XInput.lib")
// Define the 'XInput_ButtonIDs' struct as 'xButtons'
XInput_ButtonIDs xButtons;
// XInput_ButtonIDs struct
//------------------------------------------------------------
// Set buttton values in constructor
XInput_ButtonIDs::XInput_ButtonIDs()
{
A = 0;
B = 1;
X = 2;
Y = 3;
DPad_Up = 4;
DPad_Down = 5;
DPad_Left = 6;
DPad_Right = 7;
L_Shoulder = 8;
R_Shoulder = 9;
L_Thumbstick = 10;
R_Thumbstick = 11;
Start = 12;
Back = 13;
}
// Gamepad class
//------------------------------------------------------------
// Constructor
Gamepad::Gamepad()
{
}
// Constructor - set pad ID
Gamepad::Gamepad(int id)
{
pad_id = id - 1;
for (int i = 0; i < button_count; i++)
{
prev_buttonStates[i] = false;
buttonStates[i] = false;
}
}
// Update gamepad state
void Gamepad::Update()
{
// Get current gamepad state
state = GetState();
for (int i = 0; i < button_count; i++)
{
// Set button state on current frame
buttonStates[i] = (state.Gamepad.wButtons & XINPUT_Buttons[i]) == XINPUT_Buttons[i];
}
}
// Update gamepad state for next cycle
void Gamepad::Refresh()
{
memcpy(prev_buttonStates, buttonStates, sizeof(prev_buttonStates));
}
// Set gamepad vibration ('rumble')
void Gamepad::SetRumble(float left, float right)
{
// XInput vibration state
XINPUT_VIBRATION rumble;
// Zero memory on vibration state
ZeroMemory(&rumble, sizeof(XINPUT_VIBRATION));
// Calculate vibration intensity
int left_motor = int(left * 65535.0f);
int right_motor = int(right * 65535.0f);
rumble.wLeftMotorSpeed = left_motor;
rumble.wRightMotorSpeed = right_motor;
// Apply vibration
XInputSetState(pad_id, &rumble);
}
// Return gamepad number
int Gamepad::GetID()
{
return pad_id;
}
// Check if gamepad is connected
bool Gamepad::Connected()
{
// Zero memory
ZeroMemory(&state, sizeof(XINPUT_STATE));
DWORD result = XInputGetState(pad_id, &state);
if (result == ERROR_SUCCESS)
return true; // Connected
else
return false; // Not connected
}
// Check if specified button is pressed
bool Gamepad::GetButtonPressed(int button)
{
if (state.Gamepad.wButtons & XINPUT_Buttons[button])
{
// Button is pressed
return true;
}
return false; // Button is not pressed
}
// Check if specified button is pressed - CURRENT frame only!
bool Gamepad::GetButtonDown(int button)
{
return !prev_buttonStates[button] && buttonStates[button];
}
// Check deadzone on left thumbstick
bool Gamepad::LStick_InDeadzone()
{
short x = state.Gamepad.sThumbLX;
short y = state.Gamepad.sThumbLY;
if (x > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ||
x < -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
{
// X axis outside of deadzone
return false;
}
if (y > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ||
y < -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
{
// Y axis outside of deadzone
return false;
}
// One (or both) axis inside deadzone
return true;
}
// Check deadzone on right thumbstick
bool Gamepad::RStick_InDeadzone()
{
short x = state.Gamepad.sThumbRX;
short y = state.Gamepad.sThumbRY;
if (x > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ||
x < -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
{
// X axis outside of deadzone
return false;
}
if (y > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ||
y < -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
{
// Y axis outside of deadzone
return false;
}
// One (or both) axis inside deadzone
return true;
}
// Return X axis of left thumbstick
float Gamepad::LeftStick_X()
{
short x = state.Gamepad.sThumbLX;
// Return value as a float
return (static_cast<float>(x) / 32768.0f);
}
// Return Y axis of left thumbstick
float Gamepad::LeftStick_Y()
{
short y = state.Gamepad.sThumbLY;
// Return value as a float
return (static_cast<float>(y) / 32768.0f);
}
// Return X axis of right thumbstick
float Gamepad::RightStick_X()
{
short x = state.Gamepad.sThumbRX;
// Return value as a float
return (static_cast<float>(x) / 32768.0f);
}
// Return Y axis of right thumbstick
float Gamepad::RightStick_Y()
{
short y = state.Gamepad.sThumbRY;
// Return value as a float
return (static_cast<float>(y) / 32768.0f);
}
// Return value of left trigger
float Gamepad::LeftTrigger()
{
BYTE axis = state.Gamepad.bLeftTrigger;
if (axis > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
return axis / 255.0f;
return 0.0f; // Trigger was not pressed
}
// Return value of right trigger
float Gamepad::RightTrigger()
{
BYTE axis = state.Gamepad.bRightTrigger;
if (axis > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
return axis / 255.0f;
return 0.0f; // Trigger was not pressed
}
// Return gamepad state
XINPUT_STATE Gamepad::GetState()
{
XINPUT_STATE new_state;
// Zero memory on state
ZeroMemory(&state, sizeof(XINPUT_STATE));
// Get new state from XInput
XInputGetState(pad_id, &new_state);
return new_state;
}
Gamepad.h
//------------------------------------------------------------
// C++ Xbox 360 gamepad Input using XInput
// Demo code by Lawrence M
//------------------------------------------------------------
// This code is based off my tutorial but I have dropped the
// notation style used in the tutorial to make the code easier
// to read.
//
// Some function and variable names may have changed. For
// more details on the Gamepad class and its features, please
// refer to the tutorial.
//------------------------------------------------------------
#include <no_sal.h>
#include "Gamepad.h"
// Link the 'XInput' library
// Note: For Visual Studio 2012 and above, XInput9_1_0 is the library
// required to make XInput work.
#pragma comment(lib, "XInput.lib")
// Define the 'XInput_ButtonIDs' struct as 'xButtons'
XInput_ButtonIDs xButtons;
// XInput_ButtonIDs struct
//------------------------------------------------------------
// Set buttton values in constructor
XInput_ButtonIDs::XInput_ButtonIDs()
{
A = 0;
B = 1;
X = 2;
Y = 3;
DPad_Up = 4;
DPad_Down = 5;
DPad_Left = 6;
DPad_Right = 7;
L_Shoulder = 8;
R_Shoulder = 9;
L_Thumbstick = 10;
R_Thumbstick = 11;
Start = 12;
Back = 13;
}
// Gamepad class
//------------------------------------------------------------
// Constructor
Gamepad::Gamepad()
{
}
// Constructor - set pad ID
Gamepad::Gamepad(int id)
{
pad_id = id - 1;
for (int i = 0; i < button_count; i++)
{
prev_buttonStates[i] = false;
buttonStates[i] = false;
}
}
// Update gamepad state
void Gamepad::Update()
{
// Get current gamepad state
state = GetState();
for (int i = 0; i < button_count; i++)
{
// Set button state on current frame
buttonStates[i] = (state.Gamepad.wButtons & XINPUT_Buttons[i]) == XINPUT_Buttons[i];
}
}
// Update gamepad state for next cycle
void Gamepad::Refresh()
{
memcpy(prev_buttonStates, buttonStates, sizeof(prev_buttonStates));
}
// Set gamepad vibration ('rumble')
void Gamepad::SetRumble(float left, float right)
{
// XInput vibration state
XINPUT_VIBRATION rumble;
// Zero memory on vibration state
ZeroMemory(&rumble, sizeof(XINPUT_VIBRATION));
// Calculate vibration intensity
int left_motor = int(left * 65535.0f);
int right_motor = int(right * 65535.0f);
rumble.wLeftMotorSpeed = left_motor;
rumble.wRightMotorSpeed = right_motor;
// Apply vibration
XInputSetState(pad_id, &rumble);
}
// Return gamepad number
int Gamepad::GetID()
{
return pad_id;
}
// Check if gamepad is connected
bool Gamepad::Connected()
{
// Zero memory
ZeroMemory(&state, sizeof(XINPUT_STATE));
DWORD result = XInputGetState(pad_id, &state);
if (result == ERROR_SUCCESS)
return true; // Connected
else
return false; // Not connected
}
// Check if specified button is pressed
bool Gamepad::GetButtonPressed(int button)
{
if (state.Gamepad.wButtons & XINPUT_Buttons[button])
{
// Button is pressed
return true;
}
return false; // Button is not pressed
}
// Check if specified button is pressed - CURRENT frame only!
bool Gamepad::GetButtonDown(int button)
{
return !prev_buttonStates[button] && buttonStates[button];
}
// Check deadzone on left thumbstick
bool Gamepad::LStick_InDeadzone()
{
short x = state.Gamepad.sThumbLX;
short y = state.Gamepad.sThumbLY;
if (x > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ||
x < -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
{
// X axis outside of deadzone
return false;
}
if (y > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ||
y < -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
{
// Y axis outside of deadzone
return false;
}
// One (or both) axis inside deadzone
return true;
}
// Check deadzone on right thumbstick
bool Gamepad::RStick_InDeadzone()
{
short x = state.Gamepad.sThumbRX;
short y = state.Gamepad.sThumbRY;
if (x > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ||
x < -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
{
// X axis outside of deadzone
return false;
}
if (y > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ||
y < -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
{
// Y axis outside of deadzone
return false;
}
// One (or both) axis inside deadzone
return true;
}
// Return X axis of left thumbstick
float Gamepad::LeftStick_X()
{
short x = state.Gamepad.sThumbLX;
// Return value as a float
return (static_cast<float>(x) / 32768.0f);
}
// Return Y axis of left thumbstick
float Gamepad::LeftStick_Y()
{
short y = state.Gamepad.sThumbLY;
// Return value as a float
return (static_cast<float>(y) / 32768.0f);
}
// Return X axis of right thumbstick
float Gamepad::RightStick_X()
{
short x = state.Gamepad.sThumbRX;
// Return value as a float
return (static_cast<float>(x) / 32768.0f);
}
// Return Y axis of right thumbstick
float Gamepad::RightStick_Y()
{
short y = state.Gamepad.sThumbRY;
// Return value as a float
return (static_cast<float>(y) / 32768.0f);
}
// Return value of left trigger
float Gamepad::LeftTrigger()
{
BYTE axis = state.Gamepad.bLeftTrigger;
if (axis > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
return axis / 255.0f;
return 0.0f; // Trigger was not pressed
}
// Return value of right trigger
float Gamepad::RightTrigger()
{
BYTE axis = state.Gamepad.bRightTrigger;
if (axis > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
return axis / 255.0f;
return 0.0f; // Trigger was not pressed
}
// Return gamepad state
XINPUT_STATE Gamepad::GetState()
{
XINPUT_STATE new_state;
// Zero memory on state
ZeroMemory(&state, sizeof(XINPUT_STATE));
// Get new state from XInput
XInputGetState(pad_id, &new_state);
return new_state;
}