Source code of Windows XP (NT5)
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.

1907 lines
56 KiB

  1. //-----------------------------------------------------------------------------
  2. // File: ffdonuts.cpp
  3. //
  4. // Desc: DirectInput Semantic Mapper version of Donuts game
  5. //
  6. // Copyright (C) 1995-2000 Microsoft Corporation. All Rights Reserved.
  7. //-----------------------------------------------------------------------------
  8. #define STRICT
  9. #define INITGUID
  10. #include <windows.h>
  11. #include <cguid.h>
  12. #include <mmsystem.h>
  13. #include <ddraw.h>
  14. #include <dsound.h>
  15. #include <stdio.h>
  16. #include "DDUtil.h"
  17. #include "DIUtil.h"
  18. #include "DSUtil.h"
  19. #include "resource.h"
  20. #include "ffdonuts.h"
  21. // DirectDraw objects
  22. LPDIRECTDRAW7 g_pDD = NULL;
  23. LPDIRECTDRAWPALETTE g_pArtPalette = NULL;
  24. LPDIRECTDRAWPALETTE g_pSplashPalette = NULL;
  25. LPDIRECTDRAWSURFACE7 g_pddsFrontBuffer = NULL;
  26. LPDIRECTDRAWSURFACE7 g_pddsBackBuffer = NULL;
  27. LPDIRECTDRAWSURFACE7 g_pddsDonut = NULL;
  28. LPDIRECTDRAWSURFACE7 g_pddsPyramid = NULL;
  29. LPDIRECTDRAWSURFACE7 g_pddsCube = NULL;
  30. LPDIRECTDRAWSURFACE7 g_pddsSphere = NULL;
  31. LPDIRECTDRAWSURFACE7 g_pddsShip = NULL;
  32. LPDIRECTDRAWSURFACE7 g_pddsNumbers = NULL;
  33. LPDIRECTDRAWSURFACE7 g_pddsDIConfig = NULL;
  34. // DirectSound and DSUtil sound objects
  35. LPDIRECTSOUND g_pDS = NULL;
  36. SoundObject* g_pBeginLevelSound = NULL;
  37. SoundObject* g_pEngineIdleSound = NULL;
  38. SoundObject* g_pEngineRevSound = NULL;
  39. SoundObject* g_pSkidToStopSound = NULL;
  40. SoundObject* g_pShieldBuzzSound = NULL;
  41. SoundObject* g_pShipExplodeSound = NULL;
  42. SoundObject* g_pFireBulletSound = NULL;
  43. SoundObject* g_pShipBounceSound = NULL;
  44. SoundObject* g_pDonutExplodeSound = NULL;
  45. SoundObject* g_pPyramidExplodeSound = NULL;
  46. SoundObject* g_pCubeExplodeSound = NULL;
  47. SoundObject* g_pSphereExplodeSound = NULL;
  48. #if 0 //not used for mapper
  49. BOOL g_bEngineIdle = FALSE;
  50. BOOL g_bShieldsOn = FALSE;
  51. BOOL g_bThrusting = FALSE;
  52. DWORD lastInput = 0;
  53. BOOL g_bLastShield = FALSE;
  54. #endif //not used for mapper
  55. BOOL lastThrust = FALSE;
  56. FLOAT g_fShowDelay = 0.0f;
  57. HWND g_hWndMain;
  58. BOOL g_bIsActive;
  59. BOOL g_bIsReady = FALSE;
  60. BOOL g_bMouseVisible;
  61. DWORD g_dwLastTickCount;
  62. DWORD g_dwScore = 0;
  63. int g_ProgramState;
  64. DWORD g_dwLevel = 0;
  65. DWORD g_dwFillColor;
  66. BOOL g_bLeaveTrails = FALSE;
  67. DWORD g_dwScreenWidth = 1024;
  68. DWORD g_dwScreenHeight = 768;
  69. DWORD g_dwScreenDepth = 16;
  70. BOOL g_bSoundEnabled = FALSE;
  71. DisplayObject* g_pDisplayList = NULL; // Display List
  72. DisplayObject* g_pShip = NULL; // Main ship
  73. DisplayObject* g_pShipsArray[NUMBER_OF_PLAYERS]; //array for all the players' ships
  74. extern IDirectInput8* g_pDI; // DirectInput object
  75. extern DWORD g_dwNumDevices[NUMBER_OF_PLAYERS];
  76. extern IDirectInputDevice8* g_pDevices[NUMBER_OF_PLAYERS][MAX_INPUT_DEVICES+1];
  77. extern DIACTIONFORMAT diActF;
  78. extern LPTSTR lpUserName;
  79. DWORD dwInputState[NUMBER_OF_PLAYERS]; //to persist the input state
  80. BOOL CALLBACK ConfigureDevicesCallback(LPVOID lpVoid, LPVOID lpUserData)
  81. {
  82. UpdateFrame((LPDIRECTDRAWSURFACE7)lpVoid);
  83. return TRUE;
  84. }
  85. //-----------------------------------------------------------------------------
  86. // Name: SetupGame()
  87. // Desc:
  88. //-----------------------------------------------------------------------------
  89. VOID SetupGame()
  90. {
  91. AdvanceLevel();
  92. // Set the palette
  93. g_pddsFrontBuffer->SetPalette( g_pArtPalette );
  94. }
  95. //-----------------------------------------------------------------------------
  96. // Name: MainWndproc()
  97. // Desc: Callback for all Windows messages
  98. //-----------------------------------------------------------------------------
  99. long FAR PASCAL MainWndproc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
  100. {
  101. PAINTSTRUCT ps;
  102. HDC hdc;
  103. switch( msg )
  104. {
  105. case WM_ACTIVATEAPP:
  106. g_bIsActive = (BOOL) wParam;
  107. if( g_bIsActive )
  108. {
  109. g_bMouseVisible = FALSE;
  110. g_dwLastTickCount = GetTickCount();
  111. g_bLeaveTrails = FALSE;
  112. // Need to reacquire the device
  113. #if 0 //not used in the Semantic Mapper demo
  114. if( g_pdidJoystick )
  115. g_pdidJoystick->Acquire();
  116. #endif //not used in the Semantic Mapper demo
  117. }
  118. else
  119. {
  120. g_bMouseVisible = TRUE;
  121. }
  122. break;
  123. case WM_CREATE:
  124. break;
  125. case WM_SETCURSOR:
  126. if( !g_bMouseVisible && g_bIsReady )
  127. SetCursor(NULL);
  128. else
  129. SetCursor(LoadCursor( NULL, IDC_ARROW ));
  130. return TRUE;
  131. case WM_KEYDOWN:
  132. switch( wParam )
  133. {
  134. case VK_F3:
  135. if( g_bSoundEnabled )
  136. DestroySound();
  137. else
  138. InitializeSound( hWnd );
  139. break;
  140. case VK_ESCAPE:
  141. case VK_F12:
  142. PostMessage( hWnd, WM_CLOSE, 0, 0 );
  143. return 0;
  144. case VK_F1:
  145. g_bLeaveTrails = !g_bLeaveTrails;
  146. break;
  147. case VK_F2:
  148. {
  149. DIUtil_ConfigureDevices(hWnd, g_pddsDIConfig, DICD_DEFAULT);
  150. break;
  151. }
  152. case VK_F4:
  153. {
  154. DIUtil_ConfigureDevices(hWnd, g_pddsDIConfig, DICD_EDIT);
  155. break;
  156. }
  157. }
  158. break;
  159. #if 0 //not used in the Semantic Mapper demo
  160. case WM_KEYUP:
  161. switch( wParam )
  162. {
  163. case VK_NUMPAD7:
  164. lastInput &= ~KEY_SHIELD;
  165. break;
  166. case VK_NUMPAD5:
  167. lastInput &= ~KEY_STOP;
  168. break;
  169. case VK_DOWN:
  170. case VK_NUMPAD2:
  171. lastInput &= ~KEY_DOWN;
  172. break;
  173. case VK_LEFT:
  174. case VK_NUMPAD4:
  175. lastInput &= ~KEY_LEFT;
  176. break;
  177. case VK_RIGHT:
  178. case VK_NUMPAD6:
  179. lastInput &= ~KEY_RIGHT;
  180. break;
  181. case VK_UP:
  182. case VK_NUMPAD8:
  183. lastInput &= ~KEY_UP;
  184. break;
  185. case VK_NUMPAD3:
  186. lastInput &= ~KEY_THROW;
  187. break;
  188. case VK_SPACE:
  189. lastInput &= ~KEY_FIRE;
  190. break;
  191. }
  192. break;
  193. #endif //not used in the Semantic Mapper demo
  194. case WM_ERASEBKGND:
  195. return 1;
  196. case WM_PAINT:
  197. hdc = BeginPaint( hWnd, &ps );
  198. EndPaint( hWnd, &ps );
  199. return 1;
  200. case WM_DESTROY:
  201. #if 0 //not used for mapper
  202. lastInput=0;
  203. #endif //not used for mapper
  204. DestroyGame();
  205. PostQuitMessage( 0 );
  206. break;
  207. }
  208. return (LONG) DefWindowProc( hWnd, msg, wParam, lParam );
  209. }
  210. //-----------------------------------------------------------------------------
  211. // Name: WinMain()
  212. // Desc: Application entry point
  213. //-----------------------------------------------------------------------------
  214. int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow )
  215. {
  216. // Register the window class
  217. WNDCLASS wndClass = { CS_DBLCLKS, (WNDPROC)MainWndproc, 0, 0, hInstance,
  218. LoadIcon( hInstance, MAKEINTRESOURCE(DONUTS_ICON) ),
  219. LoadCursor( NULL, IDC_ARROW ),
  220. (HBRUSH)GetStockObject( BLACK_BRUSH ),
  221. NULL, TEXT("DonutsClass") };
  222. RegisterClass( &wndClass );
  223. // Create our main window
  224. g_hWndMain = CreateWindowEx( 0, TEXT("DonutsClass"), TEXT("Donuts"),
  225. WS_VISIBLE|WS_POPUP|WS_CAPTION|WS_SYSMENU,
  226. 0, 0, GetSystemMetrics(SM_CXSCREEN),
  227. GetSystemMetrics(SM_CYSCREEN), NULL, NULL,
  228. hInstance, NULL );
  229. if( NULL == g_hWndMain )
  230. return FALSE;
  231. UpdateWindow( g_hWndMain );
  232. g_bIsReady = TRUE;
  233. if( FAILED( InitializeGame( g_hWndMain ) ) )
  234. {
  235. DestroyWindow( g_hWndMain );
  236. return FALSE;
  237. }
  238. while( 1 )
  239. {
  240. MSG msg;
  241. if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
  242. {
  243. if( FALSE == GetMessage( &msg, NULL, 0, 0 ) )
  244. return (int) msg.wParam;
  245. TranslateMessage( &msg );
  246. DispatchMessage( &msg );
  247. }
  248. else if( g_bIsActive )
  249. {
  250. UpdateFrame();
  251. }
  252. else
  253. {
  254. WaitMessage();
  255. }
  256. }
  257. }
  258. //-----------------------------------------------------------------------------
  259. // Name: DestroyGame()
  260. // Desc:
  261. //-----------------------------------------------------------------------------
  262. VOID DestroyGame()
  263. {
  264. DestroySound();
  265. DestroyInput();
  266. }
  267. //-----------------------------------------------------------------------------
  268. // Name: UpdateShips()
  269. // Desc:
  270. //-----------------------------------------------------------------------------
  271. VOID UpdateShips()
  272. {
  273. //the main ship will always be there
  274. //but update all the others, based on whether
  275. //the particular user has any devices
  276. for (int pl = 1; pl < NUMBER_OF_PLAYERS; pl ++)
  277. {
  278. //if the corresponding player is still playing
  279. if (g_pDevices[pl][0] != NULL)
  280. {
  281. //if not created already, create new
  282. if (g_pShipsArray[pl] == NULL)
  283. {
  284. g_pShipsArray[pl] = CreateObject(OBJ_SHIP, (FLOAT)(g_dwScreenWidth/(pl+1)-16), (FLOAT)(g_dwScreenHeight/(pl+1)-16), 0, 0, pl);
  285. }
  286. //if already created, keep it
  287. }
  288. else //player is gone
  289. {
  290. //if there is a ship for this player, delete it
  291. if (g_pShipsArray[pl] != NULL)
  292. {
  293. DeleteFromList(g_pShipsArray[pl]);
  294. g_pShipsArray[pl] = NULL;
  295. }
  296. }
  297. }
  298. }
  299. //-----------------------------------------------------------------------------
  300. // Name: InitializeGame()
  301. // Desc:
  302. //-----------------------------------------------------------------------------
  303. HRESULT InitializeGame( HWND hWnd )
  304. {
  305. LPDIRECTDRAW pDD;
  306. HRESULT hr;
  307. DDSURFACEDESC2 ddsd;
  308. // Create DirectDraw
  309. if( SUCCEEDED( hr = DirectDrawCreate( NULL, &pDD, NULL ) ) )
  310. {
  311. // Get DirectDraw4 interface
  312. hr = pDD->QueryInterface( IID_IDirectDraw7, (VOID**)&g_pDD );
  313. pDD->Release();
  314. }
  315. if( FAILED(hr) )
  316. {
  317. CleanupAndDisplayError("DirectDrawCreate Failed!");
  318. return E_FAIL;
  319. }
  320. // Set the cooperative level for fullscreen mode
  321. hr = g_pDD->SetCooperativeLevel( hWnd,
  322. DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
  323. if( FAILED(hr) )
  324. {
  325. CleanupAndDisplayError("SetCooperativeLevel Failed");
  326. return E_FAIL;
  327. }
  328. // Set the display mode
  329. hr = g_pDD->SetDisplayMode( g_dwScreenWidth, g_dwScreenHeight,
  330. g_dwScreenDepth, 0, 0 );
  331. if( FAILED(hr) )
  332. {
  333. CleanupAndDisplayError("SetDisplayMode Failed!");
  334. return E_FAIL;
  335. }
  336. // Create surfaces
  337. ZeroMemory( &ddsd, sizeof( ddsd ) );
  338. ddsd.dwSize = sizeof( ddsd );
  339. ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  340. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
  341. DDSCAPS_COMPLEX;
  342. ddsd.dwBackBufferCount = 1;
  343. // Create the front buffer
  344. hr = g_pDD->CreateSurface( &ddsd, &g_pddsFrontBuffer, NULL );
  345. if( FAILED(hr) )
  346. {
  347. CleanupAndDisplayError("CreateSurface FrontBuffer Failed!");
  348. return E_FAIL;
  349. }
  350. // Get a pointer to the back buffer
  351. DDSCAPS2 ddscaps;
  352. ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  353. ddscaps.dwCaps2 = 0;
  354. ddscaps.dwCaps3 = 0;
  355. ddscaps.dwCaps4 = 0;
  356. hr = g_pddsFrontBuffer->GetAttachedSurface( &ddscaps, &g_pddsBackBuffer );
  357. if( FAILED(hr) )
  358. {
  359. CleanupAndDisplayError("GetAttachedSurface Failed!");
  360. return E_FAIL;
  361. }
  362. ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
  363. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  364. ddsd.dwWidth = 320;
  365. // Create the surfaces for the object images. (We're OR'ing the HRESULTs
  366. // together, so we only need to check for failure once).
  367. ddsd.dwHeight = 384;
  368. hr |= g_pDD->CreateSurface( &ddsd, &g_pddsDonut, NULL );
  369. ddsd.dwHeight = 128;
  370. hr |= g_pDD->CreateSurface( &ddsd, &g_pddsPyramid, NULL );
  371. ddsd.dwHeight = 32;
  372. hr |= g_pDD->CreateSurface( &ddsd, &g_pddsCube, NULL );
  373. ddsd.dwHeight = 32;
  374. hr |= g_pDD->CreateSurface( &ddsd, &g_pddsSphere, NULL );
  375. ddsd.dwHeight = 256;
  376. hr |= g_pDD->CreateSurface( &ddsd, &g_pddsShip, NULL );
  377. ddsd.dwHeight = 16;
  378. hr |= g_pDD->CreateSurface( &ddsd, &g_pddsNumbers, NULL );
  379. ddsd.dwWidth = 640;
  380. ddsd.dwHeight = 480;
  381. hr |= g_pDD->CreateSurface( &ddsd, &g_pddsDIConfig, NULL );
  382. if( FAILED(hr) )
  383. {
  384. CleanupAndDisplayError("Could not create surfaces!");
  385. return E_FAIL;
  386. }
  387. if( FAILED( RestoreSurfaces() ) )
  388. {
  389. CleanupAndDisplayError("RestoreSurfaces Failed!");
  390. return E_FAIL;
  391. }
  392. //zero out the ship ptrs
  393. for (int ship = 0; ship < NUMBER_OF_PLAYERS; ship++)
  394. {
  395. g_pShipsArray[ship] = NULL;
  396. }
  397. // Add a ship to the displaylist
  398. g_pDisplayList = new DisplayObject;
  399. g_pDisplayList->next = NULL;
  400. g_pDisplayList->prev = NULL;
  401. g_pDisplayList->type = OBJ_SHIP;
  402. g_pDisplayList->pddsSurface = g_pddsShip;
  403. g_pShip = g_pDisplayList;
  404. //and save the ptr
  405. g_pShipsArray[0] = g_pShip;
  406. //initialize input
  407. for (ship = 0; ship < NUMBER_OF_PLAYERS; ship ++)
  408. {
  409. dwInputState[ship] = 0;
  410. }
  411. g_dwLastTickCount = GetTickCount();
  412. if( FAILED( InitializeInput( hWnd ) ) )
  413. return E_FAIL;
  414. //if( FAILED( InitializeSound( hWnd ) ) )
  415. // return E_FAIL;
  416. g_ProgramState = PS_SPLASH;
  417. return S_OK;
  418. }
  419. //-----------------------------------------------------------------------------
  420. // Name: CleanupAndDisplayError()
  421. // Desc:
  422. //-----------------------------------------------------------------------------
  423. VOID CleanupAndDisplayError( CHAR* strError )
  424. {
  425. CHAR buffer[80];
  426. sprintf( buffer, "Error: %s\n", strError );
  427. OutputDebugString( buffer );
  428. // Make the cursor visible
  429. SetCursor( LoadCursor( NULL, IDC_ARROW ) );
  430. g_bMouseVisible = TRUE;
  431. if( g_pddsDonut )
  432. g_pddsDonut->Release();
  433. if( g_pddsPyramid )
  434. g_pddsPyramid->Release();
  435. if( g_pddsCube )
  436. g_pddsCube->Release();
  437. if( g_pddsSphere )
  438. g_pddsSphere->Release();
  439. if( g_pddsShip )
  440. g_pddsShip->Release();
  441. if( g_pddsNumbers )
  442. g_pddsNumbers->Release();
  443. if( g_pddsDIConfig )
  444. g_pddsDIConfig->Release();
  445. if( g_pddsFrontBuffer )
  446. g_pddsFrontBuffer->Release();
  447. if( g_pArtPalette )
  448. g_pArtPalette->Release();
  449. if( g_pSplashPalette )
  450. g_pSplashPalette->Release();
  451. if( g_pDD )
  452. g_pDD->Release();
  453. MessageBox( g_hWndMain, strError, "ERROR", MB_OK );
  454. }
  455. //-----------------------------------------------------------------------------
  456. // Name: DisplaySplashScreen()
  457. // Desc:
  458. //-----------------------------------------------------------------------------
  459. HRESULT DisplaySplashScreen()
  460. {
  461. HBITMAP hbm;
  462. hbm = (HBITMAP)LoadImage( GetModuleHandle( NULL ), "SPLASH", IMAGE_BITMAP,
  463. 0, 0, LR_CREATEDIBSECTION );
  464. if( NULL == hbm )
  465. return E_FAIL;
  466. // Set the palette before loading the splash screen
  467. g_pddsFrontBuffer->SetPalette( g_pSplashPalette );
  468. // If the surface is lost, DDCopyBitmap will fail and the surface will
  469. // be restored in FlipScreen().
  470. DDUtil_CopyBitmap( g_pddsBackBuffer, hbm, 0, 0, 0, 0 );
  471. // Done with the bitmap
  472. DeleteObject( hbm );
  473. // Show the backbuffer contents on the frontbuffer
  474. if( FAILED( FlipScreen() ) )
  475. return E_FAIL;
  476. return S_OK;
  477. }
  478. //-----------------------------------------------------------------------------
  479. // Name: PlayPannedSound()
  480. // Desc: Play a sound, but first set the panning according to where the
  481. // object is on the screen.
  482. //-----------------------------------------------------------------------------
  483. VOID PlayPannedSound( SoundObject* pSound, DisplayObject* pObject )
  484. {
  485. if( NULL == pObject )
  486. return;
  487. DWORD dwCenter = ( pObject->rcDst.right + pObject->rcDst.left ) / 2;
  488. FLOAT fCenter = ( 2.0f * ((FLOAT)dwCenter)/g_dwScreenWidth ) - 1.0f;
  489. DSUtil_PlayPannedSound( pSound, fCenter );
  490. }
  491. //-----------------------------------------------------------------------------
  492. // Name: UpdateFrame()
  493. // Desc:
  494. //-----------------------------------------------------------------------------
  495. VOID UpdateFrame(LPDIRECTDRAWSURFACE7 lpddsConfigDlg)
  496. {
  497. static FLOAT fLevelIntroTime;
  498. switch( g_ProgramState )
  499. {
  500. case PS_SPLASH:
  501. // Display the splash screen
  502. //DisplaySplashScreen();
  503. g_ProgramState = PS_BEGINREST;
  504. SetupGame();
  505. break;
  506. case PS_ACTIVE:
  507. UpdateDisplayList();
  508. CheckForHits();
  509. DrawDisplayList(lpddsConfigDlg);
  510. if( IsDisplayListEmptyExceptShips() )
  511. {
  512. DSUtil_StopSound( g_pEngineIdleSound );
  513. DSUtil_StopSound( g_pEngineRevSound );
  514. #if 0 //not used for the mulit-user mapper
  515. g_bEngineIdle = FALSE;
  516. g_bThrusting = FALSE;
  517. lastThrust = FALSE;
  518. g_bLastShield = FALSE;
  519. #endif //not used for the mulit-user mapper
  520. g_ProgramState = PS_BEGINREST;
  521. AdvanceLevel();
  522. }
  523. break;
  524. case PS_BEGINREST:
  525. DSUtil_PlaySound(g_pBeginLevelSound, 0);
  526. fLevelIntroTime = GetTickCount()/1000.0f;
  527. g_ProgramState = PS_REST;
  528. // Fall through to PS_REST state
  529. case PS_REST:
  530. // Show the Level intro screen for 3 seconds
  531. if( ( GetTickCount()/1000.0f - fLevelIntroTime ) > 3.0f )
  532. {
  533. DSUtil_PlaySound( g_pEngineIdleSound, DSBPLAY_LOOPING );
  534. #if 0 //not used for the mulit-user mapper
  535. g_bEngineIdle = TRUE;
  536. #endif //not used for the mulit-user mapper
  537. g_dwLastTickCount = GetTickCount();
  538. g_ProgramState = PS_ACTIVE;
  539. }
  540. else
  541. {
  542. DisplayLevelIntroScreen( g_dwLevel );
  543. }
  544. break;
  545. }
  546. }
  547. //-----------------------------------------------------------------------------
  548. // Name: DisplayLevelIntroScreen()
  549. // Desc:
  550. //-----------------------------------------------------------------------------
  551. VOID DisplayLevelIntroScreen( DWORD dwLevel )
  552. {
  553. // Erase the screen
  554. EraseScreen();
  555. // Output the bitmapped letters for the word "Level"
  556. CHAR buffer[10];
  557. buffer[0] = 10 + '0';
  558. buffer[1] = 11 + '0';
  559. buffer[2] = 12 + '0';
  560. buffer[3] = 11 + '0';
  561. buffer[4] = 10 + '0';
  562. buffer[5] = '\0';
  563. BltBitmappedText( buffer, g_dwScreenWidth/2-64, g_dwScreenHeight/2-8 );
  564. // Output the bitmapped numbers for the level number
  565. buffer[0] = (CHAR)(dwLevel/100) + '0';
  566. buffer[1] = (CHAR)(dwLevel/ 10) + '0';
  567. buffer[2] = (CHAR)(dwLevel% 10) + '0';
  568. buffer[3] = '\0';
  569. BltBitmappedText( buffer, g_dwScreenWidth/2+22, g_dwScreenHeight/2-8 );
  570. // Show the backbuffer screen on the front buffer
  571. FlipScreen();
  572. }
  573. //-----------------------------------------------------------------------------
  574. // Name: BltBitmappedText()
  575. // Desc:
  576. //-----------------------------------------------------------------------------
  577. VOID BltBitmappedText( CHAR* num, int x, int y )
  578. {
  579. for( CHAR* c = num; *c != '\0'; c++ )
  580. {
  581. HRESULT hr = DDERR_WASSTILLDRAWING;
  582. RECT rcSrc;
  583. rcSrc.left = (*c - '0')*16;
  584. rcSrc.top = 0;
  585. rcSrc.right = rcSrc.left + 16;
  586. rcSrc.bottom = rcSrc.top + 16;
  587. while( hr == DDERR_WASSTILLDRAWING )
  588. {
  589. hr = g_pddsBackBuffer->BltFast( x, y, g_pddsNumbers, &rcSrc,
  590. DDBLTFAST_SRCCOLORKEY );
  591. }
  592. x += 16;
  593. }
  594. }
  595. //-----------------------------------------------------------------------------
  596. // Name: CheckForHits()
  597. // Desc:
  598. //-----------------------------------------------------------------------------
  599. VOID CheckForHits()
  600. {
  601. DisplayObject* pObject;
  602. DisplayObject* bullet;
  603. // Update screen rects
  604. for( pObject = g_pDisplayList; pObject; pObject = pObject->next )
  605. {
  606. int frame = (DWORD)pObject->frame;
  607. switch( pObject->type )
  608. {
  609. case OBJ_DONUT:
  610. pObject->rcDst.left = (DWORD)pObject->posx;
  611. pObject->rcDst.top = (DWORD)pObject->posy;
  612. pObject->rcDst.right = pObject->rcDst.left + DONUT_WIDTH;
  613. pObject->rcDst.bottom = pObject->rcDst.top + DONUT_HEIGHT;
  614. pObject->rcSrc.left = DONUT_WIDTH * (frame % 5);
  615. pObject->rcSrc.top = DONUT_HEIGHT * (frame /5);
  616. pObject->rcSrc.right = pObject->rcSrc.left + DONUT_WIDTH;
  617. pObject->rcSrc.bottom = pObject->rcSrc.top + DONUT_HEIGHT;
  618. break;
  619. case OBJ_PYRAMID:
  620. pObject->rcDst.left = (DWORD)pObject->posx;
  621. pObject->rcDst.top = (DWORD)pObject->posy;
  622. pObject->rcDst.right = pObject->rcDst.left + PYRAMID_WIDTH;
  623. pObject->rcDst.bottom = pObject->rcDst.top + PYRAMID_HEIGHT;
  624. pObject->rcSrc.left = PYRAMID_WIDTH * (frame % 10);
  625. pObject->rcSrc.top = PYRAMID_HEIGHT * (frame /10);
  626. pObject->rcSrc.right = pObject->rcSrc.left + PYRAMID_WIDTH;
  627. pObject->rcSrc.bottom = pObject->rcSrc.top + PYRAMID_HEIGHT;
  628. break;
  629. case OBJ_SPHERE:
  630. pObject->rcDst.left = (DWORD)pObject->posx;
  631. pObject->rcDst.top = (DWORD)pObject->posy;
  632. pObject->rcDst.right = pObject->rcDst.left + SPHERE_WIDTH;
  633. pObject->rcDst.bottom = pObject->rcDst.top + SPHERE_HEIGHT;
  634. pObject->rcSrc.left = SPHERE_WIDTH * (frame % 20);
  635. pObject->rcSrc.top = SPHERE_HEIGHT * (frame /20);
  636. pObject->rcSrc.right = pObject->rcSrc.left + SPHERE_WIDTH;
  637. pObject->rcSrc.bottom = pObject->rcSrc.top + SPHERE_HEIGHT;
  638. break;
  639. case OBJ_CUBE:
  640. pObject->rcDst.left = (DWORD)pObject->posx;
  641. pObject->rcDst.top = (DWORD)pObject->posy;
  642. pObject->rcDst.right = pObject->rcDst.left + CUBE_WIDTH;
  643. pObject->rcDst.bottom = pObject->rcDst.top + CUBE_HEIGHT;
  644. pObject->rcSrc.left = CUBE_WIDTH * (frame % 20);
  645. pObject->rcSrc.top = CUBE_HEIGHT * (frame /20);
  646. pObject->rcSrc.right = pObject->rcSrc.left + CUBE_WIDTH;
  647. pObject->rcSrc.bottom = pObject->rcSrc.top + CUBE_HEIGHT;
  648. break;
  649. case OBJ_SHIP:
  650. pObject->rcDst.left = (DWORD)pObject->posx;
  651. pObject->rcDst.top = (DWORD)pObject->posy;
  652. pObject->rcDst.right = pObject->rcDst.left + SHIP_WIDTH;
  653. pObject->rcDst.bottom = pObject->rcDst.top + SHIP_HEIGHT;
  654. #if 0 //not used for the mulit-user mapper
  655. if( g_bLastShield )
  656. pObject->rcSrc.top = SHIP_HEIGHT * (frame / 10) + 128;
  657. else
  658. #endif //not used for the mulit-user mapper
  659. pObject->rcSrc.top = SHIP_HEIGHT * (frame /10);
  660. pObject->rcSrc.left = SHIP_WIDTH * (frame % 10);
  661. pObject->rcSrc.right = pObject->rcSrc.left + SHIP_WIDTH;
  662. pObject->rcSrc.bottom = pObject->rcSrc.top + SHIP_HEIGHT;
  663. break;
  664. case OBJ_BULLET:
  665. frame = (DWORD)pObject->frame/20 % 4;
  666. pObject->rcDst.left = (DWORD)pObject->posx;
  667. pObject->rcDst.top = (DWORD)pObject->posy;
  668. pObject->rcDst.right = pObject->rcDst.left + BULLET_WIDTH;
  669. pObject->rcDst.bottom = pObject->rcDst.top + BULLET_HEIGHT;
  670. pObject->rcSrc.left = BULLET_XOFFSET + frame*4;
  671. pObject->rcSrc.top = BULLET_YOFFSET;
  672. pObject->rcSrc.right = pObject->rcSrc.left + BULLET_WIDTH;
  673. pObject->rcSrc.bottom = pObject->rcSrc.top + BULLET_HEIGHT;
  674. break;
  675. }
  676. }
  677. for( bullet = g_pDisplayList; bullet; bullet = bullet->next )
  678. {
  679. // Only bullet objects and the ship (if shields are on) can hit
  680. // other objects. Skip all others.
  681. if( (bullet->type != OBJ_BULLET) && (bullet->type != OBJ_SHIP) )
  682. continue;
  683. #if 0 //not used for the mulit-user mapper
  684. // The ship cannot hit anything with shields on
  685. if( bullet->type == OBJ_SHIP && TRUE == g_bLastShield )
  686. continue;
  687. #endif //not used for the mulit-user mapper
  688. BOOL bBulletHit = FALSE;
  689. WORD wBulletX = (WORD)(bullet->rcDst.left + bullet->rcDst.right) / 2;
  690. WORD wBulletY = (WORD)(bullet->rcDst.top + bullet->rcDst.bottom) / 2;
  691. for( pObject = g_pDisplayList; pObject; pObject = pObject->next )
  692. {
  693. FLOAT left = (FLOAT)pObject->rcDst.left;
  694. FLOAT right = (FLOAT)pObject->rcDst.right;
  695. FLOAT top = (FLOAT)pObject->rcDst.top;
  696. FLOAT bottom = (FLOAT)pObject->rcDst.bottom;
  697. // Only trying to hit explodable targets
  698. if( ( pObject->type != OBJ_DONUT ) &&
  699. ( pObject->type != OBJ_PYRAMID ) &&
  700. ( pObject->type != OBJ_SPHERE ) &&
  701. ( pObject->type != OBJ_SHIP ) &&
  702. ( pObject->type != OBJ_CUBE ) )
  703. continue;
  704. if( ( wBulletX >= left ) && ( wBulletX < right ) &&
  705. ( wBulletY >= top ) && ( wBulletY < bottom ) )
  706. {
  707. // The object was hit
  708. switch( pObject->type )
  709. {
  710. case OBJ_DONUT:
  711. PlayPannedSound( g_pDonutExplodeSound, pObject );
  712. CreateObject( OBJ_PYRAMID, left, top, -1.0f, -1.0f, NO_PLAYER);
  713. CreateObject( OBJ_PYRAMID, left, top, -1.0f, -1.0f, NO_PLAYER );
  714. CreateObject( OBJ_PYRAMID, left, top, -1.0f, -1.0f, NO_PLAYER );
  715. g_dwScore += 10;
  716. break;
  717. case OBJ_PYRAMID:
  718. PlayPannedSound( g_pPyramidExplodeSound, pObject );
  719. CreateObject( OBJ_SPHERE, left, top, -1.0f, -1.0f, NO_PLAYER );
  720. CreateObject( OBJ_CUBE, left, top, -1.0f, -1.0f, NO_PLAYER );
  721. CreateObject( OBJ_CUBE, left, top, -1.0f, -1.0f, NO_PLAYER );
  722. g_dwScore += 20;
  723. break;
  724. case OBJ_CUBE:
  725. PlayPannedSound( g_pCubeExplodeSound, pObject );
  726. CreateObject( OBJ_SPHERE, left, top, -1.0f, -1.0f, NO_PLAYER );
  727. CreateObject( OBJ_SPHERE, left, top, -1.0f, -1.0f, NO_PLAYER );
  728. g_dwScore += 40;
  729. break;
  730. case OBJ_SPHERE:
  731. PlayPannedSound( g_pSphereExplodeSound, pObject );
  732. g_dwScore += 20;
  733. break;
  734. case OBJ_SHIP:
  735. //can't be hit by bullets that come from us
  736. if (bullet->Player != pObject->Player)
  737. {
  738. if(pObject->bVisible )
  739. {
  740. // Ship has exploded
  741. PlayPannedSound( g_pShipExplodeSound, pObject);
  742. if( g_dwScore < 150 )
  743. g_dwScore = 0;
  744. else
  745. g_dwScore -= 150;
  746. FLOAT x = pObject->posx;
  747. FLOAT y = pObject->posy;
  748. CreateObject( OBJ_SPHERE, x, y, -1.0f, -1.0f, NO_PLAYER);
  749. CreateObject( OBJ_SPHERE, x, y, -1.0f, -1.0f, NO_PLAYER);
  750. CreateObject( OBJ_SPHERE, x, y, -1.0f, -1.0f, NO_PLAYER);
  751. CreateObject( OBJ_SPHERE, x, y, -1.0f, -1.0f, NO_PLAYER);
  752. CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
  753. CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
  754. CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
  755. CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
  756. CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
  757. CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
  758. CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
  759. CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
  760. CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
  761. CreateObject( OBJ_BULLET, x, y, rnd()/2, rnd()/2, bullet->Player );
  762. // Delay for 2 seconds before displaying ship
  763. InitializeShips();
  764. g_fShowDelay = 2.0f;
  765. pObject->bVisible = FALSE;
  766. }
  767. }
  768. break;
  769. }
  770. //only delete non-"ships"
  771. if (pObject->type != OBJ_SHIP)
  772. {
  773. DisplayObject* pVictim = pObject;
  774. pObject = pObject->prev;
  775. DeleteFromList( pVictim );
  776. bBulletHit = TRUE;
  777. }
  778. }
  779. }
  780. }
  781. }
  782. //-----------------------------------------------------------------------------
  783. // Name: EraseScreen()
  784. // Desc:
  785. //-----------------------------------------------------------------------------
  786. VOID EraseScreen()
  787. {
  788. // Erase the background
  789. DDBLTFX ddbltfx;
  790. ZeroMemory( &ddbltfx, sizeof(ddbltfx) );
  791. ddbltfx.dwSize = sizeof(ddbltfx);
  792. ddbltfx.dwFillColor = g_dwFillColor;
  793. while( 1 )
  794. {
  795. HRESULT hr = g_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL,
  796. &ddbltfx );
  797. if( SUCCEEDED(hr) )
  798. break;
  799. if( hr == DDERR_SURFACELOST )
  800. if( FAILED( RestoreSurfaces() ) )
  801. return;
  802. if( hr != DDERR_WASSTILLDRAWING )
  803. return;
  804. }
  805. }
  806. //-----------------------------------------------------------------------------
  807. // Name: FlipScreen()
  808. // Desc:
  809. //-----------------------------------------------------------------------------
  810. HRESULT FlipScreen()
  811. {
  812. HRESULT hr = DDERR_WASSTILLDRAWING;
  813. // Flip the surfaces
  814. while( DDERR_WASSTILLDRAWING == hr )
  815. {
  816. hr = g_pddsFrontBuffer->Flip( NULL, 0 );
  817. if( hr == DDERR_SURFACELOST )
  818. if( FAILED( RestoreSurfaces() ) )
  819. return E_FAIL;
  820. }
  821. return hr;
  822. }
  823. //-----------------------------------------------------------------------------
  824. // Name: DrawDisplayList()
  825. // Desc:
  826. //-----------------------------------------------------------------------------
  827. VOID DrawDisplayList(LPDIRECTDRAWSURFACE7 lpConfigDlgSurf)
  828. {
  829. if( FALSE == g_bLeaveTrails )
  830. EraseScreen();
  831. char scorebuf[11];
  832. int rem;
  833. rem = g_dwScore;
  834. scorebuf[0] = rem/10000000 + '0';
  835. rem = g_dwScore % 10000000;
  836. scorebuf[1] = rem/1000000 + '0';
  837. rem = g_dwScore % 1000000;
  838. scorebuf[2] = rem/100000 + '0';
  839. rem = g_dwScore % 100000;
  840. scorebuf[3] = rem/10000 + '0';
  841. rem = g_dwScore % 10000;
  842. scorebuf[4] = rem/1000 + '0';
  843. rem = g_dwScore % 1000;
  844. scorebuf[5] = rem/100 + '0';
  845. rem = g_dwScore % 100;
  846. scorebuf[6] = rem/10 + '0';
  847. rem = g_dwScore % 10;
  848. scorebuf[7] = rem + '0';
  849. scorebuf[8] = '\0';
  850. // Draw the sound icon, if sound is enabled
  851. if( g_bSoundEnabled )
  852. {
  853. scorebuf[8] = 14 + '0';
  854. scorebuf[9] = 13 + '0';
  855. scorebuf[10] = '\0';
  856. }
  857. // Display the score
  858. BltBitmappedText( scorebuf, 10, g_dwScreenHeight-26 );
  859. // Display all visible objects in the display list
  860. for( DisplayObject* pObject = g_pDisplayList; pObject;
  861. pObject = pObject->next )
  862. {
  863. if( !pObject->bVisible )
  864. continue;
  865. HRESULT hr = DDERR_WASSTILLDRAWING;
  866. if( pObject->rcSrc.right - pObject->rcSrc.left == 0 )
  867. continue; // New objects do not have a src rect yet.
  868. while( hr == DDERR_WASSTILLDRAWING )
  869. {
  870. hr = g_pddsBackBuffer->BltFast( pObject->rcDst.left,
  871. pObject->rcDst.top, pObject->pddsSurface,
  872. &pObject->rcSrc, DDBLTFAST_SRCCOLORKEY );
  873. }
  874. }
  875. // Flip the backbuffer contents to the front buffer
  876. if (lpConfigDlgSurf)
  877. {
  878. g_pddsBackBuffer->BltFast((g_dwScreenWidth-640)/2, (g_dwScreenHeight-480)/2, lpConfigDlgSurf, NULL, DDBLTFAST_WAIT);
  879. }
  880. FlipScreen();
  881. }
  882. //-----------------------------------------------------------------------------
  883. // Name: DeleteFromList()
  884. // Desc:
  885. //-----------------------------------------------------------------------------
  886. VOID DeleteFromList( DisplayObject* pObject )
  887. {
  888. if( pObject->next )
  889. pObject->next->prev = pObject->prev;
  890. if( pObject->prev )
  891. pObject->prev->next = pObject->next;
  892. delete( pObject );
  893. }
  894. //-----------------------------------------------------------------------------
  895. // Name: UpdateDisplayList()
  896. // Desc:
  897. //-----------------------------------------------------------------------------
  898. VOID UpdateDisplayList()
  899. {
  900. DisplayObject* thisnode;
  901. FLOAT maxx, maxy;
  902. FLOAT maxframe;
  903. DWORD input[NUMBER_OF_PLAYERS];//= lastInput;
  904. for (int pl = 0; pl < NUMBER_OF_PLAYERS; pl ++)
  905. {
  906. input[pl] = 0;
  907. }
  908. // Update the game clock parameters
  909. DWORD dwTickCount = GetTickCount();
  910. FLOAT fTickDiff = ( dwTickCount - g_dwLastTickCount )/1000.0f;
  911. g_dwLastTickCount = dwTickCount;
  912. // Read input from the players' devices
  913. GetDeviceInput(input);
  914. for (int pl = 0; pl < NUMBER_OF_PLAYERS; pl ++)
  915. {
  916. BOOL bShieldState = FALSE;
  917. BOOL bThrustState = FALSE;
  918. BOOL bBounce = FALSE;
  919. LONG lAngle = 0;
  920. //if KEY_QUIT is pressed, exit
  921. if (input[pl] & KEY_QUIT)
  922. {
  923. PostMessage( g_hWndMain, WM_CLOSE, 0, 0 );
  924. return;
  925. }
  926. //if KEY_DISPLAY is pressed, call ConfigureDevices() in normal mode
  927. if (input[pl] & KEY_DISPLAY)
  928. {
  929. //call ConfigureDevices() in default mode
  930. DIUtil_ConfigureDevices(g_hWndMain, g_pddsDIConfig, DICD_DEFAULT);
  931. }
  932. //if KEY_EDIT is pressed, call ConfigureDevices() in edit mode
  933. if (input[pl] & KEY_EDIT)
  934. {
  935. //call ConfigureDevices() in edit mode
  936. DIUtil_ConfigureDevices(g_hWndMain, g_pddsDIConfig, DICD_EDIT);
  937. }
  938. if( g_fShowDelay > 0.0f )
  939. {
  940. g_fShowDelay -= fTickDiff;
  941. if( g_fShowDelay < 0.0f )
  942. {
  943. InitializeShips();
  944. #if 0 //not used for the mulit-user mapper
  945. g_bLastShield = FALSE;
  946. #endif //not used for the mulit-user mapper
  947. g_fShowDelay = 0.0f;
  948. if (g_pShipsArray[pl] != NULL)
  949. {
  950. g_pShipsArray[pl]->bVisible = TRUE;
  951. }
  952. }
  953. }
  954. // Update the ships
  955. if (g_pShipsArray[pl] != NULL)
  956. {
  957. if( g_pShipsArray[pl]->bVisible )
  958. {
  959. g_pShipsArray[pl]->posx += g_pShipsArray[pl]->velx * fTickDiff;
  960. g_pShipsArray[pl]->posy += g_pShipsArray[pl]->vely * fTickDiff;
  961. }
  962. if( g_pShipsArray[pl]->posx > (FLOAT)(MAX_SCREEN_X - SHIP_WIDTH) )
  963. {
  964. g_pShipsArray[pl]->posx = (FLOAT)(MAX_SCREEN_X - SHIP_WIDTH);
  965. g_pShipsArray[pl]->velx = -g_pShipsArray[pl]->velx;
  966. // Bounce off the right edge of the screen
  967. bBounce = TRUE;
  968. lAngle = 90;
  969. }
  970. else if( g_pShipsArray[pl]->posx < 0 )
  971. {
  972. g_pShipsArray[pl]->posx = 0;
  973. g_pShipsArray[pl]->velx = -g_pShipsArray[pl]->velx;
  974. // Bounce off the left edge of the screen
  975. bBounce = TRUE;
  976. lAngle = 270;
  977. }
  978. if( g_pShipsArray[pl]->posy > (FLOAT)(MAX_SCREEN_Y - SHIP_HEIGHT) )
  979. {
  980. g_pShipsArray[pl]->posy = (FLOAT)(MAX_SCREEN_Y - SHIP_HEIGHT);
  981. g_pShipsArray[pl]->vely = -g_pShipsArray[pl]->vely;
  982. // Bounce off the bottom edge of the screen
  983. bBounce = TRUE;
  984. lAngle = 180;
  985. }
  986. else if( g_pShipsArray[pl]->posy < 0 )
  987. {
  988. g_pShipsArray[pl]->posy =0;
  989. g_pShipsArray[pl]->vely = -g_pShipsArray[pl]->vely;
  990. // Bounce off the top edge of the screen
  991. bBounce = TRUE;
  992. lAngle = 0;
  993. }
  994. if( bBounce )
  995. {
  996. // "Bounce" the ship
  997. PlayPannedSound( g_pShipBounceSound, g_pShipsArray[pl] );
  998. #if 0 //not used in the Semantic Mapper demo
  999. DIUtil_PlayDirectionalEffect( g_pBounceFFEffect, lAngle );
  1000. #endif //not used in the Semantic Mapper demo
  1001. }
  1002. bShieldState = ( !g_pShipsArray[pl]->bVisible || ( input[pl] & KEY_SHIELD ) );
  1003. #if 0 //not used for the mulit-user mapper
  1004. if( bShieldState != g_bLastShield )
  1005. {
  1006. #endif //not used for the mulit-user mapper
  1007. if( bShieldState && g_pShipsArray[pl]->bVisible )
  1008. {
  1009. DSUtil_PlaySound( g_pShieldBuzzSound, DSBPLAY_LOOPING );
  1010. #if 0 //not used for the mulit-user mapper
  1011. g_bShieldsOn = TRUE;
  1012. #endif //not used for the mulit-user mapper
  1013. }
  1014. else
  1015. {
  1016. DSUtil_StopSound( g_pShieldBuzzSound );
  1017. #if 0 //not used for the mulit-user mapper
  1018. g_bShieldsOn = FALSE;
  1019. #endif //not used for the mulit-user mapper
  1020. }
  1021. #if 0 //not used for the mulit-user mapper
  1022. g_bLastShield = bShieldState;
  1023. }
  1024. #endif //not used for the mulit-user mapper
  1025. if( bShieldState )
  1026. {
  1027. input[pl] &= ~(KEY_FIRE);
  1028. }
  1029. if( input[pl] & KEY_FIRE )
  1030. {
  1031. // Add a bullet to the scene
  1032. if( g_pShipsArray[pl]->bVisible )
  1033. {
  1034. // Bullets cost one score point
  1035. if( g_dwScore )
  1036. g_dwScore--;
  1037. // Play the "fire" sound
  1038. DSUtil_PlaySound( g_pFireBulletSound, 0);
  1039. // Play the "fire" forcefeedback effect
  1040. #if 0 //not used in the Semantic Mapper demo
  1041. DIUtil_PlayEffect( g_pFireFFEffect );
  1042. #endif //not used in the Semantic Mapper demo
  1043. // Add a bullet to the display list
  1044. CreateObject( OBJ_BULLET,
  1045. Dirx[(int)g_pShipsArray[pl]->frame]*6.0f + 16.0f + g_pShipsArray[pl]->posx,
  1046. Diry[(int)g_pShipsArray[pl]->frame]*6.0f + 16.0f + g_pShipsArray[pl]->posy,
  1047. Dirx[(int)g_pShipsArray[pl]->frame]*500.0f,
  1048. Diry[(int)g_pShipsArray[pl]->frame]*500.0f,
  1049. pl);
  1050. }
  1051. }
  1052. if( input[pl] & KEY_LEFT )
  1053. {
  1054. g_pShipsArray[pl]->frame -= 1.0;
  1055. if( g_pShipsArray[pl]->frame < 0.0 )
  1056. g_pShipsArray[pl]->frame += MAX_SHIP_FRAME;
  1057. }
  1058. if( input[pl] & KEY_RIGHT )
  1059. {
  1060. g_pShipsArray[pl]->frame += 1.0;
  1061. if( g_pShipsArray[pl]->frame >= MAX_SHIP_FRAME )
  1062. g_pShipsArray[pl]->frame -= MAX_SHIP_FRAME;
  1063. }
  1064. if( input[pl] & KEY_UP )
  1065. {
  1066. g_pShipsArray[pl]->velx += Dirx[(int)g_pShipsArray[pl]->frame] * 10.0f;
  1067. g_pShipsArray[pl]->vely += Diry[(int)g_pShipsArray[pl]->frame] * 10.0f;
  1068. bThrustState = TRUE;
  1069. }
  1070. if( input[pl] & KEY_DOWN )
  1071. {
  1072. g_pShipsArray[pl]->velx -= Dirx[(int)g_pShipsArray[pl]->frame] * 10.0f;
  1073. g_pShipsArray[pl]->vely -= Diry[(int)g_pShipsArray[pl]->frame] * 10.0f;
  1074. bThrustState = TRUE;
  1075. }
  1076. if( bThrustState != lastThrust )
  1077. {
  1078. if( bThrustState )
  1079. {
  1080. input[pl] &= ~KEY_STOP;
  1081. DSUtil_StopSound( g_pSkidToStopSound );
  1082. DSUtil_PlaySound( g_pEngineRevSound, DSBPLAY_LOOPING );
  1083. #if 0 //not used for the mulit-user mapper
  1084. g_bThrusting = TRUE;
  1085. #endif //not used for the mulit-user mapper
  1086. }
  1087. else
  1088. {
  1089. DSUtil_StopSound( g_pEngineRevSound );
  1090. #if 0 //not used for the mulit-user mapper
  1091. g_bThrusting = FALSE;
  1092. #endif //not used for the mulit-user mapper
  1093. }
  1094. lastThrust = bThrustState;
  1095. }
  1096. if( input[pl] & KEY_STOP )
  1097. {
  1098. if( g_pShipsArray[pl]->velx || g_pShipsArray[pl]->vely )
  1099. PlayPannedSound( g_pSkidToStopSound, g_pShipsArray[pl] );
  1100. g_pShipsArray[pl]->velx = 0.0f;
  1101. g_pShipsArray[pl]->vely = 0.0f;
  1102. }
  1103. }
  1104. }
  1105. for( thisnode = g_pDisplayList->next; thisnode; )
  1106. {
  1107. //for things other than ships, which were handled above
  1108. if (thisnode->type != OBJ_SHIP)
  1109. {
  1110. thisnode->posx += thisnode->velx * fTickDiff;
  1111. thisnode->posy += thisnode->vely * fTickDiff;
  1112. thisnode->frame += thisnode->delay * fTickDiff;
  1113. switch( thisnode->type )
  1114. {
  1115. case OBJ_DONUT:
  1116. maxx = (FLOAT)(MAX_SCREEN_X - DONUT_WIDTH);
  1117. maxy = (FLOAT)(MAX_SCREEN_Y - DONUT_HEIGHT);
  1118. maxframe = MAX_DONUT_FRAME;
  1119. break;
  1120. case OBJ_PYRAMID:
  1121. maxx = (FLOAT)(MAX_SCREEN_X - PYRAMID_WIDTH);
  1122. maxy = (FLOAT)(MAX_SCREEN_Y - PYRAMID_HEIGHT);
  1123. maxframe = MAX_PYRAMID_FRAME;
  1124. break;
  1125. case OBJ_SPHERE:
  1126. maxx = (FLOAT)(MAX_SCREEN_X - SPHERE_WIDTH);
  1127. maxy = (FLOAT)(MAX_SCREEN_Y - SPHERE_HEIGHT);
  1128. maxframe = MAX_SPHERE_FRAME;
  1129. break;
  1130. case OBJ_CUBE:
  1131. maxx = (FLOAT)(MAX_SCREEN_X - CUBE_WIDTH);
  1132. maxy = (FLOAT)(MAX_SCREEN_Y - CUBE_HEIGHT);
  1133. maxframe = MAX_CUBE_FRAME;
  1134. break;
  1135. case OBJ_BULLET:
  1136. maxx = (FLOAT)(MAX_SCREEN_X - BULLET_WIDTH);
  1137. maxy = (FLOAT)(MAX_SCREEN_Y - BULLET_HEIGHT);
  1138. maxframe = MAX_BULLET_FRAME;
  1139. // If bullet "expired", removed it from list
  1140. if( thisnode->frame >= MAX_BULLET_FRAME )
  1141. {
  1142. DisplayObject* pVictim = thisnode;
  1143. thisnode = thisnode->next;
  1144. DeleteFromList( pVictim );
  1145. continue;
  1146. }
  1147. break;
  1148. }
  1149. if( thisnode != g_pDisplayList )
  1150. {
  1151. if( thisnode->posx > maxx )
  1152. {
  1153. thisnode->posx = maxx;
  1154. thisnode->velx = -thisnode->velx;
  1155. }
  1156. else if ( thisnode->posx < 0 )
  1157. {
  1158. thisnode->posx =0;
  1159. thisnode->velx = -thisnode->velx;
  1160. }
  1161. if( thisnode->posy > maxy )
  1162. {
  1163. thisnode->posy = maxy;
  1164. thisnode->vely = -thisnode->vely;
  1165. }
  1166. else if ( thisnode->posy < 0 )
  1167. {
  1168. thisnode->posy =0;
  1169. thisnode->vely = -thisnode->vely;
  1170. }
  1171. if( thisnode->frame >= maxframe )
  1172. {
  1173. thisnode->frame -= maxframe;
  1174. }
  1175. }
  1176. }
  1177. thisnode = thisnode->next;
  1178. }
  1179. }
  1180. //-----------------------------------------------------------------------------
  1181. // Name: IsDisplayListEmpty()
  1182. // Desc:
  1183. //-----------------------------------------------------------------------------
  1184. BOOL IsDisplayListEmpty()
  1185. {
  1186. DisplayObject* pObject = g_pDisplayList->next;
  1187. while( pObject )
  1188. {
  1189. if( pObject->type != OBJ_BULLET )
  1190. return FALSE;
  1191. pObject = pObject->next;
  1192. }
  1193. return TRUE;
  1194. }
  1195. //-----------------------------------------------------------------------------
  1196. // Name: IsDisplayListEmptyExceptShips()
  1197. // Desc:
  1198. //-----------------------------------------------------------------------------
  1199. BOOL IsDisplayListEmptyExceptShips()
  1200. {
  1201. DisplayObject* pObject = g_pDisplayList->next;
  1202. while( pObject )
  1203. {
  1204. if(( pObject->type != OBJ_BULLET ) && (pObject->type != OBJ_SHIP))
  1205. return FALSE;
  1206. pObject = pObject->next;
  1207. }
  1208. return TRUE;
  1209. }
  1210. //-----------------------------------------------------------------------------
  1211. // Name: InitializeShips()
  1212. // Desc:
  1213. //-----------------------------------------------------------------------------
  1214. VOID InitializeShips()
  1215. {
  1216. for (int ship = 0; ship < NUMBER_OF_PLAYERS; ship++)
  1217. {
  1218. if (g_pShipsArray[ship] != NULL)
  1219. {
  1220. g_pShipsArray[ship]->posx = (FLOAT)(g_dwScreenWidth/(ship+2)-16); // Center the ship
  1221. g_pShipsArray[ship]->posy = (FLOAT)(g_dwScreenHeight/(ship+2)-16);
  1222. g_pShipsArray[ship]->frame = 0.0f;
  1223. g_pShipsArray[ship]->velx = 0.0f; // Not moving
  1224. g_pShipsArray[ship]->vely = 0.0f;
  1225. g_pShipsArray[ship]->bVisible = TRUE;
  1226. g_pShipsArray[ship]->Player = ship;
  1227. }
  1228. }
  1229. }
  1230. //-----------------------------------------------------------------------------
  1231. // Name: AdvanceLevel()
  1232. // Desc:
  1233. //-----------------------------------------------------------------------------
  1234. VOID AdvanceLevel()
  1235. {
  1236. // Up the level
  1237. g_dwLevel++;
  1238. // Clear any stray objects (anything but the ships) out of the display list
  1239. while( (g_pShip->next != NULL) && (g_pShip->next->type != OBJ_SHIP ))
  1240. {
  1241. DeleteFromList( g_pShip->next );
  1242. }
  1243. // Create donuts for the new level
  1244. for( WORD i=0; i<(2*g_dwLevel-1); i++ )
  1245. {
  1246. FLOAT x = rnd( 0.0f, (FLOAT)(MAX_SCREEN_X - DONUT_WIDTH) );
  1247. FLOAT y = rnd( 0.0f, (FLOAT)(MAX_SCREEN_Y - DONUT_HEIGHT) );
  1248. CreateObject( OBJ_DONUT, x, y, 0.0f, 0.0f, NO_PLAYER );
  1249. }
  1250. // Delay for 2 seconds before displaying ships
  1251. InitializeShips();
  1252. g_fShowDelay = 2.0f;
  1253. }
  1254. //-----------------------------------------------------------------------------
  1255. // Name: CreateObject()
  1256. // Desc:
  1257. //-----------------------------------------------------------------------------
  1258. DisplayObject* CreateObject( SHORT type, FLOAT x, FLOAT y, FLOAT vx, FLOAT vy, int Player )
  1259. {
  1260. // Create a new display object
  1261. DisplayObject* pObject = new DisplayObject;
  1262. if( NULL == pObject )
  1263. return NULL;
  1264. // Add the object to the global display list
  1265. AddToList( pObject );
  1266. // Set object attributes
  1267. pObject->bVisible = TRUE;
  1268. pObject->type = type;
  1269. pObject->posx = x;
  1270. pObject->posy = y;
  1271. pObject->velx = vx;
  1272. pObject->vely = vy;
  1273. pObject->Player = NO_PLAYER;
  1274. switch( type )
  1275. {
  1276. case OBJ_DONUT:
  1277. pObject->velx = rnd( -50.0f, 50.0f );
  1278. pObject->vely = rnd( -50.0f, 50.0f );
  1279. pObject->frame = rnd( 0.0f, 30.0f );
  1280. pObject->delay = rnd( 3.0f, 12.0f );
  1281. pObject->pddsSurface = g_pddsDonut;
  1282. break;
  1283. case OBJ_PYRAMID:
  1284. pObject->velx = rnd( -75.0f, 75.0f );
  1285. pObject->vely = rnd( -75.0f, 75.0f );
  1286. pObject->frame = rnd( 0.0f, 30.0f );
  1287. pObject->delay = rnd( 12.0f, 40.0f );
  1288. pObject->pddsSurface = g_pddsPyramid;
  1289. break;
  1290. case OBJ_SPHERE:
  1291. pObject->velx = rnd( -150.0f, 150.0f );
  1292. pObject->vely = rnd( -150.0f, 150.0f );
  1293. pObject->frame = rnd( 0.0f, 30.0f );
  1294. pObject->delay = rnd( 60.0f, 80.0f );
  1295. pObject->pddsSurface = g_pddsSphere;
  1296. break;
  1297. case OBJ_CUBE:
  1298. pObject->velx = rnd( -200.0f, 200.0f );
  1299. pObject->vely = rnd( -200.0f, 200.0f );
  1300. pObject->frame = rnd( 0.0f, 30.0f );
  1301. pObject->delay = rnd( 32.0f, 80.0f );
  1302. pObject->pddsSurface = g_pddsCube;
  1303. break;
  1304. case OBJ_SHIP:
  1305. pObject->frame = 0.0f;
  1306. pObject->posx = x;
  1307. pObject->posy = y;
  1308. pObject->velx = 0.0f; // Not moving
  1309. pObject->vely = 0.0f;
  1310. pObject->Player = Player; //which player the ship belongs to
  1311. pObject->pddsSurface = g_pddsShip;
  1312. break;
  1313. case OBJ_BULLET:
  1314. pObject->frame = 0.0f;
  1315. pObject->delay = 1000.0f;
  1316. pObject->Player = Player; //which player's ship shot the bullet
  1317. pObject->pddsSurface = g_pddsNumbers;
  1318. break;
  1319. }
  1320. return pObject;
  1321. };
  1322. //-----------------------------------------------------------------------------
  1323. // Name: AddToList()
  1324. // Desc:
  1325. //-----------------------------------------------------------------------------
  1326. VOID AddToList( DisplayObject* pObject )
  1327. {
  1328. pObject->next = g_pDisplayList->next;
  1329. pObject->prev = g_pDisplayList;
  1330. if( g_pDisplayList->next )
  1331. g_pDisplayList->next->prev = pObject;
  1332. g_pDisplayList->next = pObject;
  1333. }
  1334. //-----------------------------------------------------------------------------
  1335. // Name: RestoreSurfaces()
  1336. // Desc:
  1337. //-----------------------------------------------------------------------------
  1338. HRESULT RestoreSurfaces()
  1339. {
  1340. HRESULT hr;
  1341. HBITMAP hbm;
  1342. if( FAILED( hr = g_pddsFrontBuffer->Restore() ) )
  1343. return E_FAIL;
  1344. if( FAILED( hr = g_pddsDonut->Restore() ) )
  1345. return E_FAIL;
  1346. if( FAILED( hr = g_pddsPyramid->Restore() ) )
  1347. return E_FAIL;
  1348. if( FAILED( hr = g_pddsCube->Restore() ) )
  1349. return E_FAIL;
  1350. if( FAILED( hr = g_pddsSphere->Restore() ) )
  1351. return E_FAIL;
  1352. if( FAILED( hr = g_pddsShip->Restore() ) )
  1353. return E_FAIL;
  1354. if( FAILED( hr = g_pddsNumbers->Restore() ) )
  1355. return E_FAIL;
  1356. // Create and set the palette for the splash bitmap
  1357. g_pSplashPalette = DDUtil_LoadPalette( g_pDD, "SPLASH" );
  1358. // Create and set the palette for the art bitmap
  1359. g_pArtPalette = DDUtil_LoadPalette( g_pDD, "DONUTS8" );
  1360. if( NULL == g_pSplashPalette || NULL == g_pArtPalette )
  1361. {
  1362. CleanupAndDisplayError("Could not load palettes");
  1363. return E_FAIL;
  1364. }
  1365. // Set the palette before loading the art
  1366. g_pddsFrontBuffer->SetPalette( g_pArtPalette );
  1367. hbm = (HBITMAP)LoadImage( GetModuleHandle(NULL), "DONUTS8", IMAGE_BITMAP, 0, 0,
  1368. LR_CREATEDIBSECTION );
  1369. if( NULL == hbm )
  1370. {
  1371. CleanupAndDisplayError("Could not load bitmap");
  1372. return E_FAIL;
  1373. }
  1374. // Copy the bitmaps. (We're OR'ing the hresults together so we only have to
  1375. // do one check for a failure case.)
  1376. hr |= DDUtil_CopyBitmap( g_pddsDonut, hbm, 0, 0, 320, 384 );
  1377. hr |= DDUtil_CopyBitmap( g_pddsPyramid, hbm, 0, 384, 320, 128 );
  1378. hr |= DDUtil_CopyBitmap( g_pddsSphere, hbm, 0, 512, 320, 32 );
  1379. hr |= DDUtil_CopyBitmap( g_pddsCube, hbm, 0, 544, 320, 32 );
  1380. hr |= DDUtil_CopyBitmap( g_pddsShip, hbm, 0, 576, 320, 256 );
  1381. hr |= DDUtil_CopyBitmap( g_pddsNumbers, hbm, 0, 832, 320, 16 );
  1382. if( FAILED(hr) )
  1383. {
  1384. CleanupAndDisplayError("Could not copy bitmaps to surfaces");
  1385. DeleteObject( hbm );
  1386. return E_FAIL;
  1387. }
  1388. // Done with the bitmap
  1389. DeleteObject( hbm );
  1390. // Set colorfill colors and color keys according to bitmap contents
  1391. g_dwFillColor = DDUtil_ColorMatch( g_pddsDonut, CLR_INVALID );
  1392. DDUtil_SetColorKey( g_pddsDonut, CLR_INVALID );
  1393. DDUtil_SetColorKey( g_pddsPyramid, CLR_INVALID );
  1394. DDUtil_SetColorKey( g_pddsCube, CLR_INVALID );
  1395. DDUtil_SetColorKey( g_pddsSphere, CLR_INVALID );
  1396. DDUtil_SetColorKey( g_pddsShip, CLR_INVALID );
  1397. DDUtil_SetColorKey( g_pddsNumbers, CLR_INVALID );
  1398. return S_OK;
  1399. }
  1400. //-----------------------------------------------------------------------------
  1401. // Name: rnd()
  1402. // Desc:
  1403. //-----------------------------------------------------------------------------
  1404. FLOAT rnd( FLOAT low, FLOAT high )
  1405. {
  1406. return low + ( high - low ) * ((FLOAT)rand())/RAND_MAX;
  1407. }
  1408. //-----------------------------------------------------------------------------
  1409. // Name: InitializeSound()
  1410. // Desc:
  1411. //-----------------------------------------------------------------------------
  1412. HRESULT InitializeSound( HWND hWnd )
  1413. {
  1414. g_bSoundEnabled = FALSE;
  1415. if( FAILED( DirectSoundCreate( NULL, &g_pDS, NULL ) ) )
  1416. //return E_FAIL;
  1417. //per Marcus's request, to run on his machine
  1418. return S_FALSE;
  1419. if( FAILED( g_pDS->SetCooperativeLevel( hWnd, DSSCL_NORMAL ) ) )
  1420. {
  1421. g_pDS->Release();
  1422. g_pDS = NULL;
  1423. return E_FAIL;
  1424. }
  1425. g_pBeginLevelSound = DSUtil_CreateSound( g_pDS, "BeginLevel", 1 );
  1426. g_pEngineIdleSound = DSUtil_CreateSound( g_pDS, "EngineIdle", 1 );
  1427. g_pEngineRevSound = DSUtil_CreateSound( g_pDS, "EngineRev", 1 );
  1428. g_pSkidToStopSound = DSUtil_CreateSound( g_pDS, "SkidToStop", 1 );
  1429. g_pShieldBuzzSound = DSUtil_CreateSound( g_pDS, "ShieldBuzz", 1 );
  1430. g_pShipExplodeSound = DSUtil_CreateSound( g_pDS, "ShipExplode", 1 );
  1431. g_pFireBulletSound = DSUtil_CreateSound( g_pDS, "Gunfire", 25 );
  1432. g_pShipBounceSound = DSUtil_CreateSound( g_pDS, "ShipBounce", 4 );
  1433. g_pDonutExplodeSound = DSUtil_CreateSound( g_pDS, "DonutExplode", 10 );
  1434. g_pPyramidExplodeSound = DSUtil_CreateSound( g_pDS, "PyramidExplode", 12 );
  1435. g_pCubeExplodeSound = DSUtil_CreateSound( g_pDS, "CubeExplode", 15 );
  1436. g_pSphereExplodeSound = DSUtil_CreateSound( g_pDS, "SphereExplode", 10 );
  1437. g_bSoundEnabled = TRUE;
  1438. // Start sounds that should be playing
  1439. #if 0 //not used for the mulit-user mapper
  1440. if( g_bEngineIdle ) DSUtil_PlaySound( g_pEngineIdleSound, DSBPLAY_LOOPING );
  1441. if( g_bShieldsOn ) DSUtil_PlaySound( g_pShieldBuzzSound, DSBPLAY_LOOPING );
  1442. if( g_bThrusting ) DSUtil_PlaySound( g_pEngineRevSound, DSBPLAY_LOOPING );
  1443. #endif //not used for the mulit-user mapper
  1444. return S_OK;
  1445. }
  1446. //-----------------------------------------------------------------------------
  1447. // Name: DestroySound()
  1448. // Desc:
  1449. //-----------------------------------------------------------------------------
  1450. VOID DestroySound()
  1451. {
  1452. if( g_pDS )
  1453. {
  1454. DSUtil_DestroySound( g_pBeginLevelSound );
  1455. DSUtil_DestroySound( g_pEngineIdleSound );
  1456. DSUtil_DestroySound( g_pEngineRevSound );
  1457. DSUtil_DestroySound( g_pSkidToStopSound );
  1458. DSUtil_DestroySound( g_pShieldBuzzSound );
  1459. DSUtil_DestroySound( g_pShipExplodeSound );
  1460. DSUtil_DestroySound( g_pFireBulletSound );
  1461. DSUtil_DestroySound( g_pShipBounceSound );
  1462. DSUtil_DestroySound( g_pDonutExplodeSound );
  1463. DSUtil_DestroySound( g_pPyramidExplodeSound );
  1464. DSUtil_DestroySound( g_pCubeExplodeSound );
  1465. DSUtil_DestroySound( g_pSphereExplodeSound );
  1466. g_pDS->Release();
  1467. }
  1468. g_pBeginLevelSound = NULL;
  1469. g_pEngineIdleSound = NULL;
  1470. g_pEngineRevSound = NULL;
  1471. g_pSkidToStopSound = NULL;
  1472. g_pShieldBuzzSound = NULL;
  1473. g_pShipExplodeSound = NULL;
  1474. g_pFireBulletSound = NULL;
  1475. g_pShipBounceSound = NULL;
  1476. g_pDonutExplodeSound = NULL;
  1477. g_pPyramidExplodeSound = NULL;
  1478. g_pCubeExplodeSound = NULL;
  1479. g_pSphereExplodeSound = NULL;
  1480. g_pDS = NULL;
  1481. g_bSoundEnabled = FALSE;
  1482. }
  1483. //-----------------------------------------------------------------------------
  1484. // Name: InitializeInput()
  1485. // Desc:
  1486. //-----------------------------------------------------------------------------
  1487. HRESULT InitializeInput( HWND hWnd )
  1488. {
  1489. // Initialize DirectInpu
  1490. if( FAILED( DIUtil_Initialize( hWnd ) ) )
  1491. {
  1492. MessageBox( hWnd, "Can't Initialize DirectInput", "TDonuts", MB_OK );
  1493. return E_FAIL;
  1494. }
  1495. return S_OK;
  1496. }
  1497. //-----------------------------------------------------------------------------
  1498. // Name: DestroyInput()
  1499. // Desc:
  1500. //-----------------------------------------------------------------------------
  1501. VOID DestroyInput()
  1502. {
  1503. // Release DirectInput
  1504. DIUtil_CleanupDirectInput();
  1505. }
  1506. //-----------------------------------------------------------------------------
  1507. // Name: GetDeviceInput(input[])
  1508. // Desc: Processes data from the input device. Uses GetDeviceData().
  1509. //-----------------------------------------------------------------------------
  1510. VOID GetDeviceInput(DWORD input[NUMBER_OF_PLAYERS])
  1511. {
  1512. HRESULT hr = S_OK;
  1513. for (int pl = 0; pl < NUMBER_OF_PLAYERS; pl++)
  1514. {
  1515. printf("pl = %i", pl);
  1516. for (int dv = 0; dv < (int) g_dwNumDevices[pl]; dv++)
  1517. {
  1518. printf("dv = %i", dv);
  1519. if (g_pDevices[pl][dv] != NULL)
  1520. {
  1521. DWORD dwItems = 10;
  1522. DIDEVICEOBJECTDATA rgdod[10];
  1523. hr = g_pDevices[pl][dv]->Poll();
  1524. if (SUCCEEDED(hr))
  1525. {
  1526. hr = g_pDevices[pl][dv]->GetDeviceData(
  1527. sizeof(DIDEVICEOBJECTDATA),
  1528. rgdod,
  1529. &dwItems,
  1530. 0);
  1531. if (SUCCEEDED(hr))
  1532. {
  1533. //get the sematics codes
  1534. for (int j=0; j < (int)dwItems; j++)
  1535. {
  1536. //for axes, do axes stuff
  1537. if (rgdod[j].uAppData & AXIS_MASK)
  1538. {
  1539. //blow out all of the axis data
  1540. dwInputState[pl] &= ~(KEY_RIGHT);
  1541. dwInputState[pl] &= ~(KEY_LEFT);
  1542. dwInputState[pl] &= ~(KEY_UP);
  1543. dwInputState[pl] &= ~(KEY_DOWN);
  1544. if( ((int)rgdod[j].dwData) > 10 )
  1545. {
  1546. dwInputState[pl] |= ( rgdod[j].uAppData == AXIS_LR ) ? KEY_RIGHT : KEY_DOWN;
  1547. }
  1548. if( ((int)rgdod[j].dwData) < -10 )
  1549. {
  1550. dwInputState[pl] |= ( rgdod[j].uAppData == AXIS_LR ) ? KEY_LEFT : KEY_UP;
  1551. }
  1552. }
  1553. else //do buttons
  1554. {
  1555. //if rgdod[j].dwData & 0x80, it means the button went down,
  1556. //else it went up
  1557. if (rgdod[j].dwData & 0x80)
  1558. {
  1559. //set the new state
  1560. dwInputState[pl] |= rgdod[j].uAppData;
  1561. }
  1562. else
  1563. {
  1564. dwInputState[pl] &= ~(rgdod[j].uAppData);
  1565. }
  1566. }
  1567. }
  1568. }
  1569. }
  1570. }
  1571. }
  1572. //set the new state
  1573. if (SUCCEEDED(hr))
  1574. {
  1575. input[pl] = dwInputState[pl];
  1576. }
  1577. }
  1578. }