🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Exit game from another class (Input)

Started by
50 comments, last by rip-off 12 years, 10 months ago
The problem is that you use a class instead of simply putting your code in the message loop function. Here's how i do it:


LRESULT CALLBACK MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
//Process quit message
case WM_DESTROY:
case WM_CLOSE:
PostQuitMessage(0);
break;


case WM_KEYDOWN:
if(wParam == VK_ESCAPE){
PostQuitMessage(0);
break;
}
pKeyState[wParam] = true;
pVortez3DEngine->OnKeyDown((UINT)wParam);
break;
case WM_KEYUP:
pKeyState[wParam] = false;
pVortez3DEngine->OnKeyUp((UINT)wParam);
break;


default: break;
}

return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

You can put more stuff there like mouse input and such. Also notice the pVortez3DEngine->OnKeyUp((UINT)wParam); wich mean that you can process all you input in another function if you want to. KeyState is simply an array of 256 bool that can be used to tell if one or multiple keys are pressed. As for the game loop, it should be done like this (that's why im using a pointer to my class object above).

void CVortez3DEngine::GameLoop()
{
MSG msg;
bool done = false;

// Application loop.
while(!done){
if(PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)){
// If a quit message is received then stop rendering and quit the app.
if(msg.message == WM_QUIT){
done = true;
}
TranslateMessage(&msg); // Translate any messages.
DispatchMessage(&msg); // Dispatch any messages.
} else {
EngineTimer.Tick(); // Update engine timer
UpdateScene(EngineTimer.g_ElapsedTime); // Control the game flow
RenderScene(); // Render a frame.
}
}
}

void CVortez3DEngine::OnKeyDown(UINT KeyPressed){}
{
// Your code...
}

void CVortez3DEngine::OnKeyUp(UINT KeyPressed){}
{
// Your code...
}
Advertisement
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?
Can you post the complete code you used that didn't work?

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

[quote=falcon93]
Won't I get a windows delay when I use this method?
[/quote]

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

[quote=falcon93]
Also, how can you reach the pKeyState and the OnKeyDown method from inside the msgProc?
[/quote]

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;
}
Why anyone chooses to use the ugliness that Win32 is in the first place is beyond me.
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.

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 :)
Does this article help any?

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

<removed post cause i realized i was posting completely off-topic>
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?

This topic is closed to new replies.

Advertisement