📄 donuts.c
字号:
lpCube->lpVtbl->Release( lpCube );
if( lpSphere != NULL )
lpSphere->lpVtbl->Release( lpSphere );
if( lpShip != NULL )
lpShip->lpVtbl->Release( lpShip );
if( lpNum != NULL )
lpNum->lpVtbl->Release( lpNum );
if( lpBackBuffer != NULL )
lpBackBuffer->lpVtbl->Release( lpBackBuffer );
if( lpFrontBuffer != NULL )
lpFrontBuffer->lpVtbl->Release( lpFrontBuffer );
if( lpArtPalette != NULL )
lpArtPalette->lpVtbl->Release( lpArtPalette );
if( lpSplashPalette != NULL )
lpSplashPalette->lpVtbl->Release( lpSplashPalette );
if( lpDD != NULL )
lpDD->lpVtbl->Release( lpDD );
if (DL.next != NULL)
{
while( DL.next != &DL )
{
DeleteFromList( DL.next );
}
}
}
BOOL InitializeGame( void )
{
DDCAPS ddcaps;
HRESULT ddrval;
DDSURFACEDESC ddsd;
DDSURFACEDESC DDSurfDesc;
DDCAPS ddCaps;
DDCAPS ddHelCaps;
if (bWantSound)
{
if (! InitializeSound()) {
return FALSE;
}
}
score = 0;
if( bTest )
ShowLevelCount = 1000;
// Initialize the display list to point at itself. This denotes an empty
// list. We need to do this here because if CleanupAndExit/DestroyGame
// will attempt to walk the display list and delete records.
DL.next = DL.prev = &DL;
ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
if( ddrval != DD_OK )
return CleanupAndExit(TEXT("DirectDrawCreate Failed!"));
ddrval = lpDD->lpVtbl->SetCooperativeLevel( lpDD, hWndMain, DDSCL_FULLSCREEN );
if( ddrval != DD_OK )
return CleanupAndExit(TEXT("SetCooperativeLevel Failed"));
lpDD->lpVtbl->GetCaps(lpDD, &ddCaps, &ddHelCaps);
if (!(ddCaps.ddsCaps.dwCaps & DDSCAPS_BACKBUFFER) || !(ddCaps.ddsCaps.dwCaps & DDSCAPS_FLIP))
{
bSingleBuffer = TRUE;
}
// Get mode info.
memset(&DDSurfDesc, 0, sizeof(DDSurfDesc));
DDSurfDesc.dwSize = sizeof(DDSurfDesc);
ddrval = lpDD->lpVtbl->GetDisplayMode( lpDD, &DDSurfDesc );
if ( ddrval != DD_OK )
return CleanupAndExit(TEXT("GetDisplayMode Failed!"));
ScreenX = DDSurfDesc.dwWidth;
ScreenY = DDSurfDesc.dwHeight;
ScreenBpp = DDSurfDesc.ddpfPixelFormat.dwRGBBitCount;
// check the color key hardware capabilities
dwTransType = DDBLT_KEYSRC;
ddcaps.dwSize = sizeof( ddcaps );
// Create surfaces
memset( &ddsd, 0, sizeof( ddsd ) );
ddsd.dwSize = sizeof( ddsd );
if (bSingleBuffer)
{
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
}
else
{
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP;
ddsd.dwBackBufferCount = 1;
}
ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpFrontBuffer, NULL );
if (ddrval != DD_OK)
{
if (ddrval == DDERR_NOFLIPHW)
return CleanupAndExit(TEXT("******** Display driver doesn't support flipping surfaces. ********"));
return CleanupAndExit(TEXT("CreateSurface FrontBuffer Failed!"));
}
if (bSingleBuffer)
{
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
ddsd.dwWidth = ScreenX;
ddsd.dwHeight = ScreenY;
ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpBackBuffer, NULL );
if (ddrval != DD_OK)
{
return CleanupAndExit(TEXT("CreateSurface BackBuffer Failed!"));
}
}
else
{
ddrval = lpFrontBuffer->lpVtbl->EnumAttachedSurfaces( lpFrontBuffer, &lpBackBuffer, EnumFunction);
if (ddrval != DD_OK)
{
return CleanupAndExit(TEXT("EnumAttachedSurfaces Failed!"));
}
}
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
ddsd.dwWidth = 320;
ddsd.dwHeight = 384;
ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpDonut, NULL );
if( ddrval != DD_OK )
return CleanupAndExit(TEXT("CreateSurface lpDonut Failed!"));
ddsd.dwHeight = 128;
ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpPyramid, NULL );
if( ddrval != DD_OK )
return CleanupAndExit(TEXT("CreateSurface lpPyramid Failed!"));
ddsd.dwHeight = 32;
ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpCube, NULL );
if( ddrval != DD_OK )
return CleanupAndExit(TEXT("CreateSurface lpCube Failed!"));
ddsd.dwHeight = 32;
ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpSphere, NULL );
if( ddrval != DD_OK )
return CleanupAndExit(TEXT("CreateSurface lpSphere Failed!"));
// Set the background color fill color
ddsd.dwHeight = 256;
ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpShip, NULL );
if( ddrval != DD_OK )
return CleanupAndExit(TEXT("CreateSurface lpShip Failed!"));
ddsd.dwHeight = 16;
ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpNum, NULL );
if( ddrval != DD_OK )
return CleanupAndExit(TEXT("CreateSurface lpNum Failed!"));
if( !RestoreSurfaces() )
return CleanupAndExit(TEXT("RestoreSurfaces Failed!"));
DL.type = OBJ_SHIP;
DL.surf = lpShip;
lastTickCount = GetTickCount();
if(bTest)
{
ProgramState = PS_ACTIVE;
setup_game();
}
else
{
ProgramState = PS_SPLASH;
}
return TRUE;
}
BOOL CleanupAndExit( TCHAR *err)
{
// Note: We're using OutputDebugString here instead of RETAILMSG to allow the user
// to read the error message, even when the sample app is running on a retail
// build of the OS. Not seeing a message in the debugger when the app mysteriously
// fails (as in the case when there is no hardware flipping support for example)
// has led to a lot of confusion.
HRESULT hr = StringCchPrintf (
DebugBuf,
sizeof(DebugBuf)/sizeof(DebugBuf[0]),
TEXT("%s: CleanupAndExit err = %s\n"),
cszAppName,
err);
if (SUCCEEDED(hr))
OutputDebugString(DebugBuf);
else
OutputDebugString(TEXT("DONUTS: Internal application error\n"));
DestroyGame();
return FALSE;
}
void bltSplash( void )
{
HRESULT ddrval;
HBITMAP hbm;
hbm = (HBITMAP)LoadImage( hInst, TEXT("SPLASH"), IMAGE_BITMAP, 0, 0, 0 );
if ( NULL == hbm )
return;
// if the surface is lost, DDCopyBitmap will fail and the surface will
// be restored in FlipScreen.
ddrval = DDCopyBitmap( lpBackBuffer, hbm, 0, 0, 0, 0 );
DeleteObject( hbm );
FlipScreen();
}
//
// play a sound, but first set the panning according to where the
// object is on the screen. fake 3D sound.
//
void playPanned(HSNDOBJ hSO, DBLNODE *object)
{
SndObjPlayPanned(hSO, (LONG)((20000.0 * ((object->dst.right + object->dst.left) / 2) / ScreenX) - 10000.0));
}
void UpdateFrame( void )
{
switch( ProgramState )
{
case PS_SPLASH:
// display the splash screen
bltSplash();
return;
case PS_ACTIVE:
UpdateDisplayList();
CheckForHits();
DrawDisplayList();
if ( isDisplayListEmpty() )
{
if(bWantSound)
{
SndObjStop(hsoEngineIdle);
SndObjStop(hsoEngineRev);
}
bPlayIdle = FALSE;
bPlayRev = FALSE;
lastThrust = lastShield = FALSE;
ProgramState = PS_BEGINREST;
restCount = GetTickCount();
initLevel( ++level );
}
return;
case PS_BEGINREST:
if(bWantSound)
{
SndObjPlay(hsoBeginLevel);
}
ProgramState = PS_REST;
//
// FALLTHRU
//
case PS_REST:
if( ( GetTickCount() - restCount ) > ShowLevelCount )
{
bPlayIdle = TRUE;
lastTickCount = GetTickCount();
ProgramState = PS_ACTIVE;
}
else
{
DisplayLevel();
}
return;
}
}
void DisplayLevel( void )
{
TCHAR buf[10];
EraseScreen();
buf[0] = 10 + TEXT('0');
buf[1] = 11 + TEXT('0');
buf[2] = 12 + TEXT('0');
buf[3] = 11 + TEXT('0');
buf[4] = 10 + TEXT('0');
buf[5] = TEXT('\0');
bltScore( buf, ScreenX/2-64, ScreenY/2-8 );
buf[0] = level / 100 + TEXT('0');
buf[1] = level / 10 + TEXT('0');
buf[2] = level % 10 + TEXT('0');
buf[3] = TEXT('\0');
bltScore( buf, ScreenX/2+22, ScreenY/2-8 );
FlipScreen();
}
void bltScore( TCHAR *num, int x, int y )
{
TCHAR *c;
RECT src;
RECT dest;
int i;
HRESULT ddrval;
for(c=num; *c != TEXT('\0'); c++)
{
while( 1 )
{
i = *c - TEXT('0');
src.left = i*16;
src.top = 0;
src.right = src.left + 16;
src.bottom = src.top + 16;
dest.left = x;
dest.top = y;
dest.right = dest.left + (src.right - src.left);
dest.bottom = dest.top + (src.bottom - src.top);
ddrval = lpBackBuffer->lpVtbl->Blt( lpBackBuffer, &dest, lpNum, &src, dwTransType, NULL );
if( ddrval == DD_OK )
{
break;
}
if( ddrval == DDERR_SURFACELOST )
{
if( !RestoreSurfaces() )
return;
}
if( ddrval != DDERR_WASSTILLDRAWING )
{
return;
}
}
x += 16;
}
}
void CheckForHits( void )
{
LPDBLNODE bullet, target, save;
int frame, x, y, l, t;
BOOL hit;
// update screen rects
target = &DL;
do
{
frame = (DWORD)target->frame;
switch( target->type )
{
case OBJ_DONUT:
target->dst.left = (DWORD)target->posx;
target->dst.top = (DWORD)target->posy;
target->dst.right = target->dst.left + 64;
target->dst.bottom = target->dst.top + 64;
target->src.left = 64 * (frame % 5);
target->src.top = 64 * (frame /5);
target->src.right = target->src.left + 64;
target->src.bottom = target->src.top + 64;
break;
case OBJ_PYRAMID:
target->dst.left = (DWORD)target->posx;
target->dst.top = (DWORD)target->posy;
target->dst.right = target->dst.left + 32;
target->dst.bottom = target->dst.top + 32;
target->src.left = 32 * (frame % 10);
target->src.top = 32 * (frame /10);
target->src.right = target->src.left + 32;
target->src.bottom = target->src.top + 32;
break;
case OBJ_SPHERE:
target->dst.left = (DWORD)target->posx;
target->dst.top = (DWORD)target->posy;
target->dst.right = target->dst.left + 16;
target->dst.bottom = target->dst.top + 16;
target->src.left = 16 * (frame % 20);
target->src.top = 16 * (frame /20);
target->src.right = target->src.left + 16;
target->src.bottom = target->src.top + 16;
break;
case OBJ_CUBE:
target->dst.left = (DWORD)target->posx;
target->dst.top = (DWORD)target->posy;
target->dst.right = target->dst.left + 16;
target->dst.bottom = target->dst.top + 16;
target->src.left = 16 * (frame % 20);
target->src.top = 16 * (frame /20);
target->src.right = target->src.left + 16;
target->src.bottom = target->src.top + 16;
break;
case OBJ_SHIP:
target->dst.left = (DWORD)target->posx;
target->dst.top = (DWORD)target->posy;
target->dst.right = target->dst.left + 32;
target->dst.bottom = target->dst.top + 32;
if( lastShield )
target->src.top = 32 * (frame / 10) + 128;
else
target->src.top = 32 * (frame /10);
target->src.left = 32 * (frame % 10);
target->src.right = target->src.left + 32;
target->src.bottom = target->src.top + 32;
break;
case OBJ_BULLET:
frame = (DWORD)target->frame/20 % 4;
target->dst.left = (DWORD)target->posx;
target->dst.top = (DWORD)target->posy;
target->dst.right = target->dst.left + 3;
target->dst.bottom = target->dst.top + 3;
target->src.left = BULLET_X + frame*4;
target->src.top = BULLET_Y;
target->src.right = target->src.left + 3;
target->src.bottom = target->src.top + 3;
break;
}
target = target->next;
}
while( target != &DL );
bullet=&DL;
do
{
hit = FALSE;
if((bullet->type != OBJ_BULLET) && (bullet != &DL))
{
bullet = bullet->next;
continue;
}
x = (bullet->dst.left + bullet->dst.right) / 2;
y = (bullet->dst.top + bullet->dst.bottom) / 2;
for(target=DL.next; target != &DL; target = target->next)
{
if( ( target->type != OBJ_DONUT ) &&
( target->type != OBJ_PYRAMID ) &&
( target->type != OBJ_SPHERE ) &&
( target->type != OBJ_CUBE ) )
continue;
if( (x >= target->dst.left) &&
(x < target->dst.right) &&
(y >= target->dst.top) &&
(y < target->dst.bottom) )
{
if ((bullet != &DL) || !lastShield)
{
// the bullet hit the target
switch( target->type )
{
case OBJ_DONUT:
if(bWantSound)
{
playPanned(hsoDonutExplode, target);
}
addObject( OBJ_PYRAMID, target->dst.left,
target->dst.top, -1.0, -1.0 );
addObject( OBJ_PYRAMID, target->dst.left,
target->dst.top, -1.0, -1.0 );
addObject( OBJ_PYRAMID, target->dst.left,
target->dst.top, -1.0, -1.0 );
score += 10;
break;
case OBJ_PYRAMID:
if(bWantSound)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -