☰ Menu

Scene.hu

Magyar demoscene portál – grafikusok, zenészek, programozók alkotói közössége

[Az előző rész itt tekinthető meg.]

Ahogy ígértem a mostani részben felhasználjuk az eddigieket és megismerkedünk igencsak egzotikus grafikai tárházunkkal. Mostantól nem írok teljes kódlistát, csak az adott kivesézett részt. A teljes forrást és a binárist persze letölthetitek majd.

Háttér

Az előző részben scanline-onként változtattuk a háttér színét és elég szép látványt produkáltunk. Ettől akár a limitációkat is hajlamosak lehetnénk elfelejteni és akár pusztán kényelmi megoldásként tekinthetünk az 5 mozgatható objektumra. Megígérem hogy ebben az írásban rengeteg ledöntendő fallal és áthidalandó szakadékkal fogtok találkozni. ;)

Vegyük is rögtön a háttérszín váltást. Mi történne ha egy scanline-on belül próbálnánk a lehető legtöbbször váltani? Aki figyelt és kicsit kutakodott, az kikövetkeztetheti, hogy ha egy scanline-on a 228 órajelből 160 jut rajzolásra, azaz van összesen 53 ciklus amikor átállíthatjuk a TIA-t. Ahogy beszéltük a TIA mindig az aktuális állapotának megfelelően rajzol – technikailag egy state machine. Ahhoz hogy átírjuk a COLUBK regisztert be kell tölteni a használni kívánt értéket egy regiszterbe és onnan kell bemásolni. Ez legjobb esetben is egy LDA + STA páros, ami 5 ciklust jelent – közvetlen értékadással és mivel a TIA regiszterek a zero page-en vannak. Így kiszámolhatjuk, hogy ha jók vagyunk, akkor 11 alkalommal válthatunk színt. Ez azt is jelenti persze hogy abban a sorban mást már nem is tudunk bűvészkedni. Esetleg a rajzolás előtti 22 ciklussal mondjuk eltolhatjuk a váltások helyét, vagy feltételesen futtathatunk más kódrészletet. Nézzünk erre egy példát!

SimpleChanges

	NOP		;2
	NOP		;2
	NOP		;2
	NOP		;2
	NOP		;2
	LDA #$18	;2
	STA COLUBK	;3
	LDA #$28	;2
	STA COLUBK	;3
	LDA #$38	;2
	STA COLUBK	;3
	LDA #$48	;2
	STA COLUBK	;3
	LDA #$58	;2
	STA COLUBK	;3
	LDA #$68	;2
	STA COLUBK	;3
	LDA #$78	;2
	STA COLUBK	;3
	LDA #$88	;2
	STA COLUBK	;3
	LDA #$98	;2
	STA COLUBK	;3
	LDA #$A8	;2
	STA COLUBK	;3
	LDA #$B8	;2
	STA COLUBK	;3

	STA WSYNC	;3

	DEX		  ;2
	BNE SimpleChanges ;3/2

Ennyi! A fenti kódrészlet a lehető legtöbbször vált színt egy scanline rajzolása alatt úgy hogy közben figyeljük hány sort rajzolunk. Ennél azért szeretnénk általában több dolgot is tenni, szóval igencsak limitált a felhasználása ennek a lehetőségnek.

Szórakozás a háttér színeivel

A képen látható a fenti kód néhány egyszerű módosításának eredménye. Az első részt szimplán az előbbi kód rajzolja. A második rész egy kis játék az időzítéssel, melynek eredménye finom léptetés. És ha már tudunk léptetni, akkor miért ne mozgatnánk tetszőleges színpalettát? Ezt mutatja be a harmadik. Végül egy egyetlen blokkot ide-oda mozgató rész. Csak egyszerű megoldás, nagy lépésközzel, mert a finom mozgatáshoz jóval bonyolultabb kódot kéne írni ami nem hiszem hogy mindenkinek a javára válna. Később viszont más kontextusban lesz olyan algoritmus ami rábírható ilyen finom mozgatás megoldására is.

Az alább mellékelt kódot átrágva rájöhettek hogyan működnek. Inkább érthető formában vannak mint halálra optimalizáltban, de azért – főleg kezdőknek – ajánlott a mélyreható vizsgálat, mert sok problémát vet fel.

[forrás és bináris] – töltsd le innen egyetlen zip-ben

Játéktér

A játéktér valamivel finomabb grafikai megjelenítést biztosít azzal, hogy a scanline-t 40 – kb. 4-szer szélesebb mint amilyen magas – részre osztja. Ez azért sokkal jobbnak tűnik, és kiválóan alkalmas elnagyolt grafikákhoz – mint amilyen például a  játéktér. Aki most azt gondolja, hogy valahol van egy kis data aminek az elejéhez odadugjuk az orrát és már rajzol is vígan az túl sok sci-fi-t nézett. :D

A valóság nem ilyen egyszerű. A 40 részhez van ugyanis 20 bitünk a játéktér első feléhez. A másik feléhez pedig beállíthatjuk, hogy megismételje az előző 20-at, vagy tükörképet rajzoljon. Persze itt jön a state machine jelleg amikor is ha jól időzítünk, átírhatjuk a regiszterek tartalmát miután már kirajzoltuk őket és ezzel a másik térfél már más grafikát kaphat. Ehhez fel kell áldoznunk némi számítási időt és persze ügyesen kell elvesztegetni a fölös ciklusokat. Majd a példából jobban látszik…

Arról még nem beszéltem, hogy melyik regiszterekbe kell beletenni a kirajzolandó biteket és hogyan. Az addig logikus lehet, hogy ahol 1-es van ott rajzolunk, ahol 0, ott nem. Még az is elfogadható mentség, hogy 8 bites gép lévén a 20 bit 3 regiszterbe van szétosztva. Ezek azonban nem túl egyértelműen rajzolódnak ki. Először is a PF0 felső 4 bitje visszafelé, aztán a PF1 a legnagyobb bittől a legkisebbig és végül a PF2 megint csak visszafelé. Az alábbi képről jobban megértitek.

A játéktér kirajzolása (*az AtariAge fórumról)

Már látható, hogy lesznek itt gondok. Általában az ilyenek miatt szokás csak minden x-edik scanline-ban változtatni a játéktér grafikáját, azaz inkább kevésbé finom és részletes rajzokat készíteni. Most nézzünk egy példát mind a három rajzolási módra.

Bulis játéktér bemutató

A felső sáv egy szimmetrikusan kirajzolt játéktér, ami – reményeim szerint felismerhetően – egy elszánt ninja szempárt ábrázol aki kegyetlenül koncentrál az alább látható célpontokra. :)
Az említett célpontok a kacsák és a halak, amik jobbra illetve balra mozognak. Ennek az effektnek a létrehozásához egyszerű bitműveleteket kell csak alkalmaznunk és eszméletlen sok memóriát. És hogy egy kicsit érdekessé tegyem, – meg mert így jobban szemlélteti, hogy mennyire sok processzor időt vesztegetünk el ha modernebb gépekhez hasonlóan akarjuk az eseményeket kezelni – a kacsák grafikája két frame-ből áll. Ez lehetőséget ad megmutatni miként valósítható meg egy választott grafikára mutató pointer létrehozása. Ezen kívül van egy kis játék a háttér színeivel is, ami pedig az összetettebb grafika létrehozása közbeni időzítési problémákat szemlélteti.
A két scroll-ozó rész között látható hullámok aszimmetrikusan vannak kirajzolva. Az egyetlen dolog velünk, hogy itt is kicsit játszok a színekkel. Azért nem mozog, hogy még érthető legyen a példa, DE házi feladat mozgásra bírni! Lehet próbálgatni a scroll-ozást, és/vagy az animáció lejátszást. Ügyesebbek kitalálhatnak valami egészen elképesztő effektet. ;)

Az alábbi kép pedig nagyon jól szemlélteti, hogy egész konkrétan mikor mi történik a játéktér rajzolása során, így azt is, hogy mikor mit lehet változtatni.

Asymetric Playfield TIA Timing

Kis segítség az időzítéshez (*az AtariAge Fórumról)

A játéktér regiszterei a PF0, PF1 és PF2. A tükrözést pedig a CTLPF D0 bitje szabályozza. A színt pedig a COLUPF tartalmazza.

[Itt a kód a fentebbi példához.] Jó bogarászást!

Még egy extra – a példában nem szemléltetett – opció van, a score mód. Ez annyi, hogy a játéktér bal oldala olyan színű lesz, mint az első játékos, a másik fele pedig mint a második játékos. Ezt a CTLPF D1 bitjével tudjuk ki/be kapcsolni.

Szemléltetésül találtam ha jól emlékszem az AtariAge fórumon valahol – de már nem találom – egy score módot használó vertikálisan scroll-ozó játéktér effektet. Itt a kódja – megfelelően kreditálva a tulajdonos által. Alább pedig egy kép belőle.

Asymmetrical Playfield With Two Vertical Scrolling V1.01 by Christian Bogey - April 17,2004

Asymmetrical Playfield With Two Vertical Scrolling V1.01 by Christian Bogey – April 17,2004

Most pedig nézzünk egy szerintem elég jól kinéző demo effektet amit csak a játéktér ügyes használatával oldottak meg.

Sphaera Stellarum - Noice / Plazma effekt

Sphaera Stellarum – Noice / Plazma effekt

Az a rész hogy honnan szedi a kirajzolandó dolgokat elég bonyolult – elég az hozzá, hogy a kód a memóriában fut, így képes önmagát futás közben módosítani + egyáltalán nem használ WSYNC-et. :) Mindenesetre a kirajzolás csak a játéktérrel történik és szerintem jól mutatja, hogy ügyesen használva, lehet látványos dolgokat összehozni. Katt a képre a pouet oldalhoz ahol találtok a kód mellett YouTube linket is.

A következő szintén egy ügyes felhasználás, szintén a Noice-tól és szintén plazma effekt. Nagyon szerethetik. :)

ISO - Noice / Plazma effekt

ISO – Noice / Plazma effekt

Ez egy másféle felhasználás és talán nem is tűnik annyira látványosnak, de ha végig nézitek a demót, látni fogjátok, hogy ugyanezzel a megjelenítési technikával mennyi különböző effektet ki lehet hozni. Szintén katt a képre a pouet linkért.

Ez utóbbi demóban egyébként találtok egy meglehetősen színes text scroller-t is ami az előző részben ismertetettel hasonló technikával használja a hátteret megjelenítésre.

Játékosok

Hogy egy kicsit jobb kedvere derüljetek, beszéljünk most a gép legfinomabb grafikáját jelentő elemekről. Ez a két játékos sprite-ja. Egyenként 8 bites felbontásban és egy pixel az úgy 2-szer szélesebb, mint amilyen magas. Ezek rengeteg trükköt tudnak, de előbb nézzük hogyan kell őket kirajzolni.
A rajzolás itt is úgy megy hogy amint belekerül a megfelelő regiszterbe az adat, azonnal megjelenik a rajz amint legközelebb elérjük a beállított pozíciót. Az adatot a GP0 és GP1 regiszterekbe kell tenni és visszafelé rajzolódnak ki – tehát D7 – D0. Itt is ahol 1 van ott lesz pixel, ahol 0 ott nem. Színt a COLUP0 és a COLUP1 állítja, a tükrözést pedig a REFP0 illetve a REFP1 regiszterek D3 bitjére írt 0 vagy 1.
Az izgalmas rész viszont az hogy lehet nyújtani vagy sokszorozni is őket. Ehhez a NUSIZ0 és a NUSIZ1 alsó 3 bitjét kell beállítani az alábbi táblázat szerint:

nusiz

NUSIZ értékek és hatásuk a sprite-okra. Egyenesen a Stella Programmers’ Guide-ból.

 

 

A következő részben mutatok egy kis példa progit ami szemlélteti a sprite kirajzolással járó problémákat – ugyanis annak ellenére hogy felüdülésnek érezzük a finom grafikát és úgy érezzük mindent szebbé tehetünk vele, használat közben hamar belefutunk a gép más limitációiba.

Látszik hogy több példányt is megjeleníthetünk egymás után különböző távolságokra egymástól, vagy megnyújthatjuk kétszeres vagy négyszeres méretre is. Az előbbi azért nagyon hasznos, mert egy sprite egy scanline-on csak egyszer rajzolható ki. Így lehetett létrehozni hogy akár több ellenfél vagy akadály is legyen egy sorban. Lásd a képeket alább.

Frogger - Parker Bros (1982)

Frogger – Parker Bros (1982)

Frogger - debug színekkel

Frogger – debug színekkel

Amint látjuk a Frogger ha nem is egy technikai zsenialitás, de kihasználja a platform adta lehetőségeket – már ami a játékos sprite-okat illeti. Azt hogy korai – még kiforratlan technológiájú – játék, a képernyő bal oldalán látható grafikus glitch-ek – vízszintes vonalak – is mutatják. De erről majd a következő részben… Nézzük meg most a Galaxian-t!

Galaxian - Atari (1983)

Galaxian – Atari (1983)

Nehéz olyan screenshot-ot készíteni amin jól látszik, de ebben a játékban nem kevesebb mint 7 az egy sorban lévő ellenfelek maximális száma. Plusz kettő közülük látszólag még összevissza is repked és közben vannak lövedékek és robbanások is. Ez egy jó kis debug-olós házi feladatnak tűnik. :) Annyit elárulok, hogy igazából többször is újra lehet kezdeni a játékos sprite-ok kirajzolását, csak nem teljesen egyértelmű, hogy mit kapunk eredménynek – kísérletezés + vason próbálgatás…  erről többet majd a következő részben.

A játéktérnél látott két demo a játékosokkal is mutat pár ügyes trükköt. Ezekből nézzük most csak ezt a két hasonló effektet.

Sphaera Stellarum - Noice / Text Scroller

Sphaera Stellarum – Noice / Text Scroller

ISO - Noice / Szalag effekt

ISO – Noice / Szalag effekt

Az eredmény hasonló, csak más a töltelék. Nagyon szépen mutatja a kreativitás jelentőségét és esetleg elleshettek pár fogást debug-olás közben.

A fentebb bemutatott kódban az idevágó részlet mutat példát két sprite egy scanline-on történő egyidejű megjelenítésére. A problémát az jelenti, hogy nem tudjuk a logikát – ami eldönti, hogy rajzolni kell-e valamelyik sprite-ot – és a grafika betöltő algoritmust elég gyorsan végrehajtani ahhoz, hogy ugyanabban a sorban még ki is tudjuk rajzolni azokat. Megoldást jelenthet, hogy csak a logikát tesszük a sorba, de a grafika már a kirajzolandó elemre mutat és a kirajzolandó pozíciót már előre beállítottuk. Ez persze csak akkor van ha nem alkalmazunk olyan trükköket mint a fenti képeken látható effektek amik a grafika betöltést egyszerűsítették le a probléma áthidalásához – amit egy játékban nem biztos hogy ilyen könnyen el tudunk érni.

A játékos karakterek finom felbontásának köszönhetően nagyon jól használhatóak képek prezentálására. A következő invitro-t végignézve sok ilyet láthatunk.

Bár ezeknek a kirajzolása az eddigieknek köszönhetően igen egyszerűnek tűnik, megpróbálva mégis egy kis nehézségbe ütközünk. Ezzel azonban csak a következő részben foglalkozunk.

Viszont ha egy kicsit még ügyesebbek vagyunk, akkor akár 12 db 3+1 pixel széles karaktert is kiírhatunk. Ügyesebbek – becses nevén Eshu – egy kicsit még több trükkel képesek voltak 32 karakternyi szöveget kirakni. Ebből 4 illetve 5 pixel magas betűkkel  16 és 20 soros szöveget írhatunk ki. Volt több próbálkozás is és meglehetősen advanced megoldások is… Fórum beszélgetés itt.

32 characters demo by Eshu

32 characters demo by Eshu

Ez is példázza, hogy a formalitás legyőzhető kreativitással. ;)

Lövedékek

Sok játékban lövöldözünk vagy éppen ránk lövöldöznek. Gondolhatnánk hogy ez egy alapvető kényelmi funkciót ellátó elem. Valóban nagyon kényelmes a használata. Alapból a játékos közepére van pozicionálva, ki/bekapcsolható, a játékoséval megegyező színű és tőle függetlenül mozgatható. Azonban a limitált rajzolási lehetőségeket figyelembe véve és tudva azt, hogy 4 különböző méretre nyújtható, könnyen azon kaphatjuk magunkat, hogy rajzolásra használjuk. Talán csak egy túl szögletes sarok lekerekítésére, de akár egy teljes játékos karakter megrajzolására.

A pozicionálással itt is csak a következő leckében foglalkozunk, de nézzük ami maradt. Arról már volt szó, hogy  a színe megegyezik a játékoséval. Kapcsolgatni az ENAM0 és ENAM1 regiszter D1 bitjével lehet őket. A mérete alapból 1 pixel, ami dupla olyan széles, mint magas – ahogy már megszokhattuk. Ezt nyújthatjuk a NUSIZ0 és NUSIZ1 D4 és D5 bitjével.

D5 D4 méret
0 0 x1
0 1 x2
1 0 x4
1 1 x8

Labda

Az egyik akkoriban nagyon népszerű játék a Pong volt. Egyértelmű tehát, hogy a rendszerbe beépítettek egy labdát is. Ez játéktér színű és hasonlóan a lövedékekhez, alapból 1 pixel széles, mozgatható és nyújtható. A nyújtás pont ugyanúgy történik így használhatjátok az előbbi táblázatot és a CTLPF regisztert. Magát a rajzolást pedig az ENABL D1-ével lehet kapcsolgatni.

Végszó

Megtanultuk hogyan használjuk a gép grafikus adottságait. Most jön a nehezebb feladat. Rá kell jönni hogyan lehet kihasználni azokat. Segítségképp javaslom pillantsatok rá erre a fórum beszélgetésre.

Sok fantáziát és kitartást! Legközelebb a mozgatásba megyünk bele.

Kellemes szenvedést! :P :)

Categories: Programozás, Retro, Tutorial

Leave a Reply

You must be logged in to post a comment.

Ugrás a lap tetejére Ugrás a lap aljára