⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 demoii12_4.cpp

📁 3D游戏编程大师技巧第十二章的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
   if ((turn_ang+=JETSKI_TURN_RATE) > MAX_JETSKI_TURN)
      turn_ang = MAX_JETSKI_TURN;

   if ((jetski_yaw-=(JETSKI_YAW_RATE*cam_speed)) < -MAX_JETSKI_YAW)
      jetski_yaw = -MAX_JETSKI_YAW;

   // scroll the background
   Scroll_Bitmap(&background_bmp, -10);

   } // end if

if (keyboard_state[DIK_LEFT])
   {
   cam.dir.y-=5;

   if ((turn_ang-=JETSKI_TURN_RATE) < -MAX_JETSKI_TURN)
      turn_ang = -MAX_JETSKI_TURN;

   if ((jetski_yaw+=(JETSKI_YAW_RATE*cam_speed)) > MAX_JETSKI_YAW)
      jetski_yaw = MAX_JETSKI_YAW;

   // scroll the background
   Scroll_Bitmap(&background_bmp, 10);

   } // end if

// is player trying to start jetski?
if ( (player_state == JETSKI_OFF) && keyboard_state[DIK_RETURN])
   {
   // start jetski
   player_state = JETSKI_START;

   // play start sound
   DSound_Play(jetski_start_sound_id);
   DSound_Set_Volume(jetski_start_sound_id, 100);

   // play idle in loop at 100%
   DSound_Play(jetski_idle_sound_id,DSBPLAY_LOOPING);
   DSound_Set_Volume(jetski_idle_sound_id, 100);

   // play fast sound in loop at 0%
   DSound_Play(jetski_fast_sound_id,DSBPLAY_LOOPING);
   DSound_Set_Volume(jetski_fast_sound_id, 0);

   } // end if 

} // end if controls enabled

// turn JETSKI straight
if (turn_ang > JETSKI_TURN_RETURN_RATE) turn_ang-=JETSKI_TURN_RETURN_RATE;
else
if (turn_ang < -JETSKI_TURN_RETURN_RATE) turn_ang+=JETSKI_TURN_RETURN_RATE;
else
   turn_ang = 0;

// turn JETSKI straight
if (jetski_yaw > JETSKI_YAW_RETURN_RATE) jetski_yaw-=JETSKI_YAW_RETURN_RATE;
else
if (jetski_yaw < -JETSKI_YAW_RETURN_RATE) jetski_yaw+=JETSKI_YAW_RETURN_RATE;
else
   jetski_yaw = 0;

// reset the object (this only matters for backface and object removal)
Reset_OBJECT4DV2(&obj_terrain);

Reset_OBJECT4DV2(&obj_terrain2);

// perform world transform to terrain now, so we can destroy the transformed
// coordinates with the wave function
Model_To_World_OBJECT4DV2(&obj_terrain, TRANSFORM_LOCAL_TO_TRANS);

obj_terrain2.world_pos.y=-220;
Model_To_World_OBJECT4DV2(&obj_terrain2, TRANSFORM_LOCAL_TO_TRANS);


// apply wind effect ////////////////////////////////////////////////////

// scroll the background
if (++scroll_count > 5) 
   {
   Scroll_Bitmap(&background_bmp, -1);
   scroll_count = 0;
   } // end if

// wave generator ////////////////////////////////////////////////////////

// for each vertex in the mesh apply wave modulation if height < water level
for (int v = 0; v < obj_terrain.num_vertices; v++)
    {
    // wave modulate below water level only
    if (obj_terrain.vlist_trans[v].y < WATER_LEVEL)
        obj_terrain.vlist_trans[v].y+=WAVE_HEIGHT*sin(wave_count+(float)v/(2*(float)obj_terrain.ivar2+0));
    } // end for v

// increase the wave position in time
wave_count+=WAVE_RATE;

// motion section /////////////////////////////////////////////////////////

// terrain following, simply find the current cell we are over and then
// index into the vertex list and find the 4 vertices that make up the 
// quad cell we are hovering over and then average the values, and based
// on the current height and the height of the terrain push the player upward

// the terrain generates and stores some results to help with terrain following
//ivar1 = columns;
//ivar2 = rows;
//fvar1 = col_vstep;
//fvar2 = row_vstep;

int cell_x = (cam.pos.x  + TERRAIN_WIDTH/2) / obj_terrain.fvar1;
int cell_y = (cam.pos.z  + TERRAIN_HEIGHT/2) / obj_terrain.fvar1;

static float terrain_height, delta;

// test if we are on terrain
if ( (cell_x >=0) && (cell_x < obj_terrain.ivar1) && (cell_y >=0) && (cell_y < obj_terrain.ivar2) )
   {
   // compute vertex indices into vertex list of the current quad
   int v0 = cell_x + cell_y*obj_terrain.ivar2;
   int v1 = v0 + 1;
   int v2 = v1 + obj_terrain.ivar2;
   int v3 = v0 + obj_terrain.ivar2;   

   // now simply index into table 
   terrain_height = 0.25 * (obj_terrain.vlist_trans[v0].y + obj_terrain.vlist_trans[v1].y +
                            obj_terrain.vlist_trans[v2].y + obj_terrain.vlist_trans[v3].y);

   // compute height difference
   delta = terrain_height - (cam.pos.y - gclearance);

   // test for penetration
   if (delta > 0)
      {
      // apply force immediately to camera (this will give it a springy feel)
      vel_y+=(delta * (VELOCITY_SCALER));

      // test for pentration, if so move up immediately so we don't penetrate geometry
      cam.pos.y+=(delta*CAM_HEIGHT_SCALER);

      // now this is more of a hack than the physics model :) let move the front
      // up and down a bit based on the forward velocity and the gradient of the 
      // hill
      cam.dir.x -= (delta*PITCH_CHANGE_RATE);
 
      } // end if

   } // end if

// decelerate camera
if (cam_speed > (CAM_DECEL) ) cam_speed-=CAM_DECEL;
else
if (cam_speed < (-CAM_DECEL) ) cam_speed+=CAM_DECEL;
else
   cam_speed = 0;

// force camera to seek a stable orientation
if (cam.dir.x > (neutral_pitch+PITCH_RETURN_RATE)) cam.dir.x -= (PITCH_RETURN_RATE);
else
if (cam.dir.x < (neutral_pitch-PITCH_RETURN_RATE)) cam.dir.x += (PITCH_RETURN_RATE);
 else 
   cam.dir.x = neutral_pitch;

// apply gravity
vel_y+=gravity;

// test for absolute sea level and push upward..
if (cam.pos.y < sea_level)
   { 
   vel_y = 0; 
   cam.pos.y = sea_level;
   } // end if

// move camera
cam.pos.x += cam_speed*Fast_Sin(cam.dir.y);
cam.pos.z += cam_speed*Fast_Cos(cam.dir.y);
cam.pos.y += vel_y;

// position point light in front of player
lights2[POINT_LIGHT_INDEX].pos.x = cam.pos.x + 170*Fast_Sin(cam.dir.y);
lights2[POINT_LIGHT_INDEX].pos.y = cam.pos.y + 50;
lights2[POINT_LIGHT_INDEX].pos.z = cam.pos.z + 170*Fast_Cos(cam.dir.y);

// position the player object slighty in front of camera and in water
obj_player.world_pos.x = cam.pos.x + (130+cam_speed*1.75)*Fast_Sin(cam.dir.y);
obj_player.world_pos.y = cam.pos.y - 20 + 7.5*sin(wave_count);
obj_player.world_pos.z = cam.pos.z + (130+cam_speed*1.75)*Fast_Cos(cam.dir.y);

// sound effect section ////////////////////////////////////////////////////////////

// make engine sound if player is pressing gas
DSound_Set_Freq(jetski_fast_sound_id,11000+fabs(cam_speed)*100+delta*8);
DSound_Set_Volume(jetski_fast_sound_id, fabs(cam_speed)*5);

// make splash sound if altitude changed enough
if ( (fabs(delta) > 30) && (cam_speed >= (.75*MAX_SPEED)) && ((rand()%20)==1) ) 
   {
   // play sound
   DSound_Play(jetski_splash_sound_id);
   DSound_Set_Freq(jetski_splash_sound_id,12000+fabs(cam_speed)*5+delta*2);
   DSound_Set_Volume(jetski_splash_sound_id, fabs(cam_speed)*5);

   // display nice one!
   nice_one_on = 1; 
   nice_count1 = 60;
   } // end if 


// begin 3D rendering section ///////////////////////////////////////////////////////

// generate camera matrix
Build_CAM4DV1_Matrix_Euler(&cam, CAM_ROT_SEQ_ZYX);

// generate rotation matrix around y axis
//Build_XYZ_Rotation_MATRIX4X4(x_ang, y_ang, z_ang, &mrot);

// rotate the local coords of the object
//Transform_OBJECT4DV2(&obj_terrain, &mrot, TRANSFORM_LOCAL_TO_TRANS,1);

// insert terrain objects into render list, check if sea floor is disabled
if (seafloor_mode == 1)
   Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_terrain2,0);

// normal terrain
Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_terrain,0);


#if 1
//MAT_IDENTITY_4X4(&mrot);

// generate rotation matrix around y axis
Build_XYZ_Rotation_MATRIX4X4(-cam.dir.x*1.5, cam.dir.y+turn_ang, jetski_yaw, &mrot);

// rotate the local coords of the object
Transform_OBJECT4DV2(&obj_player, &mrot, TRANSFORM_LOCAL_TO_TRANS,1);

// perform world transform
Model_To_World_OBJECT4DV2(&obj_player, TRANSFORM_TRANS_ONLY);

// don't show model unless in play state
if (enable_model_view)
   {
   // insert the object into render list
   Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_player,0);
   } // end if
 
#endif

// reset number of polys rendered
debug_polys_rendered_per_frame = 0;
debug_polys_lit_per_frame = 0;

// remove backfaces
if (backface_mode==1)
   Remove_Backfaces_RENDERLIST4DV2(&rend_list, &cam);

// apply world to camera transform
World_To_Camera_RENDERLIST4DV2(&rend_list, &cam);

// clip the polygons themselves now
Clip_Polys_RENDERLIST4DV2(&rend_list, &cam, ((x_clip_mode == 1) ? CLIP_POLY_X_PLANE : 0) | 
                                            ((y_clip_mode == 1) ? CLIP_POLY_Y_PLANE : 0) | 
                                            ((z_clip_mode == 1) ? CLIP_POLY_Z_PLANE : 0) );

// light scene all at once 
if (lighting_mode==1)
   {
   Transform_LIGHTSV2(lights2, 3, &cam.mcam, TRANSFORM_LOCAL_TO_TRANS);
   Light_RENDERLIST4DV2_World2_16(&rend_list, &cam, lights2, 3);
   } // end if

// sort the polygon list (hurry up!)
if (zsort_mode == 1)
   Sort_RENDERLIST4DV2(&rend_list,  SORT_POLYLIST_AVGZ);

// apply camera to perspective transformation
Camera_To_Perspective_RENDERLIST4DV2(&rend_list, &cam);

// apply screen transform
Perspective_To_Screen_RENDERLIST4DV2(&rend_list, &cam);

// lock the back buffer
DDraw_Lock_Back_Surface();

// draw background
Draw_Bitmap16(&background_bmp, back_buffer, back_lpitch,0);

// render the object

if (wireframe_mode  == 0)
   {
   Draw_RENDERLIST4DV2_Wire16(&rend_list, back_buffer, back_lpitch);
   }
else
if (wireframe_mode  == 1)
   {
   if (z_buffer_mode == -1)
      {
      // draw without a z buffer

       // set up rendering context
       rc.attr         =   RENDER_ATTR_NOBUFFER  
                         | RENDER_ATTR_ALPHA  
                         // | RENDER_ATTR_MIPMAP  
                         | RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE;

       rc.video_buffer = back_buffer;
       rc.lpitch       = back_lpitch;
       rc.mip_dist     = 2000;
       rc.zbuffer      = (UCHAR *)zbuffer.zbuffer;
       rc.zpitch       = WINDOW_WIDTH*4;
       rc.rend_list    = &rend_list;
       rc.texture_dist = 500;
       rc.alpha_override = -1;

       // render scene
       Draw_RENDERLIST4DV2_RENDERCONTEXTV1_16(&rc);
      }
   else 
      { 
       // initialize zbuffer to 32000 fixed point
       Clear_Zbuffer(&zbuffer, (0 << FIXP16_SHIFT));

       // set up rendering context
       rc.attr         =   RENDER_ATTR_INVZBUFFER  
                         | RENDER_ATTR_ALPHA  
                         // | RENDER_ATTR_MIPMAP  
                         | RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE;

       rc.video_buffer = back_buffer;
       rc.lpitch       = back_lpitch;
       rc.mip_dist     = 2000;
       rc.zbuffer      = (UCHAR *)zbuffer.zbuffer;
       rc.zpitch       = WINDOW_WIDTH*4;
       rc.rend_list    = &rend_list;
       rc.texture_dist = 500;
       rc.alpha_override = -1;

       // render scene
       Draw_RENDERLIST4DV2_RENDERCONTEXTV1_16(&rc);
       }  // end else

   } // end if 

// dislay z buffer graphically (sorta)
if (display_mode==-1)
{
// use z buffer visualization mode
// copy each line of the z buffer into the back buffer and translate each z pixel
// into a color
USHORT *screen_ptr = (USHORT *)back_buffer;
UINT   *zb_ptr    =  (UINT *)zbuffer.zbuffer;

for (int y = 0; y < WINDOW_HEIGHT; y++)
    {
    for (int x = 0; x < WINDOW_WIDTH; x++)
        {
        // z buffer is 32 bit, so be carefull
        UINT zpixel = zb_ptr[x + y*WINDOW_WIDTH];
        zpixel = (zpixel/4096 & 0xffff);
        screen_ptr[x + y* (back_lpitch >> 1)] = (USHORT)zpixel;
         } // end for
    } // end for y

} // end if

// unlock the back buffer
DDraw_Unlock_Back_Surface();

// draw overlay text
if (game_state == GAME_STATE_INTRO &&  game_state_count1 < INTRO_STATE_COUNT1)
   {
   Draw_BOB16(&intro_image, lpddsback);
   } // end if
else
if (game_state == GAME_STATE_INTRO &&  game_state_count1 > INTRO_STATE_COUNT2)
   {
   Draw_BOB16(&ready_image, lpddsback);
   } // end if

// check for nice one display
if (nice_one_on == 1 &&  game_state == GAME_STATE_PLAY)
   {
   // are we done displaying?
   if (--nice_count1 <=0)
      nice_one_on = 0;

   Draw_BOB16(&nice_one_image, lpddsback);
   } // end if draw nice one

// draw statistics 
sprintf(work_string,"Lighting [%s]: Ambient=%d, Infinite=%d, Point=%d, BckFceRM [%s], Zsort [%s], Zbuffer [%s]", 
                                                                                 ((lighting_mode == 1) ? "ON" : "OFF"),
                                                                                 lights[AMBIENT_LIGHT_INDEX].state,
                                                                                 lights[INFINITE_LIGHT_INDEX].state, 
                                                                                 lights[POINT_LIGHT_INDEX].state,
                                                                                 ((backface_mode == 1) ? "ON" : "OFF"),
                                                                                 ((zsort_mode == 1) ? "ON" : "OFF"),
                                                                                 ((z_buffer_mode == 1) ? "ON" : "OFF"));

Draw_Text_GDI(work_string, 0, WINDOW_HEIGHT-34-16, RGB(0,255,0), lpddsback);

// draw instructions
Draw_Text_GDI("Press ESC to exit. Press <H> for Help.", 0, 0, RGB(0,255,0), lpddsback);

// should we display help
int text_y = 16;
if (help_mode==1)
    {
    // draw help menu
    Draw_Text_GDI("<A>..............Toggle ambient light source.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<I>..............Toggle infinite light source.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<P>..............Toggle point light source.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<N>..............Next object.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<W>..............Toggle wire frame/solid mode.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<B>..............Toggle backface removal.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<S>..............Toggle Z sorting.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<Z>..............Toggle Z buffering.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<D>..............Toggle Normal 3D display / Z buffer visualization mode.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<T>..............Toggle Sea floor.", 0, text_y+=12, RGB(255,255,255), lpddsback);    
    Draw_Text_GDI("<H>..............Toggle Help.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<ESC>............Exit demo.", 0, text_y+=12, RGB(255,255,255), lpddsback);

    } // end help

sprintf(work_string,"Polys Rendered: %d, Polys lit: %d", debug_polys_rendered_per_frame, debug_polys_lit_per_frame);
Draw_Text_GDI(work_string, 0, WINDOW_HEIGHT-34-16-16, RGB(0,255,0), lpddsback);

sprintf(work_string,"CAM [%5.2f, %5.2f, %5.2f @ %5.2f]",  cam.pos.x, cam.pos.y, cam.pos.z, cam.dir.y);
Draw_Text_GDI(work_string, 0, WINDOW_HEIGHT-34-16-16-16, RGB(0,255,0), lpddsback);

// flip the surfaces
DDraw_Flip2();

// sync to 30ish fps
//Wait_Clock(30);

// check of user is trying to exit
if (KEY_DOWN(VK_ESCAPE) || keyboard_state[DIK_ESCAPE])
    {
    // player is requesting an exit, fine!
    game_state = GAME_STATE_EXIT;
    PostMessage(main_window_handle, WM_DESTROY,0,0);
    } // end if

// end main simulation loop
} break;

case GAME_STATE_EXIT:
     {
     // do any cleanup here, and exit

     } break;

default: break;

} // end switch game_state

// return success
return(1);
 
} // end Game_Main

//////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -