Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Exit game from another class (Input)


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
51 replies to this topic

#21 falcon93   Members   -  Reputation: 121

Like
0Likes
Like

Posted 01 August 2011 - 05:25 PM

Won't I get a windows delay when I use this method?

Anyway, I tried adding this
switch (message)
{
  case WM_DESTROY: PostQuitMesssage(0); return 0;
  case WM_KEYDOWN: if (wParam == VK_ESCAPE) { MessageBox(NULL, "Button Pressed!", NULL, NULL); } break;
}
into the message loop, but nothing happend :/

Also, how can you reach the pKeyState and the OnKeyDown method from inside the msgProc?

Sponsor:

#22 ApochPiQ   Moderators   -  Reputation: 16382

Like
0Likes
Like

Posted 01 August 2011 - 06:05 PM

Can you post the complete code you used that didn't work?

#23 Vortez   Crossbones+   -  Reputation: 2704

Like
0Likes
Like

Posted 01 August 2011 - 06:36 PM

Won't I get a windows delay when I use this method?


Calling a messagebox here is probably a bad idea since it will block all message processed by this window. You could use messagebeep(0) instead or something similar(debugger breakpoint, file input, ect).

Also, how can you reach the pKeyState and the OnKeyDown method from inside the msgProc?


Im using a pointer to my main class, so i can use it anywhere in this file, it need to be initialised before you start the message loop, or it could be created dynamically like this:

#include "Vortez3DEngine.h"

CVortez3DEngine *pVortez3DEngine = NULL;

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	// Create the game engine object
	pEngine = new CVortez3DEngine;

	if(pEngine->InitEngine()){
		pEngine->StartEngine();
	}
	pEngine->ShutdownEngine();

	delete pEngine;
}


#24 wolfscaptain   Members   -  Reputation: 200

Like
0Likes
Like

Posted 02 August 2011 - 06:36 AM

Why anyone chooses to use the ugliness that Win32 is in the first place is beyond me.

#25 Vortez   Crossbones+   -  Reputation: 2704

Like
0Likes
Like

Posted 02 August 2011 - 07:41 AM

I don't see what's ugly about that. I find this method pretty simple compared to DirectInput, plus, it only take a dozen lines of code.

#26 falcon93   Members   -  Reputation: 121

Like
0Likes
Like

Posted 02 August 2011 - 04:20 PM

Can you post the complete code you used that didn't work?


There's actually not any problem that doesn't work, the problem is that I'm stuck on how to proceed. Would you mind taking a look at my whole project and maybe suggest a solution? For example, the player class needs to be able to check if the arrow keys is pressed. I've tried attaching my project to this reply, but if it didn't work, you can get my project here: http://www.megaupload.com/?d=TK74MXXG


@Vortez: Thanks for you reply too. I don't know what I should say though as it sounds pretty complicated ;) I'm just searching for the "correct" and easiest way :)

#27 ApochPiQ   Moderators   -  Reputation: 16382

Like
1Likes
Like

Posted 02 August 2011 - 05:37 PM

Does this article help any?

#28 Net Gnome   Members   -  Reputation: 773

Like
-1Likes
Like

Posted 03 August 2011 - 07:39 AM

<removed post cause i realized i was posting completely off-topic>

#29 falcon93   Members   -  Reputation: 121

Like
0Likes
Like

Posted 03 August 2011 - 01:38 PM

Ok, thank you everyone for the help. This is however very much information for me as I'am a begginer in this area, so I'll try to break it down to one peice at a time.


Does this article help any?


Thanks very much for that article. I read it and it helped me getting a better understanding, however it was also a lot of complex things that I didn't quite understand. I tried downloading the demo you provided in the article, but that was too advanced for me :wink:

My plan was to create a class that can check all buttons on the keyboard, and then by a function check if a specific key was pressed. I know however that it's easier said then done.

This is how far I've got so far, 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;RegisterRawInputDevices(rid, 1, sizeof(RAWINPUTDEVICE));}Input::~Input(void){}void Input::CheckInput(LPARAM lParam){UINT bufferSize;GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &bufferSize, sizeof (RAWINPUTHEADER));BYTE* buffer=new BYTE[bufferSize];GetRawInputData((HRAWINPUT)lParam, RID_INPUT, (LPVOID)buffer, &bufferSize, sizeof (RAWINPUTHEADER));RAWINPUT* raw = (RAWINPUT*) buffer;if (raw->header.dwType == RIM_TYPEKEYBOARD){ USHORT keyCode = raw->data.keyboard.VKey; switch (keyCode) { case VK_LEFT: MessageBox(NULL, L"Left", NULL, NULL); break; case VK_RIGHT: MessageBox(NULL, L"Right", NULL, NULL); break; case VK_UP: MessageBox(NULL, L"Up", NULL, NULL); break; case VK_DOWN: MessageBox(NULL, L"Down", NULL, NULL); break; }}}[/source]

And in Main.cpp, the WinProc method:
[source lang="cpp"]#include <Windows.h>#include "Main.h"#include "Graphics.h"#include "Input.h"#include "Player.h"Input* input = new Input();LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){switch (message){ case WM_DESTROY: PostQuitMessage(0); return 0;}input->CheckInput(lParam);return DefWindowProc(hWnd, message, wParam, lParam);}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){WNDCLASSEX wc;ZeroMemory(&wc, sizeof(WNDCLASSEX));wc.cbSize = sizeof(WNDCLASSEX);wc.hInstance = hInstance;wc.lpfnWndProc = WindowProc;wc.lpszClassName = L"AvoidBallClass";wc.style = CS_VREDRAW | CS_HREDRAW;RegisterClassEx(&wc);HWND hWnd;hWnd = CreateWindowEx(NULL, L"AvoidBallClass", L"AvoidBall", WS_OVERLAPPED, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInstance, NULL);ShowWindow(hWnd, nCmdShow);MSG msg;Graphics* graphics = new Graphics(hWnd);Player* player = new Player(*graphics, 100, 100);while (true){ while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } graphics->Begin(); graphics->Draw(*player->sprite, player->x, player->y); graphics->End();}// TODO: Clean up resources.return msg.wParam;}[/source]

This however doesn't work. When I compile I get a direct build crash:

Unhandled exception at 0x009c15a0 in AvoidBall.exe: 0xC0000005: Access violation reading location 0x00000000.


Which points on this line in my Graphics.cpp!

d3ddev->CreateVertexBuffer(4*sizeof(CUSTOMVERTEX), 0, CUSTOMFVF, D3DPOOL_MANAGED, &v_buffer, NULL);



This makes no sence for me :( When I comment the content in the GetInput method, the game builds fine, but when I enable the code, it crashes.

1. What's wrong with the code?
2. Does this seem to be a "correct" way to check input?

#30 rip-off   Moderators   -  Reputation: 8667

Like
1Likes
Like

Posted 03 August 2011 - 03:40 PM

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.

#31 falcon93   Members   -  Reputation: 121

Like
0Likes
Like

Posted 03 August 2011 - 04:22 PM

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?

#32 rip-off   Moderators   -  Reputation: 8667

Like
1Likes
Like

Posted 03 August 2011 - 05:07 PM

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...

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.

#33 falcon93   Members   -  Reputation: 121

Like
0Likes
Like

Posted 03 August 2011 - 06:34 PM

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 Posted Image

#34 rip-off   Moderators   -  Reputation: 8667

Like
1Likes
Like

Posted 04 August 2011 - 03:05 AM

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.

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.

#35 falcon93   Members   -  Reputation: 121

Like
0Likes
Like

Posted 04 August 2011 - 01:03 PM

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)...

#36 rip-off   Moderators   -  Reputation: 8667

Like
1Likes
Like

Posted 04 August 2011 - 01:18 PM

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.

#37 falcon93   Members   -  Reputation: 121

Like
0Likes
Like

Posted 04 August 2011 - 03:52 PM

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 :)

#38 rip-off   Moderators   -  Reputation: 8667

Like
0Likes
Like

Posted 04 August 2011 - 05:04 PM

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

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)

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)
{
   // ...
}


#39 falcon93   Members   -  Reputation: 121

Like
0Likes
Like

Posted 05 August 2011 - 11:56 AM

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?

#40 rip-off   Moderators   -  Reputation: 8667

Like
0Likes
Like

Posted 05 August 2011 - 12:26 PM

I have no idea why you expect that to work. If you want to query if a given key is down, you should use the GetASyncKeyState() function I linked you to earlier.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS