mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1887 lines
48 KiB
1887 lines
48 KiB
/*==========================================================================
|
|
*
|
|
* Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: roids.c
|
|
* Content: Shoot-em-up game
|
|
*
|
|
* @@BEGIN_MSINTERNAL
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 17-jul-95 kylej initial
|
|
*
|
|
* @@END_MSINTERNAL
|
|
*
|
|
***************************************************************************/
|
|
#include "roids.h"
|
|
|
|
|
|
LPDIRECTDRAWSURFACE lpFrontBuffer;
|
|
LPDIRECTDRAWSURFACE lpBackBuffer;
|
|
LPDIRECTDRAWSURFACE lpDonut;
|
|
LPDIRECTDRAWSURFACE lpPyramid;
|
|
LPDIRECTDRAWSURFACE lpCube;
|
|
LPDIRECTDRAWSURFACE lpSphere;
|
|
LPDIRECTDRAWSURFACE lpShip;
|
|
LPDIRECTDRAWSURFACE lpNum;
|
|
LPDIRECTDRAW lpDD;
|
|
LPDIRECTDRAWPALETTE lpArtPalette;
|
|
LPDIRECTDRAWPALETTE lpSplashPalette;
|
|
BOOL bSoundEnabled = FALSE;
|
|
BOOL bPlayIdle = FALSE;
|
|
BOOL bPlayBuzz = FALSE;
|
|
BOOL bPlayRev = FALSE;
|
|
DWORD lastInput = 0;
|
|
BOOL lastThrust = FALSE;
|
|
BOOL lastShield = FALSE;
|
|
int showDelay = 0;
|
|
HWND hWndMain;
|
|
BOOL bShowFrameCount=TRUE;
|
|
BOOL bIsActive;
|
|
BOOL bMouseVisible;
|
|
DWORD dwFrameCount;
|
|
DWORD dwFrameTime;
|
|
DWORD dwFrames;
|
|
DWORD dwFramesLast;
|
|
BOOL bUseEmulation;
|
|
BOOL bTest=FALSE;
|
|
BOOL bStress=FALSE;
|
|
DWORD dwTransType;
|
|
RGBQUAD SPalette[256];
|
|
DWORD lastTickCount;
|
|
int score;
|
|
int ProgramState;
|
|
int level;
|
|
int restCount;
|
|
DWORD dwFillColor;
|
|
BOOL bSpecialEffects = FALSE;
|
|
DWORD ShowLevelCount = 3000;
|
|
DWORD ScreenX;
|
|
DWORD ScreenY;
|
|
DWORD ScreenBpp;
|
|
BOOL bWantSound = TRUE; //global hack to turn off sound
|
|
|
|
int getint(char**p, int def);
|
|
|
|
#ifdef DEBUG
|
|
char DebugBuf[256];
|
|
BOOL bHELBlt = FALSE;
|
|
#endif
|
|
|
|
DBLNODE DL; // Display List
|
|
|
|
#ifdef USE_DSOUND
|
|
LPDIRECTSOUND lpDS;
|
|
HSNDOBJ hsoBeginLevel = NULL;
|
|
HSNDOBJ hsoEngineIdle = NULL;
|
|
HSNDOBJ hsoEngineRev = NULL;
|
|
HSNDOBJ hsoSkidToStop = NULL;
|
|
HSNDOBJ hsoShieldBuzz = NULL;
|
|
HSNDOBJ hsoShipExplode = NULL;
|
|
HSNDOBJ hsoFireBullet = NULL;
|
|
HSNDOBJ hsoShipBounce = NULL;
|
|
HSNDOBJ hsoDonutExplode = NULL;
|
|
HSNDOBJ hsoPyramidExplode = NULL;
|
|
HSNDOBJ hsoCubeExplode = NULL;
|
|
HSNDOBJ hsoSphereExplode = NULL;
|
|
#endif
|
|
|
|
|
|
void setup_game(void)
|
|
{
|
|
restCount = GetTickCount();
|
|
initLevel( ++level );
|
|
// set the palette
|
|
lpFrontBuffer->lpVtbl->SetPalette( lpFrontBuffer, lpArtPalette );
|
|
}
|
|
|
|
/*
|
|
* MainWndproc
|
|
*
|
|
* Callback for all Windows messages
|
|
*/
|
|
long FAR PASCAL MainWndproc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
PAINTSTRUCT ps;
|
|
HDC hdc;
|
|
|
|
switch( message )
|
|
{
|
|
case WM_ACTIVATEAPP:
|
|
bIsActive = (BOOL) wParam;
|
|
if( bIsActive )
|
|
{
|
|
bMouseVisible = FALSE;
|
|
lastTickCount = GetTickCount();
|
|
bSpecialEffects = FALSE;
|
|
}
|
|
else
|
|
{
|
|
bMouseVisible = TRUE;
|
|
}
|
|
break;
|
|
|
|
case WM_CREATE:
|
|
break;
|
|
|
|
case WM_SETCURSOR:
|
|
if( !bMouseVisible )
|
|
{
|
|
SetCursor(NULL);
|
|
}
|
|
else
|
|
{
|
|
SetCursor(LoadCursor( NULL, IDC_ARROW ));
|
|
}
|
|
return TRUE;
|
|
|
|
case WM_KEYDOWN:
|
|
switch( wParam )
|
|
{
|
|
case VK_NUMPAD7:
|
|
lastInput |= KEY_SHIELD;
|
|
break;
|
|
case VK_NUMPAD5:
|
|
lastInput |= KEY_STOP;
|
|
break;
|
|
case VK_DOWN:
|
|
case VK_NUMPAD2:
|
|
lastInput |= KEY_DOWN;
|
|
break;
|
|
case VK_LEFT:
|
|
case VK_NUMPAD4:
|
|
lastInput |= KEY_LEFT;
|
|
break;
|
|
case VK_RIGHT:
|
|
case VK_NUMPAD6:
|
|
lastInput |= KEY_RIGHT;
|
|
break;
|
|
case VK_UP:
|
|
case VK_NUMPAD8:
|
|
lastInput |= KEY_UP;
|
|
break;
|
|
case VK_NUMPAD3:
|
|
lastInput |= KEY_THROW;
|
|
break;
|
|
case VK_SPACE:
|
|
lastInput |= KEY_FIRE;
|
|
break;
|
|
case VK_F5:
|
|
bShowFrameCount = !bShowFrameCount;
|
|
if( bShowFrameCount )
|
|
{
|
|
dwFrameCount = 0;
|
|
dwFrameTime = timeGetTime();
|
|
}
|
|
break;
|
|
case VK_RETURN:
|
|
if( ProgramState == PS_SPLASH )
|
|
{
|
|
ProgramState = PS_BEGINREST;
|
|
setup_game();
|
|
}
|
|
break;
|
|
case VK_ESCAPE:
|
|
case VK_F12:
|
|
PostMessage( hWnd, WM_CLOSE, 0, 0 );
|
|
return 0;
|
|
case VK_F3:
|
|
#ifdef USE_DSOUND
|
|
if(bWantSound)
|
|
{
|
|
if( bSoundEnabled )
|
|
{
|
|
DestroySound();
|
|
}
|
|
else
|
|
{
|
|
InitializeSound();
|
|
}
|
|
}
|
|
#endif
|
|
break;
|
|
case VK_F1:
|
|
bSpecialEffects = !bSpecialEffects;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
|
|
case WM_KEYUP:
|
|
switch( wParam )
|
|
{
|
|
case VK_NUMPAD7:
|
|
lastInput &= ~KEY_SHIELD;
|
|
break;
|
|
case VK_NUMPAD5:
|
|
lastInput &= ~KEY_STOP;
|
|
break;
|
|
case VK_DOWN:
|
|
case VK_NUMPAD2:
|
|
lastInput &= ~KEY_DOWN;
|
|
break;
|
|
case VK_LEFT:
|
|
case VK_NUMPAD4:
|
|
lastInput &= ~KEY_LEFT;
|
|
break;
|
|
case VK_RIGHT:
|
|
case VK_NUMPAD6:
|
|
lastInput &= ~KEY_RIGHT;
|
|
break;
|
|
case VK_UP:
|
|
case VK_NUMPAD8:
|
|
lastInput &= ~KEY_UP;
|
|
break;
|
|
case VK_NUMPAD3:
|
|
lastInput &= ~KEY_THROW;
|
|
break;
|
|
case VK_SPACE:
|
|
lastInput &= ~KEY_FIRE;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_ERASEBKGND:
|
|
return 1;
|
|
|
|
case WM_PAINT:
|
|
hdc = BeginPaint( hWnd, &ps );
|
|
EndPaint( hWnd, &ps );
|
|
return 1;
|
|
|
|
case WM_DESTROY:
|
|
lastInput=0;
|
|
DestroyGame();
|
|
PostQuitMessage( 0 );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
|
|
} /* MainWndproc */
|
|
|
|
/*
|
|
* initApplication
|
|
*
|
|
* Do that Windows initialization stuff...
|
|
*/
|
|
static BOOL initApplication( HANDLE hInstance, int nCmdShow )
|
|
{
|
|
WNDCLASS wc;
|
|
BOOL rc;
|
|
|
|
wc.style = CS_DBLCLKS;
|
|
wc.lpfnWndProc = MainWndproc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = hInstance;
|
|
wc.hIcon = LoadIcon( hInstance, "ROIDS_ICON");
|
|
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
|
|
wc.hbrBackground = GetStockObject( BLACK_BRUSH );
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = "RoidClass";
|
|
rc = RegisterClass( &wc );
|
|
if( !rc )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
hWndMain = CreateWindowEx(0, // WS_EX_TOPMOST,
|
|
"RoidClass",
|
|
"Roids",
|
|
WS_VISIBLE | // so we don't have to call ShowWindow
|
|
WS_POPUP | // non-app window
|
|
WS_SYSMENU, // so we get an icon in the tray
|
|
0,
|
|
0,
|
|
GetSystemMetrics(SM_CXSCREEN),
|
|
GetSystemMetrics(SM_CYSCREEN),
|
|
NULL,
|
|
NULL,
|
|
hInstance,
|
|
NULL );
|
|
|
|
if( !hWndMain )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
UpdateWindow( hWndMain );
|
|
|
|
return TRUE;
|
|
|
|
} /* initApplication */
|
|
|
|
/*
|
|
* WinMain
|
|
*/
|
|
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
|
|
int nCmdShow )
|
|
{
|
|
MSG msg;
|
|
|
|
while( lpCmdLine[0] == '-' )
|
|
{
|
|
lpCmdLine++;
|
|
|
|
switch (*lpCmdLine++)
|
|
{
|
|
case 'e':
|
|
bUseEmulation = TRUE;
|
|
break;
|
|
case 't':
|
|
bTest = TRUE;
|
|
break;
|
|
case 'S':
|
|
bWantSound = FALSE;
|
|
break;
|
|
case 'x':
|
|
bStress= TRUE;
|
|
bTest = TRUE;
|
|
break;
|
|
}
|
|
while( IS_SPACE(*lpCmdLine) )
|
|
{
|
|
lpCmdLine++;
|
|
}
|
|
}
|
|
|
|
ScreenX = getint(&lpCmdLine, 640);
|
|
ScreenY = getint(&lpCmdLine, 480);
|
|
ScreenBpp = getint(&lpCmdLine, 8);
|
|
|
|
if( !initApplication(hInstance, nCmdShow) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if( !InitializeGame() )
|
|
{
|
|
DestroyWindow( hWndMain );
|
|
return FALSE;
|
|
}
|
|
|
|
dwFrameTime = timeGetTime();
|
|
|
|
while( 1 )
|
|
{
|
|
if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
|
|
{
|
|
if( !GetMessage( &msg, NULL, 0, 0 ) )
|
|
{
|
|
return msg.wParam;
|
|
}
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
else if ( bIsActive )
|
|
{
|
|
UpdateFrame();
|
|
}
|
|
else
|
|
{
|
|
WaitMessage();
|
|
}
|
|
}
|
|
} /* WinMain */
|
|
|
|
|
|
void DestroyGame( void )
|
|
{
|
|
}
|
|
|
|
BOOL InitializeGame( void )
|
|
{
|
|
DDCAPS ddcaps;
|
|
HRESULT ddrval;
|
|
DDSURFACEDESC ddsd;
|
|
DDSCAPS ddscaps;
|
|
#ifdef NT_HACK
|
|
DDSURFACEDESC DDSurfDesc;
|
|
#endif
|
|
|
|
score = 0;
|
|
if( bTest )
|
|
ShowLevelCount = 1000;
|
|
|
|
if( bUseEmulation )
|
|
ddrval = DirectDrawCreate( (LPVOID) DDCREATE_EMULATIONONLY, &lpDD, NULL );
|
|
else
|
|
ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
|
|
|
|
if( ddrval != DD_OK )
|
|
return CleanupAndExit("DirectDrawCreate Failed!");
|
|
|
|
ddrval = lpDD->lpVtbl->SetCooperativeLevel( lpDD, hWndMain,
|
|
DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
|
|
if( ddrval != DD_OK )
|
|
return CleanupAndExit("SetCooperativeLevel Failed");
|
|
|
|
#ifdef NT_HACK
|
|
DDSurfDesc.dwSize = sizeof(DDSurfDesc);
|
|
ddrval = lpDD->lpVtbl->GetDisplayMode(lpDD,&DDSurfDesc);
|
|
if(ddrval == DD_OK)
|
|
ScreenBpp = DDSurfDesc.ddpfPixelFormat.dwRGBBitCount;
|
|
#endif
|
|
|
|
// set the mode
|
|
ddrval = lpDD->lpVtbl->SetDisplayMode( lpDD, ScreenX, ScreenY, ScreenBpp );
|
|
if( ddrval != DD_OK )
|
|
return CleanupAndExit("SetDisplayMode Failed!");
|
|
|
|
// check the color key hardware capabilities
|
|
dwTransType = DDBLTFAST_SRCCOLORKEY;
|
|
ddcaps.dwSize = sizeof( ddcaps );
|
|
|
|
#ifdef DEBUG
|
|
if( GetProfileInt( "Roids", "force_dest_blt", 0) )
|
|
{
|
|
dwTransType = DDBLTFAST_DESTCOLORKEY;
|
|
}
|
|
bHELBlt = GetProfileInt( "Roids", "force_HEL_blt", bHELBlt );
|
|
#endif
|
|
|
|
// Create surfaces
|
|
memset( &ddsd, 0, sizeof( ddsd ) );
|
|
ddsd.dwSize = sizeof( ddsd );
|
|
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
|
|
DDSCAPS_FLIP |
|
|
DDSCAPS_COMPLEX;
|
|
ddsd.dwBackBufferCount = 1;
|
|
ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpFrontBuffer, NULL );
|
|
if( ddrval != DD_OK )
|
|
return CleanupAndExit("CreateSurface FrontBuffer Failed!");
|
|
|
|
// get a pointer to the back buffer
|
|
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
|
|
ddrval = lpFrontBuffer->lpVtbl->GetAttachedSurface(
|
|
lpFrontBuffer,
|
|
&ddscaps,
|
|
&lpBackBuffer );
|
|
if( ddrval != DD_OK )
|
|
return CleanupAndExit("GetAttachedDurface Failed!");
|
|
|
|
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
|
|
#ifdef DEBUG
|
|
if( bHELBlt )
|
|
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
|
#endif
|
|
ddsd.dwWidth = 320;
|
|
ddsd.dwHeight = 384;
|
|
ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpDonut, NULL );
|
|
if( ddrval != DD_OK )
|
|
return CleanupAndExit("CreateSurface lpDonut Failed!");
|
|
|
|
ddsd.dwHeight = 128;
|
|
ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpPyramid, NULL );
|
|
if( ddrval != DD_OK )
|
|
return CleanupAndExit("CreateSurface lpPyramid Failed!");
|
|
|
|
ddsd.dwHeight = 32;
|
|
ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpCube, NULL );
|
|
if( ddrval != DD_OK )
|
|
return CleanupAndExit("CreateSurface lpCube Failed!");
|
|
|
|
ddsd.dwHeight = 32;
|
|
ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpSphere, NULL );
|
|
if( ddrval != DD_OK )
|
|
return CleanupAndExit("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("CreateSurface lpShip Failed!");
|
|
|
|
ddsd.dwHeight = 16;
|
|
ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpNum, NULL );
|
|
if( ddrval != DD_OK )
|
|
return CleanupAndExit("CreateSurface lpNum Failed!");
|
|
|
|
if( !RestoreSurfaces() )
|
|
return CleanupAndExit("RestoreSurfaces Failed!");
|
|
|
|
DL.next = DL.prev = &DL; // null display list
|
|
DL.type = OBJ_SHIP;
|
|
DL.surf = lpShip;
|
|
lastTickCount = GetTickCount();
|
|
|
|
#ifdef USE_DSOUND
|
|
if(bWantSound)
|
|
{
|
|
InitializeSound();
|
|
}
|
|
#endif
|
|
if(bTest)
|
|
{
|
|
ProgramState = PS_ACTIVE;
|
|
setup_game();
|
|
}
|
|
else
|
|
{
|
|
ProgramState = PS_SPLASH;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CleanupAndExit( char *err)
|
|
{
|
|
#ifdef DEBUG
|
|
wsprintf(DebugBuf, "___CleanupAndExit err = %s\n", err );
|
|
OutputDebugString( DebugBuf );
|
|
#endif
|
|
|
|
// make the cursor visible
|
|
SetCursor(LoadCursor( NULL, IDC_ARROW ));
|
|
bMouseVisible = TRUE;
|
|
|
|
if( lpDonut != NULL )
|
|
lpDonut->lpVtbl->Release( lpDonut );
|
|
|
|
if( lpPyramid != NULL )
|
|
lpPyramid->lpVtbl->Release( lpPyramid );
|
|
|
|
if( lpCube != NULL )
|
|
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( 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 );
|
|
|
|
//
|
|
// warn user if there is one
|
|
//
|
|
|
|
if( !bStress )
|
|
{
|
|
MessageBox( hWndMain, err, "ERROR", MB_OK );
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
void bltSplash( void )
|
|
{
|
|
HRESULT ddrval;
|
|
HBITMAP hbm;
|
|
|
|
// set the palette before loading the splash screen
|
|
lpFrontBuffer->lpVtbl->SetPalette( lpFrontBuffer, lpSplashPalette );
|
|
|
|
hbm = (HBITMAP)LoadImage( GetModuleHandle( NULL ), "SPLASH", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION );
|
|
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();
|
|
}
|
|
|
|
#ifdef USE_DSOUND
|
|
//
|
|
// 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)
|
|
{
|
|
IDirectSoundBuffer *pDSB = SndObjGetFreeBuffer(hSO);
|
|
|
|
if(!bWantSound)
|
|
return; // No sound our Work is done
|
|
|
|
if (pDSB)
|
|
{
|
|
switch(ScreenX)
|
|
{
|
|
case 320:
|
|
IDirectSoundBuffer_SetPan(pDSB, (LONG)((20000.0 *
|
|
((object->dst.right + object->dst.left) / 2) / 320.0) - 10000.0));
|
|
break;
|
|
case 640:
|
|
IDirectSoundBuffer_SetPan(pDSB, (LONG)((20000.0 *
|
|
((object->dst.right + object->dst.left) / 2) / 640.0) - 10000.0));
|
|
break;
|
|
case 1024:
|
|
IDirectSoundBuffer_SetPan(pDSB, (LONG)((20000.0 *
|
|
((object->dst.right + object->dst.left) / 2) / 1024.0) - 10000.0));
|
|
break;
|
|
case 1280:
|
|
IDirectSoundBuffer_SetPan(pDSB, (LONG)((20000.0 *
|
|
((object->dst.right + object->dst.left) / 2) / 1280.0) - 10000.0));
|
|
break;
|
|
}
|
|
|
|
IDirectSoundBuffer_Play(pDSB, 0, 0, 0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void UpdateFrame( void )
|
|
{
|
|
switch( ProgramState )
|
|
{
|
|
case PS_SPLASH:
|
|
// display the splash screen
|
|
bltSplash();
|
|
return;
|
|
case PS_ACTIVE:
|
|
UpdateDisplayList();
|
|
CheckForHits();
|
|
DrawDisplayList();
|
|
if ( isDisplayListEmpty() )
|
|
{
|
|
#ifdef USE_DSOUND
|
|
if(bWantSound)
|
|
{
|
|
SndObjStop(hsoEngineIdle);
|
|
SndObjStop(hsoEngineRev);
|
|
}
|
|
#endif
|
|
bPlayIdle = FALSE;
|
|
bPlayRev = FALSE;
|
|
lastThrust = lastShield = FALSE;
|
|
ProgramState = PS_BEGINREST;
|
|
restCount = GetTickCount();
|
|
initLevel( ++level );
|
|
}
|
|
return;
|
|
case PS_BEGINREST:
|
|
#ifdef USE_DSOUND
|
|
if(bWantSound)
|
|
{
|
|
SndObjPlay(hsoBeginLevel, 0);
|
|
}
|
|
#endif
|
|
ProgramState = PS_REST;
|
|
//
|
|
// FALLTHRU
|
|
//
|
|
case PS_REST:
|
|
if( ( GetTickCount() - restCount ) > ShowLevelCount )
|
|
{
|
|
#ifdef USE_DSOUND
|
|
if(bWantSound)
|
|
{
|
|
SndObjPlay(hsoEngineIdle, DSBPLAY_LOOPING);
|
|
}
|
|
#endif
|
|
bPlayIdle = TRUE;
|
|
lastTickCount = GetTickCount();
|
|
ProgramState = PS_ACTIVE;
|
|
}
|
|
else
|
|
{
|
|
DisplayLevel();
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
void DisplayLevel( void )
|
|
{
|
|
char buf[10];
|
|
|
|
EraseScreen();
|
|
buf[0] = 10 + '0';
|
|
buf[1] = 11 + '0';
|
|
buf[2] = 12 + '0';
|
|
buf[3] = 11 + '0';
|
|
buf[4] = 10 + '0';
|
|
buf[5] = '\0';
|
|
bltScore( buf, ScreenX/2-64, ScreenY/2-8 );
|
|
buf[0] = level / 100 + '0';
|
|
buf[1] = level / 10 + '0';
|
|
buf[2] = level % 10 + '0';
|
|
buf[3] = '\0';
|
|
bltScore( buf, ScreenX/2+22, ScreenY/2-8 );
|
|
FlipScreen();
|
|
}
|
|
|
|
void bltScore( char *num, int x, int y )
|
|
{
|
|
char *c;
|
|
RECT src;
|
|
int i;
|
|
HRESULT ddrval;
|
|
|
|
for(c=num; *c != '\0'; c++)
|
|
{
|
|
while( 1 )
|
|
{
|
|
i = *c - '0';
|
|
src.left = i*16;
|
|
src.top = 0;
|
|
src.right = src.left + 16;
|
|
src.bottom = src.top + 16;
|
|
ddrval = lpBackBuffer->lpVtbl->BltFast( lpBackBuffer, x, y, lpNum, &src, dwTransType );
|
|
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:
|
|
#ifdef USE_DSOUND
|
|
if(bWantSound)
|
|
{
|
|
playPanned(hsoDonutExplode, target);
|
|
}
|
|
#endif
|
|
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:
|
|
#ifdef USE_DSOUND
|
|
if(bWantSound)
|
|
{
|
|
playPanned(hsoPyramidExplode, target);
|
|
}
|
|
#endif
|
|
addObject( OBJ_SPHERE, target->dst.left,
|
|
target->dst.top, -1.0, -1.0 );
|
|
addObject( OBJ_CUBE, target->dst.left,
|
|
target->dst.top, -1.0, -1.0 );
|
|
addObject( OBJ_CUBE, target->dst.left,
|
|
target->dst.top, -1.0, -1.0 );
|
|
score += 20;
|
|
break;
|
|
case OBJ_CUBE:
|
|
#ifdef USE_DSOUND
|
|
if(bWantSound)
|
|
{
|
|
playPanned(hsoCubeExplode, target);
|
|
}
|
|
#endif
|
|
addObject( OBJ_SPHERE, target->dst.left,
|
|
target->dst.top, -1.0, -1.0 );
|
|
addObject( OBJ_SPHERE, target->dst.left,
|
|
target->dst.top, -1.0, -1.0 );
|
|
break;
|
|
score += 40;
|
|
case OBJ_SPHERE:
|
|
#ifdef USE_DSOUND
|
|
if(bWantSound)
|
|
{
|
|
playPanned(hsoSphereExplode, target);
|
|
}
|
|
#endif
|
|
score += 20;
|
|
}
|
|
|
|
l = target->dst.left;
|
|
t = target->dst.top;
|
|
DeleteFromList( target );
|
|
}
|
|
|
|
hit = TRUE;
|
|
}
|
|
|
|
if( hit )
|
|
{
|
|
if( bullet == &DL )
|
|
{
|
|
hit = FALSE;
|
|
if (!lastShield && !showDelay && !bTest)
|
|
{
|
|
#ifdef USE_DSOUND
|
|
if(bWantSound)
|
|
{
|
|
playPanned(hsoShipExplode, bullet);
|
|
}
|
|
#endif
|
|
score -= 150;
|
|
if (score < 0)
|
|
score = 0;
|
|
|
|
addObject( OBJ_SPHERE, l, t, -1.0, -1.0 );
|
|
addObject( OBJ_SPHERE, l, t, -1.0, -1.0 );
|
|
addObject( OBJ_SPHERE, l, t, -1.0, -1.0 );
|
|
addObject( OBJ_SPHERE, l, t, -1.0, -1.0 );
|
|
addObject( OBJ_BULLET, l, t,
|
|
randDouble( -0.5, 0.5 ), randDouble( -0.5, 0.5 ) );
|
|
addObject( OBJ_BULLET, l, t,
|
|
randDouble( -0.5, 0.5 ), randDouble( -0.5, 0.5 ) );
|
|
addObject( OBJ_BULLET, l, t,
|
|
randDouble( -0.5, 0.5 ), randDouble( -0.5, 0.5 ) );
|
|
addObject( OBJ_BULLET, l, t,
|
|
randDouble( -0.5, 0.5 ), randDouble( -0.5, 0.5 ) );
|
|
addObject( OBJ_BULLET, l, t,
|
|
randDouble( -0.5, 0.5 ), randDouble( -0.5, 0.5 ) );
|
|
addObject( OBJ_BULLET, l, t,
|
|
randDouble( -0.5, 0.5 ), randDouble( -0.5, 0.5 ) );
|
|
addObject( OBJ_BULLET, l, t,
|
|
randDouble( -0.5, 0.5 ), randDouble( -0.5, 0.5 ) );
|
|
addObject( OBJ_BULLET, l, t,
|
|
randDouble( -0.5, 0.5 ), randDouble( -0.5, 0.5 ) );
|
|
addObject( OBJ_BULLET, l, t,
|
|
randDouble( -0.5, 0.5 ), randDouble( -0.5, 0.5 ) );
|
|
addObject( OBJ_BULLET, l, t,
|
|
randDouble( -0.5, 0.5 ), randDouble( -0.5, 0.5 ) );
|
|
initShip(TRUE);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( hit )
|
|
{
|
|
save = bullet;
|
|
bullet = bullet->next;
|
|
|
|
DeleteFromList( save );
|
|
}
|
|
else
|
|
{
|
|
bullet = bullet->next;
|
|
}
|
|
|
|
} while (bullet != &DL);
|
|
}
|
|
|
|
void EraseScreen( void )
|
|
{
|
|
DDBLTFX ddbltfx;
|
|
HRESULT ddrval;
|
|
|
|
if( bSpecialEffects ) // cool looking screen with no colorfill
|
|
return;
|
|
|
|
// Erase the background
|
|
ddbltfx.dwSize = sizeof( ddbltfx );
|
|
ddbltfx.dwFillColor = dwFillColor;
|
|
while( 1 )
|
|
{
|
|
ddrval = lpBackBuffer->lpVtbl->Blt( lpBackBuffer, NULL, NULL,
|
|
NULL, DDBLT_COLORFILL, &ddbltfx );
|
|
|
|
if( ddrval == DD_OK )
|
|
{
|
|
break;
|
|
}
|
|
if( ddrval == DDERR_SURFACELOST )
|
|
{
|
|
if( !RestoreSurfaces() )
|
|
return;
|
|
}
|
|
if( ddrval != DDERR_WASSTILLDRAWING )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void FlipScreen( void )
|
|
{
|
|
HRESULT ddrval;
|
|
|
|
// Flip the surfaces
|
|
while( 1 )
|
|
{
|
|
ddrval = lpFrontBuffer->lpVtbl->Flip( lpFrontBuffer, NULL, 0 );
|
|
if( ddrval == DD_OK )
|
|
{
|
|
break;
|
|
}
|
|
if( ddrval == DDERR_SURFACELOST )
|
|
{
|
|
if( !RestoreSurfaces() )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
if( ddrval != DDERR_WASSTILLDRAWING )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void DrawDisplayList( void )
|
|
{
|
|
LPDBLNODE this;
|
|
LPDBLNODE last;
|
|
HRESULT ddrval;
|
|
char scorebuf[11];
|
|
int rem;
|
|
|
|
// blt everything in reverse order if we are doing destination transparency
|
|
// calculate score string
|
|
scorebuf[0] = score/10000000 + '0';
|
|
rem = score % 10000000;
|
|
scorebuf[1] = rem/1000000 + '0';
|
|
rem = score % 1000000;
|
|
scorebuf[2] = rem/100000 + '0';
|
|
rem = score % 100000;
|
|
scorebuf[3] = rem/10000 + '0';
|
|
rem = score % 10000;
|
|
scorebuf[4] = rem/1000 + '0';
|
|
rem = score % 1000;
|
|
scorebuf[5] = rem/100 + '0';
|
|
rem = score % 100;
|
|
scorebuf[6] = rem/10 + '0';
|
|
rem = score % 10;
|
|
scorebuf[7] = rem + '0';
|
|
#ifdef USE_DSOUND
|
|
if( bSoundEnabled )
|
|
{
|
|
scorebuf[8] = 14 + '0';
|
|
scorebuf[9] = 13 + '0';
|
|
scorebuf[10] = '\0';
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
scorebuf[8] = '\0';
|
|
}
|
|
|
|
EraseScreen();
|
|
if( dwTransType == DDBLTFAST_DESTCOLORKEY )
|
|
{
|
|
bltScore(scorebuf, 10, ScreenY-26);
|
|
|
|
if( bShowFrameCount )
|
|
DisplayFrameRate();
|
|
|
|
this = DL.next; // start with the topmost bitmap
|
|
last = DL.next; // don't blt it twice
|
|
|
|
if (showDelay)
|
|
last = &DL;
|
|
}
|
|
else
|
|
{
|
|
this = &DL; // start with the bottommost bitmap (the ship)
|
|
last = &DL; // don't blt it twice
|
|
|
|
if (showDelay)
|
|
this = this->prev;
|
|
}
|
|
|
|
do
|
|
{
|
|
while( 1 )
|
|
{
|
|
ddrval = lpBackBuffer->lpVtbl->BltFast( lpBackBuffer, this->dst.left, this->dst.top, this->surf, &(this->src), dwTransType );
|
|
if( ddrval == DD_OK )
|
|
{
|
|
break;
|
|
}
|
|
if( ddrval == DDERR_SURFACELOST )
|
|
{
|
|
if( !RestoreSurfaces() )
|
|
return;
|
|
}
|
|
if( ddrval != DDERR_WASSTILLDRAWING )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
if( dwTransType != DDBLTFAST_DESTCOLORKEY )
|
|
{
|
|
this = this->prev;
|
|
}
|
|
else
|
|
{
|
|
this = this->next;
|
|
}
|
|
}
|
|
while( this != last );
|
|
|
|
if( dwTransType != DDBLTFAST_DESTCOLORKEY )
|
|
{
|
|
bltScore(scorebuf, 10, ScreenY-26);
|
|
|
|
if( bShowFrameCount )
|
|
DisplayFrameRate();
|
|
}
|
|
|
|
FlipScreen();
|
|
}
|
|
|
|
void DisplayFrameRate( void )
|
|
{
|
|
DWORD time2;
|
|
char buff[256];
|
|
|
|
dwFrameCount++;
|
|
time2 = timeGetTime() - dwFrameTime;
|
|
if( time2 > 1000 )
|
|
{
|
|
dwFrames = (dwFrameCount*1000)/time2;
|
|
dwFrameTime = timeGetTime();
|
|
dwFrameCount = 0;
|
|
}
|
|
if( dwFrames == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (dwFrames != dwFramesLast)
|
|
{
|
|
dwFramesLast = dwFrames;
|
|
}
|
|
|
|
if( dwFrames > 99 )
|
|
{
|
|
dwFrames = 99;
|
|
}
|
|
buff[0] = (char)((dwFrames / 10) + '0');
|
|
buff[1] = (char)((dwFrames % 10) + '0');
|
|
buff[2] = '\0';
|
|
bltScore(buff, ScreenX/2-25, 10);
|
|
}
|
|
|
|
void DeleteFromList( LPDBLNODE this )
|
|
{
|
|
this->next->prev = this->prev;
|
|
this->prev->next = this->next;
|
|
LocalFree( this );
|
|
}
|
|
|
|
void UpdateDisplayList( void )
|
|
{
|
|
LPDBLNODE this;
|
|
LPDBLNODE save;
|
|
DWORD thisTickCount = GetTickCount();
|
|
DWORD tickDiff = thisTickCount - lastTickCount;
|
|
double maxx, maxy;
|
|
double maxframe;
|
|
DWORD input = lastInput;
|
|
BOOL event = FALSE;
|
|
|
|
if( bTest )
|
|
{
|
|
input |= (KEY_RIGHT | KEY_FIRE);
|
|
}
|
|
lastTickCount = thisTickCount;
|
|
|
|
if (showDelay)
|
|
{
|
|
showDelay -= (int)tickDiff;
|
|
if (showDelay < 0)
|
|
{
|
|
showDelay = 0;
|
|
lastShield = FALSE;
|
|
initShip( FALSE );
|
|
}
|
|
}
|
|
|
|
// update the ship
|
|
if( !showDelay )
|
|
{
|
|
DL.posx += DL.velx * (double)tickDiff;
|
|
DL.posy += DL.vely * (double)tickDiff;
|
|
}
|
|
if( DL.posx > MAX_SHIP_X )
|
|
{
|
|
DL.posx = MAX_SHIP_X;
|
|
DL.velx = -DL.velx;
|
|
event = TRUE;
|
|
}
|
|
else if ( DL.posx < 0 )
|
|
{
|
|
DL.posx =0;
|
|
DL.velx = -DL.velx;
|
|
event = TRUE;
|
|
}
|
|
if( DL.posy > MAX_SHIP_Y )
|
|
{
|
|
DL.posy = MAX_SHIP_Y;
|
|
DL.vely = -DL.vely;
|
|
event = TRUE;
|
|
}
|
|
else if ( DL.posy < 0 )
|
|
{
|
|
DL.posy =0;
|
|
DL.vely = -DL.vely;
|
|
event = TRUE;
|
|
}
|
|
if (event)
|
|
{
|
|
#ifdef USE_DSOUND
|
|
if(bWantSound)
|
|
{
|
|
playPanned(hsoShipBounce, &DL);
|
|
}
|
|
#endif
|
|
event = FALSE;
|
|
}
|
|
|
|
if ((event = (showDelay || ((input & KEY_SHIELD) == KEY_SHIELD))) !=
|
|
lastShield)
|
|
{
|
|
if (event && !showDelay)
|
|
{
|
|
#ifdef USE_DSOUND
|
|
if(bWantSound)
|
|
{
|
|
SndObjPlay(hsoShieldBuzz, DSBPLAY_LOOPING);
|
|
}
|
|
#endif
|
|
bPlayBuzz = TRUE;
|
|
}
|
|
else
|
|
{
|
|
#ifdef USE_DSOUND
|
|
if(bWantSound)
|
|
{
|
|
SndObjStop(hsoShieldBuzz);
|
|
}
|
|
#endif
|
|
bPlayBuzz = FALSE;
|
|
}
|
|
lastShield = event;
|
|
}
|
|
if (event)
|
|
{
|
|
input &= ~(KEY_FIRE);
|
|
}
|
|
|
|
if (input & KEY_FIRE)
|
|
{
|
|
if( !showDelay )
|
|
{
|
|
// add a bullet to the scene
|
|
score--;
|
|
if(score < 0)
|
|
score = 0;
|
|
|
|
#ifdef USE_DSOUND
|
|
if(bWantSound)
|
|
{
|
|
SndObjPlay(hsoFireBullet, 0);
|
|
}
|
|
#endif
|
|
addObject( OBJ_BULLET, Dirx[(int)DL.frame]*6.0 + 16.0 + DL.posx,
|
|
Diry[(int)DL.frame]*6.0 + 16.0 + DL.posy,
|
|
Dirx[(int)DL.frame]*500.0/1000.0,
|
|
Diry[(int)DL.frame]*500.0/1000.0 );
|
|
}
|
|
}
|
|
|
|
event = FALSE;
|
|
if( input & KEY_LEFT )
|
|
{
|
|
DL.frame -= 1.0;
|
|
if( DL.frame < 0.0 )
|
|
DL.frame += MAX_SHIP_FRAME;
|
|
}
|
|
if( input & KEY_RIGHT )
|
|
{
|
|
DL.frame += 1.0;
|
|
if( DL.frame >= MAX_SHIP_FRAME)
|
|
DL.frame -= MAX_SHIP_FRAME;
|
|
}
|
|
if( input & KEY_UP )
|
|
{
|
|
DL.velx += Dirx[(int)DL.frame] * 10.0/1000.0;
|
|
DL.vely += Diry[(int)DL.frame] * 10.0/1000.0;
|
|
event = TRUE;
|
|
}
|
|
if( input & KEY_DOWN )
|
|
{
|
|
DL.velx -= Dirx[(int)DL.frame] * 10.0/1000.0;
|
|
DL.vely -= Diry[(int)DL.frame] * 10.0/1000.0;
|
|
event = TRUE;
|
|
}
|
|
|
|
if (event != lastThrust)
|
|
{
|
|
if (event)
|
|
{
|
|
input &= ~KEY_STOP;
|
|
#ifdef USE_DSOUND
|
|
if(bWantSound)
|
|
{
|
|
SndObjStop(hsoSkidToStop);
|
|
SndObjPlay(hsoEngineRev, DSBPLAY_LOOPING);
|
|
}
|
|
#endif
|
|
bPlayRev = TRUE;
|
|
}
|
|
else
|
|
{
|
|
#ifdef USE_DSOUND
|
|
if(bWantSound)
|
|
{
|
|
SndObjStop(hsoEngineRev);
|
|
}
|
|
#endif
|
|
bPlayRev = FALSE;
|
|
}
|
|
|
|
lastThrust = event;
|
|
}
|
|
|
|
if( input & KEY_STOP )
|
|
{
|
|
#ifdef USE_DSOUND
|
|
if(bWantSound)
|
|
{
|
|
if (DL.velx || DL.vely)
|
|
playPanned(hsoSkidToStop, &DL);
|
|
}
|
|
#endif
|
|
|
|
DL.velx = 0;
|
|
DL.vely = 0;
|
|
}
|
|
|
|
this = DL.next;
|
|
do
|
|
{
|
|
this->posx += this->velx * (double)tickDiff;
|
|
this->posy += this->vely * (double)tickDiff;
|
|
this->frame += this->delay * (double)tickDiff;
|
|
switch( this->type )
|
|
{
|
|
case OBJ_DONUT:
|
|
maxx = (double)MAX_DONUT_X;
|
|
maxy = (double)MAX_DONUT_Y;
|
|
maxframe = (double)MAX_DONUT_FRAME;
|
|
break;
|
|
case OBJ_PYRAMID:
|
|
maxx = (double)MAX_PYRAMID_X;
|
|
maxy = (double)MAX_PYRAMID_Y;
|
|
maxframe = (double)MAX_PYRAMID_FRAME;
|
|
break;
|
|
case OBJ_SPHERE:
|
|
maxx = (double)MAX_SPHERE_X;
|
|
maxy = (double)MAX_SPHERE_Y;
|
|
maxframe = (double)MAX_SPHERE_FRAME;
|
|
break;
|
|
case OBJ_CUBE:
|
|
maxx = (double)MAX_CUBE_X;
|
|
maxy = (double)MAX_CUBE_Y;
|
|
maxframe = (double)MAX_CUBE_FRAME;
|
|
break;
|
|
case OBJ_BULLET:
|
|
maxx = (double)MAX_BULLET_X;
|
|
maxy = (double)MAX_BULLET_Y;
|
|
maxframe = (double)MAX_BULLET_FRAME;
|
|
if( this->frame >= (double)MAX_BULLET_FRAME )
|
|
{
|
|
save = this;
|
|
this = this->next;
|
|
DeleteFromList( save );
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
if( this != &DL )
|
|
{
|
|
if( this->posx > maxx )
|
|
{
|
|
this->posx = maxx;
|
|
this->velx = -this->velx;
|
|
}
|
|
else if ( this->posx < 0 )
|
|
{
|
|
this->posx =0;
|
|
this->velx = -this->velx;
|
|
}
|
|
if( this->posy > maxy )
|
|
{
|
|
this->posy = maxy;
|
|
this->vely = -this->vely;
|
|
}
|
|
else if ( this->posy < 0 )
|
|
{
|
|
this->posy =0;
|
|
this->vely = -this->vely;
|
|
}
|
|
if( this->frame >= maxframe )
|
|
{
|
|
this->frame -= maxframe;
|
|
}
|
|
this = this->next;
|
|
}
|
|
}
|
|
while( this != &DL );
|
|
}
|
|
|
|
BOOL isDisplayListEmpty( void )
|
|
{
|
|
LPDBLNODE ptr;
|
|
|
|
for(ptr=DL.next; ptr != &DL; ptr = ptr->next)
|
|
{
|
|
if(ptr->type != OBJ_BULLET)
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void initShip( BOOL delay )
|
|
{
|
|
DL.posx = (double)(ScreenX/2-16); // center the ship
|
|
DL.posy = (double)(ScreenY/2-16);
|
|
DL.frame = 0.0;
|
|
if( bTest )
|
|
{
|
|
DL.velx = 0.25;
|
|
DL.vely = 0.5;
|
|
}
|
|
else
|
|
{
|
|
DL.velx = DL.vely = 0.0; // not moving
|
|
}
|
|
if( !bTest && delay )
|
|
showDelay = DEF_SHOW_DELAY;
|
|
}
|
|
|
|
void initLevel( int level )
|
|
{
|
|
int i;
|
|
|
|
// clear any stray bullets out of the display list
|
|
while( DL.next != &DL )
|
|
{
|
|
DeleteFromList( DL.next );
|
|
}
|
|
for(i=0; i<(2*level-1); i++)
|
|
{
|
|
addObject( OBJ_DONUT, -1.0, -1.0, -1.0, -1.0 );
|
|
}
|
|
initShip(TRUE);
|
|
}
|
|
|
|
void addObject( SHORT type, double x, double y, double vx, double vy )
|
|
{
|
|
LPDBLNODE new;
|
|
|
|
new = (LPDBLNODE) LocalAlloc( LPTR, sizeof( DBLNODE ) );
|
|
if( new == NULL)
|
|
return;
|
|
|
|
new->type = type;
|
|
switch( type )
|
|
{
|
|
case OBJ_DONUT:
|
|
if( x < 0.0) // no position specified?
|
|
{
|
|
new->posx = randDouble( 0.0, (double)MAX_DONUT_X );
|
|
new->posy = randDouble( 0.0, (double)MAX_DONUT_Y );
|
|
}
|
|
else
|
|
{
|
|
new->posx = x;
|
|
new->posy = y;
|
|
}
|
|
new->velx = randDouble( -50.0/1000.0, 50.0/1000.0 );
|
|
new->vely = randDouble( -50.0/1000.0, 50.0/1000.0 );
|
|
new->frame = randDouble( 0, 30 );
|
|
new->delay = 30.0*randDouble( 0.1, 0.4 )/1000.0;
|
|
new->surf = lpDonut;
|
|
linkObject( new );
|
|
break;
|
|
case OBJ_PYRAMID:
|
|
if( x < 0) // no position specified?
|
|
{
|
|
new->posx = randDouble( 0.0, (double)MAX_PYRAMID_X );
|
|
new->posy = randDouble( 0.0, (double)MAX_PYRAMID_Y );
|
|
}
|
|
else
|
|
{
|
|
new->posx = x;
|
|
new->posy = y;
|
|
}
|
|
new->velx = 1.5*randDouble( -50.0/1000.0, 50.0/1000.0 );
|
|
new->vely = 1.5*randDouble( -50.0/1000.0, 50.0/1000.0 );
|
|
new->frame = randDouble( 0, 30 );
|
|
new->delay = 40.0*randDouble( 0.3, 1.0 )/1000.0;
|
|
new->surf = lpPyramid;
|
|
linkObject( new );
|
|
break;
|
|
case OBJ_SPHERE:
|
|
if( x < 0) // no position specified?
|
|
{
|
|
new->posx = randDouble( 0.0, (double)MAX_SPHERE_X );
|
|
new->posy = randDouble( 0.0, (double)MAX_SPHERE_Y );
|
|
}
|
|
else
|
|
{
|
|
new->posx = x;
|
|
new->posy = y;
|
|
}
|
|
new->velx = 3.0*randDouble( -50.0/1000.0, 50.0/1000.0 );
|
|
new->vely = 3.0*randDouble( -50.0/1000.0, 50.0/1000.0 );
|
|
new->frame = randDouble( 0, 30 );
|
|
new->delay = 40.0*randDouble( 1.5, 2.0 )/1000.0;
|
|
new->surf = lpSphere;
|
|
linkObject( new );
|
|
break;
|
|
case OBJ_CUBE:
|
|
if( x < 0) // no position specified?
|
|
{
|
|
new->posx = randDouble( 0.0, (double)MAX_CUBE_X );
|
|
new->posy = randDouble( 0.0, (double)MAX_CUBE_Y );
|
|
}
|
|
else
|
|
{
|
|
new->posx = x;
|
|
new->posy = y;
|
|
}
|
|
new->velx = 4.0*randDouble( -50.0/1000.0, 50.0/1000.0 );
|
|
new->vely = 4.0*randDouble( -50.0/1000.0, 50.0/1000.0 );
|
|
new->frame = randDouble( 0, 30 );
|
|
new->delay = 40.0*randDouble( 0.8, 2.0 )/1000.0;
|
|
new->surf = lpCube;
|
|
linkObject( new );
|
|
break;
|
|
case OBJ_BULLET:
|
|
new->posx = x;
|
|
new->posy = y;
|
|
new->velx = vx;
|
|
new->vely = vy;
|
|
new->frame = 0.0;
|
|
new->delay = 1.0;
|
|
new->surf = lpNum;
|
|
linkObject( new );
|
|
break;
|
|
}
|
|
}
|
|
|
|
void linkObject( LPDBLNODE new )
|
|
{
|
|
new->next = DL.next;
|
|
new->prev = &DL;
|
|
DL.next->prev = new;
|
|
DL.next = new;
|
|
}
|
|
|
|
void linkLastObject( LPDBLNODE new )
|
|
{
|
|
new->prev = DL.prev;
|
|
new->next = &DL;
|
|
DL.prev->next = new;
|
|
DL.prev = new;
|
|
}
|
|
|
|
|
|
BOOL RestoreSurfaces( void )
|
|
{
|
|
HRESULT ddrval;
|
|
HBITMAP hbm;
|
|
|
|
ddrval = lpFrontBuffer->lpVtbl->Restore(lpFrontBuffer);
|
|
if( ddrval != DD_OK )
|
|
return FALSE;
|
|
ddrval = lpDonut->lpVtbl->Restore(lpDonut);
|
|
if( ddrval != DD_OK )
|
|
return FALSE;
|
|
ddrval = lpPyramid->lpVtbl->Restore(lpPyramid);
|
|
if( ddrval != DD_OK )
|
|
return FALSE;
|
|
ddrval = lpCube->lpVtbl->Restore(lpCube);
|
|
if( ddrval != DD_OK )
|
|
return FALSE;
|
|
ddrval = lpSphere->lpVtbl->Restore(lpSphere);
|
|
if( ddrval != DD_OK )
|
|
return FALSE;
|
|
ddrval = lpShip->lpVtbl->Restore(lpShip);
|
|
if( ddrval != DD_OK )
|
|
return FALSE;
|
|
ddrval = lpNum->lpVtbl->Restore(lpNum);
|
|
if( ddrval != DD_OK )
|
|
return FALSE;
|
|
|
|
// Create and set the palette for the splash bitmap
|
|
lpSplashPalette = DDLoadPalette( lpDD, "SPLASH" );
|
|
if( NULL == lpSplashPalette )
|
|
return CleanupAndExit("DDLoadPalette SPLASH");
|
|
|
|
// Create and set the palette for the art bitmap
|
|
lpArtPalette = DDLoadPalette( lpDD, "ROIDS8" );
|
|
if( NULL == lpArtPalette )
|
|
return CleanupAndExit("DDLoadPalette ROIDS");
|
|
|
|
// set the palette before loading the art
|
|
lpFrontBuffer->lpVtbl->SetPalette( lpFrontBuffer, lpArtPalette );
|
|
|
|
hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), "ROIDS8", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION );
|
|
|
|
if( NULL == hbm )
|
|
return FALSE;
|
|
|
|
ddrval = DDCopyBitmap( lpDonut, hbm, 0, 0, 320, 384 );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
DeleteObject( hbm );
|
|
return FALSE;
|
|
}
|
|
|
|
// NOTE: Why are we calling LoadImage again? StretchBlt (which is
|
|
// called in DDCopyBitmap) does not work properly when performing
|
|
// an 8-bpp to 24- or 32-bpp blt multiple times from the same
|
|
// bitmap. The workaround is to call LoadImage before each
|
|
// StretchBlt because the first StretchBlt after a LoadImage will
|
|
// work.
|
|
if(ScreenBpp >= 24)
|
|
{
|
|
DeleteObject( hbm );
|
|
hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), "ROIDS8", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION );
|
|
|
|
if( NULL == hbm )
|
|
return FALSE;
|
|
}
|
|
|
|
ddrval = DDCopyBitmap( lpPyramid, hbm, 0, 384, 320, 128 );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
DeleteObject( hbm );
|
|
return FALSE;
|
|
}
|
|
|
|
if(ScreenBpp >= 24)
|
|
{
|
|
DeleteObject( hbm );
|
|
hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), "ROIDS8", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION );
|
|
|
|
if( NULL == hbm )
|
|
return FALSE;
|
|
}
|
|
|
|
ddrval = DDCopyBitmap( lpSphere, hbm, 0, 512, 320, 32 );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
DeleteObject( hbm );
|
|
return FALSE;
|
|
}
|
|
|
|
if(ScreenBpp >= 24)
|
|
{
|
|
DeleteObject( hbm );
|
|
hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), "ROIDS8", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION );
|
|
|
|
if( NULL == hbm )
|
|
return FALSE;
|
|
}
|
|
|
|
ddrval = DDCopyBitmap( lpCube, hbm, 0, 544, 320, 32 );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
DeleteObject( hbm );
|
|
return FALSE;
|
|
}
|
|
|
|
if(ScreenBpp >= 24)
|
|
{
|
|
DeleteObject( hbm );
|
|
hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), "ROIDS8", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION );
|
|
|
|
if( NULL == hbm )
|
|
return FALSE;
|
|
}
|
|
|
|
ddrval = DDCopyBitmap( lpShip, hbm, 0, 576, 320, 256 );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
DeleteObject( hbm );
|
|
return FALSE;
|
|
}
|
|
|
|
if(ScreenBpp >= 24)
|
|
{
|
|
DeleteObject( hbm );
|
|
hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), "ROIDS8", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION );
|
|
|
|
if( NULL == hbm )
|
|
return FALSE;
|
|
}
|
|
|
|
ddrval = DDCopyBitmap( lpNum, hbm, 0, 832, 320, 16 );
|
|
if( ddrval != DD_OK )
|
|
{
|
|
DeleteObject( hbm );
|
|
return FALSE;
|
|
}
|
|
|
|
DeleteObject( hbm );
|
|
|
|
// set colorfill colors and color keys according to bitmap contents
|
|
dwFillColor = DDColorMatch( lpDonut, CLR_INVALID );
|
|
|
|
DDSetColorKey( lpDonut, CLR_INVALID );
|
|
DDSetColorKey( lpPyramid, CLR_INVALID );
|
|
DDSetColorKey( lpCube, CLR_INVALID );
|
|
DDSetColorKey( lpSphere, CLR_INVALID );
|
|
DDSetColorKey( lpShip, CLR_INVALID );
|
|
DDSetColorKey( lpNum, CLR_INVALID );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
int randInt( int low, int high )
|
|
{
|
|
int range = high - low;
|
|
int num = rand() % range;
|
|
return( num + low );
|
|
}
|
|
|
|
double randDouble( double low, double high )
|
|
{
|
|
double range = high - low;
|
|
double num = range * (double)rand()/(double)RAND_MAX;
|
|
return( num + low );
|
|
}
|
|
|
|
#ifdef USE_DSOUND
|
|
void InitializeSound( void )
|
|
{
|
|
if(!bWantSound)
|
|
return; // out of here
|
|
bSoundEnabled = FALSE;
|
|
if (SUCCEEDED(DirectSoundCreate(NULL, &lpDS, NULL)))
|
|
{
|
|
if (SUCCEEDED(lpDS->lpVtbl->SetCooperativeLevel(lpDS, hWndMain,
|
|
DSSCL_NORMAL)))
|
|
{
|
|
hsoBeginLevel = SndObjCreate(lpDS, "BeginLevel", 1);
|
|
hsoEngineIdle = SndObjCreate(lpDS, "EngineIdle", 1);
|
|
hsoEngineRev = SndObjCreate(lpDS, "EngineRev", 1);
|
|
hsoSkidToStop = SndObjCreate(lpDS, "SkidToStop", 1);
|
|
hsoShieldBuzz = SndObjCreate(lpDS, "ShieldBuzz", 1);
|
|
hsoShipExplode = SndObjCreate(lpDS, "ShipExplode", 1);
|
|
hsoFireBullet = SndObjCreate(lpDS, "Gunfire", 25);
|
|
hsoShipBounce = SndObjCreate(lpDS, "ShipBounce", 4);
|
|
hsoDonutExplode = SndObjCreate(lpDS, "DonutExplode", 10);
|
|
hsoPyramidExplode = SndObjCreate(lpDS, "PyramidExplode", 12);
|
|
hsoCubeExplode = SndObjCreate(lpDS, "CubeExplode", 15);
|
|
hsoSphereExplode = SndObjCreate(lpDS, "SphereExplode", 10);
|
|
bSoundEnabled = TRUE;
|
|
|
|
//#ifdef USE_DSOUND this should be dead code Josephc
|
|
if( bPlayIdle )
|
|
SndObjPlay(hsoEngineIdle, DSBPLAY_LOOPING);
|
|
|
|
if( bPlayBuzz )
|
|
SndObjPlay(hsoShieldBuzz, DSBPLAY_LOOPING);
|
|
|
|
if( bPlayRev )
|
|
SndObjPlay(hsoEngineRev, DSBPLAY_LOOPING);
|
|
//#endif
|
|
}
|
|
else
|
|
{
|
|
lpDS->lpVtbl->Release(lpDS);
|
|
lpDS = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void DestroySound( void )
|
|
{
|
|
if(!bWantSound)
|
|
return; //No work to be done
|
|
bSoundEnabled = FALSE;
|
|
if (lpDS)
|
|
{
|
|
SndObjDestroy(hsoBeginLevel);
|
|
hsoBeginLevel = NULL;
|
|
SndObjDestroy(hsoEngineIdle);
|
|
hsoEngineIdle = NULL;
|
|
SndObjDestroy(hsoEngineRev);
|
|
hsoEngineRev = NULL;
|
|
SndObjDestroy(hsoSkidToStop);
|
|
hsoSkidToStop = NULL;
|
|
SndObjDestroy(hsoShieldBuzz);
|
|
hsoShieldBuzz = NULL;
|
|
SndObjDestroy(hsoShipExplode);
|
|
hsoShipExplode = NULL;
|
|
SndObjDestroy(hsoFireBullet);
|
|
hsoFireBullet = NULL;
|
|
SndObjDestroy(hsoShipBounce);
|
|
hsoShipBounce = NULL;
|
|
SndObjDestroy(hsoDonutExplode);
|
|
hsoDonutExplode = NULL;
|
|
SndObjDestroy(hsoPyramidExplode);
|
|
hsoPyramidExplode = NULL;
|
|
SndObjDestroy(hsoCubeExplode);
|
|
hsoCubeExplode = NULL;
|
|
SndObjDestroy(hsoSphereExplode);
|
|
hsoSphereExplode = NULL;
|
|
|
|
lpDS->lpVtbl->Release(lpDS);
|
|
lpDS = NULL;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
int getint(char**p, int def)
|
|
{
|
|
int i=0;
|
|
|
|
|
|
while (IS_SPACE(**p))
|
|
(*p)++;
|
|
|
|
if (!IS_NUM(**p))
|
|
return def;
|
|
|
|
while (IS_NUM(**p))
|
|
i = i*10 + *(*p)++ - '0';
|
|
|
|
while (IS_SPACE(**p))
|
|
(*p)++;
|
|
|
|
return i;
|
|
}
|
|
|