Autor Wątek: "Migające" sprajty dla zachowania framerate  (Przeczytany 19619 razy)

RafalM

  • *****
  • Wiadomości: 1133
  • Miejsce pobytu:
    Sulejówek
Odp: "Migające" sprajty dla zachowania framerate
« Odpowiedź #15 dnia: 2016.01.21, 16:27:23 »
Do rysowania na ekranie stos się rzeczywiście słabo nadaje.

Ale do czytania danych sprajta z pamięci to już prędzej.


Np. typowe rysowanie sprajta z maską na Spectrum to:

POP DE ;pobierz 2 bajty
LD A,(HL)  ;czytaj tło
AND E ;   złóż z maską
OR D ;złóż ze sprajtem
LD (HL),A  ;pisz na ekran

ssr86

  • *
  • Wiadomości: 37
  • Miejsce pobytu:
    Bydgoszcz
Odp: "Migające" sprajty dla zachowania framerate
« Odpowiedź #16 dnia: 2016.01.21, 19:35:45 »
Do rysowania na ekranie stos się rzeczywiście słabo nadaje.

Ale do czytania danych sprajta z pamięci to już prędzej.


Np. typowe rysowanie sprajta z maską na Spectrum to:

POP DE ;pobierz 2 bajty
LD A,(HL)  ;czytaj tło
AND E ;   złóż z maską
OR D ;złóż ze sprajtem
LD (HL),A  ;pisz na ekran

No właśnie... co ja się tak uparłem by używać stosu dla obu odczytu i zapisu...
Bardzo możliwe, że uda się tak trochę oszczędzić. Chyba trochę więcej pamięci zeżre.

EDIT: Niestety użycie  stosu w ten sposób nie pozwoli mi na ściąganie z niego wartości, które muszę dodać do adresów pamięci by przejść do kolejnych linii ekranu i bufora. To z kolei oznacza, że nie mogę tego dołączyć do procedury obsługi linii, tylko do kaŻdej linii dodawać jako makro po powrocie... To już będzie sporo więcej pamięci.
Wydaje mi się, że takie makro będzie musiało wyglądać jakoś tak:
ld bc,var1
add hl,bc ; aktualizacja adresu ekranu
ex de,hl
ld hl,var2
add hl,sp
ld sp,hl ; akrualizacja adresu danych
ex de,hl
...obecnie w większości zapis jednej linii to 6 bajtów (adres powrotu dla ret + var1 i var2 z powyższego), a tak wyjdzie 3+11 (call+powyższe makro).
Może się zmieści...
« Ostatnia zmiana: 2016.01.21, 19:51:03 wysłana przez ssr86 »
"Kto zawsze tylko żył w pustyni..."

Dr Piotr

  • ***
  • Wiadomości: 196
Odp: "Migające" sprajty dla zachowania framerate
« Odpowiedź #17 dnia: 2016.01.21, 19:42:21 »
Używanie stosu do sprite jest mocno nieefektywne, co już sam zauważyłeś. Stosem można szybko wypełniać duże obszary pamięci identyczną wartością, maksymalnie 16 powtarzającymi się bajtami. No i tu nie ma mowy o maskach dla sprite.
Mozna wiecej niz 16 bajtow np taka konstrukcja
ld sp,source
pop af
ex af,af'
pop af
pop bc
pop de
pop hl
exx
pop bc
pop de
pop hl
pop ix
pop iy
ld sp, dest
push iy
push ix
push hl
push de
push bc
exx
push hl
push de
push bc
push af
ex af,af'
push af
pozwoli na przeniesienie 20 bajtow jedna operacja.
Z maskami mozna pokombinowac z odpowiednim ulozeniem danych sprajtow tj 2 bajty sprajta, 2 bajty maski:
ls sp, spriteend
pop af
ex af,af'
dec sp
pop af
dec sp
pop hl
dec sp
pop de
and h
ex af,af'
and d
ls sp, dest
push af
inc sp
ex af,af'
push af
tylko niekoniecznie to bedzie szybsze :)
Stos faktycznie najlepszy jest do czyszczenia obszaru pamieci/ekranu czy wypelniania jakims wzorem. Robilem jakis czas temu testy, ponizej masz timingi prcedurek kopiujacych blok o zadanej szerokosci I wysokosci. Wyliczenie przejscia do nastepnej linii zostalo pominiete dla jasnosci wyliczen.

Profiling summary for cleartest1.sym, loaded at 0x0000 and executed in 419658 tstates ( 104914.50 ms).

di ;          4T 
ld sp,#bfff ;         10T 
call clear ;     163917T 
call clear1 ;     136173T 
call clear2 ;      79687T 
call clear3 ;      39857T 
ret ;         10T 
clear:
ld hl,(screenbase) ;         16T 
ld c,#60 ;          7T 
clearloop:
xor a ;        384T 
ld b,#40 ;        672T 
push hl ;       1056T 
clearloop_1:
ld (hl),a ;      43008T 
inc hl ;      36864T 
djnz clearloop_1 ;      79392T 
pop hl ;        960T 
dec c ;        384T 
jr nz,clearloop ;       1147T 
ret ;         10T 
clear1:
ld hl,(screenbase) ;         16T 
ld a,#60 ;          7T 
clearloop1:
ex af,af' ;        384T 
ld bc,screen_width ;        960T 
push hl ;       1056T 
ld (hl),#00 ;        960T 
ld e,l ;        384T 
ld d,h ;        384T 
inc de ;        576T 
ldir ;     128544T 
pop hl ;        960T 
ex af,af' ;        384T 
dec a ;        384T 
jr nz,clearloop1 ;       1147T 
ret ;         10T 
clear2:
di ;          4T 
ld (savesp),sp ;         20T 
ld hl,(screenbase) ;         16T 
ld a,#60 ;          7T 
ld de,#0000 ;         10T 
clearloop2:
ex af,af' ;        384T 
ld bc,#0020 ;        960T 
add hl,bc ;       1056T 
add hl,bc ;       1056T 
ld sp,hl ;        576T 
ld b,c ;        384T 
clearloop21:
push de ;      33792T 
djnz clearloop21 ;      39456T 
ex af,af' ;        384T 
dec a ;        384T 
jr nz,clearloop2 ;       1147T 
ld sp,(savesp) ;         20T 
ei ;          4T 
ret ;         10T 
clear3:
di ;          4T 
ld (savesp),sp ;         20T 
ld hl,(screenbase) ;         16T 
ld hl,screen_buf ;         10T 
ld a,#60 ;          7T 
ld de,#ffff ;         10T 
clearloop3:
ex af,af' ;        384T 
ld bc,#0020 ;        960T 
add hl,bc ;       1056T 
add hl,bc ;       1056T 
ld sp,hl ;        576T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
push de ;       1056T 
ex af,af' ;        384T 
dec a ;        384T 
jr nz,clearloop3 ;       1147T 
ld sp,(savesp) ;         20T 
ei ;          4T 
ret ;         10T 

Executed calls:
Address Executed code No of calls Time
call clear        1      163917T (39.06%)
call clear1        1      136173T (32.45%)
call clear2        1       79687T (18.99%)
call clear3        1       39857T ( 9.50%)


Subroutines called:
Address Calling address No of calls Time
clear        1      163900T (39.06%)
0004        1      163900T (39.06%)
clear1        1      136156T (32.44%)
0007        1      136156T (32.44%)
clear2        1       79670T (18.98%)
000a        1       79670T (18.98%)
clear3        1       39840T ( 9.49%)
000d        1       39840T ( 9.49%)

clear to wypelnianie w petli djnz
clear1 to ldir
clear2 to czyszczenie przez stos w petli djnz
clear3 to clear2 w wersji unrolled.
Jak widac po wynikach, czyszczenie stosem jest do 4 razy szybsze, ldir 3 razy wolniejszy...

ssr86

  • *
  • Wiadomości: 37
  • Miejsce pobytu:
    Bydgoszcz
Odp: "Migające" sprajty dla zachowania framerate
« Odpowiedź #18 dnia: 2016.01.21, 20:40:01 »
Cytuj
No właśnie... co ja się tak uparłem by używać stosu dla obu odczytu i zapisu...
Bardzo możliwe, że uda się tak trochę oszczędzić. Chyba trochę więcej pamięci zeżre.
Jednak obecna metoda jest wydajniejsza niż proponowane użycie stosu...
Teraz jest:
Procedura mażąca zapisuje co ma robić w ciągu wartości (wskaźnik stosu wskazuje na tę listę) jak poniżej:
dw LcprE__OD6e
dw   -1 * BUFFER_LINE_WIDTH_IN_BYTES +6, -1 * $100 +6
LcprE_OD6e to adres "powrotu"/skoku do procedury, która obsługuje linie mającą 6 nieprzezroczystych bajtów pod rząd i przejściem do następnej linii przy użyciu dwóch kolejnych parametrów (pierwszy do aktualizacji adresu bufora ekranu, drugi do aktualizacji adresu kopii tła)
LcprE__OD6e:
        ldi
LcprE__OD5e:
        ldi
LcprE__OD4e:
        ldi
LcprE__OD3e:
        ldi
        ldi
LcprE__OD1e:
        ldi

        pop bc
        add hl,bc
        ex de,hl
        pop bc
        add hl,bc
        ex de,hl
        ret
Taka linia wg moich obliczeń to jakieś 164 cykle i zapis takiej linii to 6 bajtów + procedura (ale ta jednak jest wielokrotnie używalna).

Wersja z innym użyciem stosu wyglądałaby wg mnie jakoś tak:
call LcprE__OD6e

ld bc,-1 * BUFFER_LINE_WIDTH_IN_BYTES +?
add hl,bc
ex de,hl
ld hl, -1 * $100 +?
add hl,sp
ld sp,hl
ex de,hl

call Lcpr.......
[...]
Odpowiednik procedury LcprE__OD6e wyglądałby tu jakoś tak:
pop bc
ld (hl),c
inc l
ld (hl),b
inc l
pop bc
ld (hl),c
inc l
ld (hl),b
inc l
pop bc
ld (hl),c
inc l
ld (hl),b
ret

To wg moich obliczeń wymaga jakieś 183 cykle i taka linia to 3+13 bajtów.
Chyba nawet nie byłoby bardziej opłacalne gdyby to kompletnie rozwinąć (czyli bez call i ret), bo wtedy byłoby 154 vs 156 cykli a z pamięcią jeszcze gorzej.[/code]
« Ostatnia zmiana: 2016.01.21, 20:50:48 wysłana przez ssr86 »
"Kto zawsze tylko żył w pustyni..."

Dr Piotr

  • ***
  • Wiadomości: 196
Odp: "Migające" sprajty dla zachowania framerate
« Odpowiedź #19 dnia: 2016.01.22, 09:34:21 »
Cytuj
No właśnie... co ja się tak uparłem by używać stosu dla obu odczytu i zapisu...
Bardzo możliwe, że uda się tak trochę oszczędzić. Chyba trochę więcej pamięci zeżre.
Jednak obecna metoda jest wydajniejsza niż proponowane użycie stosu...
Teraz jest:
Procedura mażąca zapisuje co ma robić w ciągu wartości (wskaźnik stosu wskazuje na tę listę) jak poniżej:
dw LcprE__OD6e
dw   -1 * BUFFER_LINE_WIDTH_IN_BYTES +6, -1 * $100 +6
LcprE_OD6e to adres "powrotu"/skoku do procedury, która obsługuje linie mającą 6 nieprzezroczystych bajtów pod rząd i przejściem do następnej linii przy użyciu dwóch kolejnych parametrów (pierwszy do aktualizacji adresu bufora ekranu, drugi do aktualizacji adresu kopii tła)
LcprE__OD6e:
        ldi
LcprE__OD5e:
        ldi
LcprE__OD4e:
        ldi
LcprE__OD3e:
        ldi
        ldi
LcprE__OD1e:
        ldi

        pop bc
        add hl,bc
        ex de,hl
        pop bc
        add hl,bc
        ex de,hl
        ret
Taka linia wg moich obliczeń to jakieś 164 cykle i zapis takiej linii to 6 bajtów + procedura (ale ta jednak jest wielokrotnie używalna).

Wersja z innym użyciem stosu wyglądałaby wg mnie jakoś tak:
call LcprE__OD6e

ld bc,-1 * BUFFER_LINE_WIDTH_IN_BYTES +?
add hl,bc
ex de,hl
ld hl, -1 * $100 +?
add hl,sp
ld sp,hl
ex de,hl

call Lcpr.......
[...]
Odpowiednik procedury LcprE__OD6e wyglądałby tu jakoś tak:
pop bc
ld (hl),c
inc l
ld (hl),b
inc l
pop bc
ld (hl),c
inc l
ld (hl),b
inc l
pop bc
ld (hl),c
inc l
ld (hl),b
ret

To wg moich obliczeń wymaga jakieś 183 cykle i taka linia to 3+13 bajtów.
Chyba nawet nie byłoby bardziej opłacalne gdyby to kompletnie rozwinąć (czyli bez call i ret), bo wtedy byłoby 154 vs 156 cykli a z pamięcią jeszcze gorzej.[/code]
Tu masz procedurke kopiujaca przez stos:

ld hl, sprite_data
ld ix, dest_address
ld bc, screen_buffer_width
ld de, sprite_width
ld a, sprite_height
call draw
ret

draw:
ld iy,0
add iy,sp
add ix, de
draw_loop:
;****
ld sp, hl ; 6
exx ; 4
pop bc ; 10
pop de ; 10
pop hl ; 10
ld sp, ix ; 10
push bc ; 11
push de ; 11
push hl ; 11
exx ; 4
add ix, bc ; 15
add hl, de ; 11
; ***
dec a
jr nz,draw_loop

ld sp, iy
ret
Glowna petla zajmuje 14 bajtow i wykonuje sie w 113 tstates na 6 bajtow do przekopiowania (jesli zrobisz unroll tego co jest miedzy ;*** )



RafalM

  • *****
  • Wiadomości: 1133
  • Miejsce pobytu:
    Sulejówek
Odp: "Migające" sprajty dla zachowania framerate
« Odpowiedź #20 dnia: 2016.01.22, 10:32:09 »
Cytuj
Tu masz procedurke kopiujaca przez stos:

Tylko z takim PUSH trzeba uważać żeby czegoś nie narysować w lustrzanym odbiciu  bo przy wykonaniu PUSH wskaźnik stosu przesuwa się w dół a nie w górę czyli rysujemy od prawej do lewej (przynajmniej na Spectrum).

Mogę się mylić pisząc coś na sucho bez sprawdzenia ale chyba rejestry należy robić w odwrotnej kolejności przy PUSH i POP.

Dr Piotr

  • ***
  • Wiadomości: 196
Odp: "Migające" sprajty dla zachowania framerate
« Odpowiedź #21 dnia: 2016.01.22, 10:41:05 »
Cytuj
Tu masz procedurke kopiujaca przez stos:

Tylko z takim PUSH trzeba uważać żeby czegoś nie narysować w lustrzanym odbiciu  bo przy wykonaniu PUSH wskaźnik stosu przesuwa się w dół a nie w górę czyli rysujemy od prawej do lewej (przynajmniej na Spectrum).

Mogę się mylić pisząc coś na sucho bez sprawdzenia ale chyba rejestry należy robić w odwrotnej kolejności przy PUSH i POP.
Tak, push bc i push hl nalezy zamienic miejscami.

ssr86

  • *
  • Wiadomości: 37
  • Miejsce pobytu:
    Bydgoszcz
Odp: "Migające" sprajty dla zachowania framerate
« Odpowiedź #22 dnia: 2016.01.22, 18:41:13 »
Jeszcze nie implementowałem powyższej metody, ale wstępne rachunki wyglądają jakoś tak...:

Jest 6 klatek animacji.
Porównanie obecnej metody (ldi tylko gdy trzeba, ale skoki przez ret) z push/pop:
f00 | 2125 | 1842
f01 | 2286 | 2026
f02 | 2236 | 2005
f03 | 2236 | 2064
f04 | 1936 | 1961
f05 | 1207 | 1284
+ koszty setupu: dla pierwszej to ~72, dla drugiej jeszcze nie wiem, ale na pewno mniej.
Gdyby obecnie zastosowaną przeze mnie metodę rozwinąć (bez skoków, więc akurat w tym wypadku bez stosu) to od czasów dla niej trzeba by poodejmować ~160 cykli i wyszłoby takie porównanie:
f00 | 1975 | 1842
f01 | 2136 | 2026
f02 | 2076 | 2005
f03 | 2076 | 2064
f04 | 1786 | 1961
f05 | 1077 | 1284
Wniosek taki (o ile się nie walnąłem w rachunkach), że gdy sprajt jest rzadki to lepiej jest używać ldi, a tak to druga metoda daje pewne oszczędności, jednak wszystko kosztem pamięci... Jednak powinno się zmieścić i wtedy parę linii uda się uratować.

W sumie to okazuje się, że i push/pop można połączyć z tą kompresją ze skokami na ret...
ld sp, hl ; 6

pop bc ; 10
pop de ; 10
pop af ; 10
ld sp, ix ; 10
push af ; 11
push de ; 11
push bc ; 11

ld sp,iy
pop bc
add ix, bc ; 15
pop bc
add hl, bc ; 11
ret
i w sumie dochodzi "tylko" koszt ret...no i w sumie tego ld sp,iy.

Dzięki za kod:)
"Kto zawsze tylko żył w pustyni..."

Dr Piotr

  • ***
  • Wiadomości: 196
Odp: "Migające" sprajty dla zachowania framerate
« Odpowiedź #23 dnia: 2016.01.22, 19:38:26 »
Jeszcze nie implementowałem powyższej metody, ale wstępne rachunki wyglądają jakoś tak...:

Jest 6 klatek animacji.
Porównanie obecnej metody (ldi tylko gdy trzeba, ale skoki przez ret) z push/pop:
f00 | 2125 | 1842
f01 | 2286 | 2026
f02 | 2236 | 2005
f03 | 2236 | 2064
f04 | 1936 | 1961
f05 | 1207 | 1284
+ koszty setupu: dla pierwszej to ~72, dla drugiej jeszcze nie wiem, ale na pewno mniej.
Gdyby obecnie zastosowaną przeze mnie metodę rozwinąć (bez skoków, więc akurat w tym wypadku bez stosu) to od czasów dla niej trzeba by poodejmować ~160 cykli i wyszłoby takie porównanie:
f00 | 1975 | 1842
f01 | 2136 | 2026
f02 | 2076 | 2005
f03 | 2076 | 2064
f04 | 1786 | 1961
f05 | 1077 | 1284
Wniosek taki (o ile się nie walnąłem w rachunkach), że gdy sprajt jest rzadki to lepiej jest używać ldi, a tak to druga metoda daje pewne oszczędności, jednak wszystko kosztem pamięci... Jednak powinno się zmieścić i wtedy parę linii uda się uratować.

W sumie to okazuje się, że i push/pop można połączyć z tą kompresją ze skokami na ret...
ld sp, hl ; 6

pop bc ; 10
pop de ; 10
pop af ; 10
ld sp, ix ; 10
push af ; 11
push de ; 11
push bc ; 11

ld sp,iy
pop bc
add ix, bc ; 15
pop bc
add hl, bc ; 11
ret
i w sumie dochodzi "tylko" koszt ret...no i w sumie tego ld sp,iy.

Dzięki za kod:)
Prosze bardzo :)
Jak chcesz jeszcze je przyspieszyc, to pozbadz sie call/ret (zajmuja one 27 tstates na wywolanie) i zastap je np. jp (hl)

ssr86

  • *
  • Wiadomości: 37
  • Miejsce pobytu:
    Bydgoszcz
Odp: "Migające" sprajty dla zachowania framerate
« Odpowiedź #24 dnia: 2016.01.22, 20:09:28 »
W obecnej metodzie nie używam call tylko samych ret - lista adresów do skoków (i pozostałe parametry) jest na stosie (stos wskazuje szczyt listy), więc instrukcje ret wykonują skoki do kolejnej instrukcji z listy (np. rysuj_linie: erase_4_bytes - skip_2_bytes - erase_2_bytes - update_pointers).
Jp (hl) nie mógłbym za bardzo użyć, bo kosztowne byłoby załadowanie adresu skoku do hl.
"Kto zawsze tylko żył w pustyni..."

rafamiga

  • ***
  • Wiadomości: 215
  • Miejsce pobytu:
    Warszawa
Odp: "Migające" sprajty dla zachowania framerate
« Odpowiedź #25 dnia: 2016.05.11, 19:10:07 »
Zbieg okoliczności, przedwczoraj natrafiłem na informacje o tym, jak takie gry jak Cobra czy Sidewize nie tylko płynnie wyświetlały sprajty, ale równie płynnie w tym samym czasie przewijało się w nich tło, w pełnych 50 ramkach.

Otóż niekoniecznie można zacząć obraz odbudowywać od przerwania, czyli w czasie wygaszania albo borderu. Jest sposób na to, by mieć prawie pół ekranu czasu. Tu jest opis:

http://stevewetherill.com/blog/2015/02/24/the-sidewize-test-zx-spectrum-floating-bus-shenanigans/

Tl;dr -- czekamy aż na szynie pojawi się jakiś znany kolor i wtedy rozpoczynamy rysowanie.

Dla tych, co sądzą, ze to herezja -- nie do końca. ULA, w trakcie rysowania ekranu, wystawia na szynie kolor rysowanego właśnie atrybutu. Oczywiście, jest to zachowanie nieudokumentowane, ale w większości wypadków działa [ale nie wiem czy też na 128]. Kolor może być dowolny, ale Wetherill zmyślnie wstawił, zaraz pod obszarem gry, linię koloru 8, czyli "jasnej" czerni, co samo w sobie stanowi cwany hack. 8^) Wstawiając, zamiast HALT, pętle czekającą na $08 na porcie $40ff, zyskujemy prawie pół ramki na rysowanie ekranu. Łącząc to z cwanymi 16-bajtowymi buforami wypluwanymi z pamięci serią pushy czy np. wymyślnym rysowaniem tła rodem z Cobry [link niżej] to mamy receptę na naprawdę niesamowitą, płynnie ruszającą się grafikę.

https://sites.google.com/site/kevinphair/home/jonathan-smith---a-tribute/frobush/Cobra/4-graphicstorage

Swoją drogą, Cobra używa też technik wstępnie poprzesuwanych sprajtów oraz dynamicznych masek, jak w Heatland:

http://stevewetherill.com/blog/2014/09/17/heartland-for-zx-spectrum/
« Ostatnia zmiana: 2016.05.11, 19:38:43 wysłana przez rafamiga »
--
rafamiga

ZX Freeq

  • *****
  • Wiadomości: 1835
  • Miejsce pobytu:
    Warszawa
Odp: "Migające" sprajty dla zachowania framerate
« Odpowiedź #26 dnia: 2016.05.11, 19:27:29 »
Rewelacyjna lektura. Niesamowite, jak można ze Spectrum wyciskać siódme poty. Pokazuje też jak dobrze trzeba znać maaszynkę, aby napisać świetną grę.
ZX80|ZX81+16kB+PandAY|ZX 48k/+/128k+/+2/+2A/+3/Vega/Next|QL+QIDE|JS128|Timex 2048+2040|UK2086|FDD3000+3.5''|AY|ZX HD|Divide2k11/2k14|DivMMC/PicoDivSD|BetaDisk 128|Opus|Masakrator FM|If 1/2/Microdrv|Multiface 1|+2A\B SDI-1|SJS 1/2|ZX Printer|TZXDuino|+3 HxC USB|ZXUno|Omni
Z88|A500/600|PC200|Ent128

matofesi

  • *****
  • Wiadomości: 2049
  • Miejsce pobytu:
    Toruń/Poland
Odp: "Migające" sprajty dla zachowania framerate
« Odpowiedź #27 dnia: 2016.05.12, 10:11:03 »
Tl;dr -- czekamy aż na szynie pojawi się jakiś znany kolor i wtedy rozpoczynamy rysowanie.

A to jest znana metoda - kiedyś się bawiłem tym efektem. Widziałem też jakieś demka, które robiły zdaje się synchronizację do floating-busa. No i są gry, które tego używają, i to są te gry, które nie działają np. na Timexach, które floating busa nie mają.

Technika fajna tylko zawsze trzeba wyważyć za i przeciw :)

RafalM

  • *****
  • Wiadomości: 1133
  • Miejsce pobytu:
    Sulejówek
Odp: "Migające" sprajty dla zachowania framerate
« Odpowiedź #28 dnia: 2016.05.12, 11:37:54 »
Floating bus to  znany trick.

Z tym że na jednych modelach Spectrum to jest, na innych nie ma więc jeśli chcemy pisać grę dla mozliwie szerokiej grupy odbiorców to tego raczej nie używamy,