GrafickΘ aplikace ve Visual C++ (4.)
V dneÜnφ lekci si koneΦn∞ vytvo°φme p°ednφ a zadnφ buffer a ukß₧eme si,
jak p°epsat funkci Run() tak, aby prohazovala oba povrchy. V²sledkem aplikace
nebude nic sv∞tobornΘho, proto₧e oba povrchy budou prßzdnΘ, ale i tak se
posuneme o notn² kus dßl.
4.2. Vytvo°enφ p°ednφho a zadnφho bufferu
Minule jsme si °φkali, ₧e zapisujeme data pouze do zadnφho bufferu
(back buffer) tzn. ₧e musφme zφskat ukazatel na tento buffer. Aby jsme tento
ukazatel mohli zφskat musφme nejd°φve vytvo°it p°ednφ buffer
(front buffer), proto₧e zadnφ je souΦßst tzv. flipovacφ smyΦky
nebo takΘ °et∞zce (flipping chain). DirectDraw poskytuje funkci
CreateSurface() , kterß je Φlenskou
funkcφ objektu DirectDraw, kter² jsme vytvo°ili u₧ minule.
HRESULT CreateSurface( LPDDSURFACEDESC lpDDSurfaceDesc,
LPDIRECTDRAWSURFACE FAR *
lplpDDSurface, IUnknown FAR *pUnkOuter);
Tato funkce mß t°i nßsledujφcφ parametry :
-
Ukazatel na strukturu typu DDSURFACEDESC2 ,
ve kterΘ jsou ulo₧eny parametry vytvß°enΘho povrchu, viz nφ₧e.
-
Ukazatel na ukazatel na vlastnφho povrch
-
Integrace COM. Prozatφm rovno NULL.
Vracφ DD_OK pokud je ·sp∞Ünß jinak n∞kterou z nßvratov²ch hodnot DirectDraw.
Struktura DDSURFACEDESC2
Tato struktura popisuje vlastnosti novΘho povrch. A¥ u₧ vytvß°φte p°ednφ,
Φi pomocn² buffer, budete ji vyu₧φvat. Obsahuje mnoho atribut∙, ale my
jich zatφm vyu₧ijeme jen mßlo. Zde p°edklßdßm ty nejd∙le₧it∞jÜφ:
-
DWORD dwSize ......................velikost struktury v bytech
-
DWORD dwFlags ........................udßvß, kterΘ Φleny jsou platnΘ
-
DWORD dwWidth ........................Üφ°ka vytvß°enΘho povrchu v pixelech
-
DWORD dwHeight .......................v²Üka vytvß°enΘho povrchu v pixelech
-
DWORD dwBackBufferCount ...............poΦet zadnφch buffer∙ p°ipojen²ch k p°ednφmu
-
DDSCAPS ddsCaps ..................dalÜφ struktura urΦujφcφ dalÜφ vlastnosti
P°φklad vytvo°enφ p°ednφho bufferu
Do t°φdy CControl p°idejte dv∞ ΦlenskΘ prom∞nnΘ typu
LPDIRECTDRAWSURFACE7 (IDirectDrawSurface7),
jednu pojmenujte m_lpDDSFront a druhou
m_lpDDSBack. Budou p°edstavovat
ukazatele na p°ednφ a zadnφ povrch. Pomocφ t∞chto ukazatel∙ budete pracovat s
povrchy.
Dßle p°idejte nßsledujφcφ k≤d do funkce DDInit().
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd, sizeof(ddsd)); //1
ddsd.dwSize = sizeof(ddsd); //2
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; //3
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
DDSCAPS_COMPLEX; //4
ddsd.dwBackBufferCount = 1; //5 mßme jeden zadnφ buffer !!!
if((dwResult = m_lpDD->CreateSurface(&ddsd, &m_lpDDSFront, NULL)) != DD_OK) {
TRACE("Cannot create front buffer due %d\n", dwResult);
return dwResult;
} //6
Nynφ mßme ukazatel na p°ednφ buffer : m_lpDDSPrimary
Postup :
-
Vynulovßnφ pam∞ti p°ed inicializacφ struktury. Tento bod nenφ nutn², ale obecn∞
se doporuΦuje, proto₧e tak m∙₧ete p°edejφt chybßm.
-
Inicializace prom∞nΘ dwSize na velikost struktury.
Naproti bodu 1 je tento krok naprosto nutn². Atribut
dwSize se objevφ i u jin²ch
struktur a v₧dy se musφ inicializovat na sprßvnou velikost struktury.
-
Nastavenφ p°φznak∙, kterΘ atributy struktury budou platnΘ. V naÜem
p°φpad∞ jsou to dssCaps a dwBackBufferCount
-
Inicializace Φlenu dssCaps Inicializace Φlenu dwBackBufferCount .
UrΦuje poΦet zadnφch buffer∙, v naÜem p°φpad∞ mßme jen jeden, ale m∙₧eme jich
pou₧φt vφce (triple buffer). -
Zavolßnφ funkce CreateSurface() se zadanou strukturou.
KoneΦnΘ vytvo°enφ povrchu, alokovßnφ pam∞ti pro povrch a vrßcenφ ukazatele.
K zφskßnφ ukazatele na zadnφ buffer je zde ovÜem jinß funkce, kterß
poΦφtß s tφm, ₧e je zadnφ buffer ve flippovacφ smyΦce :
HRESULT GetAttachedSurface( LPDDSCAPS2 lpDDSCaps,
LPDIRECTDRAWSURFACE7 FAR * lplpDDSurface);
D∙le₧itΘ je, ₧e tato funkce je Φlenskß funkce rozhranφ
IDirectDrawSurface7 a nikoliv (jak tomu bylo dosud)
IDirectDraw7 .
P°φklad vytvo°enφ zadnφho bufferu
DDSCAPS2 ddscaps;
ZeroMemory(&ddscaps, sizeof(ddscaps));//1
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;//2
if((dwResult = m_lpDDSFront->GetAttachedSurface(&ddscaps, &m_lpDDSBack)) != DD_OK)
{
TRACE("Cannot create back buffer due %d\n", dwResult);
return dwResult;
} //3
Postup :
-
Vynulovßnφ pam∞ti p°ed inicializaci struktury. Viz v²Üe. -
Nastavenφ, ₧e vytvß°en² povrch bude zadnφ (back).
Vidφte, ₧e nepou₧φvßme strukturu DDSURFACEDESC2,
ale jen jejφ Φßst DDSCAPS2. -
Zφskßnφ ukazatele na povrch: m_lpDDSBack .
VÜimn∞te si, ₧e nepou₧φvßme v²Üe zmφn∞nou funkci
CreateSurface(), je to z toho d∙vodu, ₧e vytvß°φme buffer ve flippovacφ
smyΦce. Povrch je vlastn∞ vytvo°en ji₧ naho°e a nynφ si ₧ßdßme jen o ukazatel na
n∞j.
4.2. P°epsßnφ funkce Run()
Minule jsme si ve t°φd∞ aplikace (CDirectDrawApp) p°ipravili funkci
Run(). V dneÜnφ lekci ji upravφme tak, aby volala funkci
UpdateFrame()
t°φdy CControl, kdy₧ smyΦka zprßv nep°ijφmß ₧ßdnΘ zprßvy.
Objekt CControl mßte vytvo°en² bu∩ p°φmo jako Φlenskou prom∞nnou
ve t°φd∞ aplikace nebo ji m∙₧ete vytvo°it
globßln∞ a funkci UpdateFrame() vytvo°it takΘ jako globßlnφ
funkci.
PotΘ bude vypadat funkce Run() nßsledovn∞.
int CDirectDrawApp::Run()
{
MSG msg;
while( 1 )
{
if( ::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
{
if( !::GetMessage( &msg, NULL, 0, 0 ) )
{
return msg.wParam;
}
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
else
{
m_theControl.UpdateFrame();
}
}
}
Nesmφte zapomenout vymazat p∙vodnφ jeden °ßdek tΘto funkce.
Funkce nynφ bude volat funkci UpdateFrame()
jak nejrychleji to p∙jde û pokud nemß co na prßci.
4.3. Funkce UpdateFrame()
Jako poslednφ v tΘto lekci jeÜt∞ n∞co napφÜeme do funkce
UpdateFrame() , aby se povrchy skuteΦn∞ prohazovaly.
void CControl::UpdateFrame()
{
if(m_lpDDSFront) {
m_lpDDSFront->Flip(NULL, DDFLIP_WAIT);
}
}
Zatφm zde nemßme ₧ßdnΘ ochrany proti ztracenφ povrchu atd.
Druh² parametr funkce Flip() znamenß,
₧e funkce poΦkß a₧ se ostatnφ blitovacφ akce dokonΦφ. P°φÜt∞ funkci dßle rozÜφ°φme.
4.4. Zßv∞r
Pokud dneÜnφ aplikaci zkompilujete, m∞lo
by se vßm p°epnout rozliÜenφ a obrazovka je zatφm bφlß.
Prohazovßnφ povrch∙ probφhß, ale nenφ vid∞t jeliko₧ majφ
oba buffery stejn² obsah. N∞kdy se m∙₧e stßt, ₧e v zadnφm
bufferu zbudou n∞jakΘ zbytky oken z Windows, proto₧e p°i
vytvß°enφ povrchu se m∙₧e alokovat pam∞¥, kterou p°edtφm
pou₧φvaly Windows a nechaly ji "prasßcky" nevymazanou.
P°φÜt∞ si vytvo°φme pomocnΘ buffery (off-screen surfaces) v systΘmovΘ pam∞ti,
do kter²ch ulo₧φme bitmapy, kterΘ potom budeme vykreslovat do zadnφho bufferu.
T∞Üφm se p°φÜt∞ nashledanou.
|