Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: C++: Lumisade-efekti

shadez [08.05.2003 20:35:30]

#

Toistaa ruudulla kaunista lumisadekuviota, aivan kuten sinun televisiosi. Varoitus! Ohjelma vaatii väh. Windows 95, ja se käyttää directdrawia

#include <windows.h>
#include <ddraw.h>
#include <mmsystem.h>


HWND hWnd;
LPDIRECTDRAW lpDD;
LPDIRECTDRAWSURFACE surf;
DDSURFACEDESC ddsd;
unsigned int *dBuffer;

#define WIDTH 320
#define HEIGHT 240
#define MAX 320*240

inline static void* __cdecl ALLOC(unsigned int cb)
{
	return HeapAlloc(GetProcessHeap(),0,cb);
}

inline unsigned int fastrand()
{
	static int seed=0xcafebabe;
	return (unsigned)(seed=seed*0x97654321+1)>>17;
}
inline unsigned int rgb(short r, short g, short b)
{
	return ((r<<16)+(g<<8)+b);
}


//kääntäjän juttuja
#if defined(__cplusplus)
    extern "C" {
#endif

	extern const int _fltused = 1;

#if defined(__cplusplus)
	}
#endif

void mainCRTStartup()
{
	hWnd = CreateWindowEx(WS_EX_TOPMOST, "STATIC",
                             0,
                             WS_POPUP | WS_VISIBLE,
                             0, 0,
                             WIDTH, HEIGHT,
                             0, 0, 0, 0);
	ShowCursor(FALSE);
	ShowWindow(hWnd,SW_SHOW);
	DirectDrawCreate(NULL,&lpDD,NULL);
	lpDD->SetCooperativeLevel(hWnd,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN);
	lpDD->SetDisplayMode(WIDTH,HEIGHT,32);
	ddsd.dwSize=sizeof(ddsd);
	ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
	ddsd.dwBackBufferCount = 1;
	ddsd.ddsCaps.dwCaps = DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY | DDSCAPS_PRIMARYSURFACE;
	lpDD->CreateSurface(&ddsd,&surf,NULL);
	dBuffer=(unsigned int*)ALLOC(320*240*4);

	bool done=false;

	while(!done)
	{

		static float kak;
		kak+=0.10f;
		for(int c=0;c<MAX;c++)
		{
			int ja=fastrand()%255;
			dBuffer[c]=rgb(ja,ja,ja);
		}


		surf->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);

		int w=ddsd.dwWidth;
		int h=ddsd.dwHeight;
		int bpl=ddsd.lPitch;
		int bpp=32;
		char *dest = (char *) ddsd.lpSurface;
		char *src = (char *)dBuffer;
		_asm
		{
			mov edi,dest
			mov esi,src

			mov eax,w
			shl eax,2
			mov ebx,bpl
			sub ebx,eax
			mov eax,w
			mov ecx,h
        looppi:
			mov edx,ecx
			mov ecx,eax
			rep movsd
			add edi,ebx

		    mov ecx,edx
	        loop looppi
		}
		surf->Unlock(NULL);
		if(GetAsyncKeyState(VK_ESCAPE) & 0x8000)
		{
			done=true;
		}
	}
	DestroyWindow(hWnd);
}

Tatu Peltola [10.05.2003 12:26:17]

#

Joo.. Tästähän voi opetella DirectDraw-ohjelmointia :-)

arcatan [11.05.2003 09:08:21]

#

lainaus:

Varoitus! Ohjelma vaatii väh. Windows 95, ja se käyttää directdrawia

Heh! Aika hyvä huomio tuo sana varoitus.

Vaan en nyt tiedä mitä tuo inline-asm varsinaisesti tekee, mutta eikö se nyt olisi parempi toteuttaa C:llä kun nyt kerran tämä on niinkuin esimerkki. Tietysti ehkä nopeus kärsii. Ehkä. En tiedä.

shadez [11.05.2003 12:45:11]

#

Koodi on tarkoitettu ripattavaksi, eikä siitä kannata oppia mitään. Siksi tarjoankin Teille talon parasta, inline asm koodia. Sen avulla kyllä pikselit hyrräävät ruudulla kuin kiimaiset koirat :)

Ande [30.05.2003 10:39:51]

#

Inline-assyn käyttö on ihan järjetöntä tuollaisissa paikoissa (ja melkein kaikissa muissakin paikoissa). Koodin ymmärrettävyys lähenee nollaa ja vaikutus nopeuteen on todennäköisesti negatiivinen. Kyllä ne nykykääntäjät tuottavat aivan riittävän hyvää koodia ja todennäköisesti tuo sinunkin pätkäsi toimisi vain nopeammin, jos antaisit kääntäjän tehdä optimoinnit.

Enkä tiedä DirectX-ohjelmoinnista paljonkaan, mutta täytyykö siinä tosiaankin manuaalisesti itse kopioida surfacen data? Luulisi että siellä on joku blit-funktio, joka tekisi täsmälleen saman ja paljon nopeammin.

tejeez [22.07.2005 19:21:23]

#

Ei lumisadekuvio oo kaunista eikä minulla oo televisioo :< virheellinen kuvaus :<

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta