Skip to main content
GameDev.net gamedev.net
🔒 Locked

direct input

Started by spacemonkey005 May 28, 2004 at 3:51 PM 16 replies 1.3k views
Original Post
spacemonkey005
spacemonkey005
Im using direct input with DX8, and I am doing a if (KEYDOWN(buffer, DIK_S)) statement to toggle sound. It works intermittently though, but when I put a message box in that statement it works everytime. - Has anyone heard anything along the lines that DX takes over the WIN32 message queue or vise versa. I am thinking that perhaps that may be happening. Anyone else ever have this?
neneboricua19
neneboricua19
The problem is that since the render loop happens so fast, the system toggles sound many times during the second that you have your finger on the ''s'' key. For simple toggles, it''s better to use Win32 messages.

neneboricua
spacemonkey005
spacemonkey005
heh ok, I am a little new at this (surprise!). Can you/anyone give an example. Do you mean capturing the KEYDOWN message event or something like that?
Jiia
Jiia
KEYDOWN should specify when the key held. Make a KEYPRESSED as well. Keep a record of all the key states from the previous frame. If one is down on the current frame and wasn''t in the last frame, then it was just pressed.
neneboricua19
neneboricua19
quote:
Original post by spacemonkey005
heh ok, I am a little new at this (surprise!). Can you/anyone give an example. Do you mean capturing the KEYDOWN message event or something like that?

What I mean is you can put something like the following in your message handler:

switch( msg )
{
case WM_KEYDOWN:
{
switch( wParam )
{
case ''S'':
m_bSound = !m_bSound;
break;
}
}
}

This will allow you to toggle sound in your application without any problems.

neneboricua
spacemonkey005
spacemonkey005
quote:


switch( msg )
{
case WM_KEYDOWN:
{
switch( wParam )
{
case ''S'':
m_bSound = !m_bSound;
break;
}
}
}

This will allow you to toggle sound in your application without any problems.


ok so I slapped this case WM_KEYDOWN in my msg loop and it doesn''t do anything. I also tried KEYUP, and CHAR and neither work. Is there something else I should be doing?


J_Vitel
J_Vitel
It should be in your Windows message handler, are you doing it ok? if so, post some code so that we can see the mistake.


LRESULT CALLBACK WinProc(HWND hwnd,
UINT Message,
WPARAM wparam,
LPARAM lparam)
{
...
switch(Message)
{
case WM_KEYDOWN:
if( (int)wparam=='S')
{
m_bSound = !m_bSound;
return 0; // message processed
}
}
...
return (DefWindowProc(hwnd,Mensaje,wparam,lparam));
}


[edited by - j_vitel on June 1, 2004 11:50:44 AM]
My site Jvitel.com
spacemonkey005
spacemonkey005
switch (msg){
case WM_GETMINMAXINFO:
{
// Don't allow resizing in windowed mode.
// Fix the size of the window to 640x480 (client size)
MINMAXINFO* pMinMax = (MINMAXINFO*) lParam;

DWORD dwFrameWidth = GetSystemMetrics(SM_CXSIZEFRAME);
DWORD dwFrameHeight = GetSystemMetrics(SM_CYSIZEFRAME );
DWORD dwMenuHeight = GetSystemMetrics(SM_CYMENU );
DWORD dwCaptionHeight = GetSystemMetrics(SM_CYCAPTION );

pMinMax->ptMinTrackSize.x = SCREEN_WIDTH + dwFrameWidth * 2;
pMinMax->ptMinTrackSize.y = SCREEN_HEIGHT + dwFrameHeight * 2 + dwMenuHeight + dwCaptionHeight;

pMinMax->ptMaxTrackSize.x = pMinMax->ptMinTrackSize.x;
pMinMax->ptMaxTrackSize.y = pMinMax->ptMinTrackSize.y;
}
return 0L;
case WM_MOVE:
// Retrieve the window position after a move.
if (g_pDisplay ) g_pDisplay->UpdateBounds();
return 0L;
case WM_SIZE:
// Check to see if we are losing our window...
if ((SIZE_MAXHIDE == wParam) || (SIZE_MINIMIZED == wParam))
g_bActive = FALSE;
else
g_bActive = TRUE;

if (g_pDisplay)
g_pDisplay->UpdateBounds();
break;
case WM_QUERYNEWPALETTE:
if (g_pDisplay && g_pDisplay->GetFrontBuffer()){
LPDIRECTDRAWPALETTE pDDPal = NULL;
g_pDisplay->GetFrontBuffer()->GetPalette(&pDDPal);
g_pDisplay->GetFrontBuffer()->SetPalette(pDDPal);
SAFE_RELEASE( pDDPal );
}
break;
case WM_SYSCOMMAND:
switch (wParam){
case SC_MOVE:
case SC_SIZE:
case SC_MAXIMIZE:
case SC_MONITORPOWER:
if (!g_bWindowed) return TRUE;
}
break;

case WM_KEYDOWN: //WM_CHAR:
switch(wParam){
case 'S':
g_bBufferPaused = !g_bBufferPaused;
MessageBox( hWnd, TEXT("s key down"), TEXT("WW"), MB_ICONERROR | MB_OK );
break;
case 'c':
g_wGameMode = TITLEPAGE;
break;
}
break;

case WM_MOUSEMOVE:
if (g_wGameMode == DESIGN){
g_iMouseX = LOWORD(lParam);
g_iMouseY = HIWORD(lParam);
}
break;
case WM_LBUTTONUP:
//g_bButtonOne = FALSE;
break;
case WM_LBUTTONDOWN:
//g_bButtonOne = TRUE;
break;
case WM_RBUTTONUP:
//g_bButtonTwo = FALSE;
break;
case WM_RBUTTONDOWN:
//g_bButtonTwo = TRUE;
break;
case WM_DESTROY:
SaveGame();
FreeDirectDraw();
PostQuitMessage(0);
return 0L;
}

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

that is what I have for the message loop - anyone see anything funky?

[edited by - spacemonkey005 on June 1, 2004 12:00:55 PM]

[edited by - spacemonkey005 on June 1, 2004 4:34:36 PM]
3DXD
3DXD
I use directinput for my stuff and although you can use windows messages too of course, the problem isn''t so much based on what you appear to have as a problem, as much as you don''t appear to be storing the state of the key either. You shouldn''t just check if the key is down so much as checking to see if it is down compared to the last time you checked.

Since you can have immediate or buffered more, I use immediate for the fact I dont need buffered at the moment. Now how often you sample of course could "possibly" mean that you could press the S key and it not be recorded as being pressed, but unless you have the worlds slowest readinput loop I doubt it would happen often.

However, you can use buffered mode in which case you would NOT toggle sound until you have traversed all the data in the buffer to see what the final state of the key is, then compare it to the final state the key was in from the last time you read the buffer.

This way you don''t have on/off/on/off/on/off happening 100 times a second.

Windows Messages do of course work well too don''t get me wrong.

J_Vitel
J_Vitel
Isn´t it even showing the message box you placed inside the case statement??
My site Jvitel.com
spacemonkey005
spacemonkey005
quote:
Original post by J_Vitel
Isn´t it even showing the message box you placed inside the case statement??


ha, nope. I don''t get it...
J_Vitel
J_Vitel
mmmm, so where are you calling your WinProc function? are the other events being called properly??
My site Jvitel.com
Teric
Teric
The way I''ve done it is I have a boolean variable for the key state (such as bSKeyDown).

On the KEYDOWN message, I set bSKeyDown to true and process a keystroke for the S key. But I only process it the first time; if another KEYDOWN comes but the bSKeyDown is already true, I don''t process the keystroke.

On the KEYUP message, I set bSKeyDown to false. Then when another KEYDOWN message comes, I can process the keystroke again.
I am always open to feedback, positive or negative...
spacemonkey005
spacemonkey005
quote:
Original post by J_Vitel
mmmm, so where are you calling your WinProc function? are the other events being called properly??


There is no explicit call to MainWndProc, when the winow is made it is set to use MainWndProc. The other functions I have for menu items etc.. and the WM_DESTROY is being called and thats in there as well.

Is this what you mean?
SoulSpectre
SoulSpectre
As others have said, you problem is most likely from the bool value rapidly toggling between true/false every time you press the key due to high frame rates. What you need to do is:


//once only initialisation (do not put this in your loop)
bool keydown = false;
bool keypressed = false;

(loop)
keydown = KEYDOWN();
if(keydown && !keypressed){
keypressed = true;
playsound != playsound;
}else if(!keydown){
keypressed = false;
}

Oluseyi
Oluseyi
The real question is, Are you still using DirectInput? If you are, is your cooperative level exclusive? AFAIK, DirectInput can not share the keyboard with the Windows message queue within the same application - it''s a one or the other situation. Of course, I could be wrong...

The cooperative level dictates whether DirectInput relinquishes control when its window is not the foreground or focus window. That''s to allow it share access with other applications.

If you''re still using DirectInput for other purposes, you''ll simply have to design a more robust capture mechanism.
spacemonkey005
spacemonkey005
well I found that it was the cooperation level of the keyboard. It was DISCL_EXCLUSIVE | DISCL_FOREGROUND, and this told me that it was so greedy that it did not even let WIN32 messages come through. So I changed it to NONEXCLUSIVE instead, and then the WIN32 messages started to work. Now everyone is playing nice and sharing.

thanks all for the help! much appreciative

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.