Tastatureingabe träge (DirectInput)

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Tactive
Beiträge: 61
Registriert: 21.07.2004, 15:10
Kontaktdaten:

Tastatureingabe träge (DirectInput)

Beitrag von Tactive »

Hallo,

ich arbeite gerade das Buch "Advanced 3D Game Programming with DirectX 10.0" von Peter Walsh durch und habe mir zum besseren Verständnis ein DX10 Testprojekt erstellt,
in dem ich die Dinge ausprogrobiere und ein wenig erweitere die in dem Buch stehen. Jetzt bin ich Kapitel mit Direct Input angekommen und habe die Input Klasse für die Tastatur
in das Projekt integriert. Sound hatte ich bereits im Vorfeld gemacht und das läuft auch einwandfrei. Nur die Tastatureingabe ist ein wenig träge, so muss ich eine Taste nun mindestens
eine Sekunde gedrückt halten bis die Routine das merkt. Die Input-Abfrage wird über den Main-Loop angestossen:

Code: Alles auswählen

while (!stateManager->IsExitApplicationSet())
{
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    inputManager->UpdateDevices();

    window.Clear();
    siTriRenderer.Render();
    window.Present();
}
Die Render-Methode zeichnet dabei nur ein einfaches Dreieck und wenn ich sie weglasse reagiert die Tastaturabfrage weiterhin so bescheiden.
Jetzt wäre meine Idee, die Tastaturabfrage innerhalb des Input-Managers über einen eigenen Thread laufen zu lassen, ähnlich wie die Sound-Ausgabe.
Nur fürchte ich, das es dann zu Problemen kommt da die Tastaturabfrage die Meldung über gedrückte Tasten direkt an die entsprechenden Klassen
(in meinem Testprojekt die Application-Class) weitergibt.

Hier der Code für die Tastaturabfrage:

Code: Alles auswählen

#include "Keyboard.h"
#include <boost/foreach.hpp>

// Initialize static variables
const UINT Keyboard::ms_keyArraySize = (256 * sizeof(BYTE));

Keyboard::Keyboard(HWND hwnd, IUnknownHolder<IDirectInput8>& directInput)
	: m_keyState(new BYTE[256])
{
	// Create direct input 8 object
	////////////////////////////////////

	if (FAILED(directInput->CreateDevice(GUID_SysKeyboard, &m_directInputDevice, NULL)))
		throw Exception("Unable to create direct input device for keyboard");

	// Set the keyboard data format
	////////////////////////////////////

	if (FAILED(m_directInputDevice->SetDataFormat(&c_dfDIKeyboard)))
	{
		SafeRelease(m_directInputDevice);
		throw Exception("Unable to set data format for keyboard input device");
	}

	// Set the cooperative level
	////////////////////////////////////

	if (FAILED(m_directInputDevice->SetCooperativeLevel(hwnd, (DISCL_FOREGROUND | DISCL_NONEXCLUSIVE))))
		throw Exception("Unable to set cooperative level for keyboard input device");

	// Initialize the keystate array
	ZeroMemory(m_keyState.get(), ms_keyArraySize);
}

Keyboard::~Keyboard()
{
	if (m_directInputDevice)
	{
		m_directInputDevice->Unacquire();
		SafeRelease(m_directInputDevice);
	}
}

bool Keyboard::Poll(unsigned int key) const
{
	return (m_keyState[key] & 0x80) ? true : false;
}

bool Keyboard::Update()
{
	BYTE keyState[256];
	ZeroMemory(&keyState, sizeof(keyState));

	for (unsigned int i = 0; i < 1; i++)
	{
		if (FAILED(m_directInputDevice->Poll()) 
			|| FAILED(m_directInputDevice->GetDeviceState(sizeof(keyState), &keyState)))
		{
			if (i > 0 || FAILED(m_directInputDevice->Acquire()))
				return false;
			else
				continue;
		}
	}

	if (m_receivers.size() > 0)
	{
		for (unsigned int i = 0; i < 256; i++)
		{
			if (m_keyState.get()[i] != keyState[i])
			{
				// Something happened to this key since last check
				if (!(keyState[i] & 0x80))
					BOOST_FOREACH(IKeyboardReceiver* receiver, m_receivers)
					{
						receiver->KeyUp(i);
					}
				else
				{
					// We do nothing cause the key was just pressed and it'll get a
					// key down signal next from us; otherwise the receiver would be
					// triggered twice.
				}
			}

			// copy the key state over
			m_keyState[i] = keyState[i];

			if (Poll(i))
			{
				// Key was pressed
				BOOST_FOREACH(IKeyboardReceiver* receiver, m_receivers)
				{
					receiver->KeyDown(i);
				}
			}
		}
	}
	else
	{
		// copy the new states over
		memcpy(m_keyState.get(), keyState, 256);
	}

	return true;
}
Kann mir das vielleicht jemand einen Tip geben, wie ich das am besten lösen könnte bzw. was die gängige Vorgehensweise ist??

Danke im Voraus.
Helmut
Establishment
Beiträge: 237
Registriert: 11.07.2002, 15:49
Wohnort: Bonn
Kontaktdaten:

Re: Tastatureingabe träge (DirectInput)

Beitrag von Helmut »

Bist du sicher, dass es am Input liegt und nicht etwa der Renderer hinterherhinkt? Teste das doch mal schnell, indem du bei nem Tastendruck ein MessageBeep(0) machst.

Sollte es wirklich am Input liegen würd ich einfach mal auf DirectInput verzichten. Die API ist nur veraltet und kompliziert zu benutzen. Benutz lieber Fensternachrichten und GetAsyncKeyState(). Auch auf den Joystick kannst du mit der Win32 API zugreifen.

Ciao
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Tastatureingabe träge (DirectInput)

Beitrag von Zudomon »

Die Funktion GetAsyncKeyState() wird von manchen Virenprogrammen als Keylogger interpretiert.
Antworten