Archived

This topic is now archived and is closed to further replies.

direct input

This topic is 4945 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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?


Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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;
}

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites