Gå til innhold

Anbefalte innlegg

Videoannonse
Annonse

Her er tråden som tar seg av tastetrykk. Problemet med tastetrykk er:

 

1. Brukeren skal ha mulighet for å forandre retning på ormen.

2. Om ormen ikke har beveget seg enda så skal brukeren ha ENDA en mulighet for å forandre den FØR ormen beveger seg.

3. Det er ikke lov å flytte ormen i motsatt retning av den retningen den har. Altså VK_UP så blir VK_DOWN motsatt retning. VK_LEFT så blir VK_RIGHT motsatt retning.

4. Jeg bufrer keyboard pollingen i 2 tastetrykk. Bufferen inneholder 2 tastetrykk's historie, mer enn det er ikke nødvendig som jeg kan se.

5. Problemet når brukeren har registrert 2 tastetrykk i historien og brukeren om bestemmer retningen så må den sjekke ulovlig retning i det første tastetrykket, ikke den siste som ble registrert i bufferen, da må tastebufferen slettes. Ulovlige retninger skal kun registreres hvis den første retningen i bufferen er lovlig. Osv. he-he. For hvis en ny retning er lovlig i første tastetrykk så betyr det at nåværende ulovlige retninger vil være lovlig i neste key i bufferen.

 

proc KeyPoller lpParameter
local Buf[4]:DWORD
	; Save all registers
	push ebx
	push edi
	; Set items in Buf to not keypressed (0)
	cld
	lea edi,[buf]
	mov ecx,4
	xor eax,eax
	mov esi,edi
	rep stosd
	; Set up registers
	mov ebx,$8000		   ; Test bit 15.. (if bit is set, key is down)
	mov edi,1
	xor ebp,ebp			 ; always zero
; ebx=$8000 esi=Buf edi=1 ebp=always zero
;-------------------------------------------------------------------------------
align 16
.main:  invoke WaitForSingleObject,[DirMutex],-1
	invoke GetAsyncKeyState,VK_LEFT
	test eax,ebx
	jnz @F
	mov [esi],ebp   ; Allow this key next time since its released now
	jmp .right	  ; All keys must be parsed every time, we can't jump back to main until all keys are processed
@@:	 cmp [esi],ebp   ; if already DOWN, skip this key
	jnz .right	  ; skip key since its already down and not allowed this time
	mov dword [esi],edi	 ; key allowed this time, set status to keydown
	cmp [NibbleDir],VK_LEFT ; if same dir, skip it
	je .bad1
	cmp [NibbleDir],VK_RIGHT; if opposite dir, skip it
	je .bad1
	mov [NibbleDirNext],VK_LEFT ; save this new key
	mov [illegalDir],VK_LEFT
	jmp .right
.bad1:  mov ecx,[NibbleDir]
	mov edx,[NibbleDirNext]
	cmp ecx,edx
	je .right
	mov [illegalDir],VK_LEFT
.right: invoke GetAsyncKeyState,VK_RIGHT
	test eax,ebx
	jnz @F
	mov [esi+4],ebp   ; Allow this key next time since its released now
	jmp .up		 ; All keys must be parsed every time, we can't jump back to main until all keys are processed
@@:	 cmp [esi+4],ebp   ; if already DOWN, skip this key
	jnz .up		 ; skip key since its already down and not allowed this time
	mov dword [esi+4],edi	 ; key allowed this time, set status to keydown
	cmp [NibbleDir],VK_RIGHT ; if same dir, skip it
	je .bad2
	cmp [NibbleDir],VK_LEFT ; if opposite dir, skip it
	je .bad2
	mov [NibbleDirNext],VK_RIGHT ; save this new key
	mov [illegalDir],VK_RIGHT
	jmp .up
.bad2:  mov ecx,[NibbleDir]
	mov edx,[NibbleDirNext]
	cmp ecx,edx
	je .up
	mov [illegalDir],VK_RIGHT
.up:	invoke GetAsyncKeyState,VK_UP
	test eax,ebx
	jnz @F
	mov [esi+8],ebp   ; Allow this key next time since its released now
	jmp .down	   ; All keys must be parsed every time, we can't jump back to main until all keys are processed
@@:	 cmp [esi+8],ebp   ; if already DOWN, skip this key
	jnz .down	   ; skip key since its already down and not allowed this time
	mov dword [esi+8],edi	 ; key allowed this time, set status to keydown
	cmp [NibbleDir],VK_UP ; if same dir, skip it
	je .bad3
	cmp [NibbleDir],VK_DOWN ; if opposite dir, skip it
	je .bad3
	mov [NibbleDirNext],VK_UP ; save this new key
	mov [illegalDir],VK_UP
	jmp .down
.bad3:  mov ecx,[NibbleDir]
	mov edx,[NibbleDirNext]
	cmp ecx,edx
	je .down
	mov [illegalDir],VK_UP
.down:  invoke GetAsyncKeyState,VK_DOWN
	test eax,ebx
	jnz @F
	mov [esi+12],ebp   ; Allow this key next time since its released now
	jmp .done		; All keys must be parsed every time, we can't jump back to main until all keys are processed
@@:	 cmp [esi+12],ebp   ; if already DOWN, skip this key
	jnz .done	   ; skip key since its already down and not allowed this time
	mov dword [esi+12],edi	 ; key allowed this time, set status to keydown
	cmp [NibbleDir],VK_DOWN ; if same dir, skip it
	je .bad4
	cmp [NibbleDir],VK_UP ; if opposite dir, skip it
	je .bad4
	mov [NibbleDirNext],VK_DOWN ; save this new key
	mov [illegalDir],VK_DOWN
	jmp .done
.bad4:  mov ecx,[NibbleDir]
	mov edx,[NibbleDirNext]
	cmp ecx,edx
	je .done
	mov [illegalDir],VK_DOWN
.done:  invoke ReleaseMutex,[DirMutex]
	jmp .main
	; pop registers
	pop edi
	pop ebx
	; return
	ret
endp	  

Endret av LonelyMan
Lenke til kommentar

GammelTid = QueryPerformanceTimer
while(hurra)
{
 NyTid = QueryPerformanceCounter
 DeltaTid = NyTid - GammelTid
 GammelTid = NyTid
 LesInput
 Logikk
 DispatchDataSett // Valgfritt avhengig av kravene til applikasjonen
 SignalRender
 Yield
}

 

Problemet her er at Logikken tar tid å kjøre og et mikrosekund eller noen hundre nanosekund utgjør uhell som mister tastetrykk. Rendertråden burde heller la polle tråden kontinuerlig lagre tastetrykk og om polletråden IKKE er ferdig akkurat idet den rendererer så kan den vente på en mutex eller gjøre noe forberedningsarbeid, på den måten vil man spare tid og unngå uhell og samtidig få raskere kjøring.

 

Når du har de ferskeste tastetrykk tilgjengelig nøyaktig idet du har beveget ormen og er klar for å tegne den, så vil du få god tasterespons. Og om du putter denne polle logikken direkte i rendertråden så vil rendertråden få mer å gjøre. Det er bedre at rendertråden forbereder rendereringen og samtidig lar keytråden gjøre jobben sin, og nøyaktig idet du skal tegne ormen, så henter du tastetrykket som polletråden har lagret og som er ferskest.

Endret av LonelyMan
Lenke til kommentar

Det er helt vanlig for folk å tro at "Datamaskinen er så rask, kan bare polle tastene i game loopen, det har ingen verdens effekt i det hele tatt"... Og det er riktig at datamaskinen er rask, men det ligger mer forståelse i det. Det de ikke tar med i kalkuleringen er at selv om det bare er snakk om nanosekunder, så vil du ved jevne mellomrom treffe akkurat disse nanosekundene som et slags vakum og miste tastetrykkene ved rene uhell, uansett hvor rask datamaskinen er, så spiller de siste nanosekundene en rolle og det er om å gjøre å minimere denne bieffekten. Dette er en vanlig misforståelse blant programmerere.

 

You see :)

 

Tastetrykk er som lotto. Hver gang du treffer nanosekundene som ikke registrerer keys, så mister du et tastetrykk. Og denne "lottogevinsten" får du ved jevne mellomrom, ikke ved hensikt, men ved uhell. Forskjellen mellom lotto og keypolling er at i dette tilfellet håper man på å ikke vinne en lottogevinst og lottogevinstene får man ved sekunders mellomrom.

Endret av LonelyMan
Lenke til kommentar

Det er det den ikke gjør. :)

 

I rendertråden har den mutexen bare 1% av tiden like etter den har forberedt alt som må gjøres, tiden som spares er enorm hvis du skalerer det opp. Du mangler litt innsikt i akkurat dette som jeg kan se.

 

Men hvis jeg skulle kritisert meg selv så ville jeg implementert en critical section med spin count og en pause instruksjon. Det skylder jeg på at spillet ikke er ferdig enda.

 

Det er ekstremt komplekst helhetlig, det du ser på overflaten er ikke hva som skjer under. Det er nøye gjennomtenkt, om du skal skumme gjennom det med dine c++ øyne i skrivende øyeblikk vil du ikke se en eneste ting.

Endret av LonelyMan
Lenke til kommentar
Det er det den ikke gjør. :) I rendertråden har den mutexen bare 1% av tiden like etter den har forberedt alt som må gjøres, tiden som spares er enorm hvis du skalerer det opp. Du mangler litt innsikt i akkurat dette som jeg kan se.

What? Du har et helt skada design. Du bruker 4 tråder, hvor to av dem går i 100% CPU-tid for noe som ikke burde tatt 1% engang, og selv blitt opplevd helt naturlig.

Du trenger ikke mutexer, du trenger ikke polle, du trenger ikke buffre keyboard input. Du kaster bort CPU-tid på noe du umulig kan ha tenkt godt igjennom.

 

Du har forresten feilimplementert GetAsyncKeyState.

Endret av GeirGrusom
Lenke til kommentar

Det er det som er så flott med flere kjerner er at en av de kan dedikeres til 100% og polle taster kontinuerlig og raskt uten at det påvirker de andre kjernene. Om det hadde vært 100% på en kjerne hadde det vært et problem. Det er ikke skada, det er en prioritering for å få god tasterespons. Det er bare du som ikke liker tallene, du liker ikke at det står 50 foran nesa di og et lavt tall på de andre, det "føles ikke riktig" for en c++ programmerer. Men for de som er teknisk anlagt så har det betydning. For deg er det en kosmetisk ting, for meg er det en teknisk ting.

Endret av LonelyMan
Lenke til kommentar

Du har forresten feilimplementert GetAsyncKeyState.

 

Du hopper fra det ene dårlige poenget til det andre. Hva er det nå du forsøker å si? :)

 

At Nibbles implementasjonen din er rævva.

 

If the function succeeds, the return value specifies whether the key was pressed since the last call to GetAsyncKeyState, and whether the key is currently up or down. If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState. However, you should not rely on this last behavior; for more information, see the Remarks.

 

(...)

 

Although the least significant bit of the return value indicates whether the key has been pressed since the last query, due to the pre-emptive multitasking nature of Windows, another application can call GetAsyncKeyState and receive the "recently pressed" bit instead of your application. The behavior of the least significant bit of the return value is retained strictly for compatibility with 16-bit Windows applications (which are non-preemptive) and should not be relied upon.

 

Og det er ikke greit at en kjerne bruker 100% cpu.

Endret av GeirGrusom
Lenke til kommentar

Det var ikke det du nevnte, du nevnte GetASyncKeyState. Du vet bare ikke hva du snakker om i det hele tatt. Programmering er ikke en kosmetisk ting. Oppgavebehandlingen og prosent tall er bare kosmetikk Geirern. Hvis du overser kosmetikken og den stimuleringen det gir og fokuserer på det tekniske, så ser du at implementeringen er veldig god.

Endret av LonelyMan
Lenke til kommentar

Det var ikke det du nevnte, du nevnte GetASyncKeyState. Du vet bare ikke hva du snakker om i det hele tatt. Programmering er ikke en kosmetisk ting. Oppgavebehandlingen og prosent tall er bare kosmetikk Geirern. Hvis du overser kosmetikken og den stimuleringen det gir og fokuserer på det tekniske, så ser du at implementeringen er veldig god.

Overhode ikke. Hvis du kjører programmet ditt på en tokjerneprosessor, så kan du drepe ytelsen på rendering.

Lenke til kommentar

..og som jeg sa, spillet er designet utelukket for 4 kjerner, jeg skrev det ganske tydelig. Dvs, det er ikke et teknisk problem for formålet, men et spill som jeg hensiktsmessig designet for 4 kjerner.

 

Og det er primært fordi jeg selv har 4 kjerner. Det er bare et leketøy for meg selv egentlig. :)

Endret av LonelyMan
Lenke til kommentar

..og som jeg sa, spillet er designet utelukket for 4 kjerner, jeg skrev det ganske tydelig. Dvs, det er ikke et teknisk problem for formålet, men et spill som jeg hensiktsmessig designet for 4 kjerner. :)

Da har du fokus helt feil, fordi du implementerer noe som i praksis er verdiløst. har du forsøkt å lage det med bare én kjerne?

Nibbles i FastTracker 2 klarte det helt fint, og det var skrevet i Pascal.

Endret av GeirGrusom
Lenke til kommentar

Det er ikke noe problem å endre koden til å støtte en, to, fire, seks eller åtte kjerner. Det kan gjøres ganske fort.

 

Men hvis jeg gjør det så tror jeg at jeg vil bruke rawinput istedet. Bufret rawinput. Geir, jeg bruker heller ingen form for hardware rendering, grafikken rendereres i kode, i ren assembler kode og dib sections.

 

Geir så er det også viktig å forstå at i dos dagene hadde du tilgang til hardwaren direkte, i windows må du bruke api. Svakheten til keypolling i windows api'et tvinger meg til å tenke litt annerledes der i forhold til fasttracker.

Endret av LonelyMan
Lenke til kommentar

Det er ikke noe problem å endre koden til å støtte en, to, fire, seks eller åtte kjerner. Det kan gjøres ganske fort.

 

Men hvis jeg gjør det så tror jeg at jeg vil bruke rawinput istedet. Bufret rawinput.

RawInput er nok et bedre valg.

 

Prøv også å legg inn en Sleep(0) i tastaturpolling. Jeg er temmelig sikker på at du ikke vil merke noe som helst bortsett fra at CPU-tiden faller dramatisk.

 

A value of zero causes the thread to relinquish the remainder of its time slice to any other thread that is ready to run. If there are no other threads ready to run, the function returns immediately, and the thread continues execution.
Lenke til kommentar

Geir, det eksemplet du la øverst i tråden, det var faktisk den metoden jeg brukte da ormen hakket. Og det med sleep har jeg også prøvd, det hjelper enormt på cpu aktivitet, men det gjør at tastene får en liten økning i failrate og det liker jeg ikke :(

Egentlig mener jeg du skal kunne ha dette rett før ormen blir flyttet, men da må du AND eax, 0x80000000 som fjerner bitet som forteller om knappen var trykket tidligere eller ikke.

edit: altså rett etter GetAsyncKeyState

Endret av GeirGrusom
Lenke til kommentar

Egentlig mener jeg du skal kunne ha dette rett før ormen blir flyttet, men da må du AND eax, 0x80000000 som fjerner bitet som forteller om knappen var trykket tidligere eller ikke.

edit: altså rett etter GetAsyncKeyState

 

0x8000 :) det er en short, men antar det var en typo. Tsja, kanskje kanskje. Jeg har ikke prøvd det. Men nå er spillet ikke ferdig og jeg holder ennå på å lage det ferdig, håper jeg får det ferdig til i kveld, jeg laget en rutine for å omgjøre paint bilder til maps. Altså, du kan bare tegne røde linjer over et grid system og så har jeg et program som omgjør det til digitale maps. Det fine med det er at man bare kan bruke linjer og rektangler direkte i ms paint. Som du ser har jeg designet gridsystemet med oddetall, slik at det alltid er en midtlinje horisontalt og vertikalt.

 

Her er malen for gridsystemet. Jeg har markert viktige tall med tjukke linjer.

 

e2YZv.png

 

så tegner du bare over med røde linjer, behøver ikke være nøyaktig, sålenge det er innenfor gridboksene. Så konverteres det til et digitalt map av et verktøy som jeg holder på å lage nå.

 

PS958.png

Endret av LonelyMan
Lenke til kommentar
Gjest Slettet+9871234

Hva med assembly på iPhone? Er det en mulighet?

 

Hadde vært kult, ja ... :) Tviler litt, dog, da Apple trolig ikke vil slippe folk inn på for nært. Er det ikke slik at man ikke engang vet specs på den nyeste prosessoren de bruker?

 

Det kan være riktig og Apple er svært strenge, men flere og flere plattformer kan tvinge frem mer åpenhet. Du og jeg har som forbrukere sterk makt. Ikke som enkeltpersoner, men som summen av alle forbrukere. Våre penger og kjøp snakker.

 

Jeg blir liit overrasket om de ulike selskapene ikke publiserer manualer for prosessorens assembler instruksjoner. Intel gjorde alltid det den gangen jeg drev med assembly.

 

Jeg har vurdert å se litt på assembly igjen. Jeg er spesielt interessert i 64 bits assembly, men assembly på en smart telefon hadde selvsagt også vært interessant. En time i uken kan være nok til å følge med på kode og etter hvert beherske assembly for 64 bist prosessoren.

 

Er det noen som kjenner en god assemly bok / kild på Intel 64 bits prosessorer? Andre moderne prosessorer som litteratur om assembly på mobile plattformer er selvsagt også interessant.

 

Følgende Amazon bok søk: assembly

 

gir jo en god del treff på eldre literatur. Den nyeste

 

The Art of Assembly Language er fra 2010.

Endret av Slettet+9871234
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...