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

游戏

开发平台:

Visual C++

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