Exit game from another class (Input)

Started by
50 comments, last by rip-off 12 years, 9 months ago
That is a null pointer access. One of the values in that expression involves dereferencing a null pointer. Use your debugger to check the values and check whether they are all valid.
Advertisement
My debugger gives me this information:

&d3ddev = 0x00993ab0
&d3dpp = 0x0099abc
&v_buffer = 0x00993ab8
D3DDEVTYPE_HAL = 1
D3DPOOL_MANAGED = 1
d3d = 0x00a90800
d3ddev = 0x00000000
hWnd = 0x00000000
this = 0x00993ab0

I guess that 0x00000000 means null? How can my d3dd3d and hWnd be null depending on the code in my GetInput method in Input.cpp?
0x00000000 is null, yes. There is no GetInput() method in the last version of Input.cpp you posted. Are you sure it is in the GetInput() function? The line mentions creating a vertex buffer, which means it probably is in your graphics code (or should be - decouple input from rendering if not).

I don't really see why you are using raw input for reading from the keyboard, what is wrong with reading windows messages in a window procedure? It is probably the simplest solution here.


How can my d3dd3d and hWnd be null depending on the code...
[/quote]
I have no idea how these variables are being passed/referenced. Use your debugger to inspect these values at various critical points in the code (the point where they are first assigned, points where they are passed to subsystems, etc). You should look for any times the pointer is incorrect.

This article might help, depending on the root problem.
Oh, sorry, I mean the CheckInput method.

Yes, when I comment/erase everything in the CheckInput method, the game builds and runs fine. If I add the code back to the CheckInput method, it crashes on build again. It's even more strange that I get a graphics error when we clearly see that the problem is in the input class (no graphics code is placed in the Input class). Any ideas?

I tried using the basic windows message for input before, but it didn't work for some buttons, like the Esc button, and then I was recommended to use the Raw Input smile.gif
Crashes on build? Be clear - is the problem at compile time or run time. "Crash" is a verb used to describe a running program terminating unexpectedly - so "crashes on build" would imply the compiler crashed, which is hard to believe.

You don't have enough error checking. GetRawInputData() has an error code, you should be checking it. When dealing with external APIs, you should check every single function call - otherwise you'll get strange behaviour as your code will continue trying when the API has signaled something is wrong. Your code seems to assume there is raw input ready, I don't know if this is safe.

Your symptoms sound like a classic case of a buffer overflow. Have you taken a look at the sample code?


I tried using the basic windows message for input before, but it didn't work for some buttons, like the Esc button, and then I was recommended to use the Raw Input.[/quote]
Raw input is more complicated that basic windows messages. If you can't get the basics to work, then the chances of getting raw input to work are slimmer still.
I've re-written the Input.cpp from the beginning and now my game manages to detect button presses :D This is my current code:


Input.cpp
[source lang="cpp"]
#include <Windows.h>
#include "Input.h"
#include "Main.h"


Input::Input()
{
RAWINPUTDEVICE rid[1];

rid[0].usUsagePage = 1;
rid[0].usUsage = 6;
rid[0].dwFlags = 0;
rid[0].hwndTarget = NULL;

if (!RegisterRawInputDevices(rid, 1, sizeof(RAWINPUTDEVICE)))
{
MessageBox(NULL, L"Failed to register input device", NULL, NULL);
}

buffer = new BYTE[40];
}


Input::~Input(void)
{
}


void Input::Read(LPARAM lParam)
{
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &buffer_size, sizeof(RAWINPUTHEADER)) < 0)
{
MessageBox(NULL, L"Failed to receive input data", NULL, NULL);
}

if (buffer_size > sizeof(buffer))
{
buffer = new BYTE[buffer_size];
}

if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, (LPVOID)buffer, &buffer_size, sizeof(RAWINPUTHEADER)) < 0)
{
MessageBox(NULL, L"Failed to receive input data", NULL, NULL);
}

raw = (RAWINPUT*)buffer;

if (raw->header.dwType == RIM_TYPEKEYBOARD)
{
key_code = raw->data.keyboard.VKey;

switch (key_code)
{
case VK_LEFT: key_down.left = true; break;
case VK_RIGHT: key_down.right = true; break;
}
}
}
[/source]


I tested to move my player around on the x-axis and it worked. The only problem is that if I press the right arrow button once, the player will continue moving to the right untill I press another key. How can I do so the player will only move to the right when I hold down the right arrow key, and stop when I release it? It should also ignore that other buttons is pressed? Any ideas?

Also, is there anyway to log/alert fails without using the messagebox? The messagebox doesn't work so well as it shows up behind my game window (fullscreen)...
sizeof() is a compile time construct. You cannot use it to determine the size of a dynamically allocated array. The result of the expression is the sizeof of the pointer variable. Instead, consider using std::vector<char> as your buffer. It won't leak, unlike your current code.

Your current code sets "left" or "right" to "true" when any activity occurs on the keyboard. Instead you should inspect the members of the RAWKEYBOARD structure, and determine if the key has been pressed or released.

Another option is to use GetKeyboardState() or GetASyncKeyState(), rather than using raw input.

sizeof() is a compile time construct. You cannot use it to determine the size of a dynamically allocated array. The result of the expression is the sizeof of the pointer variable. Instead, consider using std::vector<char> as your buffer. It won't leak, unlike your current code.

Your current code sets "left" or "right" to "true" when any activity occurs on the keyboard. Instead you should inspect the members of the RAWKEYBOARD structure, and determine if the key has been pressed or released.

Another option is to use GetKeyboardState() or GetASyncKeyState(), rather than using raw input.


Didn't understand the thing with "dynamically allocated array". Do you mind giving an example?

I've tested to use the "flag" member in RAWKEYBOARD, this however doesn't work (no crash, but it returns false)
[source lang="cpp"]
bool Input::KeyDown(USHORT key)
{
raw = (RAWINPUT*)buffer;

if (raw->header.dwType == RIM_TYPEKEYBOARD)
{
key_code = raw->data.keyboard.VKey;
}

if (raw->data.keyboard.VKey == key)
{
if (raw->data.keyboard.Flags == RI_KEY_MAKE)
{
MessageBox(NULL, L"PRESS", NULL, NULL);

return true;
}
}

return false;
}
[/source]


How should I do?

Thanks for helping :)

Didn't understand the thing with "dynamically allocated array". Do you mind giving an example?
[/quote]
A dynamically allocated array is any expression like new Type[someValue]. The array is sized at runtime, and a pointer to the first element is typically saved. If you use the sizeof() operator on the pointer, it does not tell you how many bytes are in the array, it tells you how many bytes are in a pointer. This value is a compile time constant, and is typically either 4 or 8 on the systems you are likely to encounter.


I've tested to use the "flag" member in RAWKEYBOARD, this however doesn't work (no crash, but it returns false)
[/quote]
data.keyboard.flags is a mask, you should use bitwise operators to test it:

if((raw->data.keyboard.Flags & RI_KEY_MAKE) == RI_KEY_MAKE)
{
// ...
}
Ok, I've changed it to this:
[source lang="cpp"]
bool Input::KeyDown(USHORT key)
{
raw = (RAWINPUT*)buffer;

if (raw->header.dwType == RIM_TYPEKEYBOARD)
{
key_code = raw->data.keyboard.VKey;
}

if (raw->data.keyboard.VKey == key)
{
if ((raw->data.keyboard.Flags & RI_KEY_MAKE) == RI_KEY_MAKE)
{
return true;
}
}

return false;
}
[/source]

It returns true when I press a key, but it still continues returning true even if I've released the button. It only stops if I press another button. How should I solve this?

This topic is closed to new replies.

Advertisement