|
JLI Spieleprogrammierung
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
cHaoS Mini JLI'ler
Anmeldedatum: 14.06.2007 Beiträge: 7
Medaillen: Keine
|
Verfasst am: 14.06.2007, 18:47 Titel: Probleme bei Mausklicks über DirectInput |
|
|
Hi, ich bin grad dabei ein wenig mit dem Buch "Spieleprogrammierung mit DirectX" herumzuexperimentieren und eine kleine 2D-Spieleengine zusammenzubasteln.
Mein Problem habe ich dabei mit der Maussteuerung, die ich wie im Buch beschrieben über Direct Input programmiert habe.
Code: |
int CInputManager::getMouseInput()
{
DWORD NumElements = 1;
DIDEVICEOBJECTDATA data;
ZeroMemory(&data, sizeof(data));
if(FAILED(m_lpDIDevice->GetDeviceData(sizeof(data), &data, &NumElements, 0)))
{
m_lpDIDevice->Acquire();
return 0;
}
int Input = 0;
switch(data.dwOfs)
{
case DIMOFS_BUTTON0:
Input += MOUSE_LCLICK;
break;
case DIMOFS_BUTTON1:
Input += MOUSE_RCLICK;
break;
case DIMOFS_X:
m_MousePos[0] += data.dwData;
if(m_MousePos[0] < 0) m_MousePos[0] = 0;
if(m_MousePos[0] > SCR_WIDTH) m_MousePos[0] = SCR_WIDTH;
break;
case DIMOFS_Y:
m_MousePos[1] += data.dwData;
if(m_MousePos[1] < 0) m_MousePos[1] = 0;
if(m_MousePos[1] > SCR_HEIGHT) m_MousePos[1] = SCR_HEIGHT;
break;
}
return Input;
}
|
Über diese Funktion hole ich mir die Aktionen der Maus. Die Mausposition abzufragen klappt super, ich kann damit ein sprite über den bildschirm bewegen, jedoch klappt die Abfrage der Tasten nicht wirklich. Wenn ich eine Maustaste Drücke passiert entweder nichts oder nur ab und zu was.
Es sind die richtigen Tasten, die Abgefragt werden, das habe ich schon mit den Beispielprogrammen zum DIrect input überprüft.
Eigentlich sollte das Sprite durch Mausklicks gedreht werden. Der code befindet sich in der Main Funktion in der Spielschleife:
Code: |
Sprite.SetPosition(Input.GetMousePos(X), Input.GetMousePos(Y));
if(Input.GetInput() & MOUSE_LCLICK)
{
Sprite.Rotate(-600.0f, Framerate);
}
if(Input.GetInput() & MOUSE_RCLICK)
{
Sprite.Rotate(600.0f, Framerate);
}
|
GetInput ruft dabei nur die Funktion getMouseInput auf:
Code: |
int CInputManager::GetInput()
{
if(m_CurrentDevice == USE_KEYBOARD)
{
return getKeyboardInput();
}
if(m_CurrentDevice == USE_MOUSE)
{
return getMouseInput();
}
return 0;
}
|
Ich hab absolut keinen Plan, warum der nicht auf die Mausklicks reagiert.
Edit: Interessanterweise dreht sich das Sprite, wenn ich schnell klicke und es dabei bewege. |
|
Nach oben |
|
|
The Lord of Programming Living Legend
Alter: 37 Anmeldedatum: 14.03.2003 Beiträge: 3122
Medaillen: Keine
|
Verfasst am: 14.06.2007, 20:42 Titel: |
|
|
1. Was speicherst du in m_CurrentDevice bzw. wo wird diese Variable aktualisiert?
2. Als was hast du MOUSE_LCLICK bzw. MOUSE_RCLICK definiert?
3. Falls du beabsichtigt hast, in der Mainfunktion durch das &-Zeichen zwei boolesische If-Anweisungen mit einer "und"-Beziehung zu kombinieren, muss das anders aussehen. Das Einfache &-Zeichen steht für die Bitweise &-Verknüpfung. Für die Kombination von If-Anweisungen wird && verwendet. _________________ www.visualgamesentertainment.net
Current projects: RDTDC(1), JLI-Vor-Projekt, Tetris(-Tutorial), JLI-Format
(1) Realtime Developer Testing and Debugging Console
Anschlag, Anleitung zum Atombombenbau, Sprengkörper...
Hilf Schäuble! Damit er auch was findet... |
|
Nach oben |
|
|
cHaoS Mini JLI'ler
Anmeldedatum: 14.06.2007 Beiträge: 7
Medaillen: Keine
|
Verfasst am: 14.06.2007, 21:33 Titel: |
|
|
Also die m_currentDevice wird in der Init() Funktion des Input Managers übergeben. Am besten poste ich mal den gesamten Code:
CPP: | #include "CInputManager.h"
CInputManager::CInputManager()
{
m_CurrentDevice = 0;
m_lpDI = 0;
m_lpDIDevice = 0;
m_MousePos[0] = SCR_WIDTH/2;
m_MousePos[1] = SCR_HEIGHT/2;
}
CInputManager::~CInputManager()
{
if(m_lpDIDevice != 0)
{
m_lpDIDevice->Unacquire();
m_lpDIDevice->Release();
m_lpDIDevice = 0;
}
if(m_lpDI != 0)
{
m_lpDI->Release();
m_lpDI = 0;
}
}
//Hier wird das Direct Input Objekt erstellt und je nachdem welches eingabegerät verwendet werden soll initMouse() oder initKeyboard aufgerufen
BOOL CInputManager::Init(HWND hWnd, HINSTANCE hInst, int Device)
{
m_CurrentDevice = Device;
if(FAILED(DirectInput8Create(hInst,
DIRECTINPUT_VERSION,
IID_IDirectInput8,
reinterpret_cast<LPVOID*>(&m_lpDI),
NULL)))
{
MessageBox(0, "Fehler beim Anlegen des DirectInput8-Objekts!", "Fehler", MB_OK);
return false;
}
switch(m_CurrentDevice)
{
case USE_KEYBOARD:
return initKeyboard(hWnd);
break;
case USE_MOUSE:
return initMouse(hWnd);
break;
default:
m_CurrentDevice = USE_KEYBOARD;
return initKeyboard(hWnd);
}
return true;
}
//dies ist die Sammelklasse, die den Input einer Funktion zurückgibt, je nachdem welches Eingabegerät verwendet wird
int CInputManager::GetInput()
{
if(m_CurrentDevice == USE_KEYBOARD)
{
return getKeyboardInput();
}
if(m_CurrentDevice == USE_MOUSE)
{
return getMouseInput();
}
return 0;
}
//hiermit wird ein Direct Input Device als Keyboard Initialisiert
BOOL CInputManager::initKeyboard(HWND hWnd)
{
m_lpDI->CreateDevice(GUID_SysKeyboard, &m_lpDIDevice, NULL);
m_lpDIDevice->SetDataFormat(&c_dfDIKeyboard);
m_lpDIDevice->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
m_lpDIDevice->Acquire();
return true;
}
//hiermit werden sämtliche gedrückten Tasten der Tastatur zurückgegeben (klappt Tadellos)
int CInputManager::getKeyboardInput()
{
bool bKeyboard[256];
if(FAILED(m_lpDIDevice->GetDeviceState(sizeof(bKeyboard), &bKeyboard)))
{
m_lpDIDevice->Acquire();
return 0;
}
int Input = 0;
if(bKeyboard[DIK_LEFT])
{
Input += KEY_LEFT;
}
if(bKeyboard[DIK_RIGHT])
{
Input += KEY_RIGHT;
}
if(bKeyboard[DIK_UP])
{
Input += KEY_UP;
}
if(bKeyboard[DIK_DOWN])
{
Input += KEY_DOWN;
}
if(bKeyboard[DIK_SPACE])
{
Input += KEY_SPACE;
}
if(bKeyboard[DIK_LCONTROL])
{
Input += KEY_LCTRL;
}
if(bKeyboard[DIK_LSHIFT])
{
Input += KEY_LSHIFT;
}
return Input;
}
//hiermit wird ein Direct Input Object als Maus initialisiert
BOOL CInputManager::initMouse(HWND hWnd)
{
m_lpDI->CreateDevice(GUID_SysMouse, &m_lpDIDevice, NULL);
m_lpDIDevice->SetDataFormat(&c_dfDIMouse);
m_lpDIDevice->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
DIPROPDWORD DIProperties;
ZeroMemory(&DIProperties, sizeof(DIProperties));
DIProperties.diph.dwSize = sizeof(DIPROPDWORD);
DIProperties.diph.dwHeaderSize = sizeof(DIPROPHEADER);
DIProperties.diph.dwObj = 0;
DIProperties.diph.dwHow = DIPH_DEVICE;
DIProperties.dwData = 16;
m_lpDIDevice->SetProperty(DIPROP_BUFFERSIZE, &DIProperties.diph);
m_lpDIDevice->Acquire();
return true;
}
//Hiermit wird die Absolute Mausposition Aktualisiert und die Maustasten die gedrückt sind werden abgefragt
int CInputManager::getMouseInput()
{
DWORD NumElements = 1;
DIDEVICEOBJECTDATA data;
ZeroMemory(&data, sizeof(data));
if(FAILED(m_lpDIDevice->GetDeviceData(sizeof(data), &data, &NumElements, 0)))
{
m_lpDIDevice->Acquire();
return 0;
}
int Input = 0;
if (data.dwOfs == DIMOFS_BUTTON0)
{
Input += MOUSE_LCLICK;
return Input;
}
switch(data.dwOfs)
{
case DIMOFS_BUTTON0:
Input += MOUSE_LCLICK;
break;
case DIMOFS_BUTTON1:
Input += MOUSE_RCLICK;
break;
case DIMOFS_X:
m_MousePos[0] += data.dwData;
if(m_MousePos[0] < 0) m_MousePos[0] = 0;
if(m_MousePos[0] > SCR_WIDTH) m_MousePos[0] = SCR_WIDTH;
break;
case DIMOFS_Y:
m_MousePos[1] += data.dwData;
if(m_MousePos[1] < 0) m_MousePos[1] = 0;
if(m_MousePos[1] > SCR_HEIGHT) m_MousePos[1] = SCR_HEIGHT;
break;
}
return Input;
}
//Diese Funktion kann sowohl die X- als auch die Y-Koordinate der Maus zurück geben
int CInputManager::GetMousePos(int xy)
{
GetInput();
if(xy == X) return m_MousePos[0];
if(xy == Y) return m_MousePos[1];
return 0;
}
} |
USE_MOUSE, USE_KEYBOARD und alle anderen Konstanten auch sind Integers, die in der Headerdatei der InputManager Klasse definiert sind:
CPP: | #include <dinput.h>
#include "global.h"
#define KEY_LEFT 1
#define KEY_RIGHT 2
#define KEY_UP 4
#define KEY_DOWN 8
#define KEY_SPACE 16
#define KEY_LCTRL 32
#define KEY_LSHIFT 64
#define MOUSE_LCLICK 1
#define MOUSE_RCLICK 2
#define USE_KEYBOARD 1
#define USE_MOUSE 2
#define X 0
#define Y 1
class CInputManager
{
public:
CInputManager();
virtual ~CInputManager();
BOOL Init(HWND hWnd, HINSTANCE hInst, int Device);
int GetInput();
int GetMousePos(int xy);
private:
BOOL initKeyboard(HWND hWnd);
BOOL initMouse(HWND hWnd);
int getKeyboardInput();
int getMouseInput();
int m_CurrentDevice;
LPDIRECTINPUT8 m_lpDI;
LPDIRECTINPUTDEVICE8 m_lpDIDevice;
int m_MousePos[2];
};
|
Diese sind in zweierpotenzen definiert. Deshalb bekommt man durch ihre Bitweise verknüpfung raus, ob die Variable, in der sämtliche Inputs "addiert werden" diese eine Variable enthalten ist.
Zumindest in der Theorie, bzw soweit ich das Buch verstanden hatte. |
|
Nach oben |
|
|
cHaoS Mini JLI'ler
Anmeldedatum: 14.06.2007 Beiträge: 7
Medaillen: Keine
|
Verfasst am: 15.06.2007, 12:48 Titel: |
|
|
Hm, ok, ich hab jetzt ein paar Schleifen umgestellt und habe in der Main Funktion die Abfrage des Mausklicks vor die Abfrage der Mausbewegung gestellt.
Die Mausbewegung wird immer noch ohne Probleme abgefragt, jedoch ist es immer noch so, dass sich das Sprite pro klick immer nur ein stückchen dreht, jedoch nicht, wenn ich die Maustaste gedrückt halte. Mache ich vielleicht bei der Abfrage der Maustasten nen Fehler? |
|
Nach oben |
|
|
The Lord of Programming Living Legend
Alter: 37 Anmeldedatum: 14.03.2003 Beiträge: 3122
Medaillen: Keine
|
Verfasst am: 15.06.2007, 14:40 Titel: |
|
|
cHaoS hat Folgendes geschrieben: | CPP: | //Hiermit wird die Absolute Mausposition Aktualisiert und die Maustasten die gedrückt sind werden abgefragt
int CInputManager::getMouseInput()
{
DWORD NumElements = 1;
DIDEVICEOBJECTDATA data;
ZeroMemory(&data, sizeof(data));
if(FAILED(m_lpDIDevice->GetDeviceData(sizeof(data), &data, &NumElements, 0)))
{
m_lpDIDevice->Acquire();
return 0;
}
// [...]
} |
|
NumElements gibt an, wieviele Einträge aus dem Puffer betrachtet werden. Schau dir die Stelle im Buch am besten noch mal an. Bei mir steht da, dass hier für DIDEVICEOBJECTDATA data mehr Speicher reservieren muss, um auf mehr als nur eine Information über die Maus zuzugreifen. Kann gut sein, dass so oft nur die Position berücksichtigt wird und das Proframm aufgrund des zu kleinen Puffers gar nicht zu den Buttons kommt.
Falls das nicht hilft, such am besten mal hier mit der Forensuche nach DirectInput. Da gibt es schon recht viele Threads, in denen Probleme gerade zu DI in Verbindung mit der Maus besprochen werden
PS: Bitte nächstes mal statt [code] [cpp] benutzen. Letzteres ist wegen dem Syntaxhighlighting wesentlich übersichtlicher. _________________ www.visualgamesentertainment.net
Current projects: RDTDC(1), JLI-Vor-Projekt, Tetris(-Tutorial), JLI-Format
(1) Realtime Developer Testing and Debugging Console
Anschlag, Anleitung zum Atombombenbau, Sprengkörper...
Hilf Schäuble! Damit er auch was findet... |
|
Nach oben |
|
|
cHaoS Mini JLI'ler
Anmeldedatum: 14.06.2007 Beiträge: 7
Medaillen: Keine
|
Verfasst am: 15.06.2007, 15:56 Titel: |
|
|
Ich hatte das schonmal mit nem größeren Data-Puffer versucht, jedoch hatte ich dann ein Problem mit dem Auslesen der Daten.
Ich habe NumElements höher gesetzt und aus dem data-Object ein Array gemacht mit ebensovielen elementen.
Ich wollte dann alle data-Array-Stellen in einer for-schleife auslesen, jedoch hat dann die Mauspositionsabfrage gespackt, die Maus (bzw das damit gesteuerte sprite) befand sind dann immer am rechten bildschirmrand. Die For-Schleife hatte ich um den switch befehl in der getMouseInput-Funktion gepackt. |
|
Nach oben |
|
|
cHaoS Mini JLI'ler
Anmeldedatum: 14.06.2007 Beiträge: 7
Medaillen: Keine
|
|
Nach oben |
|
|
manu Super JLI'ler
Alter: 35 Anmeldedatum: 09.03.2006 Beiträge: 327 Wohnort: allgäu (DE) Medaillen: Keine
|
Verfasst am: 15.06.2007, 16:32 Titel: |
|
|
Hm. danke. hab nochmal wegen dem hier in meine DInput klasse geguckt und mir ist da ein mehr als nicht unschwerer leichtsinnsfehler aufgefallen.. oO bzw. ein Loch in der Fehlerüberwachung... danke, dass du dieses thema erstellt hast
also die GetDeviceData methode rufe ich irgendwie niee auf. Vllt . aus unwissenheit..
also ich habe eine Funktion, die in jedem Mainloop durchlauf aufgerufen werden muss. In sachen maus mache ich dann folgendes.
Mausstate aktualisieren.
CPP: | if(FAILED(m_mouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&m_mousestate)))
{
this->AddError(L"Mouse Devicestate error!", false, L"GetDeviceState");
return false;
}
|
und noch, weil mir eigentlich nicht bekannt wäre, dass DInput überhaupt absolute Koordinaten liefern kann, die relativen bewegungen abfangen und in einem "imaginären" Koordinatensystem den "absoluten" imaginären mauszeiger entsprechend bewegen.
CPP: | //[.....] unwichtig... gucken ob die maus einen festgelegten bereich
//überschritten hat [....]
//neue maus position berechnen
if(m_koord.mouseSpeed <= 0)
{//mousespeed ist <= 0 und somit deaktiviert.. daher die standard geschwindigkeit verwenden
m_koord.x += m_mousestate.lX;
m_koord.y += m_mousestate.lY;
}
else
{// nur wenn die mausgeschwindigkeit über 0 ist, diese auch verwenden
m_koord.x += (long)(m_mousestate.lX * (m_koord.mouseSpeed));
m_koord.y += (long)(m_mousestate.lY * (m_koord.mouseSpeed));
}
//[.....] unwichtig... gucken ob die maus einen festgelegten bereich
//überschritten hat [.....]
|
hm. und in sachen Maustastendruck hab ich da auch nur was recht kleines:
CPP: | bool CInput::IsButtonDown(unsigned short int number)
{
if(!m_useMouse)//wurde Maus überhaupt initialisiert?
{
this->AddError(L"no Mouse available!", false, L"Mouse stuff");
return false;
}
if(m_mousestate.rgbButtons[number] & 0x80)
return true;
return false; //Taste ist nicht gedrückt
}
|
wobei m_mousestate so definiert ist: DIMOUSESTATE m_mousestate; und ja jeden Schleifendurchlauf durch die aktualisierungsmethode erneuert wird.
Also so wie es bei mir ist, geht eigentlich alles wunderbar und recht fix.. vllt. findeste ja was..
edit: ok, bereits gelöst.. da sieht man.. die suchfunktion hat schon ihre Lebensberechtigung |
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB.de
|