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.cpp
    

    diesen 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.295

    sorry, geht richtung wochenende 🤡


Anmelden zum Antworten