Alpha IIMedlem sedan maj 20002 579 inlägg
Verkar inte få så många svar på gamedev så jag testar om jag har bättre tur här.
Enklaste sättet att flytta ett object är ju att varende gång skärmen uppdateras flytta objektet en vis bit. Men om man har en segare eller snabbare dator än vad spelet är programmerat på då kommer objektet antingen att flyttas jätte fort eller jätte segt.
För att göra så att objektet går lika snabbt på alla datorer brukar man bestämma hur mycket det ska flyttas per sekund istället för per ruta.
Och sedan för att bestämma hur mycket objektet ska flyttas har jag använt denna kod:
objekt_x += ( rorelse_x / 1000.0f ) * tid_mellan_uppdateringar_i_ms;
Jag tycker att det borde fungera, men det fungerar inet som jag vill. I o f så flyttas den lika snabbt oberoende av fps (tror jag i a f), men den flyttar sig väldigt hackigt. Så istället för att flya på bra som ett spel borde göra i 200 fps så hackar den som om jag skulle ha haft 1 fps.
Vad är fel i denna kod? Kan tilläggas att jag använder den två gånger. Först ökar jag velocityn(rörelsen) oberoende av fps, och sedan lägger jag till velocityn till objektets position oberoende av fps.
PeWMedlem sedan juni 20006 839 inlägg
Flyttal tenderar att vara arbetsamma, även på de snabbare maskinerna. Tror inte att du behöver vara så pass exakt att du måste använda det, speciellt om du kör i större upplösningar ;)
Alpha IIMedlem sedan maj 20002 579 inlägg
Flyttal måste jag definitivt använda! Kanske är det att jag har fel kod men på gamedev verkar de säga att det är rätt. Kan jag behäöva bättre upplösning på tiden mellan rutorna? Från ms till um... 10000 delssekunder? :OO
PeWMedlem sedan juni 20006 839 inlägg
Hursomhelst så tar en flyttalsberäkning betydligt längre tid att utföra och beroende på vart den placeras (tidpunkt som den sker) i koden kan det totala programflödet variera med avseende på tid. En till parameter är ju hur resten av programmet är strukturerat. Det kanske går att göra samma sak men på ett smartare sätt? Dvs räkna med heltal men konvertera dessa i det sista som görs?
Av det du hitills beskrivit så ser jag iaf ett tänkbart problem med flyttal, men det kan ju finnas annat som stör exekveringen.
Alpha IIMedlem sedan maj 20002 579 inlägg
Har inte riktigt fattat någonting om vad du har pratat om. Om rymdskeppet kanske rör sig 0,0015 pixel/fram så är det väl klart att jag måste använda flyttal?!
Det måste vara min kod för rörelsebaserat på tiden som är fel eftersom om jag tar bort det och sätter en fps limiter istället så går det utmärkt! Men det är en ganska ful lösning.
PeWMedlem sedan juni 20006 839 inlägg
Hmm... det jag menade är att flyttal tar längre tid att räkna ut än integers. Om man i ett programflöde använder integers eller chars kan det uppfattas som fördröjning när en operation med flyttal inblandat görs mitt i programflödet.
Har man beräkningar med flyttal och dessa "stoppar upp" kan det löna sig att utföra beräkningen med stora heltal istället och göra en enda konvertering när variablen ska användas.
Ska du exempelvis beräkna 0,0015 pixel mot lite andra (konstanta) flyttal, så kan man ju tänka sig man ligger några snäpp över detta (till heltalet 15) och likaledes på de andra talen för att (efter beräkningen) tagga ned igen det som behövs och det i ett enda steg. En bra matteövning... :birp
Nu är detta som jag redan skrivit endast en tänkbar orsak till ditt problem, jag skriver inte att det verkligen är lösningen på just detta problem, men det kanske kan vara värt att begrunda och testa :)
*andra optimeringar kan vara att utföra bitoperationer istället för att använda math-funktioner
Alpha IIMedlem sedan maj 20002 579 inlägg
Stämmer min kod? Borde den inte röra skeppet rätt? Det är ju inte direkt några krävande uträkningar så jag tycker att allt borde fungera utmärkt med flyttal. Kan det bero på hur jag räknar ut tiden mellan rutorna?
Just nu gör jag ungefär så här:
while(1)
{
lag = GetTickCount()-lastTick;
lastTick = GetTickCount();
RitaGrafik();
}
aasahMedlem sedan mars 20033 451 inlägg
Det PEW försöker förklara för dig är att datorn tar mycket längre tid på sig för att hantera flyttal än heltal. Det spelar ingen roll hur snabb din dator är, detta beror på hur talen är representerade i kombination med hur operationer på dem är definierade. Vanligtvis när du använder flyttal är du mån om att få så stor precision på flyttalet som möjligt, det påverkar hur datorn jobbar med talen. (Populärt uttryckt.) Detta innebär att om du har
float pi = 3.14159265, third = 1/3;
så kommer det att ta längre tid att räkna ut pi + third än att räkna ut 3 + 7. Det har alltså inte att göra med om dina matematiska formler är enkla eller ej. Varje uträkning med flyttal tar längre tid än motsvarande uttryck med heltal. Vanligtvis är den extra tidsåtgången försumbar, men om du upplever att koden hackar kan du ju pröva att göra uträkningen med heltal och sedan dividera ner dem till flyttal det sista du gör. Du gör ju redan en division så du kan antagligen skriva om det så att du inte får en extra division för det. Nu gör du ju:
objekt_x += ( rorelse_x / 1000.0f ) * tid_mellan_uppdateringar_i_ms;
Det är en tilldelning och 3 uträkningar med flyttal. Om du skalar om uttrycket skulle du kunna få 2 uträkningar med heltal och en skalning, det skulle kanske kunna gå fortare.
PeWMedlem sedan juni 20006 839 inlägg
Jo, det var så jag menade.
En annan sak som man kan titta på är om det är vettigt att beräkna och uppdatera pixelförflyttningar som är mindre än heltalet 1. I vissa fall kan detta kanske utökas till att gälla för högre tal än 1... (2..4 eller nåt).
Nånstans i din kod har du ju en flaskhals och det gäller att hitta den och sedan eventuellt optimera.
- Kan vara flyttalsberäkningen.
- Kan även vara några tusen onödiga loopvarv, kan även vid trådning vara trådschemaläggaren som fattat tycke för en annan tråd...
- m.m..
Problemet kan istortsett vara många olika saker men det du visade var en beräkning med flyttal och pixlar så av det delger jag lite synpunkter ;)
btw.. du skulle i ditt sista kodexempel köra getTickCount() mot en lokal variabel och på så sätt få en lokal optimering, av just detta metodanrop eftersom du då bara behöver köra getTickCount() 1 gång (det kan ju vara tung kod där, vad vet jag?).
Alpha IIMedlem sedan maj 20002 579 inlägg
Ja jag vet det men det var inte heller min riktiga kod utan bara en liten kort snutt jag skrev för att visa i vilken ordningsföljd jag utförde de olika sakerna.
Problemet är att det inte är någon flaskhalls utan snarare är en bug. Tror problemet kan bero på att det är fär kort tid mellan rutorna? (0 ms?)
Även om bilden hackar så är det bara det som ritas oberoende av fps och inte resten eftersom jag har 2xx fps och detta är en sunkig gammal p2 450 mhz.
Har inte riktigt testat men på något sätt ska det väl gå. Får testa mer i morgon för nu ska jag sova :)
PeWMedlem sedan juni 20006 839 inlägg
Tja... sätter du 0ms i din ekvation blir det garanterat fel ;)
Alpha IIMedlem sedan maj 20002 579 inlägg
Men blir det verkligen det? Om det inte har gått nån tid alls mellan rutorna (kan inte förstå hur det nu än skulle hända...) så ska väl ingenting flyttas heller?
aasahMedlem sedan mars 20033 451 inlägg
tid_mellan_uppdateringar_i_ms är alltså inte ett konstant värde då? Är det inte meningen att det ska vara det om dina rymdskepp ska röra sig i jämn takt? Om det värdet varierar men inte sällan är 0 så skulle jag skriva:
if (tid_mellan_uppdateringar_i_ms != 0)
objekt_x += ( rorelse_x / 1000.0f ) * tid_mellan_uppdateringar_i_ms;
Särskilt om du har en flaskhals någonstans, att räkna ut allt det där för ingen förändring är ju att slänga tid rakt i sjön.
Marcus EMedlem sedan maj 20021 294 inlägg
Re: "timebased movement"
Alpha II skrev:
Enklaste sättet att flytta ett object är ju att varende gång skärmen uppdateras flytta objektet en vis bit.
Är det? Nu har jag inte följt med i tråden så mycket, men varför inte göra som jag alltid har gjort och flytta objektet efter en viss tid istället? Det måste vara enklare att synkronisera ett objekt till klockan än till uppfateringsfrekvensen.
Alpha II skrev:
Och sedan för att bestämma hur mycket objektet ska flyttas har jag använt denna kod
Är du säker på att den körs den före varje skärmuppdatering?
PeWMedlem sedan juni 20006 839 inlägg
Tror att den berömda tesen att "programmera på pappret" skulle göra sig bra i det här fallet. Dvs dela upp programmet i små enheter och skriva ytlig pseudo tills alla problem är nedbrutna. Sen iterera ovan förfarande med vassare pseudo tills "riktigt" kod står endera på pappret eller på skärmen. Även de mest triviala uppgifterna kan bli hur struliga som helst om de utförs i fel ordning eller på ett mindre lyckat sätt.
Kod som ligger på nätet är sällan 100%-ig även om den är signerad av nån community-stjärna. Kod som funkar finfint i en utvecklingsmiljö kanske inte alls är lika smärtfri i en annan. Speciellt inom spelvärlden kastar man gärna in lite "finesser" och "smarta" kodsnuttar. Dessa kanske är kalas på en 1Ghz - burk med ett visst grafikkort, men blir skit om man testar samma kod på en 500MHz med ett annat grafikkort. Det blir lätt så då programmeraren antagligen sitter hemma med sin 1GHz och bara hackar fram en lösning.. men det är inte säkert att det är en bra lösning bara för att den fanns på en etablerad community - tyvärr.
parantes begin>
För några år sedan satt jag och hackade mig fram men en bok om spelprogrammering (skriven av en "stjärna" inom området).. men koden var egentligen riktig, riktig fulkod och totalt oåteranvändbar. Lyckades till slut konvertera vissa filer till fungerande återanvändbara prototyper men... usch! Blir faktiskt lite fundersam när man ser hur en del communitys sen upprepar samma mönster som i boken.. det syns att man inriktar sig på att göra enklaste lösningen, framför den mest fungerande vilket sällan är så lyckat.
<parantes end
Så... fram med pappret och pennan nu :)