Mausbewegungen abfragen.



  • du hat wahrscheinlich mal "<" und ">" oder so vertauscht...

    Schau mit dem debugger durch und wenns dann ned funktioniert kannst ja deinen code posten...



  • hab gerade eine Debugg-Orgie hinter mir und hab eine Fehlerquelle gefunden.
    Und zwar hab ich nicht bedacht das man ja mit der Maus erstmal den Ball durchs ganze Fenster bewegen kann bevor man Schwung nimmt. Also setze ich mousemovex jetzt nicht mehr bie WM_LBUTTONDOWN sondern bei WM_MOUSEMOVE.

    Allerdings ändert sich nicht viel.
    von 10 Versuchen gehen 2 bis 3 in die falsche Richtung.

    Um die seitliche geschwindigkeit zu berechnen teile ich die "Pixelentfernung"
    durch 100, drum hab ich zuerst vermutet daß das Ergebnis manchmal kleiner als 0 ist und dann die Adition bzw Subtraktion der X-Koordinate ins Gegenteil umschlägt.
    Das hab ich jetzt aber durch eine weitere If abfrage beseitigt und hab immernoch das selbe Problem.

    An den < und > Operatoren wirds wohl auch nicht liegen.
    Erstens hab ich die nochmal genau gecheckt und zweitens sollte ja dann die Richtung immer falsch sein.

    Bei schnellen Mausbewegungen tritt das Problem übrigens seltener auf.

    Ich hab Probeweise auch mal die berechnung der Pixelentfernung außen vorgelaßen und einfach mal anstelle der Berechnung eine Konstante geschwindigkeit eingetragen. Mit dem selben Ergebniß.

    Wenn ich die Maus nur um wenige Pixel langsam verschiebe gehts fast immer in die falsche Richtung.

    Irgendwie steig ich da nicht mehr ganz durch! 😕



  • Wenn du uns den teil des codes zeigst können wir dir vlt mehr helfen...so können wir nur raten...



  • O.K.

    hier die Messageloop:

    /*  Declare Windows procedure  */
    LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
    
    /*  Make the class name into a global variable  */
    char szClassName[ ] = "WindowsApp";
    
    int WINAPI WinMain (HINSTANCE hThisInstance,
                        HINSTANCE hPrevInstance,
                        LPSTR lpszArgument,
                        int nFunsterStil)
    
    {
        HWND hwnd;               /* This is the handle for our window */
        MSG messages;            /* Here messages to the application are saved */
        WNDCLASSEX wincl;        /* Data structure for the windowclass */
    
        /* The Window structure */
        wincl.hInstance = hThisInstance;
        wincl.lpszClassName = szClassName;
        wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
        wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
        wincl.cbSize = sizeof (WNDCLASSEX);
    
        /* Use default icon and mouse-pointer */
        wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
        wincl.lpszMenuName = NULL;                 /* No menu */
        wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
        wincl.cbWndExtra = 0;                      /* structure or the window instance */
        /* Use Windows's default color as the background of the window */
        wincl.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH); //COLOR_BACKGROUND;
    
        /* Register the window class, and if it fails quit the program */
        if (!RegisterClassEx (&wincl))
            return 0;
    
        /* The class is registered, let's create the program*/
        hwnd = CreateWindowEx (
               0,                   /* Extended possibilites for variation */
               szClassName,         /* Classname */
               "Windows App",       /* Title Text */
               WS_OVERLAPPEDWINDOW | CS_VREDRAW, /* default window */
               CW_USEDEFAULT,       /* Windows decides the position */
               CW_USEDEFAULT,       /* where the window ends up on the screen */
               544,                 /* The programs width */
               375,                 /* and height in pixels */
               HWND_DESKTOP,        /* The window is a child-window to desktop */
               NULL,                /* No menu */
               hThisInstance,       /* Program Instance handler */
               NULL                 /* No Window Creation data */
               );
    
        /* Make the window visible on the screen */
        ShowWindow (hwnd, nFunsterStil);
        SetTimer (hwnd,1,10,NULL);
        /* Run the message loop. It will run until GetMessage() returns 0 */
        while (GetMessage (&messages, NULL, 0, 0))
        {
            /* Translate virtual-key messages into character messages */
            TranslateMessage(&messages);
            /* Send message to WindowProcedure */
            DispatchMessage(&messages);
        }
    
        /* The program return-value is 0 - The value that PostQuitMessage() gave */
        return messages.wParam;
    }
    
    /*  This function is called by the Windows function DispatchMessage()  */
    
    LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        static HBITMAP hBitmap;        // die Bitmap für den Ball
        static HINSTANCE hInstance;
        static HDC hdc,hdcmem;         
        static PAINTSTRUCT ps;
        static RECT rcClient;                 /* client area rectangle     */ 
        static POINT ptClientUL;              /* client upper left corner  */ 
        static POINT ptClientLR;              /* client lower right corner */ 
        static cBall ball1(12);        // Ein Ball Objekt der cBall Klasse
        static float cx=10;            // Koordinatenpuffer für den Ball
        static float cy=10;
        static int oldx;
        static float oldy;
        static float ce=1;             // Energiepuffer für den Ball
        static float cd=0;             // Seitenbewegungspuffer
        static int mox;                // Mauskoordinaten
        static int moy;
        static float oldmousemovex;    // Variablen um die Mausbewegung
        static float mousemovex;       // zu berechnen
    
        switch (message)                  /* handle the messages */
        {
            case WM_CREATE:
                hInstance = ((LPCREATESTRUCT) lParam)->hInstance;
                hBitmap = LoadBitmap (hInstance, "BALLBMP");   // den Ball laden
                static bool dir=false;                         // Abwärtsbewegung
                static bool draftdir=false;                    // Rechtsbewegung
    
                GetClientRect(hwnd, &rcClient);                // Größe des Fensters
    
                ptClientUL.x = rcClient.left;                  // Linker Rand
                ptClientLR.x = rcClient.right + 1;             // Rechter Rand
    
                InvalidateRect(hwnd,&rcClient,false);          // Neuzeichnen         
                                                               // des Fensters
    
                break;
            case WM_PAINT:
    
                hdc = BeginPaint (hwnd, &ps);
    
                hdcmem = CreateCompatibleDC (hdc);      // Gerätekontext erstellen
                SelectObject (hdcmem, hBitmap);         
    
                BitBlt (hdc,                     // Ball an alter Position
                          oldx,                  // löschen
                          (int) oldy,
                          32,
                          32,
                          hdcmem,
                          0,
                          0,
                          BLACKNESS);
    
                BitBlt (hdc,                     // Ball an neue Position
                          ball1.GetXpos(),       // Bliten
                          (int) ball1.GetYpos(),
                          32,
                          32,
                          hdcmem,
                          0,
                          0,
                          SRCCOPY);
    
                     oldy = ball1.GetYpos();     // Aktuelle Position speichern
                     oldx = ball1.GetXpos();
    
                DeleteDC (hdcmem);               // Gerätekontext löschen
                EndPaint (hwnd, &ps);
                return 0;
    
            case WM_TIMER:
    
                ce=ball1.GetEnergie();           // Puffervariablen füllen
                cd=ball1.GetDraft();
                cx=ball1.GetXpos();
                cy=ball1.GetYpos();
    
    //##################################Hüpfbewegung###########################
    
    if (ce!=0)                         // wenn die Auf-Ab-Energie nicht Null ist
        {
    
             if (cy<(ptClientLR.y-32+ce))  // wenn der Ball oberhalb des unteren
                {                          // Fensterands liegt
                     if (dir==false)       // bei Abwärtsbewegung
                         {
                            ce=ce+0.05;    // Gravitation zur Energie hinzufügen
                            cy=cy+ce;      // Energie zur Y-Position hinzufügen
    
                                if (cy>(ptClientLR.y-32)) // wenn Ball am untern
                                    {                     // Fensterrand
                                      cd=cd-0.02;         // Seitenenrgie droßeln              
                                      dir=true;           // Richtung ändern
                                    }    
    
                          }    
                      else                                // bei Aufwärtsbewegung
                          {
                            ce=ce-0.07;                   // energie droßeln
                            cy=cy-ce;                     // energie von Y-Position
                                                          // abziehen
                                  if (ce<=0)              // wenn höchster Punkt             
                                     {                    // ereicht (energie 0)
                                       dir=false;         // richtung ändern
                                     }    
                          }
                  }
                 else                                    // Ball liegt am
                  {                                      // unteren Rand
                      if (cd>0)                          // Seitenenergie größer 0
                          cd=cd-0.009;                   // seitenenergie droßeln
                      else                               // falls seitenenergie
                          cd=0;                          // kleiner als 0 isr
                                                         // auf 0 setzen
                  }
          }
    
    //######################Seitenbewegung#########################
    
            if (ce!=0)                   // wenn auf-ab-Energie nicht 0
                {
    
                 if (draftdir==false)     // rechtsbewegung
                     {
                       cx = cx+cd;        // seitenenergie zu X-Position hinzufügen
                           if (cx>rcClient.right-32)  // wenn Ball am rechten Rand
                               {
                                  cd=cd-0.2;          // seitenenergie droßeln
                                  draftdir=true;      // richtung ändern
                               }                     
                     }
    
                           if (draftdir==true)    // linksbewegung
                               {
                                  cx =cx-cd;      // seitenenergie von X-Position
                                                  // abziehen
                                     if (cx<0)    // Ball am linken Rand
                                        {
                                          cd=cd-0.2;        // seitenenergie droßeln
                                          draftdir=false;   // richtung ändern
                                        }                
                                }           
    
                       if (cd<0)          // wenn seitenenrgie kleiner als 0
                           cd=0;          // auf 0 setzen
    
               }
    
    //#############################################################
    
     // Pufervariablen zurück in Objekt schreiben
                ball1.SetXpos(cx);
                ball1.SetYpos(cy);
                ball1.SetEnergie(ce);
                ball1.SetDraft(cd);
    
                // Neuzeichnen veranlassen
                InvalidateRect(hwnd,&rcClient,false);        
    
                break;
    
            case WM_SIZE:
    
                GetClientRect(hwnd, &rcClient);  // Fenstergröße ermitteln
                ptClientUL.x = rcClient.left;
                ptClientLR.x = rcClient.right + 1;    
                ptClientLR.y = rcClient.bottom + 1;
    
                // wenn Ball außerhalb von Fenster Position korigieren
    
                if (ball1.GetYpos()>ptClientLR.y)
                    ball1.SetYpos(ptClientLR.y-42);
                if (ball1.GetXpos()>ptClientLR.x)
                    ball1.SetXpos(ptClientLR.x-32);
    
                    InvalidateRect(hwnd,&rcClient,false);  // Neuzeichnen veranlaßen
    
                break;
    
            case WM_MOUSEMOVE:
    
                mox = LOWORD(lParam);    // Mausposition ermitteln
                moy = HIWORD (lParam);
    
         // wenn Ball liegt und Maustate gedrückt
    
               if(ball1.GetEnergie()==0 && (wParam & MK_LBUTTON)) 
               {
                      ball1.SetYpos(moy-16);   // Ball an Mausposition
                      ball1.SetXpos(mox-16);   // ( Bitmap ist 32*32 deshalb -16)
    
                      oldmousemovex=mox;       //  Mausbewegung puffern
    
               }
    
               break;
    
            case WM_LBUTTONDOWN:
    
             // Wenn Mauszeiger auf Ball - Ball hochheben
    
                  if(moy>oldy && mox>oldx && moy<(oldy+32) && mox<(oldx+32))
                  {
    
                      ball1.SetYpos(moy-16);
                      ball1.SetXpos(mox-16);
                      ball1.SetEnergie(0);
                      ball1.SetDraft(0);
    
               }    
    
                break;
    
            case WM_LBUTTONUP:
    
                ball1.SetEnergie(1);   // Abwärtsbewegung Initiieren
    
                if (mousemovex>oldmousemovex)      // bei Maus-Rechtsbewegung
                {
                    ball1.SetDraft(1);           
                    draftdir=false;
                }
                else                                // bei Maus-Linksbewegung
                {
                    ball1.SetDraft(1);
                    draftdir=true;
                }
    
                if (mousemovex==oldmousemovex)      // keine Maus-Seitenbewegung
                    ball1.SetDraft(0);             // Seitenenergie auf 0 setzen
    
                break;
    
            case WM_DESTROY:
    
                PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
                DeleteObject (hBitmap);
                break;
            default:                      /* for messages that we don't deal with */
    
                return DefWindowProc (hwnd, message, wParam, lParam);
        }
    
        return 0;
    }
    

    für Verbesserungsvorschläge die nicht das eigentliche Problem betreffen binn ich auch dankbar. Hab erst vor ca. eineinhalb Monaten mit C++ angefangen.



  • Wo setzt du mousemovex?!



  • Jetzt setz ich mousemovex bei WM_MOUSEMOVE

    case WM_MOUSEMOVE:
    
                mox = LOWORD(lParam);    // Mausposition ermitteln
                moy = HIWORD (lParam);
    
         // wenn Ball liegt und Maustate gedrückt
    
               if(ball1.GetEnergie()==0 && (wParam & MK_LBUTTON))
               {
                      ball1.SetYpos(moy-16);   // Ball an Mausposition
                      ball1.SetXpos(mox-16);   // ( Bitmap ist 32*32 deshalb -16)
    
                      mousemovex=mox;       //  Mausbewegung puffern
    
               }
    
               break;
    

    und oldmousemovex am ende von WM_LBUTTONUP

    case WM_LBUTTONUP:
    
                ball1.SetEnergie(1);   // Abwärtsbewegung Initiieren
    
                if (mousemovex>oldmousemovex)      // bei Maus-Rechtsbewegung
                {
                    ball1.SetDraft(1);          
                    draftdir=false;
                }
                else                                // bei Maus-Linksbewegung
                {
                    ball1.SetDraft(1);
                    draftdir=true;
                }
    
                if (mousemovex==oldmousemovex)      // keine Maus-Seitenbewegung
                    ball1.SetDraft(0);             // Seitenenergie auf 0 setzen
    
                   oldmousemovex=mousemovex;
                break;
    

    Jetzt gehts fast immer, aber hin und wieder geht der Ball trotzdem in die falsche Richtung.



  • Dass das so nicht zuverlässig funktioniert ist klar, denn dann vergleichst du ja die aktuelle Mausposition, mit der an der zuletzt der Ball losgelassen wurde. Du musst dir ja eher die letzten paar Positionen aus WM_MOUSEMOVE anschauen (evtl. in einem Array speichern + ggf. noch die jeweils dazugehörige Zeit)



  • "mousemovex" wird nie initialisiert. [edit] da war ich wohl etwas langsam, naja, guck ja auch noch Fehrnseh dabei [/edit]
    Aber:
    Wenn man den Ball werfen können soll, nachdem er schon herumbewegt wurde, kriegst du Probleme damit, festzustellen, wann denn nun der Wurf angefangen wurde, also wann du "oldmousemovex" setzten musst. Normalerweise wäre ja die Entfernung, zwischen Anfang vom Wurf (oldmousemovex?) bis zum loslassen des Balls (mousemovex?), die Geschwindigkeit. Je nachdem ob dann von links nach rechts oder umgekehrt geworfen wurde, wäre die Geschwindigkeit dann positiv oder negativ, aber durch eine Mögliche Bewegung davor, wüsstest du nicht, wann man mit dem Wurf angefangen hat. Ich hoffe du verstehst, was ich dir sagen will. Das selbe Problem hast du dann auch beim Winkel.

    Vom Programm her aber nicht schlecht für 1,5 Monate 👍



  • Die Problematik wann der Wurf anfängt ist genau wos bei mir hängt.
    Ich bräuchte eine Möglichkeit die Geschwindigkeit und Richtung der Mausbewegung abzufragen. Dann könnte man nach jeder Richtungsänderung von einem Wurfstart ausgehen. Und das Wurfende mit WM_LBUTTONUP bestimmen.

    Die Idee von flenders die letzten Positionen zu speichern ist glaub ich der richtige Ansatz.
    Ich werd mal damit etwas experimentieren.

    Ach ja... $chumann ohne Petzold und diesem Forum hätt ich das in der Zeit nicht geschaft!!! 👍



  • Es kommt eben darauf an, einen wie großen Verlauf du berücksichtigen willst - wenn es dir wirklich nur um das allerletzte Stückchen geht, also ob das letzte Stück einen Pixel nach links oder rechts ging, dann kannst du es einfach so machen:

    xPosOld = xPos;
    xPos = LOWORD(lParam);
    

    Allerdings bekommst du dann halt keine Richtungs-Info, wenn es zuletzt einen Pixel nach oben oder unten ging (aber das kann ja auch so erwünscht sein) 😉



  • Da zeigt sich mal wieder daß es oft einfache Details sind an denen man sich als
    Anfänger aufhängt.

    Jetzt hab ich bei WM_MOUSEMOVE

    oldmousemovex=mousemovex;
                mox = LOWORD(lParam);
                moy = HIWORD (lParam);
                mousemovex=mox;
    

    Und berechne mir dann die Geschwindigkeit des Balles bei WM_LBUTTONUP

    ball1.SetDraft((mousemovex-oldmousemovex)/10);
    

    Hab den Ball jetzt schon mindestens 30 mal hin und hergeworfen und jedesmal hat die Richtung gestimmt.
    Das reicht mir auch fürs erste. Vertikale bewegungen brauch ich in dem Fall eh nicht , daß erledigt die Schwerkraft.

    Jetzt werd ich schaun ob ich mehrere Bälle hinkrieg, die dynamisch hinzugefügt werden können. Ach Ja... und den Code bischen übersichtlicher gestalten und einiges in Funktionen auslagern.

    Man liest sich.... 😉


Anmelden zum Antworten