1908 lines
56 KiB
C++
1908 lines
56 KiB
C++
//-----------------------------------------------------------------------------
|
|
// File: ffdonuts.cpp
|
|
//
|
|
// Desc: DirectInput Semantic Mapper version of Donuts game
|
|
//
|
|
// Copyright (C) 1995-2000 Microsoft Corporation. All Rights Reserved.
|
|
//-----------------------------------------------------------------------------
|
|
#define STRICT
|
|
#define INITGUID
|
|
#include <windows.h>
|
|
#include <cguid.h>
|
|
#include <mmsystem.h>
|
|
#include <ddraw.h>
|
|
#include <dsound.h>
|
|
#include <stdio.h>
|
|
#include "DDUtil.h"
|
|
#include "DIUtil.h"
|
|
#include "DSUtil.h"
|
|
#include "resource.h"
|
|
#include "ffdonuts.h"
|
|
|
|
|
|
// DirectDraw objects
|
|
LPDIRECTDRAW7 g_pDD = NULL;
|
|
LPDIRECTDRAWPALETTE g_pArtPalette = NULL;
|
|
LPDIRECTDRAWPALETTE g_pSplashPalette = NULL;
|
|
LPDIRECTDRAWSURFACE7 g_pddsFrontBuffer = NULL;
|
|
LPDIRECTDRAWSURFACE7 g_pddsBackBuffer = NULL;
|
|
LPDIRECTDRAWSURFACE7 g_pddsDonut = NULL;
|
|
LPDIRECTDRAWSURFACE7 g_pddsPyramid = NULL;
|
|
LPDIRECTDRAWSURFACE7 g_pddsCube = NULL;
|
|
LPDIRECTDRAWSURFACE7 g_pddsSphere = NULL;
|
|
LPDIRECTDRAWSURFACE7 g_pddsShip = NULL;
|
|
LPDIRECTDRAWSURFACE7 g_pddsNumbers = NULL;
|
|
LPDIRECTDRAWSURFACE7 g_pddsDIConfig = NULL;
|
|
|
|
// DirectSound and DSUtil sound objects
|
|
LPDIRECTSOUND g_pDS = NULL;
|
|
SoundObject* g_pBeginLevelSound = NULL;
|
|
SoundObject* g_pEngineIdleSound = NULL;
|
|
SoundObject* g_pEngineRevSound = NULL;
|
|
SoundObject* g_pSkidToStopSound = NULL;
|
|
SoundObject* g_pShieldBuzzSound = NULL;
|
|
SoundObject* g_pShipExplodeSound = NULL;
|
|
SoundObject* g_pFireBulletSound = NULL;
|
|
SoundObject* g_pShipBounceSound = NULL;
|
|
SoundObject* g_pDonutExplodeSound = NULL;
|
|
SoundObject* g_pPyramidExplodeSound = NULL;
|
|
SoundObject* g_pCubeExplodeSound = NULL;
|
|
SoundObject* g_pSphereExplodeSound = NULL;
|
|
|
|
#if 0 //not used for mapper
|
|
BOOL g_bEngineIdle = FALSE;
|
|
BOOL g_bShieldsOn = FALSE;
|
|
BOOL g_bThrusting = FALSE;
|
|
|
|
DWORD lastInput = 0;
|
|
BOOL g_bLastShield = FALSE;
|
|
#endif //not used for mapper
|
|
BOOL lastThrust = FALSE;
|
|
FLOAT g_fShowDelay = 0.0f;
|
|
HWND g_hWndMain;
|
|
BOOL g_bIsActive;
|
|
BOOL g_bIsReady = FALSE;
|
|
BOOL g_bMouseVisible;
|
|
DWORD g_dwLastTickCount;
|
|
DWORD g_dwScore = 0;
|
|
int g_ProgramState;
|
|
DWORD g_dwLevel = 0;
|
|
DWORD g_dwFillColor;
|
|
BOOL g_bLeaveTrails = FALSE;
|
|
DWORD g_dwScreenWidth = 1024;
|
|
DWORD g_dwScreenHeight = 768;
|
|
DWORD g_dwScreenDepth = 16;
|
|
BOOL g_bSoundEnabled = FALSE;
|
|
|
|
DisplayObject* g_pDisplayList = NULL; // Display List
|
|
DisplayObject* g_pShip = NULL; // Main ship
|
|
DisplayObject* g_pShipsArray[NUMBER_OF_PLAYERS]; //array for all the players' ships
|
|
|
|
extern IDirectInput8* g_pDI; // DirectInput object
|
|
extern DWORD g_dwNumDevices[NUMBER_OF_PLAYERS];
|
|
extern IDirectInputDevice8* g_pDevices[NUMBER_OF_PLAYERS][MAX_INPUT_DEVICES+1];
|
|
extern DIACTIONFORMAT diActF;
|
|
extern LPTSTR lpUserName;
|
|
DWORD dwInputState[NUMBER_OF_PLAYERS]; //to persist the input state
|
|
|
|
|
|
BOOL CALLBACK ConfigureDevicesCallback(LPVOID lpVoid, LPVOID lpUserData)
|
|
{
|
|
UpdateFrame((LPDIRECTDRAWSURFACE7)lpVoid);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: SetupGame()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID SetupGame()
|
|
{
|
|
AdvanceLevel();
|
|
|
|
// Set the palette
|
|
g_pddsFrontBuffer->SetPalette( g_pArtPalette );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: MainWndproc()
|
|
// Desc: Callback for all Windows messages
|
|
//-----------------------------------------------------------------------------
|
|
long FAR PASCAL MainWndproc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
PAINTSTRUCT ps;
|
|
HDC hdc;
|
|
|
|
switch( msg )
|
|
{
|
|
case WM_ACTIVATEAPP:
|
|
g_bIsActive = (BOOL) wParam;
|
|
if( g_bIsActive )
|
|
{
|
|
g_bMouseVisible = FALSE;
|
|
g_dwLastTickCount = GetTickCount();
|
|
g_bLeaveTrails = FALSE;
|
|
|
|
// Need to reacquire the device
|
|
#if 0 //not used in the Semantic Mapper demo
|
|
if( g_pdidJoystick )
|
|
g_pdidJoystick->Acquire();
|
|
#endif //not used in the Semantic Mapper demo
|
|
}
|
|
else
|
|
{
|
|
g_bMouseVisible = TRUE;
|
|
}
|
|
break;
|
|
|
|
case WM_CREATE:
|
|
break;
|
|
|
|
case WM_SETCURSOR:
|
|
if( !g_bMouseVisible && g_bIsReady )
|
|
SetCursor(NULL);
|
|
else
|
|
SetCursor(LoadCursor( NULL, IDC_ARROW ));
|
|
return TRUE;
|
|
|
|
case WM_KEYDOWN:
|
|
switch( wParam )
|
|
{
|
|
case VK_F3:
|
|
if( g_bSoundEnabled )
|
|
DestroySound();
|
|
else
|
|
InitializeSound( hWnd );
|
|
|
|
break;
|
|
|
|
|
|
case VK_ESCAPE:
|
|
case VK_F12:
|
|
PostMessage( hWnd, WM_CLOSE, 0, 0 );
|
|
return 0;
|
|
|
|
case VK_F1:
|
|
g_bLeaveTrails = !g_bLeaveTrails;
|
|
break;
|
|
|
|
case VK_F2:
|
|
{
|
|
|
|
DIUtil_ConfigureDevices(hWnd, g_pddsDIConfig, DICD_DEFAULT);
|
|
break;
|
|
|
|
}
|
|
case VK_F4:
|
|
{
|
|
DIUtil_ConfigureDevices(hWnd, g_pddsDIConfig, DICD_EDIT);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
#if 0 //not used in the Semantic Mapper demo
|
|
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;
|
|
#endif //not used in the Semantic Mapper demo
|
|
|
|
case WM_ERASEBKGND:
|
|
return 1;
|
|
|
|
case WM_PAINT:
|
|
hdc = BeginPaint( hWnd, &ps );
|
|
EndPaint( hWnd, &ps );
|
|
return 1;
|
|
|
|
case WM_DESTROY:
|
|
#if 0 //not used for mapper
|
|
lastInput=0;
|
|
#endif //not used for mapper
|
|
DestroyGame();
|
|
PostQuitMessage( 0 );
|
|
break;
|
|
}
|
|
|
|
return (LONG) DefWindowProc( hWnd, msg, wParam, lParam );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: WinMain()
|
|
// Desc: Application entry point
|
|
//-----------------------------------------------------------------------------
|
|
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow )
|
|
{
|
|
|
|
// Register the window class
|
|
WNDCLASS wndClass = { CS_DBLCLKS, (WNDPROC)MainWndproc, 0, 0, hInstance,
|
|
LoadIcon( hInstance, MAKEINTRESOURCE(DONUTS_ICON) ),
|
|
LoadCursor( NULL, IDC_ARROW ),
|
|
(HBRUSH)GetStockObject( BLACK_BRUSH ),
|
|
NULL, TEXT("DonutsClass") };
|
|
RegisterClass( &wndClass );
|
|
|
|
// Create our main window
|
|
g_hWndMain = CreateWindowEx( 0, TEXT("DonutsClass"), TEXT("Donuts"),
|
|
WS_VISIBLE|WS_POPUP|WS_CAPTION|WS_SYSMENU,
|
|
0, 0, GetSystemMetrics(SM_CXSCREEN),
|
|
GetSystemMetrics(SM_CYSCREEN), NULL, NULL,
|
|
hInstance, NULL );
|
|
if( NULL == g_hWndMain )
|
|
return FALSE;
|
|
UpdateWindow( g_hWndMain );
|
|
|
|
g_bIsReady = TRUE;
|
|
|
|
if( FAILED( InitializeGame( g_hWndMain ) ) )
|
|
{
|
|
DestroyWindow( g_hWndMain );
|
|
return FALSE;
|
|
}
|
|
|
|
while( 1 )
|
|
{
|
|
MSG msg;
|
|
|
|
if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
|
|
{
|
|
if( FALSE == GetMessage( &msg, NULL, 0, 0 ) )
|
|
return (int) msg.wParam;
|
|
|
|
TranslateMessage( &msg );
|
|
DispatchMessage( &msg );
|
|
}
|
|
else if( g_bIsActive )
|
|
{
|
|
UpdateFrame();
|
|
}
|
|
else
|
|
{
|
|
WaitMessage();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DestroyGame()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID DestroyGame()
|
|
{
|
|
DestroySound();
|
|
DestroyInput();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: UpdateShips()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID UpdateShips()
|
|
{
|
|
//the main ship will always be there
|
|
//but update all the others, based on whether
|
|
//the particular user has any devices
|
|
for (int pl = 1; pl < NUMBER_OF_PLAYERS; pl ++)
|
|
{
|
|
//if the corresponding player is still playing
|
|
if (g_pDevices[pl][0] != NULL)
|
|
{
|
|
//if not created already, create new
|
|
if (g_pShipsArray[pl] == NULL)
|
|
{
|
|
g_pShipsArray[pl] = CreateObject(OBJ_SHIP, (FLOAT)(g_dwScreenWidth/(pl+1)-16), (FLOAT)(g_dwScreenHeight/(pl+1)-16), 0, 0, pl);
|
|
}
|
|
//if already created, keep it
|
|
}
|
|
else //player is gone
|
|
{
|
|
//if there is a ship for this player, delete it
|
|
if (g_pShipsArray[pl] != NULL)
|
|
{
|
|
DeleteFromList(g_pShipsArray[pl]);
|
|
g_pShipsArray[pl] = NULL;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: InitializeGame()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT InitializeGame( HWND hWnd )
|
|
{
|
|
LPDIRECTDRAW pDD;
|
|
HRESULT hr;
|
|
DDSURFACEDESC2 ddsd;
|
|
|
|
// Create DirectDraw
|
|
if( SUCCEEDED( hr = DirectDrawCreate( NULL, &pDD, NULL ) ) )
|
|
{
|
|
// Get DirectDraw4 interface
|
|
hr = pDD->QueryInterface( IID_IDirectDraw7, (VOID**)&g_pDD );
|
|
pDD->Release();
|
|
}
|
|
if( FAILED(hr) )
|
|
{
|
|
CleanupAndDisplayError("DirectDrawCreate Failed!");
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Set the cooperative level for fullscreen mode
|
|
hr = g_pDD->SetCooperativeLevel( hWnd,
|
|
DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
|
|
if( FAILED(hr) )
|
|
{
|
|
CleanupAndDisplayError("SetCooperativeLevel Failed");
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Set the display mode
|
|
hr = g_pDD->SetDisplayMode( g_dwScreenWidth, g_dwScreenHeight,
|
|
g_dwScreenDepth, 0, 0 );
|
|
if( FAILED(hr) )
|
|
{
|
|
CleanupAndDisplayError("SetDisplayMode Failed!");
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Create surfaces
|
|
ZeroMemory( &ddsd, sizeof( ddsd ) );
|
|
ddsd.dwSize = sizeof( ddsd );
|
|
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
|
|
DDSCAPS_COMPLEX;
|
|
ddsd.dwBackBufferCount = 1;
|
|
|
|
// Create the front buffer
|
|
hr = g_pDD->CreateSurface( &ddsd, &g_pddsFrontBuffer, NULL );
|
|
if( FAILED(hr) )
|
|
{
|
|
CleanupAndDisplayError("CreateSurface FrontBuffer Failed!");
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Get a pointer to the back buffer
|
|
DDSCAPS2 ddscaps;
|
|
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
|
|
ddscaps.dwCaps2 = 0;
|
|
ddscaps.dwCaps3 = 0;
|
|
ddscaps.dwCaps4 = 0;
|
|
hr = g_pddsFrontBuffer->GetAttachedSurface( &ddscaps, &g_pddsBackBuffer );
|
|
if( FAILED(hr) )
|
|
{
|
|
CleanupAndDisplayError("GetAttachedSurface Failed!");
|
|
return E_FAIL;
|
|
}
|
|
|
|
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
|
|
ddsd.dwWidth = 320;
|
|
|
|
// Create the surfaces for the object images. (We're OR'ing the HRESULTs
|
|
// together, so we only need to check for failure once).
|
|
ddsd.dwHeight = 384;
|
|
hr |= g_pDD->CreateSurface( &ddsd, &g_pddsDonut, NULL );
|
|
|
|
ddsd.dwHeight = 128;
|
|
hr |= g_pDD->CreateSurface( &ddsd, &g_pddsPyramid, NULL );
|
|
|
|
ddsd.dwHeight = 32;
|
|
hr |= g_pDD->CreateSurface( &ddsd, &g_pddsCube, NULL );
|
|
|
|
ddsd.dwHeight = 32;
|
|
hr |= g_pDD->CreateSurface( &ddsd, &g_pddsSphere, NULL );
|
|
|
|
ddsd.dwHeight = 256;
|
|
hr |= g_pDD->CreateSurface( &ddsd, &g_pddsShip, NULL );
|
|
|
|
ddsd.dwHeight = 16;
|
|
hr |= g_pDD->CreateSurface( &ddsd, &g_pddsNumbers, NULL );
|
|
|
|
ddsd.dwWidth = 640;
|
|
ddsd.dwHeight = 480;
|
|
hr |= g_pDD->CreateSurface( &ddsd, &g_pddsDIConfig, NULL );
|
|
|
|
if( FAILED(hr) )
|
|
{
|
|
CleanupAndDisplayError("Could not create surfaces!");
|
|
return E_FAIL;
|
|
}
|
|
|
|
if( FAILED( RestoreSurfaces() ) )
|
|
{
|
|
CleanupAndDisplayError("RestoreSurfaces Failed!");
|
|
return E_FAIL;
|
|
}
|
|
|
|
//zero out the ship ptrs
|
|
for (int ship = 0; ship < NUMBER_OF_PLAYERS; ship++)
|
|
{
|
|
g_pShipsArray[ship] = NULL;
|
|
}
|
|
|
|
// Add a ship to the displaylist
|
|
g_pDisplayList = new DisplayObject;
|
|
g_pDisplayList->next = NULL;
|
|
g_pDisplayList->prev = NULL;
|
|
g_pDisplayList->type = OBJ_SHIP;
|
|
g_pDisplayList->pddsSurface = g_pddsShip;
|
|
g_pShip = g_pDisplayList;
|
|
|
|
//and save the ptr
|
|
g_pShipsArray[0] = g_pShip;
|
|
|
|
//initialize input
|
|
for (ship = 0; ship < NUMBER_OF_PLAYERS; ship ++)
|
|
{
|
|
dwInputState[ship] = 0;
|
|
}
|
|
|
|
g_dwLastTickCount = GetTickCount();
|
|
|
|
if( FAILED( InitializeInput( hWnd ) ) )
|
|
return E_FAIL;
|
|
//if( FAILED( InitializeSound( hWnd ) ) )
|
|
// return E_FAIL;
|
|
|
|
g_ProgramState = PS_SPLASH;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CleanupAndDisplayError()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID CleanupAndDisplayError( CHAR* strError )
|
|
{
|
|
CHAR buffer[80];
|
|
sprintf( buffer, "Error: %s\n", strError );
|
|
OutputDebugString( buffer );
|
|
|
|
// Make the cursor visible
|
|
SetCursor( LoadCursor( NULL, IDC_ARROW ) );
|
|
g_bMouseVisible = TRUE;
|
|
|
|
if( g_pddsDonut )
|
|
g_pddsDonut->Release();
|
|
|
|
if( g_pddsPyramid )
|
|
g_pddsPyramid->Release();
|
|
|
|
if( g_pddsCube )
|
|
g_pddsCube->Release();
|
|
|
|
if( g_pddsSphere )
|
|
g_pddsSphere->Release();
|
|
|
|
if( g_pddsShip )
|
|
g_pddsShip->Release();
|
|
|
|
if( g_pddsNumbers )
|
|
g_pddsNumbers->Release();
|
|
|
|
if( g_pddsDIConfig )
|
|
g_pddsDIConfig->Release();
|
|
|
|
if( g_pddsFrontBuffer )
|
|
g_pddsFrontBuffer->Release();
|
|
|
|
if( g_pArtPalette )
|
|
g_pArtPalette->Release();
|
|
|
|
if( g_pSplashPalette )
|
|
g_pSplashPalette->Release();
|
|
|
|
if( g_pDD )
|
|
g_pDD->Release();
|
|
|
|
MessageBox( g_hWndMain, strError, "ERROR", MB_OK );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DisplaySplashScreen()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT DisplaySplashScreen()
|
|
{
|
|
HBITMAP hbm;
|
|
hbm = (HBITMAP)LoadImage( GetModuleHandle( NULL ), "SPLASH", IMAGE_BITMAP,
|
|
0, 0, LR_CREATEDIBSECTION );
|
|
if( NULL == hbm )
|
|
return E_FAIL;
|
|
|
|
// Set the palette before loading the splash screen
|
|
g_pddsFrontBuffer->SetPalette( g_pSplashPalette );
|
|
|
|
// If the surface is lost, DDCopyBitmap will fail and the surface will
|
|
// be restored in FlipScreen().
|
|
DDUtil_CopyBitmap( g_pddsBackBuffer, hbm, 0, 0, 0, 0 );
|
|
|
|
// Done with the bitmap
|
|
DeleteObject( hbm );
|
|
|
|
// Show the backbuffer contents on the frontbuffer
|
|
if( FAILED( FlipScreen() ) )
|
|
return E_FAIL;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: PlayPannedSound()
|
|
// Desc: Play a sound, but first set the panning according to where the
|
|
// object is on the screen.
|
|
//-----------------------------------------------------------------------------
|
|
VOID PlayPannedSound( SoundObject* pSound, DisplayObject* pObject )
|
|
{
|
|
if( NULL == pObject )
|
|
return;
|
|
|
|
DWORD dwCenter = ( pObject->rcDst.right + pObject->rcDst.left ) / 2;
|
|
FLOAT fCenter = ( 2.0f * ((FLOAT)dwCenter)/g_dwScreenWidth ) - 1.0f;
|
|
|
|
DSUtil_PlayPannedSound( pSound, fCenter );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: UpdateFrame()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID UpdateFrame(LPDIRECTDRAWSURFACE7 lpddsConfigDlg)
|
|
{
|
|
static FLOAT fLevelIntroTime;
|
|
|
|
switch( g_ProgramState )
|
|
{
|
|
case PS_SPLASH:
|
|
// Display the splash screen
|
|
//DisplaySplashScreen();
|
|
g_ProgramState = PS_BEGINREST;
|
|
SetupGame();
|
|
|
|
break;
|
|
|
|
case PS_ACTIVE:
|
|
UpdateDisplayList();
|
|
CheckForHits();
|
|
DrawDisplayList(lpddsConfigDlg);
|
|
|
|
if( IsDisplayListEmptyExceptShips() )
|
|
{
|
|
DSUtil_StopSound( g_pEngineIdleSound );
|
|
DSUtil_StopSound( g_pEngineRevSound );
|
|
|
|
#if 0 //not used for the mulit-user mapper
|
|
g_bEngineIdle = FALSE;
|
|
g_bThrusting = FALSE;
|
|
lastThrust = FALSE;
|
|
g_bLastShield = FALSE;
|
|
#endif //not used for the mulit-user mapper
|
|
g_ProgramState = PS_BEGINREST;
|
|
AdvanceLevel();
|
|
}
|
|
break;
|
|
|
|
case PS_BEGINREST:
|
|
DSUtil_PlaySound(g_pBeginLevelSound, 0);
|
|
fLevelIntroTime = GetTickCount()/1000.0f;
|
|
g_ProgramState = PS_REST;
|
|
|
|
// Fall through to PS_REST state
|
|
|
|
case PS_REST:
|
|
// Show the Level intro screen for 3 seconds
|
|
if( ( GetTickCount()/1000.0f - fLevelIntroTime ) > 3.0f )
|
|
{
|
|
DSUtil_PlaySound( g_pEngineIdleSound, DSBPLAY_LOOPING );
|
|
#if 0 //not used for the mulit-user mapper
|
|
g_bEngineIdle = TRUE;
|
|
#endif //not used for the mulit-user mapper
|
|
g_dwLastTickCount = GetTickCount();
|
|
g_ProgramState = PS_ACTIVE;
|
|
}
|
|
else
|
|
{
|
|
DisplayLevelIntroScreen( g_dwLevel );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DisplayLevelIntroScreen()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID DisplayLevelIntroScreen( DWORD dwLevel )
|
|
{
|
|
// Erase the screen
|
|
EraseScreen();
|
|
|
|
// Output the bitmapped letters for the word "Level"
|
|
CHAR buffer[10];
|
|
buffer[0] = 10 + '0';
|
|
buffer[1] = 11 + '0';
|
|
buffer[2] = 12 + '0';
|
|
buffer[3] = 11 + '0';
|
|
buffer[4] = 10 + '0';
|
|
buffer[5] = '\0';
|
|
BltBitmappedText( buffer, g_dwScreenWidth/2-64, g_dwScreenHeight/2-8 );
|
|
|
|
// Output the bitmapped numbers for the level number
|
|
buffer[0] = (CHAR)(dwLevel/100) + '0';
|
|
buffer[1] = (CHAR)(dwLevel/ 10) + '0';
|
|
buffer[2] = (CHAR)(dwLevel% 10) + '0';
|
|
buffer[3] = '\0';
|
|
BltBitmappedText( buffer, g_dwScreenWidth/2+22, g_dwScreenHeight/2-8 );
|
|
|
|
// Show the backbuffer screen on the front buffer
|
|
FlipScreen();
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: BltBitmappedText()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID BltBitmappedText( CHAR* num, int x, int y )
|
|
{
|
|
for( CHAR* c = num; *c != '\0'; c++ )
|
|
{
|
|
HRESULT hr = DDERR_WASSTILLDRAWING;
|
|
RECT rcSrc;
|
|
|
|
rcSrc.left = (*c - '0')*16;
|
|
rcSrc.top = 0;
|
|
rcSrc.right = rcSrc.left + 16;
|
|
rcSrc.bottom = rcSrc.top + 16;
|
|
|
|
while( hr == DDERR_WASSTILLDRAWING )
|
|
{
|
|
hr = g_pddsBackBuffer->BltFast( x, y, g_pddsNumbers, &rcSrc,
|
|
DDBLTFAST_SRCCOLORKEY );
|
|
}
|
|
|
|
x += 16;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CheckForHits()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID CheckForHits()
|
|
{
|
|
DisplayObject* pObject;
|
|
DisplayObject* bullet;
|
|
|
|
// Update screen rects
|
|
for( pObject = g_pDisplayList; pObject; pObject = pObject->next )
|
|
{
|
|
int frame = (DWORD)pObject->frame;
|
|
|
|
switch( pObject->type )
|
|
{
|
|
case OBJ_DONUT:
|
|
pObject->rcDst.left = (DWORD)pObject->posx;
|
|
pObject->rcDst.top = (DWORD)pObject->posy;
|
|
pObject->rcDst.right = pObject->rcDst.left + DONUT_WIDTH;
|
|
pObject->rcDst.bottom = pObject->rcDst.top + DONUT_HEIGHT;
|
|
pObject->rcSrc.left = DONUT_WIDTH * (frame % 5);
|
|
pObject->rcSrc.top = DONUT_HEIGHT * (frame /5);
|
|
pObject->rcSrc.right = pObject->rcSrc.left + DONUT_WIDTH;
|
|
pObject->rcSrc.bottom = pObject->rcSrc.top + DONUT_HEIGHT;
|
|
break;
|
|
|
|
case OBJ_PYRAMID:
|
|
pObject->rcDst.left = (DWORD)pObject->posx;
|
|
pObject->rcDst.top = (DWORD)pObject->posy;
|
|
pObject->rcDst.right = pObject->rcDst.left + PYRAMID_WIDTH;
|
|
pObject->rcDst.bottom = pObject->rcDst.top + PYRAMID_HEIGHT;
|
|
pObject->rcSrc.left = PYRAMID_WIDTH * (frame % 10);
|
|
pObject->rcSrc.top = PYRAMID_HEIGHT * (frame /10);
|
|
pObject->rcSrc.right = pObject->rcSrc.left + PYRAMID_WIDTH;
|
|
pObject->rcSrc.bottom = pObject->rcSrc.top + PYRAMID_HEIGHT;
|
|
break;
|
|
|
|
case OBJ_SPHERE:
|
|
pObject->rcDst.left = (DWORD)pObject->posx;
|
|
pObject->rcDst.top = (DWORD)pObject->posy;
|
|
pObject->rcDst.right = pObject->rcDst.left + SPHERE_WIDTH;
|
|
pObject->rcDst.bottom = pObject->rcDst.top + SPHERE_HEIGHT;
|
|
pObject->rcSrc.left = SPHERE_WIDTH * (frame % 20);
|
|
pObject->rcSrc.top = SPHERE_HEIGHT * (frame /20);
|
|
pObject->rcSrc.right = pObject->rcSrc.left + SPHERE_WIDTH;
|
|
pObject->rcSrc.bottom = pObject->rcSrc.top + SPHERE_HEIGHT;
|
|
break;
|
|
case OBJ_CUBE:
|
|
pObject->rcDst.left = (DWORD)pObject->posx;
|
|
pObject->rcDst.top = (DWORD)pObject->posy;
|
|
pObject->rcDst.right = pObject->rcDst.left + CUBE_WIDTH;
|
|
pObject->rcDst.bottom = pObject->rcDst.top + CUBE_HEIGHT;
|
|
pObject->rcSrc.left = CUBE_WIDTH * (frame % 20);
|
|
pObject->rcSrc.top = CUBE_HEIGHT * (frame /20);
|
|
pObject->rcSrc.right = pObject->rcSrc.left + CUBE_WIDTH;
|
|
pObject->rcSrc.bottom = pObject->rcSrc.top + CUBE_HEIGHT;
|
|
break;
|
|
|
|
case OBJ_SHIP:
|
|
pObject->rcDst.left = (DWORD)pObject->posx;
|
|
pObject->rcDst.top = (DWORD)pObject->posy;
|
|
pObject->rcDst.right = pObject->rcDst.left + SHIP_WIDTH;
|
|
pObject->rcDst.bottom = pObject->rcDst.top + SHIP_HEIGHT;
|
|
#if 0 //not used for the mulit-user mapper
|
|
if( g_bLastShield )
|
|
pObject->rcSrc.top = SHIP_HEIGHT * (frame / 10) + 128;
|
|
else
|
|
#endif //not used for the mulit-user mapper
|
|
pObject->rcSrc.top = SHIP_HEIGHT * (frame /10);
|
|
pObject->rcSrc.left = SHIP_WIDTH * (frame % 10);
|
|
pObject->rcSrc.right = pObject->rcSrc.left + SHIP_WIDTH;
|
|
pObject->rcSrc.bottom = pObject->rcSrc.top + SHIP_HEIGHT;
|
|
break;
|
|
|
|
case OBJ_BULLET:
|
|
frame = (DWORD)pObject->frame/20 % 4;
|
|
pObject->rcDst.left = (DWORD)pObject->posx;
|
|
pObject->rcDst.top = (DWORD)pObject->posy;
|
|
pObject->rcDst.right = pObject->rcDst.left + BULLET_WIDTH;
|
|
pObject->rcDst.bottom = pObject->rcDst.top + BULLET_HEIGHT;
|
|
pObject->rcSrc.left = BULLET_XOFFSET + frame*4;
|
|
pObject->rcSrc.top = BULLET_YOFFSET;
|
|
pObject->rcSrc.right = pObject->rcSrc.left + BULLET_WIDTH;
|
|
pObject->rcSrc.bottom = pObject->rcSrc.top + BULLET_HEIGHT;
|
|
break;
|
|
}
|
|
}
|
|
for( bullet = g_pDisplayList; bullet; bullet = bullet->next )
|
|
{
|
|
// Only bullet objects and the ship (if shields are on) can hit
|
|
// other objects. Skip all others.
|
|
if( (bullet->type != OBJ_BULLET) && (bullet->type != OBJ_SHIP) )
|
|
continue;
|
|
|
|
#if 0 //not used for the mulit-user mapper
|
|
// The ship cannot hit anything with shields on
|
|
if( bullet->type == OBJ_SHIP && TRUE == g_bLastShield )
|
|
continue;
|
|
#endif //not used for the mulit-user mapper
|
|
|
|
BOOL bBulletHit = FALSE;
|
|
WORD wBulletX = (WORD)(bullet->rcDst.left + bullet->rcDst.right) / 2;
|
|
WORD wBulletY = (WORD)(bullet->rcDst.top + bullet->rcDst.bottom) / 2;
|
|
|
|
for( pObject = g_pDisplayList; pObject; pObject = pObject->next )
|
|
{
|
|
FLOAT left = (FLOAT)pObject->rcDst.left;
|
|
FLOAT right = (FLOAT)pObject->rcDst.right;
|
|
FLOAT top = (FLOAT)pObject->rcDst.top;
|
|
FLOAT bottom = (FLOAT)pObject->rcDst.bottom;
|
|
|
|
// Only trying to hit explodable targets
|
|
if( ( pObject->type != OBJ_DONUT ) &&
|
|
( pObject->type != OBJ_PYRAMID ) &&
|
|
( pObject->type != OBJ_SPHERE ) &&
|
|
( pObject->type != OBJ_SHIP ) &&
|
|
( pObject->type != OBJ_CUBE ) )
|
|
continue;
|
|
|
|
if( ( wBulletX >= left ) && ( wBulletX < right ) &&
|
|
( wBulletY >= top ) && ( wBulletY < bottom ) )
|
|
{
|
|
// The object was hit
|
|
switch( pObject->type )
|
|
{
|
|
case OBJ_DONUT:
|
|
PlayPannedSound( g_pDonutExplodeSound, pObject );
|
|
CreateObject( OBJ_PYRAMID, left, top, -1.0f, -1.0f, NO_PLAYER);
|
|
CreateObject( OBJ_PYRAMID, left, top, -1.0f, -1.0f, NO_PLAYER );
|
|
CreateObject( OBJ_PYRAMID, left, top, -1.0f, -1.0f, NO_PLAYER );
|
|
g_dwScore += 10;
|
|
break;
|
|
|
|
case OBJ_PYRAMID:
|
|
PlayPannedSound( g_pPyramidExplodeSound, pObject );
|
|
CreateObject( OBJ_SPHERE, left, top, -1.0f, -1.0f, NO_PLAYER );
|
|
CreateObject( OBJ_CUBE, left, top, -1.0f, -1.0f, NO_PLAYER );
|
|
CreateObject( OBJ_CUBE, left, top, -1.0f, -1.0f, NO_PLAYER );
|
|
g_dwScore += 20;
|
|
break;
|
|
|
|
case OBJ_CUBE:
|
|
PlayPannedSound( g_pCubeExplodeSound, pObject );
|
|
CreateObject( OBJ_SPHERE, left, top, -1.0f, -1.0f, NO_PLAYER );
|
|
CreateObject( OBJ_SPHERE, left, top, -1.0f, -1.0f, NO_PLAYER );
|
|
g_dwScore += 40;
|
|
break;
|
|
|
|
case OBJ_SPHERE:
|
|
PlayPannedSound( g_pSphereExplodeSound, pObject );
|
|
g_dwScore += 20;
|
|
break;
|
|
|
|
case OBJ_SHIP:
|
|
//can't be hit by bullets that come from us
|
|
if (bullet->Player != pObject->Player)
|
|
{
|
|
if(pObject->bVisible )
|
|
{
|
|
// Ship has exploded
|
|
PlayPannedSound( g_pShipExplodeSound, pObject);
|
|
if( g_dwScore < 150 )
|
|
g_dwScore = 0;
|
|
else
|
|
g_dwScore -= 150;
|
|
|
|
FLOAT x = pObject->posx;
|
|
FLOAT y = pObject->posy;
|
|
|
|
CreateObject( OBJ_SPHERE, x, y, -1.0f, -1.0f, NO_PLAYER);
|
|
CreateObject( OBJ_SPHERE, x, y, -1.0f, -1.0f, NO_PLAYER);
|
|
CreateObject( OBJ_SPHERE, x, y, -1.0f, -1.0f, NO_PLAYER);
|
|
CreateObject( OBJ_SPHERE, x, y, -1.0f, -1.0f, NO_PLAYER);
|
|
CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
|
|
CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
|
|
CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
|
|
CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
|
|
CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
|
|
CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
|
|
CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
|
|
CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
|
|
CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
|
|
CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
|
|
|
|
// Delay for 2 seconds before displaying ship
|
|
InitializeShips();
|
|
g_fShowDelay = 2.0f;
|
|
pObject->bVisible = FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
//only delete non-"ships"
|
|
if (pObject->type != OBJ_SHIP)
|
|
{
|
|
DisplayObject* pVictim = pObject;
|
|
pObject = pObject->prev;
|
|
DeleteFromList( pVictim );
|
|
bBulletHit = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: EraseScreen()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID EraseScreen()
|
|
{
|
|
// Erase the background
|
|
DDBLTFX ddbltfx;
|
|
ZeroMemory( &ddbltfx, sizeof(ddbltfx) );
|
|
ddbltfx.dwSize = sizeof(ddbltfx);
|
|
ddbltfx.dwFillColor = g_dwFillColor;
|
|
|
|
while( 1 )
|
|
{
|
|
HRESULT hr = g_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL,
|
|
&ddbltfx );
|
|
if( SUCCEEDED(hr) )
|
|
break;
|
|
|
|
if( hr == DDERR_SURFACELOST )
|
|
if( FAILED( RestoreSurfaces() ) )
|
|
return;
|
|
|
|
if( hr != DDERR_WASSTILLDRAWING )
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: FlipScreen()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT FlipScreen()
|
|
{
|
|
HRESULT hr = DDERR_WASSTILLDRAWING;
|
|
|
|
// Flip the surfaces
|
|
while( DDERR_WASSTILLDRAWING == hr )
|
|
{
|
|
hr = g_pddsFrontBuffer->Flip( NULL, 0 );
|
|
|
|
if( hr == DDERR_SURFACELOST )
|
|
if( FAILED( RestoreSurfaces() ) )
|
|
return E_FAIL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DrawDisplayList()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID DrawDisplayList(LPDIRECTDRAWSURFACE7 lpConfigDlgSurf)
|
|
{
|
|
if( FALSE == g_bLeaveTrails )
|
|
EraseScreen();
|
|
|
|
char scorebuf[11];
|
|
int rem;
|
|
|
|
rem = g_dwScore;
|
|
scorebuf[0] = rem/10000000 + '0';
|
|
rem = g_dwScore % 10000000;
|
|
scorebuf[1] = rem/1000000 + '0';
|
|
rem = g_dwScore % 1000000;
|
|
scorebuf[2] = rem/100000 + '0';
|
|
rem = g_dwScore % 100000;
|
|
scorebuf[3] = rem/10000 + '0';
|
|
rem = g_dwScore % 10000;
|
|
scorebuf[4] = rem/1000 + '0';
|
|
rem = g_dwScore % 1000;
|
|
scorebuf[5] = rem/100 + '0';
|
|
rem = g_dwScore % 100;
|
|
scorebuf[6] = rem/10 + '0';
|
|
rem = g_dwScore % 10;
|
|
scorebuf[7] = rem + '0';
|
|
scorebuf[8] = '\0';
|
|
|
|
// Draw the sound icon, if sound is enabled
|
|
if( g_bSoundEnabled )
|
|
{
|
|
scorebuf[8] = 14 + '0';
|
|
scorebuf[9] = 13 + '0';
|
|
scorebuf[10] = '\0';
|
|
}
|
|
|
|
// Display the score
|
|
BltBitmappedText( scorebuf, 10, g_dwScreenHeight-26 );
|
|
|
|
// Display all visible objects in the display list
|
|
for( DisplayObject* pObject = g_pDisplayList; pObject;
|
|
pObject = pObject->next )
|
|
{
|
|
if( !pObject->bVisible )
|
|
continue;
|
|
|
|
HRESULT hr = DDERR_WASSTILLDRAWING;
|
|
|
|
if( pObject->rcSrc.right - pObject->rcSrc.left == 0 )
|
|
continue; // New objects do not have a src rect yet.
|
|
|
|
while( hr == DDERR_WASSTILLDRAWING )
|
|
{
|
|
hr = g_pddsBackBuffer->BltFast( pObject->rcDst.left,
|
|
pObject->rcDst.top, pObject->pddsSurface,
|
|
&pObject->rcSrc, DDBLTFAST_SRCCOLORKEY );
|
|
|
|
}
|
|
}
|
|
|
|
// Flip the backbuffer contents to the front buffer
|
|
if (lpConfigDlgSurf)
|
|
{
|
|
g_pddsBackBuffer->BltFast((g_dwScreenWidth-640)/2, (g_dwScreenHeight-480)/2, lpConfigDlgSurf, NULL, DDBLTFAST_WAIT);
|
|
}
|
|
|
|
FlipScreen();
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DeleteFromList()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID DeleteFromList( DisplayObject* pObject )
|
|
{
|
|
if( pObject->next )
|
|
pObject->next->prev = pObject->prev;
|
|
if( pObject->prev )
|
|
pObject->prev->next = pObject->next;
|
|
delete( pObject );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: UpdateDisplayList()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID UpdateDisplayList()
|
|
{
|
|
DisplayObject* thisnode;
|
|
FLOAT maxx, maxy;
|
|
FLOAT maxframe;
|
|
DWORD input[NUMBER_OF_PLAYERS];//= lastInput;
|
|
for (int pl = 0; pl < NUMBER_OF_PLAYERS; pl ++)
|
|
{
|
|
input[pl] = 0;
|
|
}
|
|
|
|
// Update the game clock parameters
|
|
DWORD dwTickCount = GetTickCount();
|
|
FLOAT fTickDiff = ( dwTickCount - g_dwLastTickCount )/1000.0f;
|
|
g_dwLastTickCount = dwTickCount;
|
|
|
|
// Read input from the players' devices
|
|
GetDeviceInput(input);
|
|
|
|
for (int pl = 0; pl < NUMBER_OF_PLAYERS; pl ++)
|
|
{
|
|
BOOL bShieldState = FALSE;
|
|
BOOL bThrustState = FALSE;
|
|
BOOL bBounce = FALSE;
|
|
LONG lAngle = 0;
|
|
|
|
//if KEY_QUIT is pressed, exit
|
|
if (input[pl] & KEY_QUIT)
|
|
{
|
|
PostMessage( g_hWndMain, WM_CLOSE, 0, 0 );
|
|
return;
|
|
}
|
|
|
|
//if KEY_DISPLAY is pressed, call ConfigureDevices() in normal mode
|
|
if (input[pl] & KEY_DISPLAY)
|
|
{
|
|
//call ConfigureDevices() in default mode
|
|
DIUtil_ConfigureDevices(g_hWndMain, g_pddsDIConfig, DICD_DEFAULT);
|
|
}
|
|
|
|
//if KEY_EDIT is pressed, call ConfigureDevices() in edit mode
|
|
if (input[pl] & KEY_EDIT)
|
|
{
|
|
//call ConfigureDevices() in edit mode
|
|
DIUtil_ConfigureDevices(g_hWndMain, g_pddsDIConfig, DICD_EDIT);
|
|
}
|
|
|
|
if( g_fShowDelay > 0.0f )
|
|
{
|
|
g_fShowDelay -= fTickDiff;
|
|
|
|
if( g_fShowDelay < 0.0f )
|
|
{
|
|
InitializeShips();
|
|
#if 0 //not used for the mulit-user mapper
|
|
g_bLastShield = FALSE;
|
|
#endif //not used for the mulit-user mapper
|
|
g_fShowDelay = 0.0f;
|
|
if (g_pShipsArray[pl] != NULL)
|
|
{
|
|
g_pShipsArray[pl]->bVisible = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update the ships
|
|
if (g_pShipsArray[pl] != NULL)
|
|
{
|
|
if( g_pShipsArray[pl]->bVisible )
|
|
{
|
|
g_pShipsArray[pl]->posx += g_pShipsArray[pl]->velx * fTickDiff;
|
|
g_pShipsArray[pl]->posy += g_pShipsArray[pl]->vely * fTickDiff;
|
|
}
|
|
if( g_pShipsArray[pl]->posx > (FLOAT)(MAX_SCREEN_X - SHIP_WIDTH) )
|
|
{
|
|
g_pShipsArray[pl]->posx = (FLOAT)(MAX_SCREEN_X - SHIP_WIDTH);
|
|
g_pShipsArray[pl]->velx = -g_pShipsArray[pl]->velx;
|
|
|
|
// Bounce off the right edge of the screen
|
|
bBounce = TRUE;
|
|
lAngle = 90;
|
|
}
|
|
else if( g_pShipsArray[pl]->posx < 0 )
|
|
{
|
|
g_pShipsArray[pl]->posx = 0;
|
|
g_pShipsArray[pl]->velx = -g_pShipsArray[pl]->velx;
|
|
|
|
// Bounce off the left edge of the screen
|
|
bBounce = TRUE;
|
|
lAngle = 270;
|
|
}
|
|
|
|
if( g_pShipsArray[pl]->posy > (FLOAT)(MAX_SCREEN_Y - SHIP_HEIGHT) )
|
|
{
|
|
g_pShipsArray[pl]->posy = (FLOAT)(MAX_SCREEN_Y - SHIP_HEIGHT);
|
|
g_pShipsArray[pl]->vely = -g_pShipsArray[pl]->vely;
|
|
|
|
// Bounce off the bottom edge of the screen
|
|
bBounce = TRUE;
|
|
lAngle = 180;
|
|
}
|
|
else if( g_pShipsArray[pl]->posy < 0 )
|
|
{
|
|
g_pShipsArray[pl]->posy =0;
|
|
g_pShipsArray[pl]->vely = -g_pShipsArray[pl]->vely;
|
|
|
|
// Bounce off the top edge of the screen
|
|
bBounce = TRUE;
|
|
lAngle = 0;
|
|
}
|
|
|
|
if( bBounce )
|
|
{
|
|
// "Bounce" the ship
|
|
PlayPannedSound( g_pShipBounceSound, g_pShipsArray[pl] );
|
|
#if 0 //not used in the Semantic Mapper demo
|
|
DIUtil_PlayDirectionalEffect( g_pBounceFFEffect, lAngle );
|
|
#endif //not used in the Semantic Mapper demo
|
|
}
|
|
|
|
bShieldState = ( !g_pShipsArray[pl]->bVisible || ( input[pl] & KEY_SHIELD ) );
|
|
|
|
#if 0 //not used for the mulit-user mapper
|
|
if( bShieldState != g_bLastShield )
|
|
{
|
|
#endif //not used for the mulit-user mapper
|
|
if( bShieldState && g_pShipsArray[pl]->bVisible )
|
|
{
|
|
DSUtil_PlaySound( g_pShieldBuzzSound, DSBPLAY_LOOPING );
|
|
#if 0 //not used for the mulit-user mapper
|
|
g_bShieldsOn = TRUE;
|
|
#endif //not used for the mulit-user mapper
|
|
}
|
|
else
|
|
{
|
|
DSUtil_StopSound( g_pShieldBuzzSound );
|
|
#if 0 //not used for the mulit-user mapper
|
|
g_bShieldsOn = FALSE;
|
|
#endif //not used for the mulit-user mapper
|
|
}
|
|
#if 0 //not used for the mulit-user mapper
|
|
g_bLastShield = bShieldState;
|
|
}
|
|
#endif //not used for the mulit-user mapper
|
|
if( bShieldState )
|
|
{
|
|
input[pl] &= ~(KEY_FIRE);
|
|
}
|
|
|
|
if( input[pl] & KEY_FIRE )
|
|
{
|
|
// Add a bullet to the scene
|
|
if( g_pShipsArray[pl]->bVisible )
|
|
{
|
|
// Bullets cost one score point
|
|
if( g_dwScore )
|
|
g_dwScore--;
|
|
|
|
// Play the "fire" sound
|
|
DSUtil_PlaySound( g_pFireBulletSound, 0);
|
|
|
|
// Play the "fire" forcefeedback effect
|
|
#if 0 //not used in the Semantic Mapper demo
|
|
DIUtil_PlayEffect( g_pFireFFEffect );
|
|
#endif //not used in the Semantic Mapper demo
|
|
|
|
// Add a bullet to the display list
|
|
CreateObject( OBJ_BULLET,
|
|
Dirx[(int)g_pShipsArray[pl]->frame]*6.0f + 16.0f + g_pShipsArray[pl]->posx,
|
|
Diry[(int)g_pShipsArray[pl]->frame]*6.0f + 16.0f + g_pShipsArray[pl]->posy,
|
|
Dirx[(int)g_pShipsArray[pl]->frame]*500.0f,
|
|
Diry[(int)g_pShipsArray[pl]->frame]*500.0f,
|
|
pl);
|
|
}
|
|
}
|
|
|
|
if( input[pl] & KEY_LEFT )
|
|
{
|
|
g_pShipsArray[pl]->frame -= 1.0;
|
|
if( g_pShipsArray[pl]->frame < 0.0 )
|
|
g_pShipsArray[pl]->frame += MAX_SHIP_FRAME;
|
|
}
|
|
if( input[pl] & KEY_RIGHT )
|
|
{
|
|
g_pShipsArray[pl]->frame += 1.0;
|
|
if( g_pShipsArray[pl]->frame >= MAX_SHIP_FRAME )
|
|
g_pShipsArray[pl]->frame -= MAX_SHIP_FRAME;
|
|
}
|
|
if( input[pl] & KEY_UP )
|
|
{
|
|
g_pShipsArray[pl]->velx += Dirx[(int)g_pShipsArray[pl]->frame] * 10.0f;
|
|
g_pShipsArray[pl]->vely += Diry[(int)g_pShipsArray[pl]->frame] * 10.0f;
|
|
bThrustState = TRUE;
|
|
}
|
|
if( input[pl] & KEY_DOWN )
|
|
{
|
|
g_pShipsArray[pl]->velx -= Dirx[(int)g_pShipsArray[pl]->frame] * 10.0f;
|
|
g_pShipsArray[pl]->vely -= Diry[(int)g_pShipsArray[pl]->frame] * 10.0f;
|
|
bThrustState = TRUE;
|
|
}
|
|
|
|
if( bThrustState != lastThrust )
|
|
{
|
|
if( bThrustState )
|
|
{
|
|
input[pl] &= ~KEY_STOP;
|
|
DSUtil_StopSound( g_pSkidToStopSound );
|
|
DSUtil_PlaySound( g_pEngineRevSound, DSBPLAY_LOOPING );
|
|
#if 0 //not used for the mulit-user mapper
|
|
g_bThrusting = TRUE;
|
|
#endif //not used for the mulit-user mapper
|
|
}
|
|
else
|
|
{
|
|
DSUtil_StopSound( g_pEngineRevSound );
|
|
#if 0 //not used for the mulit-user mapper
|
|
g_bThrusting = FALSE;
|
|
#endif //not used for the mulit-user mapper
|
|
}
|
|
|
|
lastThrust = bThrustState;
|
|
}
|
|
|
|
if( input[pl] & KEY_STOP )
|
|
{
|
|
if( g_pShipsArray[pl]->velx || g_pShipsArray[pl]->vely )
|
|
PlayPannedSound( g_pSkidToStopSound, g_pShipsArray[pl] );
|
|
|
|
g_pShipsArray[pl]->velx = 0.0f;
|
|
g_pShipsArray[pl]->vely = 0.0f;
|
|
}
|
|
}
|
|
}
|
|
|
|
for( thisnode = g_pDisplayList->next; thisnode; )
|
|
{
|
|
//for things other than ships, which were handled above
|
|
if (thisnode->type != OBJ_SHIP)
|
|
{
|
|
thisnode->posx += thisnode->velx * fTickDiff;
|
|
thisnode->posy += thisnode->vely * fTickDiff;
|
|
thisnode->frame += thisnode->delay * fTickDiff;
|
|
switch( thisnode->type )
|
|
{
|
|
case OBJ_DONUT:
|
|
maxx = (FLOAT)(MAX_SCREEN_X - DONUT_WIDTH);
|
|
maxy = (FLOAT)(MAX_SCREEN_Y - DONUT_HEIGHT);
|
|
maxframe = MAX_DONUT_FRAME;
|
|
break;
|
|
case OBJ_PYRAMID:
|
|
maxx = (FLOAT)(MAX_SCREEN_X - PYRAMID_WIDTH);
|
|
maxy = (FLOAT)(MAX_SCREEN_Y - PYRAMID_HEIGHT);
|
|
maxframe = MAX_PYRAMID_FRAME;
|
|
break;
|
|
case OBJ_SPHERE:
|
|
maxx = (FLOAT)(MAX_SCREEN_X - SPHERE_WIDTH);
|
|
maxy = (FLOAT)(MAX_SCREEN_Y - SPHERE_HEIGHT);
|
|
maxframe = MAX_SPHERE_FRAME;
|
|
break;
|
|
case OBJ_CUBE:
|
|
maxx = (FLOAT)(MAX_SCREEN_X - CUBE_WIDTH);
|
|
maxy = (FLOAT)(MAX_SCREEN_Y - CUBE_HEIGHT);
|
|
maxframe = MAX_CUBE_FRAME;
|
|
break;
|
|
case OBJ_BULLET:
|
|
maxx = (FLOAT)(MAX_SCREEN_X - BULLET_WIDTH);
|
|
maxy = (FLOAT)(MAX_SCREEN_Y - BULLET_HEIGHT);
|
|
maxframe = MAX_BULLET_FRAME;
|
|
|
|
// If bullet "expired", removed it from list
|
|
if( thisnode->frame >= MAX_BULLET_FRAME )
|
|
{
|
|
DisplayObject* pVictim = thisnode;
|
|
thisnode = thisnode->next;
|
|
DeleteFromList( pVictim );
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
if( thisnode != g_pDisplayList )
|
|
{
|
|
if( thisnode->posx > maxx )
|
|
{
|
|
thisnode->posx = maxx;
|
|
thisnode->velx = -thisnode->velx;
|
|
}
|
|
else if ( thisnode->posx < 0 )
|
|
{
|
|
thisnode->posx =0;
|
|
thisnode->velx = -thisnode->velx;
|
|
}
|
|
if( thisnode->posy > maxy )
|
|
{
|
|
thisnode->posy = maxy;
|
|
thisnode->vely = -thisnode->vely;
|
|
}
|
|
else if ( thisnode->posy < 0 )
|
|
{
|
|
thisnode->posy =0;
|
|
thisnode->vely = -thisnode->vely;
|
|
}
|
|
if( thisnode->frame >= maxframe )
|
|
{
|
|
thisnode->frame -= maxframe;
|
|
}
|
|
}
|
|
}
|
|
thisnode = thisnode->next;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: IsDisplayListEmpty()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
BOOL IsDisplayListEmpty()
|
|
{
|
|
DisplayObject* pObject = g_pDisplayList->next;
|
|
|
|
while( pObject )
|
|
{
|
|
if( pObject->type != OBJ_BULLET )
|
|
return FALSE;
|
|
|
|
pObject = pObject->next;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: IsDisplayListEmptyExceptShips()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
BOOL IsDisplayListEmptyExceptShips()
|
|
{
|
|
DisplayObject* pObject = g_pDisplayList->next;
|
|
|
|
while( pObject )
|
|
{
|
|
if(( pObject->type != OBJ_BULLET ) && (pObject->type != OBJ_SHIP))
|
|
return FALSE;
|
|
|
|
pObject = pObject->next;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: InitializeShips()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID InitializeShips()
|
|
{
|
|
for (int ship = 0; ship < NUMBER_OF_PLAYERS; ship++)
|
|
{
|
|
if (g_pShipsArray[ship] != NULL)
|
|
{
|
|
g_pShipsArray[ship]->posx = (FLOAT)(g_dwScreenWidth/(ship+2)-16); // Center the ship
|
|
g_pShipsArray[ship]->posy = (FLOAT)(g_dwScreenHeight/(ship+2)-16);
|
|
g_pShipsArray[ship]->frame = 0.0f;
|
|
g_pShipsArray[ship]->velx = 0.0f; // Not moving
|
|
g_pShipsArray[ship]->vely = 0.0f;
|
|
g_pShipsArray[ship]->bVisible = TRUE;
|
|
g_pShipsArray[ship]->Player = ship;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: AdvanceLevel()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID AdvanceLevel()
|
|
{
|
|
// Up the level
|
|
g_dwLevel++;
|
|
|
|
// Clear any stray objects (anything but the ships) out of the display list
|
|
while( (g_pShip->next != NULL) && (g_pShip->next->type != OBJ_SHIP ))
|
|
{
|
|
DeleteFromList( g_pShip->next );
|
|
}
|
|
|
|
// Create donuts for the new level
|
|
for( WORD i=0; i<(2*g_dwLevel-1); i++ )
|
|
{
|
|
FLOAT x = rnd( 0.0f, (FLOAT)(MAX_SCREEN_X - DONUT_WIDTH) );
|
|
FLOAT y = rnd( 0.0f, (FLOAT)(MAX_SCREEN_Y - DONUT_HEIGHT) );
|
|
|
|
CreateObject( OBJ_DONUT, x, y, 0.0f, 0.0f, NO_PLAYER );
|
|
}
|
|
|
|
// Delay for 2 seconds before displaying ships
|
|
InitializeShips();
|
|
g_fShowDelay = 2.0f;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CreateObject()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
DisplayObject* CreateObject( SHORT type, FLOAT x, FLOAT y, FLOAT vx, FLOAT vy, int Player )
|
|
{
|
|
// Create a new display object
|
|
DisplayObject* pObject = new DisplayObject;
|
|
if( NULL == pObject )
|
|
return NULL;
|
|
|
|
// Add the object to the global display list
|
|
AddToList( pObject );
|
|
|
|
// Set object attributes
|
|
pObject->bVisible = TRUE;
|
|
pObject->type = type;
|
|
pObject->posx = x;
|
|
pObject->posy = y;
|
|
pObject->velx = vx;
|
|
pObject->vely = vy;
|
|
pObject->Player = NO_PLAYER;
|
|
|
|
switch( type )
|
|
{
|
|
case OBJ_DONUT:
|
|
pObject->velx = rnd( -50.0f, 50.0f );
|
|
pObject->vely = rnd( -50.0f, 50.0f );
|
|
pObject->frame = rnd( 0.0f, 30.0f );
|
|
pObject->delay = rnd( 3.0f, 12.0f );
|
|
pObject->pddsSurface = g_pddsDonut;
|
|
break;
|
|
|
|
case OBJ_PYRAMID:
|
|
pObject->velx = rnd( -75.0f, 75.0f );
|
|
pObject->vely = rnd( -75.0f, 75.0f );
|
|
pObject->frame = rnd( 0.0f, 30.0f );
|
|
pObject->delay = rnd( 12.0f, 40.0f );
|
|
pObject->pddsSurface = g_pddsPyramid;
|
|
break;
|
|
|
|
case OBJ_SPHERE:
|
|
pObject->velx = rnd( -150.0f, 150.0f );
|
|
pObject->vely = rnd( -150.0f, 150.0f );
|
|
pObject->frame = rnd( 0.0f, 30.0f );
|
|
pObject->delay = rnd( 60.0f, 80.0f );
|
|
pObject->pddsSurface = g_pddsSphere;
|
|
break;
|
|
|
|
case OBJ_CUBE:
|
|
pObject->velx = rnd( -200.0f, 200.0f );
|
|
pObject->vely = rnd( -200.0f, 200.0f );
|
|
pObject->frame = rnd( 0.0f, 30.0f );
|
|
pObject->delay = rnd( 32.0f, 80.0f );
|
|
pObject->pddsSurface = g_pddsCube;
|
|
break;
|
|
|
|
case OBJ_SHIP:
|
|
pObject->frame = 0.0f;
|
|
pObject->posx = x;
|
|
pObject->posy = y;
|
|
pObject->velx = 0.0f; // Not moving
|
|
pObject->vely = 0.0f;
|
|
pObject->Player = Player; //which player the ship belongs to
|
|
pObject->pddsSurface = g_pddsShip;
|
|
break;
|
|
|
|
|
|
case OBJ_BULLET:
|
|
pObject->frame = 0.0f;
|
|
pObject->delay = 1000.0f;
|
|
pObject->Player = Player; //which player's ship shot the bullet
|
|
pObject->pddsSurface = g_pddsNumbers;
|
|
break;
|
|
}
|
|
|
|
return pObject;
|
|
};
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: AddToList()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID AddToList( DisplayObject* pObject )
|
|
{
|
|
pObject->next = g_pDisplayList->next;
|
|
pObject->prev = g_pDisplayList;
|
|
|
|
if( g_pDisplayList->next )
|
|
g_pDisplayList->next->prev = pObject;
|
|
g_pDisplayList->next = pObject;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: RestoreSurfaces()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT RestoreSurfaces()
|
|
{
|
|
HRESULT hr;
|
|
HBITMAP hbm;
|
|
|
|
if( FAILED( hr = g_pddsFrontBuffer->Restore() ) )
|
|
return E_FAIL;
|
|
if( FAILED( hr = g_pddsDonut->Restore() ) )
|
|
return E_FAIL;
|
|
if( FAILED( hr = g_pddsPyramid->Restore() ) )
|
|
return E_FAIL;
|
|
if( FAILED( hr = g_pddsCube->Restore() ) )
|
|
return E_FAIL;
|
|
if( FAILED( hr = g_pddsSphere->Restore() ) )
|
|
return E_FAIL;
|
|
if( FAILED( hr = g_pddsShip->Restore() ) )
|
|
return E_FAIL;
|
|
if( FAILED( hr = g_pddsNumbers->Restore() ) )
|
|
return E_FAIL;
|
|
|
|
// Create and set the palette for the splash bitmap
|
|
g_pSplashPalette = DDUtil_LoadPalette( g_pDD, "SPLASH" );
|
|
|
|
// Create and set the palette for the art bitmap
|
|
g_pArtPalette = DDUtil_LoadPalette( g_pDD, "DONUTS8" );
|
|
|
|
if( NULL == g_pSplashPalette || NULL == g_pArtPalette )
|
|
{
|
|
CleanupAndDisplayError("Could not load palettes");
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Set the palette before loading the art
|
|
g_pddsFrontBuffer->SetPalette( g_pArtPalette );
|
|
|
|
hbm = (HBITMAP)LoadImage( GetModuleHandle(NULL), "DONUTS8", IMAGE_BITMAP, 0, 0,
|
|
LR_CREATEDIBSECTION );
|
|
if( NULL == hbm )
|
|
{
|
|
CleanupAndDisplayError("Could not load bitmap");
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Copy the bitmaps. (We're OR'ing the hresults together so we only have to
|
|
// do one check for a failure case.)
|
|
hr |= DDUtil_CopyBitmap( g_pddsDonut, hbm, 0, 0, 320, 384 );
|
|
hr |= DDUtil_CopyBitmap( g_pddsPyramid, hbm, 0, 384, 320, 128 );
|
|
hr |= DDUtil_CopyBitmap( g_pddsSphere, hbm, 0, 512, 320, 32 );
|
|
hr |= DDUtil_CopyBitmap( g_pddsCube, hbm, 0, 544, 320, 32 );
|
|
hr |= DDUtil_CopyBitmap( g_pddsShip, hbm, 0, 576, 320, 256 );
|
|
hr |= DDUtil_CopyBitmap( g_pddsNumbers, hbm, 0, 832, 320, 16 );
|
|
|
|
if( FAILED(hr) )
|
|
{
|
|
CleanupAndDisplayError("Could not copy bitmaps to surfaces");
|
|
DeleteObject( hbm );
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Done with the bitmap
|
|
DeleteObject( hbm );
|
|
|
|
// Set colorfill colors and color keys according to bitmap contents
|
|
g_dwFillColor = DDUtil_ColorMatch( g_pddsDonut, CLR_INVALID );
|
|
|
|
DDUtil_SetColorKey( g_pddsDonut, CLR_INVALID );
|
|
DDUtil_SetColorKey( g_pddsPyramid, CLR_INVALID );
|
|
DDUtil_SetColorKey( g_pddsCube, CLR_INVALID );
|
|
DDUtil_SetColorKey( g_pddsSphere, CLR_INVALID );
|
|
DDUtil_SetColorKey( g_pddsShip, CLR_INVALID );
|
|
DDUtil_SetColorKey( g_pddsNumbers, CLR_INVALID );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: rnd()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
FLOAT rnd( FLOAT low, FLOAT high )
|
|
{
|
|
return low + ( high - low ) * ((FLOAT)rand())/RAND_MAX;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: InitializeSound()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT InitializeSound( HWND hWnd )
|
|
{
|
|
g_bSoundEnabled = FALSE;
|
|
|
|
if( FAILED( DirectSoundCreate( NULL, &g_pDS, NULL ) ) )
|
|
//return E_FAIL;
|
|
//per Marcus's request, to run on his machine
|
|
return S_FALSE;
|
|
|
|
if( FAILED( g_pDS->SetCooperativeLevel( hWnd, DSSCL_NORMAL ) ) )
|
|
{
|
|
g_pDS->Release();
|
|
g_pDS = NULL;
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
g_pBeginLevelSound = DSUtil_CreateSound( g_pDS, "BeginLevel", 1 );
|
|
g_pEngineIdleSound = DSUtil_CreateSound( g_pDS, "EngineIdle", 1 );
|
|
g_pEngineRevSound = DSUtil_CreateSound( g_pDS, "EngineRev", 1 );
|
|
g_pSkidToStopSound = DSUtil_CreateSound( g_pDS, "SkidToStop", 1 );
|
|
g_pShieldBuzzSound = DSUtil_CreateSound( g_pDS, "ShieldBuzz", 1 );
|
|
g_pShipExplodeSound = DSUtil_CreateSound( g_pDS, "ShipExplode", 1 );
|
|
g_pFireBulletSound = DSUtil_CreateSound( g_pDS, "Gunfire", 25 );
|
|
g_pShipBounceSound = DSUtil_CreateSound( g_pDS, "ShipBounce", 4 );
|
|
g_pDonutExplodeSound = DSUtil_CreateSound( g_pDS, "DonutExplode", 10 );
|
|
g_pPyramidExplodeSound = DSUtil_CreateSound( g_pDS, "PyramidExplode", 12 );
|
|
g_pCubeExplodeSound = DSUtil_CreateSound( g_pDS, "CubeExplode", 15 );
|
|
g_pSphereExplodeSound = DSUtil_CreateSound( g_pDS, "SphereExplode", 10 );
|
|
|
|
g_bSoundEnabled = TRUE;
|
|
|
|
// Start sounds that should be playing
|
|
#if 0 //not used for the mulit-user mapper
|
|
if( g_bEngineIdle ) DSUtil_PlaySound( g_pEngineIdleSound, DSBPLAY_LOOPING );
|
|
if( g_bShieldsOn ) DSUtil_PlaySound( g_pShieldBuzzSound, DSBPLAY_LOOPING );
|
|
if( g_bThrusting ) DSUtil_PlaySound( g_pEngineRevSound, DSBPLAY_LOOPING );
|
|
#endif //not used for the mulit-user mapper
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DestroySound()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID DestroySound()
|
|
{
|
|
if( g_pDS )
|
|
{
|
|
DSUtil_DestroySound( g_pBeginLevelSound );
|
|
DSUtil_DestroySound( g_pEngineIdleSound );
|
|
DSUtil_DestroySound( g_pEngineRevSound );
|
|
DSUtil_DestroySound( g_pSkidToStopSound );
|
|
DSUtil_DestroySound( g_pShieldBuzzSound );
|
|
DSUtil_DestroySound( g_pShipExplodeSound );
|
|
DSUtil_DestroySound( g_pFireBulletSound );
|
|
DSUtil_DestroySound( g_pShipBounceSound );
|
|
DSUtil_DestroySound( g_pDonutExplodeSound );
|
|
DSUtil_DestroySound( g_pPyramidExplodeSound );
|
|
DSUtil_DestroySound( g_pCubeExplodeSound );
|
|
DSUtil_DestroySound( g_pSphereExplodeSound );
|
|
|
|
g_pDS->Release();
|
|
}
|
|
|
|
g_pBeginLevelSound = NULL;
|
|
g_pEngineIdleSound = NULL;
|
|
g_pEngineRevSound = NULL;
|
|
g_pSkidToStopSound = NULL;
|
|
g_pShieldBuzzSound = NULL;
|
|
g_pShipExplodeSound = NULL;
|
|
g_pFireBulletSound = NULL;
|
|
g_pShipBounceSound = NULL;
|
|
g_pDonutExplodeSound = NULL;
|
|
g_pPyramidExplodeSound = NULL;
|
|
g_pCubeExplodeSound = NULL;
|
|
g_pSphereExplodeSound = NULL;
|
|
|
|
g_pDS = NULL;
|
|
g_bSoundEnabled = FALSE;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: InitializeInput()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT InitializeInput( HWND hWnd )
|
|
{
|
|
// Initialize DirectInpu
|
|
if( FAILED( DIUtil_Initialize( hWnd ) ) )
|
|
{
|
|
MessageBox( hWnd, "Can't Initialize DirectInput", "TDonuts", MB_OK );
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DestroyInput()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID DestroyInput()
|
|
{
|
|
// Release DirectInput
|
|
DIUtil_CleanupDirectInput();
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: GetDeviceInput(input[])
|
|
// Desc: Processes data from the input device. Uses GetDeviceData().
|
|
//-----------------------------------------------------------------------------
|
|
VOID GetDeviceInput(DWORD input[NUMBER_OF_PLAYERS])
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
for (int pl = 0; pl < NUMBER_OF_PLAYERS; pl++)
|
|
{
|
|
printf("pl = %i", pl);
|
|
|
|
for (int dv = 0; dv < (int) g_dwNumDevices[pl]; dv++)
|
|
{
|
|
|
|
printf("dv = %i", dv);
|
|
|
|
if (g_pDevices[pl][dv] != NULL)
|
|
{
|
|
DWORD dwItems = 10;
|
|
DIDEVICEOBJECTDATA rgdod[10];
|
|
hr = g_pDevices[pl][dv]->Poll();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = g_pDevices[pl][dv]->GetDeviceData(
|
|
sizeof(DIDEVICEOBJECTDATA),
|
|
rgdod,
|
|
&dwItems,
|
|
0);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//get the sematics codes
|
|
for (int j=0; j < (int)dwItems; j++)
|
|
{
|
|
//for axes, do axes stuff
|
|
if (rgdod[j].uAppData & AXIS_MASK)
|
|
{
|
|
//blow out all of the axis data
|
|
dwInputState[pl] &= ~(KEY_RIGHT);
|
|
dwInputState[pl] &= ~(KEY_LEFT);
|
|
dwInputState[pl] &= ~(KEY_UP);
|
|
dwInputState[pl] &= ~(KEY_DOWN);
|
|
|
|
if( ((int)rgdod[j].dwData) > 10 )
|
|
{
|
|
dwInputState[pl] |= ( rgdod[j].uAppData == AXIS_LR ) ? KEY_RIGHT : KEY_DOWN;
|
|
}
|
|
if( ((int)rgdod[j].dwData) < -10 )
|
|
{
|
|
dwInputState[pl] |= ( rgdod[j].uAppData == AXIS_LR ) ? KEY_LEFT : KEY_UP;
|
|
}
|
|
|
|
|
|
}
|
|
else //do buttons
|
|
{
|
|
//if rgdod[j].dwData & 0x80, it means the button went down,
|
|
//else it went up
|
|
if (rgdod[j].dwData & 0x80)
|
|
{
|
|
//set the new state
|
|
dwInputState[pl] |= rgdod[j].uAppData;
|
|
}
|
|
else
|
|
{
|
|
dwInputState[pl] &= ~(rgdod[j].uAppData);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
//set the new state
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
input[pl] = dwInputState[pl];
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|