gpt4 book ai didi

c++ - 为什么我的 DirectX 程序不能识别我已经释放退出键? (C++)

转载 作者:搜寻专家 更新时间:2023-10-31 02:00:45 25 4
gpt4 key购买 nike

编辑:经过更多的代码修改,错误仍然存​​在,修改后的代码显示:

KeyDown():

const int input_bit_num = 0x8000;
char keys[256];
bool KeyDown(int key)
{
return (keys[key] & input_bit_num) != 0;
}

PollKeyboard():

LPDIRECTINPUTDEVICE8 di_keyboard;
void PollKeyboard()
{
long result = di_keyboard->GetDeviceState(sizeof(keys), (LPVOID)&keys);
char para[16];
itoa(result, para, 17);
if(result != DI_OK) MessageBox(NULL, para, "ERROR", MB_OK);

}

当我尝试将 MessageBox 放在 KeyDown() if 语句中时(如下面的游戏循环所示),即使我停止按键,MessageBox 也会继续出现,即:我按 ,“你想退出吗?”消息框出现,我说不,它消失然后立即重新出现,就好像我还拿着 key 。

这是我的循环:

void GameRun(HWND hWnd) //called once every frame
{
PollKeyboard();
if(GetTickCount - start >= 30)
{
if(KeyDown(DIK_LEFT))
MoveLeft();
if(KeyDown(DIK_RIGHT))
MoveRight();
}

if(d3ddev->BeginScene())
{
//rendering
}

if(KeyDown(DIK_ESCAPE))
{
//any MessageBox()
int result = MessageBox(hWnd, "I'm causing so much trouble!", "IMMORTAL", MB_YESNOCANCEL);
if(result == IDYES)
//end
}
}

编辑:PollKeyboard() 中的 catch 显示序列 53gd6bcc,但是我找不到它对应的错误代码。

编辑:经过另一次测试,我发现即使 MessageBox 不在 KeyDown() if 语句中,故障仍然发生。

编辑:经过更多测试后,似乎是 MessageBox 本身导致了故障。

最佳答案

因为示例代码有效,所以您的程序中的其他内容导致了错误。尝试将下面的代码部分移到您自己的代码中,直到它起作用为止,然后您就会知道是哪部分代码出了问题。

示例代码

好的,巨大的代码块出现了。此代码对我来说工作正常。 (退出,以及所有其他键成功激活和停用)。它很大,有评论,并且很好地解释了事情。试试这个,如果可行,我们会检查你程序的其他部分,如果不行,我只能给你“祝你好运”,你想要什么就拿什么:

// DirectInput
#define DIRECTINPUT_VERSION 0x0800
#include<dinput.h>

// Standard stuff
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <string>

// Link from code, MSVC specific, could be done in project settings
#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "dxguid.lib")

// Utility lexical_cast, use Boost if possible.
// Simple replacement, converts a stream-able `T`
// to a string
template <typename T>
const std::string lexical_cast(const T& pValue)
{
std::stringstream ss;
ss << pValue;

return ss.str();
}

// Utility function + macro to execute DirectX code with exceptions.
// Kinda ugly, but helpful for us.
void check_error(HRESULT pResult, const std::string& pFuncName)
{
// DI_OK == S_OK, but S_OK is more general, so we'll use that
if (pResult != S_OK)
{
throw std::runtime_error("Error executing: " + pFuncName +
"! Returned: " + lexical_cast(pResult));
}
}

// Macro, makes calling the function easier. It is wrapped in
// an `if` statement for reasons outlined in:
// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.5
#define CHECK_ERROR(x) if (true) { check_error(x, #x); } else (void)0

// The above gives the warning:
// "warning C4127: conditional expression is constant", disable below:
#pragma warning(disable: 4127)

// Manages input
class input_manager
{
public:
// Constants
static const int NumberKeys = 256;

// Creation
input_manager(void)
{
// Create input and keyboard (like I said, ugly macro, but helpful :] )
CHECK_ERROR(DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
IID_IDirectInput8, reinterpret_cast<void**>(&_input), 0));


CHECK_ERROR(_input->CreateDevice(GUID_SysKeyboard, &_keyboard, 0));
CHECK_ERROR(_keyboard->SetDataFormat(&c_dfDIKeyboard));
CHECK_ERROR(_keyboard->Acquire());
}

~input_manager(void)
{
// Free resources. Note: Many programmers
// unnecessarily wrap this stuff in
// `if (_keyboard !=0)`, and then
// `_keyboard = 0`. This is completely unnecessary,
// because destructors are only run one time.

// Also, I can assume they are valid, because if they
// weren't, we wouldn't be here (an exception would have
// been thrown)

_keyboard->Unacquire();
_keyboard->Release();
_input->Release();

// Also, if we wrapped this into a nice RAII class, we wouldn't
// be forced to write a destructor, but this is outside the scope.
// Feel free to ask how; additionally, since we're on the topic, if you'd
// like more tips handling input (I've written PLENTY of input managers)
// I'm free for asking about things like testing for triggers rather than pressed
// ("was it pressed, regardless if it's being held now" versus
// "is it being pressed"), etc.
}

// Operations
void update(void)
{
CHECK_ERROR(_keyboard->GetDeviceState(NumberKeys, reinterpret_cast<void*>(&_keys)));
}

// Query
bool key_pressed(int pKey) const
{
return test_key(pKey);
}

// Might wrap into an operator[] for convenience.

private:
// Constants
static const int PressMask = 0x80;

// Sorry for the confusion, but indeed, with
// `char`s the mask is simply 0x80.

// Utility
bool test_key(int pKey) const
{
return (_keys[pKey] & PressMask) != 0;
}

// Members
LPDIRECTINPUT8 _input;
LPDIRECTINPUTDEVICE8 _keyboard;

char _keys[NumberKeys];
};

void test_keys(const input_manager& input)
{
bool anyPressed = false;

for (unsigned i = 0; i < input_manager::NumberKeys; ++i)
{
if (input.key_pressed(i))
{
std::cout << "Pressing: " << i << std::endl;

anyPressed = true;
}
}

if (!anyPressed)
{
std::cout << "No keys pressed." << std::endl;
}
}

void execute(void)
{
input_manager input;

std::cout << "Press Q to quit." << std::endl;

bool running = true;
while (running)
{
input.update();

if (input.key_pressed(DIK_Q))
{
running = false;
}

test_keys(input);

Sleep(0); // give some processor time
}
}

int main(void)
{
// Place real code in an execute function, so main
// is clean and ready to catch exceptions:
try
{
execute();
}
catch (const std::exception& e)
{
// Error!
std::cerr << "Unhandled exception:" << e.what() << std::endl;
}
}

旧建议:

尝试从 GetDeviceState 获取返回值:

HRESULT result =                              // v Prefer C++-style casts
di_keyboard->GetDeviceState(sizeof(keys), reinterpret_cast<void*>(&keys);

if (result != DI_OK)
{
// uh-oh
std::cout << result << std::endl;
}

将其与 table here 进行比较.

旧的半答案:

在编辑 Extra Stuff 部分的代码后不久,我意识到了这个错误,抱歉我没有早点发现它。你在测试错误的位:)

观察:

//                                     v HERE! Should be 0x8000, not 0x80.
return (GetAsyncKeyState(pKeyCode) & 0x8000) != 0;

试试看:

int KeyDown(int key)
{
return (keys[key] & 0x8000);
}

另外,这应该被移动到常量中以避免魔数(Magic Number):

// somewhere, probably in the private section of the class or in a detail namespace:
static const int PushedMask = 0x8000;

// code reads better:
int KeyDown(int key)
{
return (keys[key] & PushedMask);
}

最后,在 C++ 中你有一个 bool 类型,所以要好好利用它!

// v here
bool KeyDown(int key)
{
return (keys[key] & PushedMask);
}

我知道 Visual Studio 会警告这种从 intbool 的转换,因此您可以摆脱它,同时也让您的意图更清晰:

bool KeyDown(int key)
{
return (keys[key] & PushedMask) != 0; // or == 1, your choice
}

额外内容:

试试下面的代码:

#include <iostream>
#include <windows.h>

bool key_pressed(int pKeyCode)
{
return (GetAsyncKeyState(pKeyCode) & 0x8000) != 0;
}

void test_keys(void)
{
for (unsigned i = 0; i < 255; ++i)
{
if (key_pressed(i))
{
std::cout << "Pressing: " << i << std::endl;
}
}
}

int main(void)
{
bool running = true;
while (running)
{
if (key_pressed(VK_ESCAPE))
{
running = false;
}

test_keys();

Sleep(0);
}
}

这对我有用(响应所有键,退出退出)。 GetAsyncKeyState 的最小测试用例。如果这有效,请在您的评论中添加操作系统、键盘等。

关于c++ - 为什么我的 DirectX 程序不能识别我已经释放退出键? (C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1591036/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com