winmm Joystick-Programmierung falsche X, Y, Z-Werte?
-
Guten Tag!
Ich bin gerade dabei über die WinAPI ein USB-Joystick auszulesen. Habe Im Netz auch einige gute Ansätze und Anleitungen zu diesem Thema gefunden und ausprobiert.
Leider bekommt das Programm teilweise falsche Werte von der API zurückgeliefert.
Ich lese die X-, Y- und Z-Achsen-Werte aus. In der Mittelstellung des Joysticks bekomme ich auch einen Mittleren Wert von 32767. Wenn ich jetzt aber den Joystick z.B auf der X-Achse nach links bewege und die Werte eigentlich kontinuirlich kleiner werden müßten, werden mir ab einer gewissen Stellung Werte um die 90000 geliefert. Und das darf eigentlich nicht sein. Das gleiche tritt bei der Y-Achse auf. allerdings nur wenn ich vom Mittelwert nach unten wandere. Von 32767 nach 65535 gibt es keine Probeme. Da läuft das einwandfrei. Sehr merkwürdig.
Der Joystick ist auch neu und in der Systemsteuerung unter den Eigenschaften läuft er auch 100 %ig. Achso ich verwende Windows XP.
Ich habe den Sourcecode von hier:http://www.bringyou.to/games/JoyDemo.cppdiesen Code habe ich etwas modifiziert. Hier der Sourcecode:
// PhilVaz Joystick Demo // Reads a plug-and-play joystick and displays status of buttons // Feb 19, 2004 // INCLUDES /////////////////////////////////////////////// #define WIN32_LEAN_AND_MEAN #include <windows.h> // include all the windows headers #include <windowsx.h> // include useful macros #include <mmsystem.h> // for joystick info #include <stdlib.h> // for rand functions #include <stdio.h> #include <math.h> // DEFINES //////////////////////////////////////////////// // defines for windows #define WINDOW_CLASS_NAME "WINCLASS1" #define WINDOW_WIDTH 640 // size of game window #define WINDOW_HEIGHT 480 #define GAME_SPEED 30 // speed of game (increase to go slower) // MACROS ///////////////////////////////////////////////// #define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) #define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1) // GLOBALS //////////////////////////////////////////////// HWND game_window = NULL; // global game window handle HINSTANCE game_instance = NULL; // global game instance handle HDC game_dc = NULL; // global device context (for GDI) handle // global pen and brush HPEN white_pen = CreatePen(PS_SOLID, 1, RGB(255,255,255)); HBRUSH white_brush = CreateSolidBrush(RGB(255,255,255)); HPEN black_pen = CreatePen(PS_SOLID, 1, RGB(0,0,0)); HBRUSH black_brush = CreateSolidBrush(RGB(0,0,0)); bool joy_ok; // whether joystick found ok UINT joy_num; // number of joys JOYINFO joy_info; // joy init info UINT joy_ID; // joy ID JOYCAPS joy_caps; // joy capture info RECT joy_trip; // joy trip info DWORD joy_xcenter; // joy x axis center DWORD joy_ycenter; // joy y axis center // joy directions (1=true, 0=false) int xpos, xpos8bit, ypos, ypos8bit, zpos, zpos8bit, joy_left, joy_right, joy_up, joy_down, joy_but1, joy_but2, joy_but3, joy_but4; char text[80]; // for display text output // FUNCTIONS ////////////////////////////////////////////// bool GameInit(); void GameMain(); void GameQuit(); // WINPROC //////////////////////////////////////////////// LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { // this is the main message handler of the system HDC hdc; // handle to a device context PAINTSTRUCT ps; // used in WM_PAINT switch(msg) // what is the message { case WM_CREATE: { // do initialization stuff here return(0); // return success } break; case WM_PAINT: { hdc = BeginPaint(hwnd, &ps); // validate the window EndPaint(hwnd, &ps); return(0); // return success } break; case WM_DESTROY: { PostQuitMessage(0); // kill the application, sends a WM_QUIT message return(0); // return success } break; default:break; } // end switch // process any messages that we didn't take care of return (DefWindowProc(hwnd, msg, wparam, lparam)); } // end WinProc // WINMAIN //////////////////////////////////////////////// int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) { WNDCLASSEX winclass; // this will hold the class we create HWND hwnd; // generic window handle MSG msg; // generic message // first fill in the window class structure winclass.cbSize = sizeof(WNDCLASSEX); winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; winclass.lpfnWndProc = WinProc; winclass.cbClsExtra = 0; winclass.cbWndExtra = 0; winclass.hInstance = hinstance; winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); winclass.hCursor = LoadCursor(NULL, IDC_ARROW); winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); winclass.lpszMenuName = NULL; winclass.lpszClassName = WINDOW_CLASS_NAME; // save the game instance handle game_instance = hinstance; // register the window class if (!RegisterClassEx(&winclass)) return(0); // create the window if (!(hwnd = CreateWindowEx(NULL, // extended style WINDOW_CLASS_NAME, // class "Joystick Demo", // title WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0,0, // initial game window x,y WINDOW_WIDTH, // initial game width WINDOW_HEIGHT, // initial game height NULL, // handle to parent NULL, // handle to menu hinstance, // instance of this application NULL))) // extra creation parms return(0); // save the game window handle game_window = hwnd; joy_ok = GameInit(); // joystick initialization function called here // enter main event loop using PeekMessage() to retrieve messages while(TRUE) { // get initial tick count to keep game speed constant DWORD start_tick = GetTickCount(); // is there a message in queue, if so get it if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { // test if this is a quit if (msg.message == WM_QUIT) break; // translate any accelerator keys TranslateMessage(&msg); // send the message to WinProc DispatchMessage(&msg); } // end if GameMain(); // game main processing function called here // check for <ESC> key and send quit game if (KEYDOWN(VK_ESCAPE)) SendMessage (hwnd, WM_CLOSE, 0, 0); // wait until we hit correct game speed frame rate while ((GetTickCount() - start_tick) < GAME_SPEED); } // end while GameQuit(); // game quit function and clean up before exit called here return(msg.wParam); // return to Windows } // end WinMain // BEGIN GAME CODE //////////////////////////////////////// /////////////////////////////////////////////////////////// // // GAME INITIALIZATION // /////////////////////////////////////////////////////////// bool GameInit() { game_dc = GetDC(game_window); // get the GDI device context // initialize joystick // make sure joystick driver is present if ((joy_num = joyGetNumDevs()) == 0) return FALSE; // make sure the joystick is attached if (joyGetPos(JOYSTICKID1, &joy_info) != JOYERR_UNPLUGGED) joy_ID = JOYSTICKID1; else return FALSE; // calculate the trip values joyGetDevCaps(joy_ID, &joy_caps, sizeof(JOYCAPS)); joy_xcenter = ((DWORD)joy_caps.wXmin + joy_caps.wXmax) / 2; joy_ycenter = ((DWORD)joy_caps.wYmin + joy_caps.wYmax) / 2; joy_trip.left = (joy_caps.wXmin + (WORD)joy_xcenter) / 2; joy_trip.right = (joy_caps.wXmax + (WORD)joy_xcenter) / 2; joy_trip.top = (joy_caps.wYmin + (WORD)joy_ycenter) / 2; joy_trip.bottom = (joy_caps.wYmax + (WORD)joy_ycenter) / 2; // capture the joystick joySetCapture(game_window, joy_ID, NULL, TRUE); return TRUE; } // END OF GameInit /////////////////////////////////////////////////////////// // // GAME MAIN LOOP AND PROCESSING // /////////////////////////////////////////////////////////// void GameMain() { SetTextColor(game_dc, RGB(255,255,255)); // white text color SetBkColor(game_dc, RGB(0,0,0)); // black background sprintf(text,"Joystick Demo by PhilVaz"); TextOut(game_dc, 100, 25, text, strlen(text)); sprintf(text,"Move the joystick and press each button"); TextOut(game_dc, 100, 50, text, strlen(text)); sprintf(text,"Press <ESC> to exit"); TextOut(game_dc, 100, 75, text, strlen(text)); if (joy_ok && joyGetPos(joy_ID, &joy_info) == JOYERR_NOERROR) { // if we have no errors check the joystick position // check X-Position xpos = joy_info.wXpos; // check Y-Position ypos = joy_info.wYpos; // check Z-Position zpos = joy_info.wZpos; // check X-Position 8 bit xpos8bit = joy_info.wXpos/256; // check Y-Position 8 bit ypos8bit = joy_info.wYpos/256; // check Y-Position 8 bit zpos8bit = joy_info.wZpos/256; // check horizontal movement joy_left = 0; joy_right = 0; if (joy_info.wXpos < (WORD)joy_trip.left) joy_left = 1; else if (joy_info.wXpos > (WORD)joy_trip.right) joy_right = 1; // check vertical movement joy_up = 0; joy_down = 0; if (joy_info.wYpos < (WORD)joy_trip.top) joy_up = 1; else if (joy_info.wYpos > (WORD)joy_trip.bottom) joy_down = 1; // check four buttons joy_but1 = 0; joy_but2 = 0; joy_but3 = 0; joy_but4 = 0; if (joy_info.wButtons & JOY_BUTTON1) joy_but1 = 1; if (joy_info.wButtons & JOY_BUTTON2) joy_but2 = 1; if (joy_info.wButtons & JOY_BUTTON3) joy_but3 = 1; if (joy_info.wButtons & JOY_BUTTON4) joy_but4 = 1; // display the results sprintf(text,"X-POSITION = %d", xpos); TextOut(game_dc, 100, 125, text, strlen(text)); sprintf(text,"Y-POSITION = %d", ypos); TextOut(game_dc, 100, 150, text, strlen(text)); sprintf(text,"Z-POSITION = %d", zpos); TextOut(game_dc, 100, 175, text, strlen(text)); sprintf(text,"LEFT = %d", joy_left); TextOut(game_dc, 100, 200, text, strlen(text)); sprintf(text,"RIGHT = %d", joy_right); TextOut(game_dc, 100, 225, text, strlen(text)); sprintf(text,"UP = %d", joy_up); TextOut(game_dc, 100, 250, text, strlen(text)); sprintf(text,"DOWN = %d", joy_down); TextOut(game_dc, 100, 275, text, strlen(text)); sprintf(text,"BUT1 = %d", joy_but1); TextOut(game_dc, 100, 300, text, strlen(text)); sprintf(text,"BUT2 = %d", joy_but2); TextOut(game_dc, 100, 325, text, strlen(text)); sprintf(text,"BUT3 = %d", joy_but3); TextOut(game_dc, 100, 350, text, strlen(text)); sprintf(text,"BUT4 = %d", joy_but4); TextOut(game_dc, 100, 375, text, strlen(text)); sprintf(text,"X-POSITION 8-Bit = %d", xpos8bit); TextOut(game_dc, 100, 400, text, strlen(text)); sprintf(text,"Y-POSITION 8-Bit = %d", ypos8bit); TextOut(game_dc, 100, 425, text, strlen(text)); sprintf(text,"Z-POSITION 8-Bit = %d", zpos8bit); TextOut(game_dc, 100, 450, text, strlen(text)); } // end of if joy_ok AND NOERROR else // no joystick found or read error { sprintf(text,"Sorry, no joystick detected"); TextOut(game_dc, 100, 125, text, strlen(text)); } } // END OF GameMain /////////////////////////////////////////////////////////// // // GAME QUIT AND CLEAN UP // /////////////////////////////////////////////////////////// void GameQuit() { // release joystick if (joy_ok) joyReleaseCapture(joy_ID); // delete the pens and brushes DeleteObject(white_pen); DeleteObject(white_brush); DeleteObject(black_pen); DeleteObject(black_brush); // release the device context (for GDI) from the game window ReleaseDC(game_window, game_dc); } // END OF GameQuit // END GAME CODE //////////////////////////////////////////Wäre nett, wenn jemand weiß, warum das sein kann, dass ich falsche Werte wieder geliefert bekomme.
Gruß skontox
-
// joy directions (1=true, 0=false)
int xpos, xpos8bit, ypos, ypos8bit, zpos, zpos8bit, joy_left, joy_right, joy_up, joy_down, joy_but1, joy_but2, joy_but3, joy_but4;int hat den wert bis zu 65535.
dan gibts einen überlauf etc..
versuch mal double zu brauchen.
soviel ich weiss, wird beim int automatisch ein long int angenommen (4Byte -> +/-65535) double -> 8Byte
-
Besten Dank für Deine schnelle Antwort.
Ich habe die Variablen als double Definiert:// joy directions (1=true, 0=false) int joy_left, joy_right, joy_up, joy_down, joy_but1, joy_but2, joy_but3, joy_but4; double xpos, xpos8bit, ypos, ypos8bit, zpos, zpos8bit;Beim kompilieren und linken gibt es auch keine Problem, allerdings werden jetzt nur noch 0-Werte dargestellt.
Außerdem dürften die Werte die von der API geliefert werden auch 65535 nicht überschreiten, somit dürfte es auch nicht zum Überlauf von long int kommen, oder?
Das ist halt das Problem, ich weiß nicht genau woran es liegt. Ob die Werte von der API falsch geliefert werden, oder ob es bei der Darstellung auf dem Bildschirm falsch läuft???Aber trotzdem erstmal besten Dank!
Gruß skontox
-
Ohh Mißt!
Ich habe den Fehler gefunden! ,-)
Sorry es lag an der Darstellung!
Sobald die Werte kleiner Werden verschieben sich die Stellen nicht nach rechts sondern beliben vorne an und deshalb wird z.B beim herunter gehen aus 10007 nicht 9007 sondern 90077.Sorry, aber trotzdem Danke nochmal.
Sowas blödes, kam ich auch erst drauf als ich im Vorherigen Beitrag das mit der Darstellung geschrieben habe.
Gruß skontox
-
ich kenne mich da auch noch nicht so gut aus, was mir aber aufgefallen ist, dass
joy_info.wXpos;ein unsigned int wert zurück gibt.. und du deklarierst mit int oder jetzt neu mit double (double sollte aber auch gehen)
nur falls es noch fehler gibt

-
BigNeal schrieb:
// joy directions (1=true, 0=false)
int xpos, xpos8bit, ypos, ypos8bit, zpos, zpos8bit, joy_left, joy_right, joy_up, joy_down, joy_but1, joy_but2, joy_but3, joy_but4;int hat den wert bis zu 65535.
Unter Win32 hat ein int üblicherweis den Bereich zwischen -2^31 und 2^31 - 1 (wie schon gesagt: vier Byte und nicht nur zwei!).
Bye, TGGC (Denken, und gut ist.)
-
TGGC schrieb:
BigNeal schrieb:
// joy directions (1=true, 0=false)
int xpos, xpos8bit, ypos, ypos8bit, zpos, zpos8bit, joy_left, joy_right, joy_up, joy_down, joy_but1, joy_but2, joy_but3, joy_but4;int hat den wert bis zu 65535.
Unter Win32 hat ein int üblicherweis den Bereich zwischen -2^31 und 2^31 - 1 (wie schon gesagt: vier Byte und nicht nur zwei!).
ups mit den zahlen vertahn.. jep, int hat den bereich -2,147,483,648 bis 2,147,483,647
und unsigned int 0 bis 4.294.967.295sorry, geht richtung wochenende
