07. november 2002 - 08:23Der er
22 kommentarer og 1 løsning
Messageloop og animering
Jeg har lavet en animering med DC HDC hdc... HBRUSH hbrush... while(true){ paint(hdc, hbrush, ...); Sleep(100); } Når jeg så trykker på en key, eller bevæger musen, stopper animationen, hvorfor? Der er ikke defineret nogen Sleep i mit messageloop, og hvis jeg sætter ovenstående sleep til 0, virker det fint, men animeringen er for hurtig.
mens håndtering af keyevents står i WndProc switch(iMes){ case WM_KEYDOWN:{ int keyCode = lParam; if(!gamePaused){ if(keyCode==DOWN){ bool done = false; while(!done){ if(tryToMove(DOWN)){} else done = true; } } else if(keyCode==LEFT||keyCode==RIGHT){ tryToMove(keyCode); } Der er ingen Sleep i nogen af de metoder der bliver kaldt
Prøv at poste koden til din winmain, så jeg ved præcis hvad der foregår.
Det er generelt en forkert måde at håndtere animering på, Din kode bliver jo ved med at køre så længe den får CPU-tid, pga. din "while(true)"! Der er flere problemer herved: Din message procedure får ikke noget CPU-tid! Sleep(100) gør at dit program afgiver den resterende tid af sin time-slice på CPU'en...
Fordi man i spillet skal kunne sætte det på pause, men der skal stadig ske en håndtering af ovennævnte, og den vil ikke gå ind i det inderste while, hvis gamePaused
Jamen i din while(true) håndterer du først alle messages der ligger i køen, så går du videre (else) og så gør du nøjagtig det samme igen! Det giver ingen mening!!!
ok, det var noget kode jeg fandt et eller andet sted, jeg må indrømme at jeg ikke helt forstår hvad det gør, men da der virker bruger jeg det bare (newbie alert!), måske kunne jeg fjerne den ene af dem på en eller anden måde vha en bool?
ja det virker fint, nu er mit problem bare at der sker håndtering-tegning-håndtering-tegning-håndtering, ..., . Jeg gik ud fra af håndteringen sker i en Thread ligesom i Java, måske skulle jeg prøve det?
Hvordan er det et problem??? Den måde jpk beskriver, er en meget almindelig måde at styre animation i windows. Jeg har selv tidligere lavet et spil med DirectX der kørte på den måde, uden problemer.
jeg er ved at lave tetris, men problemet er at hvis jeg trykker venstre 5 gange, så rykker min brik til venstre 5 gange, men i løbet af at den falder 5. Man skulle gerne kunne rykke hurtigere hen, end ned. Men hvis det er den måde der sker på, ja så point til jpk
Jamen, hvis brikken skal falde ned hver gang den løber gennem move og repaint, så må den da falde super hurtigt ned?!?!?!? Du må vist arbejde lidt med timingen i din move.
Jeg glemte IKKE Sleep! Det er en dårlig måde at håndtere framerate på! Der er 2 typiske måder at gøre det på:
1) Du ønsker en fast frame rate og tjekker altså tiden hver gang du er klar til at rendere næste frame. Hvis der er gået tilstrækkelig tid siden sidste frame, renderer du framen, ellers laver du ingenting. Denne metode er dårlig hvis maskinen ikke kan levere den ønskede framerate, da spillet kommer til at køre langsommere...
2) Du renderer en frame så snart du kan, men bruger tiden siden sidste frame til at beregne hvor meget objekterne skal flyttes. Denne metode giver en ensarted hastighed uanset hvor hurtig maskinen er, men der er også lidt mere arbejde i den...
Du kan godt vælge at indsætte en Sleep(0) for hver gennemgang af loopet, det vil få Windows til at starte eventuelle processer der har højere prioritet og er klar til at køre...
Anvender du Sleep med et andet tal, vil din process rent faktisk blive suspenderet i MINIMUM det antal millisekunder! Med Sleep(100) bliver din maksimale frame rate jo 10fps, altså ret dårlig..!
humlen må vel være at der skal sættes et forhold op mellem hastigheden på at brikken falder og på at brugeren flytter rundt på dem. Det kunne f.eks. gøres sådan her:
const int userActionFactor = 10; // Brugeren skal kunne flytte 10 gange så hurtigt som maskinen. int actionCount = 0;
while (true) { // Process messages = user interaction if (peek_message(....)) { };
// Anitmate only when user has had the chance to move. if (++actionCount >= userActionFactor) { move(): redraw(); actionCount = 0; }; }; // Indtil break.
jpk >> Hvordan kan din metoden 2) køre hurtigere end 1) - du måler da tiden i begge, så forskellen må da være den samme - ingen af metoderne leverer en bedre framerate end hvad maskinen kan !
Humlen er vel snarere at man skal sørge for at BEVÆGELSERNE ikke for hurtige til at brugeren kan nå at reagere på dem. Hvis et objekt f.eks. skal flyttes 500 pixels og det skal minimum tage 3 sekunder - ja så må den altid ikke flytte sig mere end 500/3000 = 1/6 pixels pr. millisekund. Dermed skal du bare beregne dit move() som antal ms siden sidste frame * 1/6. (Men det var måske også det du mente.) Det betyder også at såfremt din maskine yder godt nok, så kan du have 100 gennemløb inden for det samme millisekund - og dermed 600 gennemløb, hvor du ikke skal lave noget, fordi objektet står på samme sted !
Hermed vil brugeren have 3 sekunder til at flytte på plads - hvor mange "chancer" det svarer til, afhænger så at maskinens formåen.
soepro >> At ingen af metoderne leverer en bedre framerate end hvad maskinen kan, siger vist sig selv...
Prøv at læse de to metoder igen og vis du stadig ikke er med på hvorfor metode 2 kan give en højere frame rate end metode 1, så skal jeg gerne omformulere.
jpk >> Framerate er vel antal skift (dvs. ændringer) i skærmbilledet eller ? Er max så ikke under alle omstændigheder 6/1000 ms. i mit eksempel, dvs. 1 pixels flytning ?
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.