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