demoII11_2.cpp
上传用户:husern
上传日期:2018-01-20
资源大小:42486k
文件大小:41k
源码类别:

游戏

开发平台:

Visual C++

  1. // DEMOII11_2.CPP - Water simulation 
  2. // READ THIS!
  3. // To compile make sure to include DDRAW.LIB, DSOUND.LIB,
  4. // DINPUT.LIB, DINPUT8.LIB, WINMM.LIB in the project link list, and of course 
  5. // the C++ source modules T3DLIB1-9.CPP and the headers T3DLIB1-8.H
  6. // be in the working directory of the compiler
  7. // INCLUDES ///////////////////////////////////////////////
  8. #define DEBUG_ON
  9. #define INITGUID       // make sure al the COM interfaces are available
  10.                        // instead of this you can include the .LIB file
  11.                        // DXGUID.LIB
  12. #define WIN32_LEAN_AND_MEAN  
  13. #include <windows.h>   // include important windows stuff
  14. #include <windowsx.h> 
  15. #include <mmsystem.h>
  16. #include <iostream.h> // include important C/C++ stuff
  17. #include <conio.h> 
  18. #include <stdlib.h> 
  19. #include <malloc.h> 
  20. #include <memory.h>
  21. #include <string.h>  
  22. #include <stdarg.h>  
  23. #include <stdio.h>     
  24. #include <math.h>
  25. #include <io.h>
  26. #include <fcntl.h>
  27. #include <ddraw.h>  // directX includes 
  28. #include <dsound.h>
  29. #include <dmksctrl.h>
  30. #include <dmusici.h>
  31. #include <dmusicc.h>
  32. #include <dmusicf.h>
  33. #include <dinput.h>
  34. #include "T3DLIB1.h" // game library includes
  35. #include "T3DLIB2.h"
  36. #include "T3DLIB3.h"
  37. #include "T3DLIB4.h"
  38. #include "T3DLIB5.h"
  39. #include "T3DLIB6.h"
  40. #include "T3DLIB7.h"
  41. #include "T3DLIB8.h"
  42. #include "T3DLIB9.h"
  43. // DEFINES ////////////////////////////////////////////////
  44. // defines for windows interface
  45. #define WINDOW_CLASS_NAME "WIN3DCLASS"  // class name
  46. #define WINDOW_TITLE      "T3D Graphics Console Ver 2.0"
  47. #define WINDOW_WIDTH      800     // size of window
  48. #define WINDOW_HEIGHT     600
  49. #define WINDOW_BPP        16      // bitdepth of window (8,16,24 etc.)
  50.                                   // note: if windowed and not
  51.                                   // fullscreen then bitdepth must
  52.                                   // be same as system bitdepth
  53.                                   // also if 8-bit the a pallete
  54.                                   // is created and attached
  55.    
  56. #define WINDOWED_APP      0       // 0 not windowed, 1 windowed
  57. // create some constants for ease of access
  58. #define AMBIENT_LIGHT_INDEX   0   // ambient light index
  59. #define INFINITE_LIGHT_INDEX  1   // infinite light index
  60. #define POINT_LIGHT_INDEX     2   // point light index
  61. // terrain defines
  62. #define TERRAIN_WIDTH         5000 
  63. #define TERRAIN_HEIGHT        5000
  64. #define TERRAIN_SCALE         700
  65. #define MAX_SPEED             20
  66. #define PITCH_RETURN_RATE (.50)   // how fast the pitch straightens out
  67. #define PITCH_CHANGE_RATE (.045)  // the rate that pitch changes relative to height
  68. #define CAM_HEIGHT_SCALER (.3)    // percentage cam height changes relative to height
  69. #define VELOCITY_SCALER   (.03)   // rate velocity changes with height
  70. #define CAM_DECEL         (.25)   // deceleration/friction
  71. #define WATER_LEVEL         40    // level where wave will have effect
  72. #define WAVE_HEIGHT         25    // amplitude of modulation
  73. #define WAVE_RATE        (0.1f)   // how fast the wave propagates
  74. #define MAX_JETSKI_TURN           25    // maximum turn angle
  75. #define JETSKI_TURN_RETURN_RATE   .5    // rate of return for turn
  76. #define JETSKI_TURN_RATE           2    // turn rate
  77. #define JETSKI_YAW_RATE           .1    // yaw rates, return, and max
  78. #define MAX_JETSKI_YAW            10 
  79. #define JETSKI_YAW_RETURN_RATE    .02 
  80. // game states
  81. #define GAME_STATE_INIT            0
  82. #define GAME_STATE_RESTART         1
  83. #define GAME_STATE_RUN             2
  84. #define GAME_STATE_INTRO           3
  85. #define GAME_STATE_PLAY            4
  86. #define GAME_STATE_EXIT            5
  87. // delays for introductions
  88. #define INTRO_STATE_COUNT1 (30*9)
  89. #define INTRO_STATE_COUNT2 (30*11)
  90. #define INTRO_STATE_COUNT3 (30*17)
  91. // player/jetski states
  92. #define JETSKI_OFF                 0 
  93. #define JETSKI_START               1 
  94. #define JETSKI_IDLE                2
  95. #define JETSKI_ACCEL               3 
  96. #define JETSKI_FAST                4
  97. // PROTOTYPES /////////////////////////////////////////////
  98. // game console
  99. int Game_Init(void *parms=NULL);
  100. int Game_Shutdown(void *parms=NULL);
  101. int Game_Main(void *parms=NULL);
  102.  
  103. // GLOBALS ////////////////////////////////////////////////
  104. HWND main_window_handle = NULL; // save the window handle
  105. HINSTANCE main_instance = NULL; // save the instance
  106. char buffer[2048];              // used to print text
  107. // initialize camera position and direction
  108. POINT4D  cam_pos    = {0,500,-200,1};
  109. POINT4D  cam_target = {0,0,0,1};
  110. VECTOR4D cam_dir    = {0,0,0,1};
  111. // all your initialization code goes here...
  112. VECTOR4D vscale={1.0,1.0,1.0,1}, 
  113.          vpos = {0,0,150,1}, 
  114.          vrot = {0,0,0,1};
  115. CAM4DV1         cam;           // the single camera
  116. OBJECT4DV2      obj_terrain,   // the terrain object
  117.                 obj_player;    // the player object
  118. RENDERLIST4DV2  rend_list;     // the render list
  119. RGBAV1 white, gray, lightgray, black, red, green, blue; // general colors
  120. // physical model defines play with these to change the feel of the vehicle
  121. float gravity       = -.30;    // general gravity
  122. float vel_y         = 0;       // the y velocity of camera/jetski
  123. float cam_speed     = 0;       // speed of the camera/jetski
  124. float sea_level     = 30;      // sea level of the simulation
  125. float gclearance    = 75;      // clearance from the camera to the ground/water
  126. float neutral_pitch = 1;       // the neutral pitch of the camera
  127. float turn_ang      = 0; 
  128. float jetski_yaw    = 0;
  129. float wave_count    = 0;       // used to track wave propagation
  130. int scroll_count    = 0;
  131. // ambient and in game sounds
  132. int wind_sound_id          = -1, 
  133.     water_light_sound_id   = -1,
  134.     water_heavy_sound_id   = -1,
  135.     water_splash_sound_id  = -1,
  136.     zbuffer_intro_sound_id = -1,
  137.     zbuffer_instr_sound_id = -1,
  138.     jetski_start_sound_id  = -1,
  139.     jetski_idle_sound_id   = -1,
  140.     jetski_fast_sound_id   = -1,
  141.     jetski_accel_sound_id  = -1,
  142.     jetski_splash_sound_id = -1;
  143. // game imagery assets
  144. BOB intro_image, 
  145.     ready_image, 
  146.     nice_one_image;
  147. BITMAP_IMAGE background_bmp;   // holds the background
  148.  
  149. ZBUFFERV1 zbuffer;             // out little z buffer
  150. int game_state         = GAME_STATE_INIT;
  151. int game_state_count1  = 0;
  152. int player_state       = JETSKI_OFF;
  153. int player_state_count1 = 0;
  154. int enable_model_view   = 0;
  155. // FUNCTIONS //////////////////////////////////////////////
  156. LRESULT CALLBACK WindowProc(HWND hwnd, 
  157.     UINT msg, 
  158.                             WPARAM wparam, 
  159.                             LPARAM lparam)
  160. {
  161. // this is the main message handler of the system
  162. PAINTSTRUCT ps;    // used in WM_PAINT
  163. HDC hdc;    // handle to a device context
  164. // what is the message 
  165. switch(msg)
  166. {
  167. case WM_CREATE: 
  168.         {
  169. // do initialization stuff here
  170. return(0);
  171. } break;
  172.     case WM_PAINT:
  173.          {
  174.          // start painting
  175.          hdc = BeginPaint(hwnd,&ps);
  176.          // end painting
  177.          EndPaint(hwnd,&ps);
  178.          return(0);
  179.         } break;
  180. case WM_DESTROY: 
  181. {
  182. // kill the application
  183. PostQuitMessage(0);
  184. return(0);
  185. } break;
  186. default:break;
  187.     } // end switch
  188. // process any messages that we didn't take care of 
  189. return (DefWindowProc(hwnd, msg, wparam, lparam));
  190. } // end WinProc
  191. // WINMAIN ////////////////////////////////////////////////
  192. int WINAPI WinMain( HINSTANCE hinstance,
  193. HINSTANCE hprevinstance,
  194. LPSTR lpcmdline,
  195. int ncmdshow)
  196. {
  197. // this is the winmain function
  198. WNDCLASS winclass; // this will hold the class we create
  199. HWND  hwnd; // generic window handle
  200. MSG  msg; // generic message
  201. HDC      hdc;       // generic dc
  202. PAINTSTRUCT ps;     // generic paintstruct
  203. // first fill in the window class stucture
  204. winclass.style = CS_DBLCLKS | CS_OWNDC | 
  205.                           CS_HREDRAW | CS_VREDRAW;
  206. winclass.lpfnWndProc = WindowProc;
  207. winclass.cbClsExtra = 0;
  208. winclass.cbWndExtra = 0;
  209. winclass.hInstance = hinstance;
  210. winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  211. winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  212. winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  213. winclass.lpszMenuName = NULL; 
  214. winclass.lpszClassName = WINDOW_CLASS_NAME;
  215. // register the window class
  216. if (!RegisterClass(&winclass))
  217. return(0);
  218. // create the window, note the test to see if WINDOWED_APP is
  219. // true to select the appropriate window flags
  220. if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class
  221.   WINDOW_TITLE,  // title
  222.   (WINDOWED_APP ? (WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION) : (WS_POPUP | WS_VISIBLE)),
  223.     0,0,    // x,y
  224.   WINDOW_WIDTH,  // width
  225.                           WINDOW_HEIGHT, // height
  226.   NULL,    // handle to parent 
  227.   NULL,    // handle to menu
  228.   hinstance,// instance
  229.   NULL))) // creation parms
  230. return(0);
  231. // save the window handle and instance in a global
  232. main_window_handle = hwnd;
  233. main_instance      = hinstance;
  234. // resize the window so that client is really width x height
  235. if (WINDOWED_APP)
  236. {
  237. // now resize the window, so the client area is the actual size requested
  238. // since there may be borders and controls if this is going to be a windowed app
  239. // if the app is not windowed then it won't matter
  240. RECT window_rect = {0,0,WINDOW_WIDTH-1,WINDOW_HEIGHT-1};
  241. // make the call to adjust window_rect
  242. AdjustWindowRectEx(&window_rect,
  243.      GetWindowStyle(main_window_handle),
  244.      GetMenu(main_window_handle) != NULL,  
  245.      GetWindowExStyle(main_window_handle));
  246. // save the global client offsets, they are needed in DDraw_Flip()
  247. window_client_x0 = -window_rect.left;
  248. window_client_y0 = -window_rect.top;
  249. // now resize the window with a call to MoveWindow()
  250. MoveWindow(main_window_handle,
  251.            0,                                    // x position
  252.            0,                                    // y position
  253.            window_rect.right - window_rect.left, // width
  254.            window_rect.bottom - window_rect.top, // height
  255.            FALSE);
  256. // show the window, so there's no garbage on first render
  257. ShowWindow(main_window_handle, SW_SHOW);
  258. } // end if windowed
  259. // perform all game console specific initialization
  260. Game_Init();
  261. // disable CTRL-ALT_DEL, ALT_TAB, comment this line out 
  262. // if it causes your system to crash
  263. SystemParametersInfo(SPI_SCREENSAVERRUNNING, TRUE, NULL, 0);
  264. // enter main event loop
  265. while(1)
  266. {
  267. if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  268. // test if this is a quit
  269.         if (msg.message == WM_QUIT)
  270.            break;
  271. // translate any accelerator keys
  272. TranslateMessage(&msg);
  273. // send the message to the window proc
  274. DispatchMessage(&msg);
  275. } // end if
  276.     
  277.     // main game processing goes here
  278.     Game_Main();
  279. } // end while
  280. // shutdown game and release all resources
  281. Game_Shutdown();
  282. // enable CTRL-ALT_DEL, ALT_TAB, comment this line out 
  283. // if it causes your system to crash
  284. SystemParametersInfo(SPI_SCREENSAVERRUNNING, FALSE, NULL, 0);
  285. // return to Windows like this
  286. return(msg.wParam);
  287. } // end WinMain
  288. // T3D II GAME PROGRAMMING CONSOLE FUNCTIONS ////////////////
  289. int Game_Init(void *parms)
  290. {
  291. // this function is where you do all the initialization 
  292. // for your game
  293. int index; // looping var
  294. // start up DirectDraw (replace the parms as you desire)
  295. DDraw_Init(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_BPP, WINDOWED_APP);
  296. // initialize directinput
  297. DInput_Init();
  298. // acquire the keyboard 
  299. DInput_Init_Keyboard();
  300. // add calls to acquire other directinput devices here...
  301. // initialize directsound and directmusic
  302. DSound_Init();
  303. DMusic_Init();
  304. // hide the mouse
  305. if (!WINDOWED_APP)
  306.     ShowCursor(FALSE);
  307. // seed random number generator
  308. srand(Start_Clock()); 
  309. Open_Error_File("ERROR.TXT");
  310. // initialize math engine
  311. Build_Sin_Cos_Tables();
  312. // initialize the camera with 90 FOV, normalized coordinates
  313. Init_CAM4DV1(&cam,      // the camera object
  314.              CAM_MODEL_EULER, // the euler model
  315.              &cam_pos,  // initial camera position
  316.              &cam_dir,  // initial camera angles
  317.              &cam_target,      // no target
  318.              10.0,        // near and far clipping planes
  319.              12000.0,
  320.              90.0,      // field of view in degrees
  321.              WINDOW_WIDTH,   // size of final screen viewport
  322.              WINDOW_HEIGHT);
  323. // position the terrain at 0,0,0
  324. VECTOR4D terrain_pos = {0,0,0,0};
  325. // generate terrain
  326. Generate_Terrain_OBJECT4DV2(&obj_terrain,            // pointer to object
  327.                             TERRAIN_WIDTH,           // width in world coords on x-axis
  328.                             TERRAIN_HEIGHT,          // height (length) in world coords on z-axis
  329.                             TERRAIN_SCALE,           // vertical scale of terrain
  330.                             "water_track_height_04.bmp",  // filename of height bitmap encoded in 256 colors
  331.                             "water_track_color_03.bmp",   // filename of texture map
  332.                              RGB16Bit(255,255,255),  // color of terrain if no texture        
  333.                              &terrain_pos,           // initial position
  334.                              NULL,                   // initial rotations
  335.                              POLY4DV2_ATTR_RGB16 | 
  336.                              POLY4DV2_ATTR_SHADE_MODE_FLAT | /*POLY4DV2_ATTR_SHADE_MODE_GOURAUD */
  337.                              POLY4DV2_ATTR_SHADE_MODE_TEXTURE );
  338. // we are getting divide by zero errors due to degenerate triangles
  339. // after projection, this is a problem with the rasterizer that we will
  340. // fix later, but if we add a random bias to all y components of each vertice
  341. // is fixes the problem, its a hack, but hey no one is perfect :)
  342. for (int v = 0; v < obj_terrain.num_vertices; v++)
  343.     obj_terrain.vlist_local[v].y+= ((float)RAND_RANGE(-5,5))/10;
  344. // load the jetski model for player
  345. VECTOR4D_INITXYZ(&vscale,17.5,17.50,17.50);  
  346. Load_OBJECT4DV2_COB(&obj_player, "jetski05.cob",  
  347.                    &vscale, &vpos, &vrot, VERTEX_FLAGS_SWAP_YZ  |
  348.                                           VERTEX_FLAGS_TRANSFORM_LOCAL  | VERTEX_FLAGS_INVERT_TEXTURE_V
  349.                                                /* VERTEX_FLAGS_TRANSFORM_LOCAL_WORLD*/ );
  350. // set up lights
  351. Reset_Lights_LIGHTV2(lights2, MAX_LIGHTS);
  352. // create some working colors
  353. white.rgba     = _RGBA32BIT(255,255,255,0);
  354. lightgray.rgba = _RGBA32BIT(200,200,200,0);
  355. gray.rgba      = _RGBA32BIT(100,100,100,0);
  356. black.rgba     = _RGBA32BIT(0,0,0,0);
  357. red.rgba       = _RGBA32BIT(255,0,0,0);
  358. green.rgba     = _RGBA32BIT(0,255,0,0);
  359. blue.rgba      = _RGBA32BIT(0,0,255,0);
  360. // ambient light
  361. Init_Light_LIGHTV2(lights2,               // array of lights to work with
  362.                    AMBIENT_LIGHT_INDEX,   
  363.                    LIGHTV2_STATE_ON,      // turn the light on
  364.                    LIGHTV2_ATTR_AMBIENT,  // ambient light type
  365.                    gray, black, black,    // color for ambient term only
  366.                    NULL, NULL,            // no need for pos or dir
  367.                    0,0,0,                 // no need for attenuation
  368.                    0,0,0);                // spotlight info NA
  369. VECTOR4D dlight_dir = {-1,1,0,1}; 
  370. // directional light
  371. Init_Light_LIGHTV2(lights2,               // array of lights to work with
  372.                    INFINITE_LIGHT_INDEX,  
  373.                    LIGHTV2_STATE_ON,      // turn the light on
  374.                    LIGHTV2_ATTR_INFINITE, // infinite light type
  375.                    black, lightgray, black,    // color for diffuse term only
  376.                    NULL, &dlight_dir,     // need direction only
  377.                    0,0,0,                 // no need for attenuation
  378.                    0,0,0);                // spotlight info NA
  379. VECTOR4D plight_pos = {0,200,0,1};
  380. // point light
  381. Init_Light_LIGHTV2(lights2,               // array of lights to work with
  382.                    POINT_LIGHT_INDEX,
  383.                    LIGHTV2_STATE_ON,      // turn the light on
  384.                    LIGHTV2_ATTR_POINT,    // pointlight type
  385.                    black, gray, black,    // color for diffuse term only
  386.                    &plight_pos, NULL,     // need pos only
  387.                    0,.002,0,              // linear attenuation only
  388.                    0,0,1);                // spotlight info NA
  389. // create lookup for lighting engine
  390. RGB_16_8_IndexedRGB_Table_Builder(DD_PIXEL_FORMAT565,  // format we want to build table for
  391.                                   palette,             // source palette
  392.                                   rgblookup);          // lookup table
  393. // load background sounds
  394. wind_sound_id           = DSound_Load_WAV("WIND.WAV");
  395. water_light_sound_id    = DSound_Load_WAV("WATERLIGHT01.WAV");
  396. water_heavy_sound_id    = DSound_Load_WAV("WATERHEAVY01.WAV");
  397. water_splash_sound_id   = DSound_Load_WAV("SPLASH01.WAV");
  398. zbuffer_intro_sound_id  = DSound_Load_WAV("ZBUFFER02.WAV");
  399. zbuffer_instr_sound_id  = DSound_Load_WAV("ZINSTRUCTIONS02.WAV");
  400. jetski_start_sound_id   = DSound_Load_WAV("jetskistart04.WAV");
  401. jetski_idle_sound_id    = DSound_Load_WAV("jetskiidle01.WAV");
  402. jetski_fast_sound_id    = DSound_Load_WAV("jetskifast01.WAV");
  403. jetski_accel_sound_id   = DSound_Load_WAV("jetskiaccel01.WAV");
  404. jetski_splash_sound_id  = DSound_Load_WAV("splash01.WAV");
  405. // load background image
  406. Load_Bitmap_File(&bitmap16bit, "cloud03.BMP");
  407. Create_Bitmap(&background_bmp,0,0,800,600,16);
  408. Load_Image_Bitmap16(&background_bmp, &bitmap16bit,0,0,BITMAP_EXTRACT_MODE_ABS);
  409. Unload_Bitmap_File(&bitmap16bit);
  410. // load in all the text images
  411. // intro
  412. Load_Bitmap_File(&bitmap16bit, "zbufferwr_intro01.BMP");
  413. Create_BOB(&intro_image, WINDOW_WIDTH/2 - 560/2,40,560,160,1, BOB_ATTR_VISIBLE | BOB_ATTR_SINGLE_FRAME, DDSCAPS_SYSTEMMEMORY, 0, 16); 
  414. Load_Frame_BOB16(&intro_image, &bitmap16bit,0,0,0,BITMAP_EXTRACT_MODE_ABS);
  415. Unload_Bitmap_File(&bitmap16bit);
  416. // get ready
  417. Load_Bitmap_File(&bitmap16bit, "zbufferwr_ready01.BMP");
  418. Create_BOB(&ready_image, WINDOW_WIDTH/2 - 596/2,40,596,244,1, BOB_ATTR_VISIBLE | BOB_ATTR_SINGLE_FRAME, DDSCAPS_SYSTEMMEMORY, 0, 16); 
  419. Load_Frame_BOB16(&ready_image, &bitmap16bit,0,0,0,BITMAP_EXTRACT_MODE_ABS);
  420. Unload_Bitmap_File(&bitmap16bit);
  421. // nice one
  422. Load_Bitmap_File(&bitmap16bit, "zbufferwr_nice01.BMP");
  423. Create_BOB(&nice_one_image, WINDOW_WIDTH/2 - 588/2,40,588,92,1, BOB_ATTR_VISIBLE | BOB_ATTR_SINGLE_FRAME, DDSCAPS_SYSTEMMEMORY, 0, 16); 
  424. Load_Frame_BOB16(&nice_one_image, &bitmap16bit,0,0,0,BITMAP_EXTRACT_MODE_ABS);
  425. Unload_Bitmap_File(&bitmap16bit);
  426. // set single precission
  427. //_control87( _PC_24, MCW_PC );
  428. // allocate memory for zbuffer
  429. Create_Zbuffer(&zbuffer,
  430.                WINDOW_WIDTH,
  431.                WINDOW_HEIGHT,
  432.                ZBUFFER_ATTR_32BIT);
  433. // return success
  434. return(1);
  435. } // end Game_Init
  436. ///////////////////////////////////////////////////////////
  437. int Game_Shutdown(void *parms)
  438. {
  439. // this function is where you shutdown your game and
  440. // release all resources that you allocated
  441. // shut everything down
  442. // release all your resources created for the game here....
  443. // now directsound
  444. DSound_Stop_All_Sounds();
  445. DSound_Delete_All_Sounds();
  446. DSound_Shutdown();
  447. // directmusic
  448. DMusic_Delete_All_MIDI();
  449. DMusic_Shutdown();
  450. // shut down directinput
  451. DInput_Release_Keyboard();
  452. // shutdown directinput
  453. DInput_Shutdown();
  454. // shutdown directdraw last
  455. DDraw_Shutdown();
  456. Close_Error_File();
  457. Delete_Zbuffer(&zbuffer);
  458. // return success
  459. return(1);
  460. } // end Game_Shutdown
  461. //////////////////////////////////////////////////////////
  462. int Game_Main(void *parms)
  463. {
  464. // this is the workhorse of your game it will be called
  465. // continuously in real-time this is like main() in C
  466. // all the calls for you game go here!
  467. static MATRIX4X4 mrot;   // general rotation matrix
  468. static float plight_ang = 0, 
  469.              slight_ang = 0; // angles for light motion
  470. // use these to rotate objects
  471. static float x_ang = 0, y_ang = 0, z_ang = 0;
  472. // state variables for different rendering modes and help
  473. static int wireframe_mode = 1;
  474. static int backface_mode  = 1;
  475. static int lighting_mode  = 1;
  476. static int help_mode      = -1;
  477. static int zsort_mode     = -1;
  478. static int x_clip_mode    = 1;
  479. static int y_clip_mode    = 1;
  480. static int z_clip_mode    = 1;
  481. static int z_buffer_mode  = 1;
  482. static int display_mode   = 1;
  483. char work_string[256]; // temp string
  484. static int nice_one_on = 0; // used to display the nice one text
  485. static int nice_count1 = 0;
  486. int index; // looping var
  487. // what state is the game in?
  488. switch(game_state)
  489. {
  490. case GAME_STATE_INIT:
  491.      {
  492.      // perform any important initializations
  493.  
  494.      // transition to restart
  495.      game_state = GAME_STATE_RESTART;
  496.      } break;
  497. case GAME_STATE_RESTART:
  498.      {
  499.      // reset all variables
  500.      game_state_count1   = 0;
  501.      player_state        = JETSKI_OFF;
  502.      player_state_count1 = 0;
  503.      gravity             = -.30;    
  504.      vel_y               = 0;       
  505.      cam_speed           = 0;       
  506.      sea_level           = 30;      
  507.      gclearance          = 75;      
  508.      neutral_pitch       = 10;   
  509.      turn_ang            = 0; 
  510.      jetski_yaw          = 0;
  511.      wave_count          = 0;
  512.      scroll_count        = 0;
  513.      enable_model_view   = 0;
  514.      // set camera high atop mount aleph one
  515.      cam.pos.x = 1550;
  516.      cam.pos.y = 800;
  517.      cam.pos.z = 1950;
  518.      cam.dir.y = -140;      
  519.      // turn on water sounds
  520.      // start the sounds
  521.      DSound_Play(wind_sound_id, DSBPLAY_LOOPING);
  522.      DSound_Set_Volume(wind_sound_id, 75);
  523.      DSound_Play(water_light_sound_id, DSBPLAY_LOOPING);
  524.      DSound_Set_Volume(water_light_sound_id, 50);
  525.      DSound_Play(water_heavy_sound_id, DSBPLAY_LOOPING);
  526.      DSound_Set_Volume(water_heavy_sound_id, 30);
  527.      DSound_Play(zbuffer_intro_sound_id);
  528.      DSound_Set_Volume(zbuffer_intro_sound_id, 100);
  529.      // transition to introduction sub-state of run
  530.      game_state = GAME_STATE_INTRO;
  531.      } break;
  532. // in any of these cases enter into the main simulation loop
  533. case GAME_STATE_RUN:   
  534. case GAME_STATE_INTRO: 
  535. case GAME_STATE_PLAY:
  536. {  
  537.     
  538. // perform sub-state transition logic here
  539. if (game_state == GAME_STATE_INTRO)
  540.    {
  541.    // update timer
  542.    ++game_state_count1;
  543.    // test for first part of intro
  544.    if (game_state_count1 == INTRO_STATE_COUNT1)
  545.       {
  546.       // change amplitude of water
  547.       DSound_Set_Volume(water_light_sound_id, 50);
  548.       DSound_Set_Volume(water_heavy_sound_id, 100);
  549.       // reposition camera in water
  550.       cam.pos.x = 444; // 560;
  551.       cam.pos.y = 200;
  552.       cam.pos.z = -534; // -580;
  553.       cam.dir.y = 45;// (-100);  
  554.       // enable model
  555.       enable_model_view = 1;
  556.       } // end if
  557.    else
  558.    if (game_state_count1 == INTRO_STATE_COUNT2)
  559.       {
  560.       // change amplitude of water
  561.       DSound_Set_Volume(water_light_sound_id, 20);
  562.       DSound_Set_Volume(water_heavy_sound_id, 50);
  563.  
  564.       // play the instructions
  565.       DSound_Play(zbuffer_instr_sound_id);
  566.       DSound_Set_Volume(zbuffer_instr_sound_id, 100);
  567.       } // end if
  568.     else
  569.     if (game_state_count1 == INTRO_STATE_COUNT3)
  570.       {
  571.       // reset counter for other use
  572.       game_state_count1 = 0;
  573.       // change amplitude of water
  574.       DSound_Set_Volume(water_light_sound_id, 30);
  575.       DSound_Set_Volume(water_heavy_sound_id, 70);
  576.       // transition to play state
  577.       game_state = GAME_STATE_PLAY;  
  578.  
  579.       } // end if
  580.    } // end if
  581. // start the timing clock
  582. Start_Clock();
  583. // clear the drawing surface 
  584. //DDraw_Fill_Surface(lpddsback, 0);
  585. // draw the sky
  586. //Draw_Rectangle(0,0, WINDOW_WIDTH, WINDOW_HEIGHT*.38, RGB16Bit(50,100,255), lpddsback);
  587. // draw the ground
  588. //Draw_Rectangle(0,WINDOW_HEIGHT*.38, WINDOW_WIDTH, WINDOW_HEIGHT, RGB16Bit(25,50,110), lpddsback);
  589. //Draw_BOB16(&background, lpddsback);
  590. // read keyboard and other devices here
  591. DInput_Read_Keyboard();
  592. // game logic here...
  593. // reset the render list
  594. Reset_RENDERLIST4DV2(&rend_list);
  595. // modes and lights
  596. // wireframe mode
  597. if (keyboard_state[DIK_W]) 
  598.    {
  599.    // toggle wireframe mode
  600.    if (++wireframe_mode > 1)
  601.        wireframe_mode=0;
  602.    Wait_Clock(100); // wait, so keyboard doesn't bounce
  603.    } // end if
  604. // backface removal
  605. if (keyboard_state[DIK_B])
  606.    {
  607.    // toggle backface removal
  608.    backface_mode = -backface_mode;
  609.    Wait_Clock(100); // wait, so keyboard doesn't bounce
  610.    } // end if
  611. // lighting
  612. if (keyboard_state[DIK_L])
  613.    {
  614.    // toggle lighting engine completely
  615.    lighting_mode = -lighting_mode;
  616.    Wait_Clock(100); // wait, so keyboard doesn't bounce
  617.    } // end if
  618. // toggle ambient light
  619. if (keyboard_state[DIK_A])
  620.    {
  621.    // toggle ambient light
  622.    if (lights2[AMBIENT_LIGHT_INDEX].state == LIGHTV2_STATE_ON)
  623.       lights2[AMBIENT_LIGHT_INDEX].state = LIGHTV2_STATE_OFF;
  624.    else
  625.       lights2[AMBIENT_LIGHT_INDEX].state = LIGHTV2_STATE_ON;
  626.    Wait_Clock(100); // wait, so keyboard doesn't bounce
  627.    } // end if
  628. // toggle infinite light
  629. if (keyboard_state[DIK_I])
  630.    {
  631.    // toggle ambient light
  632.    if (lights2[INFINITE_LIGHT_INDEX].state == LIGHTV2_STATE_ON)
  633.       lights2[INFINITE_LIGHT_INDEX].state = LIGHTV2_STATE_OFF;
  634.    else
  635.       lights2[INFINITE_LIGHT_INDEX].state = LIGHTV2_STATE_ON;
  636.    Wait_Clock(100); // wait, so keyboard doesn't bounce
  637.    } // end if
  638. // toggle point light
  639. if (keyboard_state[DIK_P])
  640.    {
  641.    // toggle point light
  642.    if (lights2[POINT_LIGHT_INDEX].state == LIGHTV2_STATE_ON)
  643.       lights2[POINT_LIGHT_INDEX].state = LIGHTV2_STATE_OFF;
  644.    else
  645.       lights2[POINT_LIGHT_INDEX].state = LIGHTV2_STATE_ON;
  646.    Wait_Clock(100); // wait, so keyboard doesn't bounce
  647.    } // end if
  648. // help menu
  649. if (keyboard_state[DIK_H])
  650.    {
  651.    // toggle help menu 
  652.    help_mode = -help_mode;
  653.    Wait_Clock(100); // wait, so keyboard doesn't bounce
  654.    } // end if
  655. // z-sorting
  656. if (keyboard_state[DIK_S])
  657.    {
  658.    // toggle z sorting
  659.    zsort_mode = -zsort_mode;
  660.    Wait_Clock(100); // wait, so keyboard doesn't bounce
  661.    } // end if
  662. // z buffer
  663. if (keyboard_state[DIK_Z])
  664.    {
  665.    // toggle z buffer
  666.    z_buffer_mode = -z_buffer_mode;
  667.    Wait_Clock(100); // wait, so keyboard doesn't bounce
  668.    } // end if
  669. // display mode
  670. if (keyboard_state[DIK_D])
  671.    {
  672.    // toggle display mode
  673.    display_mode = -display_mode;
  674.    Wait_Clock(100); // wait, so keyboard doesn't bounce
  675.    } // end if
  676. // PLAYER CONTROL AREA ////////////////////////////////////////////////////////////
  677. // filter player control if not in PLAY state
  678. if (game_state==GAME_STATE_PLAY)
  679. {
  680. // forward/backward
  681. if (keyboard_state[DIK_UP] && player_state >= JETSKI_START)
  682.    {
  683.    // test for acceleration 
  684.    if (cam_speed == 0)
  685.       {
  686.       DSound_Play(jetski_accel_sound_id);
  687.       DSound_Set_Volume(jetski_accel_sound_id, 100);
  688.       } // end if
  689.       
  690.    // move forward
  691.    if ( (cam_speed+=1) > MAX_SPEED) 
  692.         cam_speed = MAX_SPEED;
  693.    } // end if
  694. /*
  695. else
  696. if (keyboard_state[DIK_DOWN])
  697.    {
  698.    // move backward
  699.    if ((cam_speed-=1) < -MAX_SPEED) cam_speed = -MAX_SPEED;
  700.    } // end if
  701. */
  702. // rotate around y axis or yaw
  703. if (keyboard_state[DIK_RIGHT])
  704.    {
  705.    cam.dir.y+=5;
  706.    if ((turn_ang+=JETSKI_TURN_RATE) > MAX_JETSKI_TURN)
  707.       turn_ang = MAX_JETSKI_TURN;
  708.    if ((jetski_yaw-=(JETSKI_YAW_RATE*cam_speed)) < -MAX_JETSKI_YAW)
  709.       jetski_yaw = -MAX_JETSKI_YAW;
  710.    // scroll the background
  711.    Scroll_Bitmap(&background_bmp, -10);
  712.    } // end if
  713. if (keyboard_state[DIK_LEFT])
  714.    {
  715.    cam.dir.y-=5;
  716.    if ((turn_ang-=JETSKI_TURN_RATE) < -MAX_JETSKI_TURN)
  717.       turn_ang = -MAX_JETSKI_TURN;
  718.    if ((jetski_yaw+=(JETSKI_YAW_RATE*cam_speed)) > MAX_JETSKI_YAW)
  719.       jetski_yaw = MAX_JETSKI_YAW;
  720.    // scroll the background
  721.    Scroll_Bitmap(&background_bmp, 10);
  722.    } // end if
  723. // is player trying to start jetski?
  724. if ( (player_state == JETSKI_OFF) && keyboard_state[DIK_RETURN])
  725.    {
  726.    // start jetski
  727.    player_state = JETSKI_START;
  728.    // play start sound
  729.    DSound_Play(jetski_start_sound_id);
  730.    DSound_Set_Volume(jetski_start_sound_id, 100);
  731.    // play idle in loop at 100%
  732.    DSound_Play(jetski_idle_sound_id,DSBPLAY_LOOPING);
  733.    DSound_Set_Volume(jetski_idle_sound_id, 100);
  734.    // play fast sound in loop at 0%
  735.    DSound_Play(jetski_fast_sound_id,DSBPLAY_LOOPING);
  736.    DSound_Set_Volume(jetski_fast_sound_id, 0);
  737.    } // end if 
  738. } // end if controls enabled
  739. // turn JETSKI straight
  740. if (turn_ang > JETSKI_TURN_RETURN_RATE) turn_ang-=JETSKI_TURN_RETURN_RATE;
  741. else
  742. if (turn_ang < -JETSKI_TURN_RETURN_RATE) turn_ang+=JETSKI_TURN_RETURN_RATE;
  743. else
  744.    turn_ang = 0;
  745. // turn JETSKI straight
  746. if (jetski_yaw > JETSKI_YAW_RETURN_RATE) jetski_yaw-=JETSKI_YAW_RETURN_RATE;
  747. else
  748. if (jetski_yaw < -JETSKI_YAW_RETURN_RATE) jetski_yaw+=JETSKI_YAW_RETURN_RATE;
  749. else
  750.    jetski_yaw = 0;
  751. // reset the object (this only matters for backface and object removal)
  752. Reset_OBJECT4DV2(&obj_terrain);
  753. // perform world transform to terrain now, so we can destroy the transformed
  754. // coordinates with the wave function
  755. Model_To_World_OBJECT4DV2(&obj_terrain, TRANSFORM_LOCAL_TO_TRANS);
  756. // apply wind effect ////////////////////////////////////////////////////
  757. // scroll the background
  758. if (++scroll_count > 5) 
  759.    {
  760.    Scroll_Bitmap(&background_bmp, -1);
  761.    scroll_count = 0;
  762.    } // end if
  763. // wave generator ////////////////////////////////////////////////////////
  764. // for each vertex in the mesh apply wave modulation if height < water level
  765. for (int v = 0; v < obj_terrain.num_vertices; v++)
  766.     {
  767.     // wave modulate below water level only
  768.     if (obj_terrain.vlist_trans[v].y < WATER_LEVEL)
  769.         obj_terrain.vlist_trans[v].y+=WAVE_HEIGHT*sin(wave_count+(float)v/(2*(float)obj_terrain.ivar2+0));
  770.     } // end for v
  771. // increase the wave position in time
  772. wave_count+=WAVE_RATE;
  773. // motion section /////////////////////////////////////////////////////////
  774. // terrain following, simply find the current cell we are over and then
  775. // index into the vertex list and find the 4 vertices that make up the 
  776. // quad cell we are hovering over and then average the values, and based
  777. // on the current height and the height of the terrain push the player upward
  778. // the terrain generates and stores some results to help with terrain following
  779. //ivar1 = columns;
  780. //ivar2 = rows;
  781. //fvar1 = col_vstep;
  782. //fvar2 = row_vstep;
  783. int cell_x = (cam.pos.x  + TERRAIN_WIDTH/2) / obj_terrain.fvar1;
  784. int cell_y = (cam.pos.z  + TERRAIN_HEIGHT/2) / obj_terrain.fvar1;
  785. static float terrain_height, delta;
  786. // test if we are on terrain
  787. if ( (cell_x >=0) && (cell_x < obj_terrain.ivar1) && (cell_y >=0) && (cell_y < obj_terrain.ivar2) )
  788.    {
  789.    // compute vertex indices into vertex list of the current quad
  790.    int v0 = cell_x + cell_y*obj_terrain.ivar2;
  791.    int v1 = v0 + 1;
  792.    int v2 = v1 + obj_terrain.ivar2;
  793.    int v3 = v0 + obj_terrain.ivar2;   
  794.    // now simply index into table 
  795.    terrain_height = 0.25 * (obj_terrain.vlist_trans[v0].y + obj_terrain.vlist_trans[v1].y +
  796.                             obj_terrain.vlist_trans[v2].y + obj_terrain.vlist_trans[v3].y);
  797.    // compute height difference
  798.    delta = terrain_height - (cam.pos.y - gclearance);
  799.    // test for penetration
  800.    if (delta > 0)
  801.       {
  802.       // apply force immediately to camera (this will give it a springy feel)
  803.       vel_y+=(delta * (VELOCITY_SCALER));
  804.       // test for pentration, if so move up immediately so we don't penetrate geometry
  805.       cam.pos.y+=(delta*CAM_HEIGHT_SCALER);
  806.       // now this is more of a hack than the physics model :) let move the front
  807.       // up and down a bit based on the forward velocity and the gradient of the 
  808.       // hill
  809.       cam.dir.x -= (delta*PITCH_CHANGE_RATE);
  810.  
  811.       } // end if
  812.    } // end if
  813. // decelerate camera
  814. if (cam_speed > (CAM_DECEL) ) cam_speed-=CAM_DECEL;
  815. else
  816. if (cam_speed < (-CAM_DECEL) ) cam_speed+=CAM_DECEL;
  817. else
  818.    cam_speed = 0;
  819. // force camera to seek a stable orientation
  820. if (cam.dir.x > (neutral_pitch+PITCH_RETURN_RATE)) cam.dir.x -= (PITCH_RETURN_RATE);
  821. else
  822. if (cam.dir.x < (neutral_pitch-PITCH_RETURN_RATE)) cam.dir.x += (PITCH_RETURN_RATE);
  823.  else 
  824.    cam.dir.x = neutral_pitch;
  825. // apply gravity
  826. vel_y+=gravity;
  827. // test for absolute sea level and push upward..
  828. if (cam.pos.y < sea_level)
  829.    { 
  830.    vel_y = 0; 
  831.    cam.pos.y = sea_level;
  832.    } // end if
  833. // move camera
  834. cam.pos.x += cam_speed*Fast_Sin(cam.dir.y);
  835. cam.pos.z += cam_speed*Fast_Cos(cam.dir.y);
  836. cam.pos.y += vel_y;
  837. // position point light in front of player
  838. lights2[POINT_LIGHT_INDEX].pos.x = cam.pos.x + 130*Fast_Sin(cam.dir.y);
  839. lights2[POINT_LIGHT_INDEX].pos.y = cam.pos.y + 50;
  840. lights2[POINT_LIGHT_INDEX].pos.z = cam.pos.z + 130*Fast_Cos(cam.dir.y);
  841. // position the player object slighty in front of camera and in water
  842. obj_player.world_pos.x = cam.pos.x + (130+cam_speed*1.75)*Fast_Sin(cam.dir.y);
  843. obj_player.world_pos.y = cam.pos.y - 25 + 7.5*sin(wave_count);
  844. obj_player.world_pos.z = cam.pos.z + (130+cam_speed*1.75)*Fast_Cos(cam.dir.y);
  845. // sound effect section ////////////////////////////////////////////////////////////
  846. // make engine sound if player is pressing gas
  847. DSound_Set_Freq(jetski_fast_sound_id,11000+fabs(cam_speed)*100+delta*8);
  848. DSound_Set_Volume(jetski_fast_sound_id, fabs(cam_speed)*5);
  849. // make splash sound if altitude changed enough
  850. if ( (fabs(delta) > 30) && (cam_speed >= (.75*MAX_SPEED)) && ((rand()%20)==1) ) 
  851.    {
  852.    // play sound
  853.    DSound_Play(jetski_splash_sound_id);
  854.    DSound_Set_Freq(jetski_splash_sound_id,12000+fabs(cam_speed)*5+delta*2);
  855.    DSound_Set_Volume(jetski_splash_sound_id, fabs(cam_speed)*5);
  856.    // display nice one!
  857.    nice_one_on = 1; 
  858.    nice_count1 = 60;
  859.    } // end if 
  860. // begin 3D rendering section ///////////////////////////////////////////////////////
  861. // generate camera matrix
  862. Build_CAM4DV1_Matrix_Euler(&cam, CAM_ROT_SEQ_ZYX);
  863. // generate rotation matrix around y axis
  864. //Build_XYZ_Rotation_MATRIX4X4(x_ang, y_ang, z_ang, &mrot);
  865. // rotate the local coords of the object
  866. //Transform_OBJECT4DV2(&obj_terrain, &mrot, TRANSFORM_LOCAL_TO_TRANS,1);
  867. // insert terrain object into render list
  868. Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_terrain,0);
  869. #if 1
  870. //MAT_IDENTITY_4X4(&mrot);
  871. // generate rotation matrix around y axis
  872. Build_XYZ_Rotation_MATRIX4X4(-cam.dir.x*1.5, cam.dir.y+turn_ang, jetski_yaw, &mrot);
  873. // rotate the local coords of the object
  874. Transform_OBJECT4DV2(&obj_player, &mrot, TRANSFORM_LOCAL_TO_TRANS,1);
  875. // perform world transform
  876. Model_To_World_OBJECT4DV2(&obj_player, TRANSFORM_TRANS_ONLY);
  877. // don't show model unless in play state
  878. if (enable_model_view)
  879.    {
  880.    // insert the object into render list
  881.    Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_player,0);
  882.    } // end if
  883. #endif
  884. // reset number of polys rendered
  885. debug_polys_rendered_per_frame = 0;
  886. debug_polys_lit_per_frame = 0;
  887. // remove backfaces
  888. if (backface_mode==1)
  889.    Remove_Backfaces_RENDERLIST4DV2(&rend_list, &cam);
  890. // apply world to camera transform
  891. World_To_Camera_RENDERLIST4DV2(&rend_list, &cam);
  892. // clip the polygons themselves now
  893. Clip_Polys_RENDERLIST4DV2(&rend_list, &cam, ((x_clip_mode == 1) ? CLIP_POLY_X_PLANE : 0) | 
  894.                                             ((y_clip_mode == 1) ? CLIP_POLY_Y_PLANE : 0) | 
  895.                                             ((z_clip_mode == 1) ? CLIP_POLY_Z_PLANE : 0) );
  896. // light scene all at once 
  897. if (lighting_mode==1)
  898.    {
  899.    Transform_LIGHTSV2(lights2, 3, &cam.mcam, TRANSFORM_LOCAL_TO_TRANS);
  900.    Light_RENDERLIST4DV2_World2_16(&rend_list, &cam, lights2, 3);
  901.    } // end if
  902. // sort the polygon list (hurry up!)
  903. if (zsort_mode == 1)
  904.    Sort_RENDERLIST4DV2(&rend_list,  SORT_POLYLIST_AVGZ);
  905. // apply camera to perspective transformation
  906. Camera_To_Perspective_RENDERLIST4DV2(&rend_list, &cam);
  907. // apply screen transform
  908. Perspective_To_Screen_RENDERLIST4DV2(&rend_list, &cam);
  909. // lock the back buffer
  910. DDraw_Lock_Back_Surface();
  911. // draw background
  912. Draw_Bitmap16(&background_bmp, back_buffer, back_lpitch,0);
  913. // render the object
  914. if (wireframe_mode  == 0)
  915.    {
  916.    Clear_Zbuffer(&zbuffer, (32000 << FIXP16_SHIFT));
  917.    Draw_RENDERLIST4DV2_SolidZB16(&rend_list, back_buffer, back_lpitch, (UCHAR *)zbuffer.zbuffer, WINDOW_WIDTH*4);
  918.    Draw_RENDERLIST4DV2_Wire16(&rend_list, back_buffer, back_lpitch);
  919.    }
  920. else
  921. if (wireframe_mode  == 1)
  922.    {
  923.    if (z_buffer_mode == 1)
  924.    {
  925.    // initialize zbuffer to 32000 fixed point
  926.    //Mem_Set_QUAD((void *)zbuffer, (32000 << FIXP16_SHIFT), (WINDOW_WIDTH*WINDOW_HEIGHT) ); 
  927.    Clear_Zbuffer(&zbuffer, (32000 << FIXP16_SHIFT));
  928.    Draw_RENDERLIST4DV2_SolidZB16(&rend_list, back_buffer, back_lpitch, (UCHAR *)zbuffer.zbuffer, WINDOW_WIDTH*4);
  929.    }
  930. else
  931.    {
  932.    // initialize zbuffer to 32000 fixed point
  933.    Draw_RENDERLIST4DV2_Solid16(&rend_list, back_buffer, back_lpitch);
  934.    } 
  935.    } // end if
  936. // dislay z buffer graphically (sorta)
  937. if (display_mode==-1)
  938. {
  939. // use z buffer visualization mode
  940. // copy each line of the z buffer into the back buffer and translate each z pixel
  941. // into a color
  942. USHORT *screen_ptr = (USHORT *)back_buffer;
  943. UINT   *zb_ptr    =  (UINT *)zbuffer.zbuffer;
  944. for (int y = 0; y < WINDOW_HEIGHT; y++)
  945.     {
  946.     for (int x = 0; x < WINDOW_WIDTH; x++)
  947.         {
  948.         // z buffer is 32 bit, so be carefull
  949.         UINT zpixel = zb_ptr[x + y*WINDOW_WIDTH];
  950.         zpixel = (zpixel/4096 & 0xffff);
  951.         screen_ptr[x + y* (back_lpitch >> 1)] = (USHORT)zpixel;
  952.          } // end for
  953.     } // end for y
  954. } // end if
  955. // unlock the back buffer
  956. DDraw_Unlock_Back_Surface();
  957. // draw overlay text
  958. if (game_state == GAME_STATE_INTRO &&  game_state_count1 < INTRO_STATE_COUNT1)
  959.    {
  960.    Draw_BOB16(&intro_image, lpddsback);
  961.    } // end if
  962. else
  963. if (game_state == GAME_STATE_INTRO &&  game_state_count1 > INTRO_STATE_COUNT2)
  964.    {
  965.    Draw_BOB16(&ready_image, lpddsback);
  966.    } // end if
  967. // check for nice one display
  968. if (nice_one_on == 1 &&  game_state == GAME_STATE_PLAY)
  969.    {
  970.    // are we done displaying?
  971.    if (--nice_count1 <=0)
  972.       nice_one_on = 0;
  973.    Draw_BOB16(&nice_one_image, lpddsback);
  974.    } // end if draw nice one
  975. // draw statistics 
  976. sprintf(work_string,"Lighting [%s]: Ambient=%d, Infinite=%d, Point=%d, BckFceRM [%s], Zsort [%s], Zbuffer [%s]", 
  977.                                                                                  ((lighting_mode == 1) ? "ON" : "OFF"),
  978.                                                                                  lights[AMBIENT_LIGHT_INDEX].state,
  979.                                                                                  lights[INFINITE_LIGHT_INDEX].state, 
  980.                                                                                  lights[POINT_LIGHT_INDEX].state,
  981.                                                                                  ((backface_mode == 1) ? "ON" : "OFF"),
  982.                                                                                  ((zsort_mode == 1) ? "ON" : "OFF"),
  983.                                                                                  ((z_buffer_mode == 1) ? "ON" : "OFF"));
  984. Draw_Text_GDI(work_string, 0, WINDOW_HEIGHT-34-16, RGB(0,255,0), lpddsback);
  985. // draw instructions
  986. Draw_Text_GDI("Press ESC to exit. Press <H> for Help.", 0, 0, RGB(0,255,0), lpddsback);
  987. // should we display help
  988. int text_y = 16;
  989. if (help_mode==1)
  990.     {
  991.     // draw help menu
  992.     Draw_Text_GDI("<A>..............Toggle ambient light source.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  993.     Draw_Text_GDI("<I>..............Toggle infinite light source.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  994.     Draw_Text_GDI("<P>..............Toggle point light source.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  995.     Draw_Text_GDI("<N>..............Next object.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  996.     Draw_Text_GDI("<W>..............Toggle wire frame/solid mode.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  997.     Draw_Text_GDI("<B>..............Toggle backface removal.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  998.     Draw_Text_GDI("<S>..............Toggle Z sorting.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  999.     Draw_Text_GDI("<Z>..............Toggle Z buffering.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  1000.     Draw_Text_GDI("<D>..............Toggle Normal 3D display / Z buffer visualization mode.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  1001.     Draw_Text_GDI("<H>..............Toggle Help.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  1002.     Draw_Text_GDI("<ESC>............Exit demo.", 0, text_y+=12, RGB(255,255,255), lpddsback);
  1003.     } // end help
  1004. sprintf(work_string,"Polys Rendered: %d, Polys lit: %d", debug_polys_rendered_per_frame, debug_polys_lit_per_frame);
  1005. Draw_Text_GDI(work_string, 0, WINDOW_HEIGHT-34-16-16, RGB(0,255,0), lpddsback);
  1006. sprintf(work_string,"CAM [%5.2f, %5.2f, %5.2f @ %5.2f]",  cam.pos.x, cam.pos.y, cam.pos.z, cam.dir.y);
  1007. Draw_Text_GDI(work_string, 0, WINDOW_HEIGHT-34-16-16-16, RGB(0,255,0), lpddsback);
  1008. // flip the surfaces
  1009. DDraw_Flip();
  1010. // sync to 30ish fps
  1011. Wait_Clock(30);
  1012. // check of user is trying to exit
  1013. if (KEY_DOWN(VK_ESCAPE) || keyboard_state[DIK_ESCAPE])
  1014.     {
  1015.     // player is requesting an exit, fine!
  1016.     game_state = GAME_STATE_EXIT;
  1017.     PostMessage(main_window_handle, WM_DESTROY,0,0);
  1018.     } // end if
  1019. // end main simulation loop
  1020. } break;
  1021. case GAME_STATE_EXIT:
  1022.      {
  1023.      // do any cleanup here, and exit
  1024.      } break;
  1025. default: break;
  1026. } // end switch game_state
  1027. // return success
  1028. return(1);
  1029.  
  1030. } // end Game_Main
  1031. //////////////////////////////////////////////////////////