játékfejlesztés.hu
FórumGarázsprojectekCikkekSegédletekJf.hu versenyekKapcsolatokEgyebek
Legaktívabb fórumozók:
Asylum:    5448
FZoli:    4892
Kuz:    4455
gaborlabor:    4449
kicsy:    4304
TPG:    3402
monostoria:    3284
DMG:    3172
HomeGnome:    2919
Matzi:    2520

Pretender:    2498
szeki:    2440
Seeting:    2306
Geri:    2188
Orphy:    1893
Joga:    1791
Bacce:    1783
MaNiAc:    1735
ddbwo:    1625
syam:    1491
(VB) DX7 DirectDraw - 1. Teljesképernyős mód 2006.05.26 12:20


DirectDraw: 1. - Teljesképernyős mód


Bevezető és az elmélet


Ez a DirectDraw legáltalánosabb felhasználása, minden DirectX-et használó játék ami teljesképernyős módot használ DirectDraw-on keresztül teszi azt. (Az újabb DirectX verziókban nincs így mivel a DirectDraw és a Direct3D össze lett vonva - a ford.)

Teljesképernyős módban - az ablakos móddal ellentétben - az alkalmazás kizárólagosan birtokolja a képernyőt, így szinte teljes mértékben szabad kezet kapunk a számítógép grafikai erőforrásainak felhasználásában.

Teljesképernyős módban beállíthatjuk a felbontást (a képpontok számát) és a színmélységet (hogy hány színt jeleníthetünk meg).

Általánosan használt felbontások:
  • 320 x 240
  • 640 x 480
  • 800 x 600
  • 1024 x 768
Természetesen sokkal több van, a grafikus kártyák nem ritkán több mint 60 különböző módot ismernek (színmélységgel kombinálva).

Itt van még a színmélység. Ez leírja hány színt használhatunk egyszerre a képernyőn. Egyszerű a szabály:
Több szín = lassabb program + szebb grafika
Kevesebb szín = gyorsabb program + rosszabb grafika
Emlékezz erre amikor eldöntöd milyen képernyőmódot használsz: ha nem kell fotóminőségű grafika ne használj magas színmélységet. A következő lista tartalmazza a négy, teljesképernyős módban használható színmélységet:
  • 8 bit - 256 szín
  • 16 bit - 65536 szín
  • 24 bit - 16 millió szín *
  • 32 bit - 16,7 millió szín *
* Csak egy kevés különbség van a 24 és 32 bites színmélység között, tapasztald ki magad - előfordulhat hogy te látsz különbséget köztük míg mások nem.

Felületek. Ez az utolsó dolog amit meg kell értened mielőtt programozni kezdessz. A DirectDraw a felületek rendszerét használja a grafikai információk tárolására. Minden felület különböző méretű lehet, gyakorlatilag csak egy mutatót jelentenek a memória azon pontjára ahol az adatokat tároljuk. Ezek a felületek tartalmazhatják előre megrajzolt képfájlok adatait, vagy állhatnak ezek és beépített grafikai elemek (primitívek) keverékéből. Később ebbe jobban belemélyedünk, most csak annyit kell tudni mi az elsődleges- és a háttérpuffer. Az elsődleges puffer mindig akkora méretű mint a képernyő (lásd fent), és minden amit az elsődleges puffer tartalmaz megjelenik a felhasználó képernyőjén. A háttérpuffer az ahol a következő képkocka/képernyő elkészül. A háttérpuffert a villódzás kivédésére használjuk. A következő kép nagy eséllyel kis részekből áll, mindegyikük először a háttérpufferbe kerül és aztán az egész kép az elsődlegesbe. Ha közvetlen az elsődlegesbe kerülne minden, látszódna a kirajzolás folyamata.

A programkód
Ez a példa egy nagyon egyszerű directdraw alkalmazás lesz. Először létrehozzuk a DirectX komponenseket, majd beállítjuk a felbontást és a színmélységet, ezután létrehozunk egy felületet egy képnek amit a képernyőre rajzolunk.

1. rész: A DirectX típuskönyvtár csatlakoztatása


Mielőtt akármilyen DirectX programkódot írnál, csatlakoztatnod kell a DirectX-et a Visual Basichez. Ez egy típuskönyvtáron keresztül történik. Kövesd az alábbi lépéseket:

1, Ellenőrizd a Visual Basic verziószámát: Visual Basic 5 vagy afölötti verzióval boldogulsz csak. (A segédlet írásakor nem létezett még VB.NET, így az itt közölt programkódok nem kompatibilisek vele. Tehát VB5 vagy VB6 használható - a ford.)
2, Indítsd el a VB-t
3, Válassz új projektként Standard Exe-t
4, Menj a Project menübe majd kattints a References menüpontra. Találsz egy bejegyzést "DirectX7 for visual basic type library" címmel. Pipáld ki, majd kattints az OK gombra.
5, Most már használhatjuk a DirectX-et!

Problémák vannak?
1, Ha nincs a listán a DirectX 7 válaszd a Browse gombot, majd keresd meg a windowssystem könyvtárban.
2, Ha ezután sem találod győződj meg róla telepítve van-e!

Még egy információ: A programod felhasználójának is telepítenie kell a DirectX 7-et. (Megj.: A DirectX 9 visszafele kompatibilis, a telepítésekor bekerülnek a szükséges fájlok a rendszerbe. - a ford.)

Most már tényleg kezdhetjük!

2. Rész: Definiáljuk a DirectX és DirectDraw változókat


Ez az egész a főform deklarációs részébe jön:

Option Explicit 'A DirectX szereti ha az összes változója előre deklarált. Így biztos nem lesz deklarálatlan.

Dim binit As Boolean 'Egyszerű jelző (true/false) ami mutatja inicializált a program vagy sem. Ha az inicializálás sikeres True-ra vált (igaz). A program figyeli az állapotát. Ha False (hamis) állapotban próbálnánk rajzolni csak hibákat kapnánk.

Dim dx As New DirectX7 'A gyökérobjektum, innen hozzuk létre a DirectDraw-ot
Dim dd As DirectDraw7 'Ez a DirectDraw
Dim Mainsurf As DirectDrawSurface7 'Ez tartalmazza a bitképünket
Dim primary As DirectDrawSurface7 'Ez jelenti a képernyőt - lásd fent
Dim backbuffer As DirectDrawSurface7 'Ő is említve volt korábban...
Dim ddsd1 As DDSURFACEDESC2 'leírja az elsődledes felületet
Dim ddsd2 As DDSURFACEDESC2 'leírja a bitképet amit betöltünk
Dim ddsd3 As DDSURFACEDESC2 'leírja a képernyő méretét

Dim brunning As Boolean 'másik jelző ami mutatja fut-e a játék fő ciklusa
Dim CurModeActiveStatus As Boolean 'Ellenőrzi hogy jó képernyőmódot használunk-e még
Dim bRestore As Boolean 'ha nem ez a jelző mutatja hogy vissza kell állítani a képernyőmódot


3. rész: A DirectDraw inicializálása


Most hogy minden változónk megvan elkezdhetjük használni őket. Elsőként létre kell hozni a DirectDraw objektumot a DirectX objektumból. Aztán beállítjuk a képernyőmódot. Ennél a pontnál láthatjuk hogy a képernyő felbontást vált. Ezután létrehozzuk az elsődleges és háttérpuffert. Ha a központi kód inicializálódott, betöltjük a képet a felületbe majd elindul a játék fő ciklusa. A fő ciklusra ügyeljünk: minél gyorsabb annál gyorsabban fut a játékunk.


Sub Init()
On Local Error GoTo errOut 'Bármilyen hiba esetén leállítjuk a programot.

Set dd = dx.DirectDrawCreate("") 'A ("") azt jelenti hogy az alapértelmezett drivert haszáljuk.
Me.Show 'maximalizálja a formot és így biztos látható lesz

'Az első sor csatolja a DirectDraw objetumot a formhoz, valamint a paramétereket is beállítja:
'ami fontos nekünk belőle az a DDSCL_FULLSCREEN és a DDCSL_EXCLUSIVE.
'Fontos kizárólagossá (exclusive) tenni a programot, mert így amíg fut senki sem
'használhatja a DirectDraw-ot, és a Windows több időt szakít rá
Call dd.SetCooperativeLevel(Me.hWnd, DDSCL_FULLSCREEN Or DDSCL_ALLOWMODEX Or DDSCL_EXCLUSIVE)
'Itt látjuk a változást. Az áll itt hogy szeretnének egy képernyőmódot
'640x480 felbontással és 16 bit színmélységgel (65536 szín). A negyedik argumentum ("0") a
'frissítési gyakoriság. Ha 0-nak hagyjuk a DirectX beállítja az optimálisat. Ajánlott nem törődni vele.
'Az ötödik paraméter akkor kap szerepet ha speciális felbontásokat használnánk
'(különösen a régi alacsony felbontásoknál)
Call dd.SetDisplayMode(640, 480, 16, 0, DDSDM_DEFAULT)

'Lekérjük a képernyő-felületet és készítünk háttérpuffert is.
ddsd1.lFlags = DDSD_CAPS Or DDSD_BACKBUFFERCOUNT
ddsd1.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE Or DDSCAPS_FLIP Or DDSCAPS_COMPLEX
ddsd1.lBackBufferCount = 1
Set primary = dd.CreateSurface(ddsd1)

'Most jön a háttérpuffer
Dim caps As DDSCAPS2
caps.lCaps = DDSCAPS_BACKBUFFER
Set backbuffer = primary.GetAttachedSurface(caps)
backbuffer.GetSurfaceDesc ddsd3

'Inicializáljuk a felületeket
InitSurfaces

'Ez a főciklus. Addig fut amíg brunning=true
binit = True
brunning = True
Do While brunning
blt
DoEvents 'KÖTELEZŐ a DoEvents használata különben túlterheled a rendszert
'a programod csak üzeneteket küld a Windowsnak és a DirtectX-nek, és ha nem adsz nekik időt
'befejezni a munkájukat lefagyhatnak.
'a doevents megengedi a windowsnak hogy tegye amit tennie kell.
Loop

errOut:
'Ha hiba van bezárjuk a programot.
EndIt
End Sub

4. rész: A felületek inicializálása


Most hogy a DirectDraw inicializálódott be kell töltenünk a felületeket és a képeket a memóriába. Elsőként meg kell értened a használt leírókat (most ddsd1-3).

Észrevehetted, hogy a leírók amik az elsődleges és a háttérpuffer létrehozására voltak használva adatstruktúrák amik a felület információit tárolják. Mielőtt létrehozol egy felületet kitöltöd az egyiket, megadod a viselkedési módját és egyebeket. A viselkedési módok konstansok formájában állnak rendelkezésre - például a DDSCAPS_PRIMARYSURFACE azt mondja a DirectDraw-nak hogy egy elsődleges felületet szeretnél létrehozni. Rengeteg különböző konstans van ami ide jöhet, túl sok hogy itt tárgyaljuk. Pillanatnyilag elegendőek lesznek a fentebb és lentebb látható konstansok. A következő rész, bár fentebb nem használtuk, a méretmegadás. Meg kell mondanod képpontokban a DirectDraw-nak mekkora felületet szeretnél. Ha a kép a felületbe töltődik a DirectDraw megnyújtja hogy igazodjon a mérethez amit megadtál, tehát hogy pontos másolat legyen a kép méreteit kell megadnod. Erre látható itt példa:


Sub InitSurfaces()
'Ez a programrész kicsinek tűnhet, de ha nagyobb programot írsz akár
'60-120 mp-ig tarthat a végrehajtása és több 1000 sor kód lehet itt.

Set Mainsurf = Nothing 'Bár amikor először hívjuk az eljárást ez a változó üres,
'mégis ki kell üríteni. Ahogy a blt eljárásban láthatod, a program
'megpróbálhatja újratölteni a felületeket, amikor is a "mainsurf" objektum
'tartalmaz információkat. Ha újra próbálunk készíteni egy felületet ami már tartalmaz információt
'a DirectDraw kiakad, mert először ki kell takarítani a puffert.

'kép töltése a felületre - backdrop.bmp
ddsd2.lFlags = DDSD_CAPS Or DDSD_HEIGHT Or DDSD_WIDTH 'alapértelmezett jelzők (konstansok)
ddsd2.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
'Egy offscreenplain annyit jelent, hogy
'a felhasználó sose látja a felületet, csak a memória egy területe.
ddsd2.lWidth = ddsd3.lWidth 'a ddsd3 struktúra már tartalmazza a képernyő méretét
'Átírhatnánk 640-ra és 480-ra - ugyanaz lenne az eredmény
ddsd2.lHeight = ddsd3.lHeight
'Itt készül el a felület. A DDraw objektumot kell használnod hogy készíts egy
'felületet a megadott fájlból és a fenti leíróból
Set Mainsurf = dd.CreateSurfaceFromFile(App.Path & "backdrop.bmp", ddsd2)
End Sub


Egy megjegyzés a Backdrop.bmp-hez.
Csak bitképeket használhatsz felület készítésére. A DirectDraw nem támogatja a .jpg vagy .gif (vagy más) képtípusok betöltését. Ezzel csak egy probléma van: a fájlméret. Ha letöltessz egy példát erről az oldalról észreveheted hogy egy kétszínű bitkép - hogy a fájlméret alacsony maradjon. Egy 640*480 méretű bitkép maximális színmélységgel 500kB körül lenne, míg egy vele megegyező Jpg 37kB körül. Itt egy segédlet arról hogyan tölthetők be jpg-k és gif-ek egy DirectDraw felületbe.

5. lépés - Rajzolás a képernyőre


Most jön el az a rész amikor végre megjelenik valami előttünk. Most eljött az ideje hogy tanuljunk valamit a blittelésről. (Blit=bitblock transfer, képet tartalmazó memóriarészlet másolása. Nincs rá szép magyar kifejezés. - a ford.)

A blittelés az amikor egy felület részét vagy egészét egy másik felületbe másoljuk. A másolandó területet egy téglalap írja le - a bal felső és a jobb alsó sarkokat kell megadnod. Ötféle módja van a blittelésnek:


  • Blt(destRect As RECT, ddS As DirectDrawSurface7, srcRect As RECT, flags As CONST_DDBLTFLAGS) As Long
    A biztonságosabb módszer, bár láthatóan lassabb. Meg kell adnod a függvénynek a cél és forrás területet (téglalapot). Hasznos, mert alapvető nyújtási műveleteket végezhetsz így, pl. ha a forrás terület 100x100 méretű, a cél meg 200x200 a DirectDraw a 100x100-as részt 200x200-ra nyújta - megduplázza a területet.

  • BltColorFill(destRect As RECT, fillvalue As Long) As Long
    Ez éppen nem másolja a képet sehova, hanem kitölti a területet a megadott színnel.

  • BltFast(dx As Long, dy As Long, ddS As DirectDrawSurface7, srcRect As RECT, trans As CONST_DDBLTFASTFLAGS) As Long
    A legtöbbször ezt az eljárást használjuk mert gyors. Nem használható transzformációkra - egy téglalapot másol a célként adott helyre ugyanakkora méretben. Ezt használjuk a következő kódban.

  • BltFx(destRect As RECT, ddS As DirectDrawSurface7, srcRect As RECT, flags As CONST_DDBLTFLAGS, BltFx As DDBLTFX) As Long
    Ezt használjuk különböző transzformációk elvégzésére, például: alpha-blending (átlátszóság), tükrözés, nyújtás és a többi. Nagyon hasonlít a blt függvényre.

  • BltToDC(hdc As Long, srcRect As RECT, destRect As RECT)
    Ez a DirectDraw és a Windows grafikus funkciói közötti együttműködésért van. Ha használtál komolyabban Windows API-t akkor használhattál már DC felületet néhol: ez lehetővé teszi a másolást egy DirectDraw felületről DC-re.


A következő eljárás mindig meg lesz hívva a főciklusban. Ezért fontos hogy hibamentes legyen és olyan gyors amilyen csak lehet. Akármilyen lassú kód van itt az egész játékot belassítja.

Sub blt()
'még egyszer: ez az eljárás egyszerűnek néz ki: az is!
'meg kell próbálnod olyan rövidnek és gyorsnak tartani ahogy lehetséges

On Local Error GoTo errOut 'Ha hiba van nem teszünk semmit, átugorjuk az egész eljárást
If binit = False Then Exit Sub 'Ha nem inicializálódtunk nem próbálunk meg semmit.

'Minden rajzoló függvénynek van visszatérési értéke, tárolnunk kell valahol.
'Ezzel az értékkel megnézhetjük volt-e hiba.
Dim ddrval As Long
'a RECT a már említett téglalap a területnek
Dim rBack As RECT

'ez nem engedi a blittelést ha elvesztettük a felületeket (alt-tab)
bRestore = False
Do Until ExModeActive
DoEvents
bRestore = True
Loop

'ha elvesztettük és visszakaptuk a felületeket, visszaállítjuk őket.
DoEvents
If bRestore Then
bRestore = False
dd.RestoreAllSurfaces 'ezt csak a memóriát adja vissza.
'ettől még újra kell tölteni a felületeket.
InitSurfaces 'felületek inicializálása ha elvesztek
End If


'lekérjük a képernyőterületet ahol az ablakunk van
'ez a képernyő méretét adja a téglalapnak
rBack.Bottom = ddsd3.lHeight
rBack.Right = ddsd3.lWidth

'blittelés a háttérpufferbe a felületünktől
'a bitképünk az ablak fölött jelenik meg
'Ez a képernyőre blittel a képernyő 0,0 pontjától. A DDBLTFAST_WAIT
'konstans jelzi a Directdraw-nak hogy várjon ha a blitter foglalt a hívás pillanatában
ddrval = backbuffer.BltFast(0, 0, Mainsurf, rBack, DDBLTFAST_WAIT)


'A háttérpuffer képernyőre másolása ("flipping")
primary.Flip Nothing, DDFLIP_WAIT
'Most végeztünk egy körrel, látnunk kellene valamit.

errOut: 'Átugrunk mindent ha hiba van. Ne rakj ide üzenetablakot:
'ha 100 fps-sel fut a programod 100 ablak jelenik meg másodpercenként...
End Sub


6. lépés: Utolsó símítások


Megcsináltuk a kemény DirectDraw kód megírását. Most néhány utolsó símításra lesz szükség hogy használható legyen a program. A legfontosabb a DirectDraw bezárása...

Sub EndIt()
'Ez az eljárás hívódik meg a fő ciklus végén, illetve akkor ha hiba történik.
'Bár boldogulhatsz enélkül, jó ha megtartod: kiszámíthatatlan eredményt kaphatsz ha hagyod hogy a Windows takarítson utánad


'Ez visszaállítja az alapértelmezett (Windows) felbontást
Call dd.RestoreDisplayMode
'Ez jelzi a Windowsnak/DirectXnek hogy nem kérünk többé kizárólagos hozzáférést a grafikai funkciókhoz
Call dd.SetCooperativeLevel(Me.hWnd, DDSCL_NORMAL)
'A program leállítása
End
End Sub


Private Sub Form_Click()
'A formra kattintás esetén a program bezáródik.
'Mivel a form maximalizált mindegy hova kattintassz.

EndIt
End Sub

Private Sub Form_Load()
'Elindítja a programot
Init
End Sub

Private Sub Form_Paint()
'Ha a Windows "Paint" üzenetet küld, lefordítjuk a DirectDraw nyelvére
blt
End Sub

Function ExModeActive() As Boolean
'Ezzel teszteljük jó felbontásban vagyunk-e.
Dim TestCoopRes As Long
TestCoopRes = dd.TestCooperativeLevel
If (TestCoopRes = DD_OK) Then
ExModeActive = True
Else
ExModeActive = False
End If
End Function



KÉSZ!


Most van egy teljesképernyős DirectDraw alkalmazás vázad. Ez az egyszerű alkalmazás könnyen továbbfejleszthető egy professzionálissá. Ehhez két dolog kell
- Több felület
- Jobb blittelő eljárás (ami több dolgot tud)



Ez az a váz ahonnan az összes DirectDraw alkalmazásomat kifejlesztem: ezt töltöm be és írom át. Gondolj rá te is így!

Bizonyosodj meg hogy MINDENT megértettél ebből a részből - ne várd hogy sokáig jutsz a DirectDraw/3D-ben ez alap tudás nélkül. A többi segédlet a DirectDraw szekcióban (az Ablakos mód kivételével) erre a tudásra és szerkezetre épít.

Kapcsolódó linkek:
A DirectX4VB oldal
Az eredeti cikk a DirectX4VB oldalon. (Jack Hoxley: DirectDraw: FullScreen Mode)
A fordításban a következő cikk is szerepel: Jack Hoxley: Setting Up a DirectX Application
Fájl : (VB) DX7 DirectDraw - 1. Teljesképernyős mód
Méret: 0,007 Mb - Letöltve : 955

Értékelés: 10.00

Új hozzászólás
valibali          2008.05.31 00:48
csatlkozom
szeki          2006.05.26 14:18
öregem! Na ezt nevezem cikknek. Ilyenek kellenek a kezdőknek.
Így tovább...