GameState * EndOfRound::Update() { int backgroundColor = 122; // clear the drawing surface DDraw_Fill_Surface(lpddsback,backgroundColor ); Draw_Blocks(); Draw_Players(); // flip the surfaces DDraw_Flip(); countDownTimer--; if(countDownTimer < 1) { Player * survivor = Universe::GetSurvivingPlayer(); if(survivor) { int numberOfSurvivorWins = survivor->GetNumberOfWins(); numberOfSurvivorWins++; survivor->SetNumberofWins(numberOfSurvivorWins); } return new EndOfRoundReport(); } return this; }
int Game_Main(void *parms = NULL, int num_parms = 0) { // this is the main loop of the game, do all your processing // here // make sure this isn't executed again if (window_closed) return(0); // for now test if user is hitting ESC and send WM_CLOSE if (KEYDOWN(VK_ESCAPE)) { PostMessage(main_window_handle,WM_CLOSE,0,0); window_closed = 1; } // end if // clear out the back buffer DDraw_Fill_Surface(lpddsback, 0); // lock primary buffer DDRAW_INIT_STRUCT(ddsd); if (FAILED(lpddsback->Lock(NULL,&ddsd, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL))) return(0); // do the graphics Draw_Polygon2D(&asteroid, (UCHAR *)ddsd.lpSurface, ddsd.lPitch); // test for scale if (KEYDOWN('A')) // scale up Scale_Polygon2D(&asteroid, 1.1, 1.1); else if (KEYDOWN('S')) // scale down Scale_Polygon2D(&asteroid, 0.9, 0.9); // rotate the polygon by 5 degrees Rotate_Polygon2D(&asteroid, 5); // unlock primary buffer if (FAILED(lpddsback->Unlock(NULL))) return(0); // perform the flip while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT))); // wait a sec Sleep(33); // return success or failure or your own return code here return(1); } // end Game_Main
int Game_Main(void *parms) { // this is the workhorse of your game it will be called // continuously in real-time this is like main() in C // all the calls for you game go here! int index; // looping var // check of user is trying to exit if (KEY_DOWN(VK_ESCAPE)) { PostMessage(main_window_handle, WM_DESTROY,0,0); // stop all sounds DSound_Stop_All_Sounds(); } // end if // start the timing clock Start_Clock(); // clear the drawing surface DDraw_Fill_Surface(lpddsback, 0); // lock back buffer and copy background into it DDraw_Lock_Back_Surface(); // draw background Draw_Bitmap16(&background_bmp, back_buffer, back_lpitch,0); // unlock back surface DDraw_Unlock_Back_Surface(); // process the fly ai, move them buzz around dead bodies Flys_AI(); // draw the flys for (index=0; index < MAX_FLYS; index++) Draw_BOB16(&flys[index], lpddsback); // flip the surfaces DDraw_Flip(); // sync to 30ish fps Wait_Clock(30); // return success return(1); } // end Game_Main
int Game_Main(void *parms, int num_parms) { // this is the workhorse of your game it will be called // continuously in real-time this is like main() in C // all the calls for you game go here! int index, index_x, index_y; // looping vars // check of user is trying to exit if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE)) PostMessage(main_window_handle, WM_DESTROY,0,0); // start the timing clock Start_Clock(); // clear the drawing surface DDraw_Fill_Surface(lpddsback, 0); // move the aliens for (index = 0; index<NUM_ALIENS; index++) Move_BOB(&aliens[index]); // draw the aliens for (index = 0; index<NUM_ALIENS; index++) Draw_BOB(&aliens[index], lpddsback); #ifndef USE_MULTITHREADING // animate the aliens -- color animation Rotate_Colors(249, 253); #endif // draw some info Draw_Text_GDI("<ESC> to Exit.",8,8,RGB(0,255,0),lpddsback); // flip the surfaces DDraw_Flip(); // sync to 30 fps Wait_Clock(30); // return success return(1); } // end Game_Main
int Game_Init(void *parms) { // this function is where you do all the initialization // for your game int index; // looping var // start up DirectDraw (replace the parms as you desire) DDraw_Init(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_BPP, WINDOWED_APP); // initialize directinput DInput_Init(); // acquire the keyboard DInput_Init_Keyboard(); // add calls to acquire other directinput devices here... // initialize directsound and directmusic DSound_Init(); DMusic_Init(); // hide the mouse if (!WINDOWED_APP) ShowCursor(FALSE); // seed random number generator srand(Start_Clock()); Open_Error_File("ERROR.TXT"); // initialize math engine Build_Sin_Cos_Tables(); // clear the drawing surface DDraw_Fill_Surface(lpddsback, 0); // return success return(1); } // end Game_Init
int Game_Main(void *parms) { // this is the workhorse of your game it will be called // continuously in real-time this is like main() in C // all the calls for you game go here! int index; // looping var // start the timing clock Start_Clock(); // clear the drawing surface DDraw_Fill_Surface(lpddsback, 0); // read keyboard and other devices here DInput_Read_Keyboard(); // game logic here... // flip the surfaces DDraw_Flip(); // sync to 30ish fps Wait_Clock(30); // check of user is trying to exit if (KEY_DOWN(VK_ESCAPE) || keyboard_state[DIK_ESCAPE]) { PostMessage(main_window_handle, WM_DESTROY,0,0); } // end if // return success return(1); } // end Game_Main
int Game_Main(void *parms) { // this is the workhorse of your game it will be called // continuously in real-time this is like main() in C // all the calls for you game go here! static MATRIX4X4 mrot; // general rotation matrix static float x_ang = 0, y_ang = 2, z_ang = 0; int index; // looping var // start the timing clock Start_Clock(); // clear the drawing surface DDraw_Fill_Surface(lpddsback, 0); // read keyboard and other devices here DInput_Read_Keyboard(); // game logic here... // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV1(&obj); // reset angles x_ang = z_ang = 0; // is user trying to rotate if (KEY_DOWN(VK_DOWN)) x_ang = 1; else if (KEY_DOWN(VK_UP)) x_ang = -1; // generate rotation matrix around y axis Build_XYZ_Rotation_MATRIX4X4(x_ang, y_ang, z_ang, &mrot); // rotate the local coords of single polygon in renderlist Transform_OBJECT4DV1(&obj, &mrot, TRANSFORM_LOCAL_ONLY,1); // perform local/model to world transform Model_To_World_OBJECT4DV1(&obj); // generate camera matrix Build_CAM4DV1_Matrix_Euler(&cam, CAM_ROT_SEQ_ZYX); // remove backfaces Remove_Backfaces_OBJECT4DV1(&obj, &cam); // apply world to camera transform World_To_Camera_OBJECT4DV1(&obj, &cam); // apply camera to perspective transformation Camera_To_Perspective_OBJECT4DV1(&obj, &cam); // apply screen transform Perspective_To_Screen_OBJECT4DV1(&obj, &cam); // draw instructions Draw_Text_GDI("Press ESC to exit. Use UP ARROW and DOWN ARROW to rotate.", 0, 0, RGB(0,255,0), lpddsback); // lock the back buffer DDraw_Lock_Back_Surface(); // render the object Draw_OBJECT4DV1_Wire16(&obj, back_buffer, back_lpitch); // unlock the back buffer DDraw_Unlock_Back_Surface(); // flip the surfaces DDraw_Flip(); // sync to 30ish fps Wait_Clock(30); // check of user is trying to exit if (KEY_DOWN(VK_ESCAPE) || keyboard_state[DIK_ESCAPE]) { PostMessage(main_window_handle, WM_DESTROY,0,0); } // end if // return success return(1); } // end Game_Main
GameState * GameStart::Update() { if(!setupCalled) { Setup(); setupCalled = 1; } bool skip = false; if(skip) { delete this; return new Playing(); } DWORD backgroundColor = _RGB32BIT(0,36,146,255); // clear the drawing surface DDraw_Fill_Surface(lpddsback,backgroundColor ); if(gameStartFlashTimer > 0) { gameStartFlashTimer--; } else { if(isDrawingGameStart) { isDrawingGameStart = false; } else { isDrawingGameStart = true; } gameStartFlashTimer = gameStartFlashTimeInitValue; } if(isDrawingGameStart) { gameStartGameObject->GetBlitterObject()->Draw(lpddsback); } winMatchGameObject->GetBlitterObject()->Draw(lpddsback); switch(numberOfRounds) { case 1: _1GameObject->GetBlitterObject()->Draw(lpddsback); break; case 2: _2GameObject->GetBlitterObject()->Draw(lpddsback); break; case 3: _3GameObject->GetBlitterObject()->Draw(lpddsback); break; case 4: _4GameObject->GetBlitterObject()->Draw(lpddsback); break; case 5: _5GameObject->GetBlitterObject()->Draw(lpddsback); break; } switch(numberOfPlayers) { case 1: whitePad1GameObject->GetBlitterObject()->Draw(lpddsback); break; case 2: whitePad1GameObject->GetBlitterObject()->Draw(lpddsback); blackPad2GameObject->GetBlitterObject()->Draw(lpddsback); break; case 3: whitePad1GameObject->GetBlitterObject()->Draw(lpddsback); blackPad2GameObject->GetBlitterObject()->Draw(lpddsback); redPad3GameObject->GetBlitterObject()->Draw(lpddsback); break; case 4: whitePad1GameObject->GetBlitterObject()->Draw(lpddsback); blackPad2GameObject->GetBlitterObject()->Draw(lpddsback); redPad3GameObject->GetBlitterObject()->Draw(lpddsback); bluePad4GameObject->GetBlitterObject()->Draw(lpddsback); break; } countdownTimer--; if(countdownTimer <= 0) { delete this; return new Playing(); } DDraw_Flip(); return this; }
int Game_Main(void *parms) { // this is the workhorse of your game it will be called // continuously in real-time this is like main() in C // all the calls for you game go here! static MATRIX4X4 mrot; // general rotation matrix static float plight_ang = 0, slight_ang = 0; // angles for light motion // use these to rotate objects static float x_ang = 0, y_ang = 0, z_ang = 0; // state variables for different rendering modes and help static int wireframe_mode = 1; static int backface_mode = 1; static int lighting_mode = 1; static int help_mode = 1; static int zsort_mode = 1; static int x_clip_mode = 1; static int y_clip_mode = 1; static int z_clip_mode = 1; char work_string[256]; // temp string int index; // looping var // start the timing clock Start_Clock(); // clear the drawing surface DDraw_Fill_Surface(lpddsback, 0); // draw the sky Draw_Rectangle(0,0, WINDOW_WIDTH, WINDOW_HEIGHT, RGB16Bit(255,120,255), lpddsback); // draw the ground //Draw_Rectangle(0,WINDOW_HEIGHT*.38, WINDOW_WIDTH, WINDOW_HEIGHT, RGB16Bit(25,50,110), lpddsback); // read keyboard and other devices here DInput_Read_Keyboard(); // game logic here... // reset the render list Reset_RENDERLIST4DV2(&rend_list); // modes and lights // wireframe mode if (keyboard_state[DIK_W]) { // toggle wireframe mode if (++wireframe_mode > 1) wireframe_mode=0; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // backface removal if (keyboard_state[DIK_B]) { // toggle backface removal backface_mode = -backface_mode; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // lighting if (keyboard_state[DIK_L]) { // toggle lighting engine completely lighting_mode = -lighting_mode; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // toggle ambient light if (keyboard_state[DIK_A]) { // toggle ambient light if (lights2[AMBIENT_LIGHT_INDEX].state == LIGHTV2_STATE_ON) lights2[AMBIENT_LIGHT_INDEX].state = LIGHTV2_STATE_OFF; else lights2[AMBIENT_LIGHT_INDEX].state = LIGHTV2_STATE_ON; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // toggle infinite light if (keyboard_state[DIK_I]) { // toggle ambient light if (lights2[INFINITE_LIGHT_INDEX].state == LIGHTV2_STATE_ON) lights2[INFINITE_LIGHT_INDEX].state = LIGHTV2_STATE_OFF; else lights2[INFINITE_LIGHT_INDEX].state = LIGHTV2_STATE_ON; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // toggle point light if (keyboard_state[DIK_P]) { // toggle point light if (lights2[POINT_LIGHT_INDEX].state == LIGHTV2_STATE_ON) lights2[POINT_LIGHT_INDEX].state = LIGHTV2_STATE_OFF; else lights2[POINT_LIGHT_INDEX].state = LIGHTV2_STATE_ON; // toggle point light if (lights2[POINT_LIGHT2_INDEX].state == LIGHTV2_STATE_ON) lights2[POINT_LIGHT2_INDEX].state = LIGHTV2_STATE_OFF; else lights2[POINT_LIGHT2_INDEX].state = LIGHTV2_STATE_ON; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // help menu if (keyboard_state[DIK_H]) { // toggle help menu help_mode = -help_mode; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // z-sorting if (keyboard_state[DIK_Z]) { // toggle z sorting zsort_mode = -zsort_mode; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // move to next object if (keyboard_state[DIK_O]) { VECTOR4D old_pos; old_pos = obj_work->world_pos; if (++curr_object >= NUM_OBJECTS) curr_object = 0; // update pointer obj_work = &obj_array[curr_object]; obj_work->world_pos = old_pos; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // forward/backward if (keyboard_state[DIK_UP]) { // move forward if ( (cam_speed+=1) > MAX_SPEED) cam_speed = MAX_SPEED; } // end if else if (keyboard_state[DIK_DOWN]) { // move backward if ((cam_speed-=1) < -MAX_SPEED) cam_speed = -MAX_SPEED; } // end if // rotate around y axis or yaw if (keyboard_state[DIK_RIGHT]) { cam.dir.y+=5; } // end if if (keyboard_state[DIK_LEFT]) { cam.dir.y-=5; } // end if // 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; // move point light source in ellipse around game world lights2[POINT_LIGHT_INDEX].pos.x = 1000*Fast_Cos(plight_ang); lights2[POINT_LIGHT_INDEX].pos.y = 200; lights2[POINT_LIGHT_INDEX].pos.z = 1000*Fast_Sin(plight_ang); // move point light source in ellipse around game world lights2[POINT_LIGHT2_INDEX].pos.x = 500*Fast_Cos(-2*plight_ang); lights2[POINT_LIGHT2_INDEX].pos.y = 400; lights2[POINT_LIGHT2_INDEX].pos.z = 1000*Fast_Sin(-2*plight_ang); if ((plight_ang+=3) > 360) plight_ang = 0; // generate camera matrix Build_CAM4DV1_Matrix_Euler(&cam, CAM_ROT_SEQ_ZYX); ////////////////////////////////////////////////////////////////////////// // the terrain // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV2(&obj_terrain); // generate rotation matrix around y axis //Build_XYZ_Rotation_MATRIX4X4(x_ang, y_ang, z_ang, &mrot); MAT_IDENTITY_4X4(&mrot); // rotate the local coords of the object Transform_OBJECT4DV2(&obj_terrain, &mrot, TRANSFORM_LOCAL_TO_TRANS,1); // perform world transform Model_To_World_OBJECT4DV2(&obj_terrain, TRANSFORM_TRANS_ONLY); // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_terrain,0); ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // render the shaded object that projects the shadow // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV2(obj_work); // update rotation angle of object obj_work->ivar1+=3.0; if (obj_work->ivar1 >= 360) obj_work->ivar1 = 0; // set position of object obj_work->world_pos.x = 200*Fast_Cos(obj_work->ivar1); obj_work->world_pos.y = 200+50*Fast_Sin(3*obj_work->ivar1); obj_work->world_pos.z = 200*Fast_Sin(obj_work->ivar1); // 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_work, &mrot, TRANSFORM_LOCAL_TO_TRANS,1); // perform world transform Model_To_World_OBJECT4DV2(obj_work, TRANSFORM_TRANS_ONLY); // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, obj_work,0); ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // draw all the light objects to represent the position of light sources // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV2(&obj_light_array[INDEX_GREEN_LIGHT_INDEX]); // set position of object to light obj_light_array[INDEX_GREEN_LIGHT_INDEX].world_pos = lights2[POINT_LIGHT_INDEX].pos; // create identity matrix MAT_IDENTITY_4X4(&mrot); // rotate the local coords of the object Transform_OBJECT4DV2(&obj_light_array[INDEX_GREEN_LIGHT_INDEX], &mrot, TRANSFORM_LOCAL_TO_TRANS,1); // perform world transform Model_To_World_OBJECT4DV2(&obj_light_array[INDEX_GREEN_LIGHT_INDEX], TRANSFORM_TRANS_ONLY); // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_light_array[INDEX_GREEN_LIGHT_INDEX],0); // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV2(&obj_light_array[INDEX_WHITE_LIGHT_INDEX]); // set position of object to light obj_light_array[INDEX_WHITE_LIGHT_INDEX].world_pos = lights2[POINT_LIGHT2_INDEX].pos; // create identity matrix MAT_IDENTITY_4X4(&mrot); // rotate the local coords of the object Transform_OBJECT4DV2(&obj_light_array[INDEX_WHITE_LIGHT_INDEX], &mrot, TRANSFORM_LOCAL_TO_TRANS,1); // perform world transform Model_To_World_OBJECT4DV2(&obj_light_array[INDEX_WHITE_LIGHT_INDEX], TRANSFORM_TRANS_ONLY); // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_light_array[INDEX_WHITE_LIGHT_INDEX],0); //////////////////////////////////////////////////////////////////////////////////// // reset number of polys rendered debug_polys_rendered_per_frame = 0; debug_polys_lit_per_frame = 0; // prepare to make first pass at rendering target, so we can alpha blend in the shadows // on the next pass // 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, CLIP_POLY_X_PLANE | CLIP_POLY_Y_PLANE | CLIP_POLY_Z_PLANE ); // light scene all at once if (lighting_mode==1) { Transform_LIGHTSV2(lights2, 4, &cam.mcam, TRANSFORM_LOCAL_TO_TRANS); Light_RENDERLIST4DV2_World2_16(&rend_list, &cam, lights2, 4); } // 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(); // reset number of polys rendered debug_polys_rendered_per_frame = 0; // render the object if (wireframe_mode == 0) Draw_RENDERLIST4DV2_Wire16(&rend_list, back_buffer, back_lpitch); else if (wireframe_mode == 1) { // perspective mode affine texturing // set up rendering context rc.attr = RENDER_ATTR_ZBUFFER // | RENDER_ATTR_ALPHA // | RENDER_ATTR_MIPMAP // | RENDER_ATTR_BILERP | RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE; // initialize zbuffer to 0 fixed point Clear_Zbuffer(&zbuffer, (16000 << FIXP16_SHIFT)); // set up remainder of rendering context rc.video_buffer = back_buffer; rc.lpitch = back_lpitch; rc.mip_dist = 0; rc.zbuffer = (UCHAR *)zbuffer.zbuffer; rc.zpitch = WINDOW_WIDTH*4; rc.rend_list = &rend_list; rc.texture_dist = 0; rc.alpha_override = -1; // render scene Draw_RENDERLIST4DV2_RENDERCONTEXTV1_16_2(&rc); } // end if // now make second rendering pass and draw shadow(s) // reset the render list Reset_RENDERLIST4DV2(&rend_list); ////////////////////////////////////////////////////////////////////////// // shadow object // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV2(&shadow_obj); // compute terrain cell shadow is over cell_x = (obj_work->world_pos.x + TERRAIN_WIDTH/2) / obj_terrain.fvar1; cell_y = (obj_work->world_pos.z + TERRAIN_HEIGHT/2) / obj_terrain.fvar1; // 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 = MAX( MAX(obj_terrain.vlist_trans[v0].y, obj_terrain.vlist_trans[v1].y), MAX(obj_terrain.vlist_trans[v2].y, obj_terrain.vlist_trans[v3].y) ); // update position shadow_obj.world_pos = obj_work->world_pos; shadow_obj.world_pos.y = terrain_height+10; // create identity matrix MAT_IDENTITY_4X4(&mrot); // transform the local coords of the object Transform_OBJECT4DV2(&shadow_obj, &mrot, TRANSFORM_LOCAL_TO_TRANS,1); // perform world transform Model_To_World_OBJECT4DV2(&shadow_obj, TRANSFORM_TRANS_ONLY); // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &shadow_obj,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, CLIP_POLY_X_PLANE | CLIP_POLY_Y_PLANE | CLIP_POLY_Z_PLANE ); // light scene all at once if (lighting_mode==1) { Transform_LIGHTSV2(lights2, 4, &cam.mcam, TRANSFORM_LOCAL_TO_TRANS); Light_RENDERLIST4DV2_World2_16(&rend_list, &cam, lights2, 4); } // 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); // render the object if (wireframe_mode == 0) Draw_RENDERLIST4DV2_Wire16(&rend_list, back_buffer, back_lpitch); else if (wireframe_mode == 1) { // perspective mode affine texturing // set up rendering context rc.attr = RENDER_ATTR_ZBUFFER | RENDER_ATTR_ALPHA // | RENDER_ATTR_MIPMAP // | RENDER_ATTR_BILERP | RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE; // initialize zbuffer to 0 fixed point //Clear_Zbuffer(&zbuffer, (16000 << FIXP16_SHIFT)); // set up remainder of rendering context rc.video_buffer = back_buffer; rc.lpitch = back_lpitch; rc.mip_dist = 0; rc.zbuffer = (UCHAR *)zbuffer.zbuffer; rc.zpitch = WINDOW_WIDTH*4; rc.rend_list = &rend_list; rc.texture_dist = 0; rc.alpha_override = -1; // render scene Draw_RENDERLIST4DV2_RENDERCONTEXTV1_16_3(&rc); } // end if // unlock the back buffer DDraw_Unlock_Back_Surface(); // draw cockpit //Draw_BOB16(&cockpit, lpddsback); #if 1 sprintf(work_string,"Lighting [%s]: Ambient=%d, Infinite=%d, Point=%d, BckFceRM [%s]", ((lighting_mode == 1) ? "ON" : "OFF"), lights2[AMBIENT_LIGHT_INDEX].state, lights2[INFINITE_LIGHT_INDEX].state, lights2[POINT_LIGHT_INDEX].state, ((backface_mode == 1) ? "ON" : "OFF")); Draw_Text_GDI(work_string, 0, WINDOW_HEIGHT-34, 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("<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("<O>..............Select different objects.", 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], CELL [%d, %d]", cam.pos.x, cam.pos.y, cam.pos.z, cell_x, cell_y); Draw_Text_GDI(work_string, 0, WINDOW_HEIGHT-34-16-16-16, RGB(0,255,0), lpddsback); #endif // 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]) { PostMessage(main_window_handle, WM_DESTROY,0,0); } // end if // return success return(1); } // end Game_Main
int Game_Main(void *parms, int num_parms) { // this is the workhorse of your game it will be called // continuously in real-time this is like main() in C // all the calls for you game go here! int index, index_x, index_y; // looping vars int start_map_x,start_map_y, // map positions end_map_x,end_map_y; int offset_x, offset_y; // pixel offsets within cell // check of user is trying to exit if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE)) PostMessage(main_window_handle, WM_DESTROY,0,0); // start the timing clock Start_Clock(); // clear the drawing surface DDraw_Fill_Surface(lpddsback, 0); // check for movement (scrolling) if (KEY_DOWN(VK_RIGHT)) { if ((world_x+=4) >= 1280) world_x = 1279; } // end if else if (KEY_DOWN(VK_LEFT)) { if ((world_x-=4) < 0) world_x = 0; } // end if if (KEY_DOWN(VK_UP)) { if ((world_y-=4) < 0) world_y = 0; } // end if else if (KEY_DOWN(VK_DOWN)) { if ((world_y+=4) >= 896) world_y = 895; } // end if // compute starting map indices by dividing position by size of cell start_map_x = world_x/64; // use >> 6 for speed, but this is clearer start_map_y = world_y/64; // compute end of map rectangle for best cast i.e. aligned on 64x64 boundary end_map_x = start_map_x + 10 - 1; end_map_y = start_map_y + 7 - 1; // now compute number of pixels in x,y we are within the tile, i.e // how much is scrolled off the edge? offset_x = -(world_x % 64); offset_y = -(world_y % 64); // adjust end_map_x,y for offsets if (offset_x) end_map_x++; if (offset_y) end_map_y++; // set starting position of first upper lh texture int texture_x = offset_x; int texture_y = offset_y; // draw the current window for (index_y = start_map_y; index_y <= end_map_y; index_y++) { for (index_x = start_map_x; index_x <= end_map_x; index_x++) { // set position to blit textures.x = texture_x; textures.y = texture_y; // set frame textures.curr_frame = world[index_y][index_x] - '0'; // draw the texture Draw_BOB(&textures,lpddsback); // update texture position texture_x+=64; } // end for map_x // reset x postion, update y texture_x = offset_x; texture_y += 64; } // end for map_y // draw some info Draw_Text_GDI("USE ARROW KEYS TO MOVE, <ESC> to Exit.",8,8,RGB(255,255,255),lpddsback); sprintf(buffer,"World Position = [%d, %d] ", world_x, world_y); Draw_Text_GDI(buffer,8,screen_height - 32 - 24,RGB(0,255,0),lpddsback); // flip the surfaces DDraw_Flip(); // sync to 30 fps Wait_Clock(30); // return success return(1); } // end Game_Main
int Game_Main(void *parms, int num_parms) { // this is the workhorse of your game it will be called // continuously in real-time this is like main() in C // all the calls for you game go here! int index; // looping var int dx,dy; // general deltas used in collision detection static int player_moving = 0; // tracks player motion // check of user is trying to exit if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE)) PostMessage(main_window_handle, WM_DESTROY,0,0); // start the timing clock Start_Clock(); // clear the drawing surface DDraw_Fill_Surface(lpddsback, 0); // lock the back buffer DDraw_Lock_Back_Surface(); // draw the background reactor image Draw_Bitmap16(&reactor, back_buffer, back_lpitch, 0); // unlock the back buffer DDraw_Unlock_Back_Surface(); // get player input // get the keyboard data lpdikey->GetDeviceState(256, (LPVOID)keyboard_state); // reset motion flag player_moving = 0; // test direction of motion, this is a good example of testing the keyboard // although the code could be optimized this is more educational if (keyboard_state[DIK_RIGHT] && keyboard_state[DIK_UP]) { // move skelaton skelaton.x+=2; skelaton.y-=2; dx=2; dy=-2; // set motion flag player_moving = 1; // check animation needs to change if (skelaton.curr_animation != SKELATON_NEAST) Set_Animation_BOB(&skelaton,SKELATON_NEAST); } // end if else if (keyboard_state[DIK_LEFT] && keyboard_state[DIK_UP]) { // move skelaton skelaton.x-=2; skelaton.y-=2; dx=-2; dy=-2; // set motion flag player_moving = 1; // check animation needs to change if (skelaton.curr_animation != SKELATON_NWEST) Set_Animation_BOB(&skelaton,SKELATON_NWEST); } // end if else if (keyboard_state[DIK_LEFT] && keyboard_state[DIK_DOWN]) { // move skelaton skelaton.x-=2; skelaton.y+=2; dx=-2; dy=2; // set motion flag player_moving = 1; // check animation needs to change if (skelaton.curr_animation != SKELATON_SWEST) Set_Animation_BOB(&skelaton,SKELATON_SWEST); } // end if else if (keyboard_state[DIK_RIGHT] && keyboard_state[DIK_DOWN]) { // move skelaton skelaton.x+=2; skelaton.y+=2; dx=2; dy=2; // set motion flag player_moving = 1; // check animation needs to change if (skelaton.curr_animation != SKELATON_SEAST) Set_Animation_BOB(&skelaton,SKELATON_SEAST); } // end if else if (keyboard_state[DIK_RIGHT]) { // move skelaton skelaton.x+=2; dx=2; dy=0; // set motion flag player_moving = 1; // check animation needs to change if (skelaton.curr_animation != SKELATON_EAST) Set_Animation_BOB(&skelaton,SKELATON_EAST); } // end if else if (keyboard_state[DIK_LEFT]) { // move skelaton skelaton.x-=2; dx=-2; dy=0; // set motion flag player_moving = 1; // check animation needs to change if (skelaton.curr_animation != SKELATON_WEST) Set_Animation_BOB(&skelaton,SKELATON_WEST); } // end if else if (keyboard_state[DIK_UP]) { // move skelaton skelaton.y-=2; dx=0; dy=-2; // set motion flag player_moving = 1; // check animation needs to change if (skelaton.curr_animation != SKELATON_NORTH) Set_Animation_BOB(&skelaton,SKELATON_NORTH); } // end if else if (keyboard_state[DIK_DOWN]) { // move skelaton skelaton.y+=2; dx=0; dy=+2; // set motion flag player_moving = 1; // check animation needs to change if (skelaton.curr_animation != SKELATON_SOUTH) Set_Animation_BOB(&skelaton,SKELATON_SOUTH); } // end if // only animate if player is moving if (player_moving) { // animate skelaton Animate_BOB(&skelaton); // see if skelaton hit a wall // lock surface, so we can scan it DDraw_Lock_Back_Surface(); // call the color scanner with WALL_COLOR the color of the walls // try to center the scan on the feet of the player // note since we are uin 16-bit mode, we need to scan the 16 bit value then compare // it against the 16-bit color code for the green pixel which has values RB(41,231,41) // but depending if this is a 5.5.5 or 5.6.5 the 16-bit value will be different, however // during ddraw_init RGB16Bit() was vectored (function pointer) to either 5.5.5 or 5.6.5 // depending on the actual surface mode, so it should all work out :) if (Color_Scan16(skelaton.x+16, skelaton.y+16, skelaton.x+skelaton.width-16, skelaton.y+skelaton.height-16, RGB16Bit(WALL_COLOR_R, WALL_COLOR_G, WALL_COLOR_B), RGB16Bit(WALL_COLOR_R, WALL_COLOR_G, WALL_COLOR_B), back_buffer,back_lpitch)) { // back the skelaton up along its last trajectory skelaton.x-=dx; skelaton.y-=dy; } // end if // done, so unlock DDraw_Unlock_Back_Surface(); // check if skelaton is off screen if (skelaton.x < 0 || skelaton.x > (screen_width - skelaton.width)) skelaton.x-=dx; if (skelaton.y < 0 || skelaton.y > (screen_height - skelaton.height)) skelaton.y-=dy; } // end if // draw the skelaton Draw_BOB16(&skelaton, lpddsback); // draw some text Draw_Text_GDI("I STILL HAVE A BONE TO PICK!",0,screen_height - 32,RGB(32,32,32),lpddsback); Draw_Text_GDI("(16-Bit Version) USE ARROW KEYS TO MOVE, <ESC> TO EXIT.",0,0,RGB(32,32,32),lpddsback); // flip the surfaces DDraw_Flip(); // sync to 30 fps Wait_Clock(30); // return success return(1); } // end Game_Main
int Game_Main(void *parms) { // this is the workhorse of your game it will be called // continuously in real-time this is like main() in C // all the calls for you game go here! int index; // looping var int dx,dy; // general deltas used in collision detection static int player_moving = 0; // tracks player motion static PALETTEENTRY glow = {0,0,0,PC_NOCOLLAPSE}; // used to animation red border static int glow_count = 0, glow_dx = 5; // start the timing clock Start_Clock(); // clear the drawing surface DDraw_Fill_Surface(lpddsback, 0); // lock the back buffer DDraw_Lock_Back_Surface(); // draw the background reactor image Draw_Bitmap(&reactor, back_buffer, back_lpitch, 0); // unlock the back buffer DDraw_Unlock_Back_Surface(); // read keyboard and other devices here DInput_Read_Keyboard(); // reset motion flag player_moving = 0; // test direction of motion, this is a good example of testing the keyboard // although the code could be optimized this is more educational if (keyboard_state[DIK_RIGHT] && keyboard_state[DIK_UP]) { // move skelaton skelaton.x+=2; skelaton.y-=2; dx=2; dy=-2; // set motion flag player_moving = 1; // check animation needs to change if (skelaton.curr_animation != SKELATON_NEAST) Set_Animation_BOB(&skelaton,SKELATON_NEAST); } // end if else if (keyboard_state[DIK_LEFT] && keyboard_state[DIK_UP]) { // move skelaton skelaton.x-=2; skelaton.y-=2; dx=-2; dy=-2; // set motion flag player_moving = 1; // check animation needs to change if (skelaton.curr_animation != SKELATON_NWEST) Set_Animation_BOB(&skelaton,SKELATON_NWEST); } // end if else if (keyboard_state[DIK_LEFT] && keyboard_state[DIK_DOWN]) { // move skelaton skelaton.x-=2; skelaton.y+=2; dx=-2; dy=2; // set motion flag player_moving = 1; // check animation needs to change if (skelaton.curr_animation != SKELATON_SWEST) Set_Animation_BOB(&skelaton,SKELATON_SWEST); } // end if else if (keyboard_state[DIK_RIGHT] && keyboard_state[DIK_DOWN]) { // move skelaton skelaton.x+=2; skelaton.y+=2; dx=2; dy=2; // set motion flag player_moving = 1; // check animation needs to change if (skelaton.curr_animation != SKELATON_SEAST) Set_Animation_BOB(&skelaton,SKELATON_SEAST); } // end if else if (keyboard_state[DIK_RIGHT]) { // move skelaton skelaton.x+=2; dx=2; dy=0; // set motion flag player_moving = 1; // check animation needs to change if (skelaton.curr_animation != SKELATON_EAST) Set_Animation_BOB(&skelaton,SKELATON_EAST); } // end if else if (keyboard_state[DIK_LEFT]) { // move skelaton skelaton.x-=2; dx=-2; dy=0; // set motion flag player_moving = 1; // check animation needs to change if (skelaton.curr_animation != SKELATON_WEST) Set_Animation_BOB(&skelaton,SKELATON_WEST); } // end if else if (keyboard_state[DIK_UP]) { // move skelaton skelaton.y-=2; dx=0; dy=-2; // set motion flag player_moving = 1; // check animation needs to change if (skelaton.curr_animation != SKELATON_NORTH) Set_Animation_BOB(&skelaton,SKELATON_NORTH); } // end if else if (keyboard_state[DIK_DOWN]) { // move skelaton skelaton.y+=2; dx=0; dy=+2; // set motion flag player_moving = 1; // check animation needs to change if (skelaton.curr_animation != SKELATON_SOUTH) Set_Animation_BOB(&skelaton,SKELATON_SOUTH); } // end if // only animate if player is moving if (player_moving) { // animate skelaton Animate_BOB(&skelaton); // see if skelaton hit a wall // lock surface, so we can scan it DDraw_Lock_Back_Surface(); // call the color scanner with WALL_ANIMATION_COLOR, the color of the glowing wall // try to center the scan in the center of the object to make it // more realistic if (Color_Scan(skelaton.x+16, skelaton.y+16, skelaton.x+skelaton.width-16, skelaton.y+skelaton.height-16, WALL_ANIMATION_COLOR, WALL_ANIMATION_COLOR, back_buffer,back_lpitch)) { // back the skelaton up along its last trajectory skelaton.x-=dx; skelaton.y-=dy; } // end if // done, so unlock DDraw_Unlock_Back_Surface(); // check if skelaton is off screen if (skelaton.x < 0 || skelaton.x > (screen_width - skelaton.width)) skelaton.x-=dx; if (skelaton.y < 0 || skelaton.y > (screen_height - skelaton.height)) skelaton.y-=dy; } // end if // draw the skelaton Draw_BOB(&skelaton, lpddsback); // animate color glow.peGreen+=glow_dx; // test boundary if (glow.peGreen == 0 || glow.peGreen == 255) glow_dx = -glow_dx; Set_Palette_Entry(WALL_ANIMATION_COLOR, &glow); // draw some text Draw_Text_GDI("I STILL HAVE A BONE TO PICK!",0,screen_height - 32,WALL_ANIMATION_COLOR,lpddsback); Draw_Text_GDI("USE ARROW KEYS TO MOVE, <ESC> TO EXIT.",0,0,RGB(32,32,32),lpddsback); // flip the surfaces DDraw_Flip(); // sync to 30ish fps Wait_Clock(30); // check of user is trying to exit if (KEY_DOWN(VK_ESCAPE) || keyboard_state[DIK_ESCAPE]) { PostMessage(main_window_handle, WM_DESTROY,0,0); } // end if // return success return(1); } // end Game_Main
int Game_Main(void *parms) { // this is the workhorse of your game it will be called // continuously in real-time this is like main() in C // all the calls for you game go here! static MATRIX4X4 mrot; // general rotation matrix // these are used to create a circling camera static float view_angle = 0; static float camera_distance = 6000; static VECTOR4D pos = {0,0,0,0}; static float tank_speed; static float turning = 0; // state variables for different rendering modes and help static int wireframe_mode = 1; static int backface_mode = 1; static int lighting_mode = 1; static int help_mode = 1; static int zsort_mode = 1; char work_string[256]; // temp string int index; // looping var // start the timing clock Start_Clock(); // clear the drawing surface DDraw_Fill_Surface(lpddsback, 0); // draw the sky //Draw_Rectangle(0,0, WINDOW_WIDTH, WINDOW_HEIGHT/2, RGB16Bit(0,35,50), lpddsback); // draw the ground //Draw_Rectangle(0,WINDOW_HEIGHT/2-1, WINDOW_WIDTH, WINDOW_HEIGHT, RGB16Bit(20,12,0), lpddsback); // read keyboard and other devices here DInput_Read_Keyboard(); // game logic here... // reset the render list Reset_RENDERLIST4DV2(&rend_list); // modes and lights // wireframe mode if (keyboard_state[DIK_W]) { // toggle wireframe mode if (++wireframe_mode > 1) wireframe_mode=0; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // backface removal if (keyboard_state[DIK_B]) { // toggle backface removal backface_mode = -backface_mode; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // lighting if (keyboard_state[DIK_L]) { // toggle lighting engine completely lighting_mode = -lighting_mode; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // toggle ambient light if (keyboard_state[DIK_A]) { // toggle ambient light if (lights[AMBIENT_LIGHT_INDEX].state == LIGHTV1_STATE_ON) lights[AMBIENT_LIGHT_INDEX].state = LIGHTV1_STATE_OFF; else lights[AMBIENT_LIGHT_INDEX].state = LIGHTV1_STATE_ON; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // toggle infinite light if (keyboard_state[DIK_I]) { // toggle ambient light if (lights[INFINITE_LIGHT_INDEX].state == LIGHTV1_STATE_ON) lights[INFINITE_LIGHT_INDEX].state = LIGHTV1_STATE_OFF; else lights[INFINITE_LIGHT_INDEX].state = LIGHTV1_STATE_ON; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // toggle point light if (keyboard_state[DIK_P]) { // toggle point light if (lights[POINT_LIGHT_INDEX].state == LIGHTV1_STATE_ON) lights[POINT_LIGHT_INDEX].state = LIGHTV1_STATE_OFF; else lights[POINT_LIGHT_INDEX].state = LIGHTV1_STATE_ON; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // toggle spot light if (keyboard_state[DIK_S]) { // toggle spot light if (lights[SPOT_LIGHT2_INDEX].state == LIGHTV1_STATE_ON) lights[SPOT_LIGHT2_INDEX].state = LIGHTV1_STATE_OFF; else lights[SPOT_LIGHT2_INDEX].state = LIGHTV1_STATE_ON; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // help menu if (keyboard_state[DIK_H]) { // toggle help menu help_mode = -help_mode; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // z-sorting if (keyboard_state[DIK_Z]) { // toggle z sorting zsort_mode = -zsort_mode; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if static float plight_ang = 0, slight_ang = 0; // angles for light motion // move point light source in ellipse around game world lights[POINT_LIGHT_INDEX].pos.x = 1000*Fast_Cos(plight_ang); lights[POINT_LIGHT_INDEX].pos.y = 100; lights[POINT_LIGHT_INDEX].pos.z = 1000*Fast_Sin(plight_ang); if ((plight_ang+=3) > 360) plight_ang = 0; // move spot light source in ellipse around game world lights[SPOT_LIGHT2_INDEX].pos.x = 1000*Fast_Cos(slight_ang); lights[SPOT_LIGHT2_INDEX].pos.y = 200; lights[SPOT_LIGHT2_INDEX].pos.z = 1000*Fast_Sin(slight_ang); if ((slight_ang-=5) < 0) slight_ang = 360; // generate camera matrix Build_CAM4DV1_Matrix_Euler(&cam, CAM_ROT_SEQ_ZYX); // use these to rotate objects static float x_ang = 0, y_ang = 0, z_ang = 0; ////////////////////////////////////////////////////////////////////////// // constant shaded water // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV2(&obj_constant_water); // set position of constant shaded water obj_constant_water.world_pos.x = -50; obj_constant_water.world_pos.y = 0; obj_constant_water.world_pos.z = 120; // 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_constant_water, &mrot, TRANSFORM_LOCAL_TO_TRANS,1); // perform world transform Model_To_World_OBJECT4DV2(&obj_constant_water, TRANSFORM_TRANS_ONLY); // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_constant_water,0); ////////////////////////////////////////////////////////////////////////// // flat shaded water // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV2(&obj_flat_water); // set position of constant shaded water obj_flat_water.world_pos.x = 0; obj_flat_water.world_pos.y = 0; obj_flat_water.world_pos.z = 120; // 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_flat_water, &mrot, TRANSFORM_LOCAL_TO_TRANS,1); // perform world transform Model_To_World_OBJECT4DV2(&obj_flat_water, TRANSFORM_TRANS_ONLY); // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_flat_water,0); ////////////////////////////////////////////////////////////////////////// // gouraud shaded water // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV2(&obj_gouraud_water); // set position of constant shaded water obj_gouraud_water.world_pos.x = 50; obj_gouraud_water.world_pos.y = 0; obj_gouraud_water.world_pos.z = 120; // 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_gouraud_water, &mrot, TRANSFORM_LOCAL_TO_TRANS,1); // perform world transform Model_To_World_OBJECT4DV2(&obj_gouraud_water, TRANSFORM_TRANS_ONLY); // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_gouraud_water,0); // update rotation angles if ((x_ang+=1) > 360) x_ang = 0; if ((y_ang+=2) > 360) y_ang = 0; if ((z_ang+=3) > 360) z_ang = 0; // remove backfaces if (backface_mode==1) Remove_Backfaces_RENDERLIST4DV2(&rend_list, &cam); // light scene all at once if (lighting_mode==1) Light_RENDERLIST4DV2_World16(&rend_list, &cam, lights, 4); // apply world to camera transform World_To_Camera_RENDERLIST4DV2(&rend_list, &cam); // 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); sprintf(work_string,"Lighting [%s]: Ambient=%d, Infinite=%d, Point=%d, Spot=%d | Zsort [%s], BckFceRM [%s]", ((lighting_mode == 1) ? "ON" : "OFF"), lights[AMBIENT_LIGHT_INDEX].state, lights[INFINITE_LIGHT_INDEX].state, lights[POINT_LIGHT_INDEX].state, lights[SPOT_LIGHT2_INDEX].state, ((zsort_mode == 1) ? "ON" : "OFF"), ((backface_mode == 1) ? "ON" : "OFF")); Draw_Text_GDI(work_string, 0, WINDOW_HEIGHT-34, 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("<S>..............Toggle spot light source.", 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("<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 // lock the back buffer DDraw_Lock_Back_Surface(); // reset number of polys rendered debug_polys_rendered_per_frame = 0; // render the object if (wireframe_mode == 0) Draw_RENDERLIST4DV2_Wire16(&rend_list, back_buffer, back_lpitch); else if (wireframe_mode == 1) Draw_RENDERLIST4DV2_Solid16(&rend_list, back_buffer, back_lpitch); // unlock the back buffer DDraw_Unlock_Back_Surface(); // flip the surfaces DDraw_Flip(); // sync to 30ish fps Wait_Clock(30); // check of user is trying to exit if (KEY_DOWN(VK_ESCAPE) || keyboard_state[DIK_ESCAPE]) { PostMessage(main_window_handle, WM_DESTROY,0,0); } // end if // return success return(1); } // end Game_Main
int Game_Main(void *parms = NULL, int num_parms = 0) { // this is the main loop of the game, do all your processing // here // make sure this isn't executed again if (window_closed) return(0); // for now test if user is hitting ESC and send WM_CLOSE if (KEYDOWN(VK_ESCAPE)) { PostMessage(main_window_handle,WM_CLOSE,0,0); window_closed = 1; } // end if // clear out the back buffer DDraw_Fill_Surface(lpddsback, 0); // lock primary buffer DDRAW_INIT_STRUCT(ddsd); if (FAILED(lpddsback->Lock(NULL,&ddsd, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL))) return(0); // draw all the asteroids for (int curr_index = 0; curr_index < NUM_ASTEROIDS; curr_index++) { // do the graphics Draw_Polygon2D(&asteroids[curr_index], (UCHAR *)ddsd.lpSurface, ddsd.lPitch); // move the asteroid Translate_Polygon2D(&asteroids[curr_index], asteroids[curr_index].xv, asteroids[curr_index].yv); // rotate the polygon by 5 degrees Rotate_Polygon2D(&asteroids[curr_index], 5); // test for out of bounds if (asteroids[curr_index].x0 > SCREEN_WIDTH+100) asteroids[curr_index].x0 = - 100; if (asteroids[curr_index].y0 > SCREEN_HEIGHT+100) asteroids[curr_index].y0 = - 100; if (asteroids[curr_index].x0 < -100) asteroids[curr_index].x0 = SCREEN_WIDTH+100; if (asteroids[curr_index].y0 < -100) asteroids[curr_index].y0 = SCREEN_HEIGHT+100; } // end for curr_asteroid // unlock primary buffer if (FAILED(lpddsback->Unlock(NULL))) return(0); // perform the flip while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT))); // wait a sec Sleep(33); // return success or failure or your own return code here return(1); } // end Game_Main
int Game_Main(void *parms, int num_parms) { // this is the workhorse of your game it will be called // continuously in real-time this is like main() in C // all the calls for you game go here! int index; // looping var // check of user is trying to exit if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE)) PostMessage(main_window_handle, WM_DESTROY,0,0); // start the timing clock Start_Clock(); // clear the drawing surface DDraw_Fill_Surface(lpddsback, 0); // get the input from the mouse lpdimouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&mouse_state); // move the mouse cursor mouse_x+=(mouse_state.lX); mouse_y+=(mouse_state.lY); // test bounds // first x boundaries if (mouse_x >= screen_width) mouse_x = screen_width-1; else if (mouse_x < 0) mouse_x = 0; // now the y boundaries if (mouse_y >= screen_height) mouse_y= screen_height-1; else if (mouse_y < 0) mouse_y = 0; // position the pointer bob to the mouse coords pointer.x = mouse_x - 16; pointer.y = mouse_y - 16; // test what the user is doing with the mouse if ((mouse_x > 3) && (mouse_x < 500-3) && (mouse_y > 3) && (mouse_y < SCREEN_HEIGHT-3)) { // mouse is within canvas region // if left button is down then draw if (mouse_state.rgbButtons[0]) { // test drawing mode if (buttons_state[BUTTON_PENCIL]) { // draw a pixel Draw_Pixel(mouse_x, mouse_y, mouse_color, canvas.buffer, canvas.width); Draw_Pixel(mouse_x+1, mouse_y, mouse_color, canvas.buffer, canvas.width); Draw_Pixel(mouse_x, mouse_y+1, mouse_color, canvas.buffer, canvas.width); Draw_Pixel(mouse_x+1, mouse_y+1, mouse_color, canvas.buffer, canvas.width); } else { // draw spray for (index=0; index<10; index++) { // get next particle int sx=mouse_x-8+rand()%16; int sy=mouse_y-8+rand()%16; // make sure particle is in bounds if (sx > 0 && sx < 500 && sy > 0 && sy < screen_height) Draw_Pixel(sx, sy, mouse_color, canvas.buffer, canvas.width); } // end for index } // end else } // end if left button else // right button is eraser if (mouse_state.rgbButtons[1]) { // test drawing mode if (buttons_state[BUTTON_PENCIL]) { // erase a pixel Draw_Pixel(mouse_x, mouse_y, 0, canvas.buffer, canvas.width); Draw_Pixel(mouse_x+1, mouse_y, 0, canvas.buffer, canvas.width); Draw_Pixel(mouse_x, mouse_y+1, 0, canvas.buffer, canvas.width); Draw_Pixel(mouse_x+1, mouse_y+1, 0, canvas.buffer, canvas.width); } // end if else { // erase spray for (index=0; index<20; index++) { // get next particle int sx=mouse_x-8+rand()%16; int sy=mouse_y-8+rand()%16; // make sure particle is in bounds if (sx > 0 && sx < 500 && sy > 0 && sy < screen_height) Draw_Pixel(sx, sy, 0, canvas.buffer, canvas.width); } // end for index } // end else } // end if left button } // end if else if ( (mouse_x > 500+16) && (mouse_x < 500+16+8*9) && (mouse_y > 8) && (mouse_y < 8+32*9)) { // within palette // test if button left button is down if (mouse_state.rgbButtons[0]) { // see what color cell user is pointing to int cell_x = (mouse_x - (500+16))/9; int cell_y = (mouse_y - (8))/9; // change color mouse_color = cell_x + cell_y*8; } // end if } // end if else if ((mouse_x > 500) && (mouse_x < (500+100)) && (mouse_y > 344) && (mouse_y < (383+34)) ) { // within button area // test for each button for (index=0; index<4; index++) { if ((mouse_x > buttons_x[index]) && (mouse_x < (buttons_x[index]+32)) && (mouse_y > buttons_y[index]) && (mouse_y < (buttons_y[index]+34)) ) break; } // end for // at this point we know where the user is, now determine what he // is doing with the buttons switch(index) { case BUTTON_SPRAY: { // if left button is down simply activate spray mode if (mouse_state.rgbButtons[0]) { // depress button buttons_state[index] = 1; // de-activate pencil mode buttons_state[BUTTON_PENCIL] = 0; } // end if else { // make sure button is up // buttons_state[index] = 0; } // end else } break; case BUTTON_PENCIL: { // if left button is down activate spray mode if (mouse_state.rgbButtons[0]) { // depress button buttons_state[index] = 1; // de-activate spray mode buttons_state[BUTTON_SPRAY] = 0; } // end if else { // make sure button is up // buttons_state[index] = 0; } // end else } break; case BUTTON_ERASE: { // test if left button is down, if so clear screen if (mouse_state.rgbButtons[0]) { // clear memory memset(canvas.buffer,0,canvas.width*canvas.height); // depress button buttons_state[index] = 1; } // end if else { // make sure button is up buttons_state[index] = 0; } // end else } break; case BUTTON_EXIT: { // test if left button down, if so bail if (mouse_state.rgbButtons[0]) PostMessage(main_window_handle, WM_DESTROY,0,0); } break; } // end switch } // end if else { // no mans land } // end else // lock back buffer DDraw_Lock_Back_Surface(); // draw the canvas Draw_Bitmap(&canvas, back_buffer, back_lpitch,0); // draw control panel Draw_Bitmap(&cpanel,back_buffer,back_lpitch,0); // unlock back buffer DDraw_Unlock_Back_Surface(); // draw the color palette for (int col=0; col < 256; col++) { Draw_Rectangle(500+16+(col%8)*9, 8+(col/8)*9, 500+16+(col%8)*9+8, 8+(col/8)*9+8, col,lpddsback); } // end for col // draw the current color selected Draw_Rectangle(533,306,533+34,306+34,mouse_color,lpddsback); // draw the buttons for (index=0; index<4; index++) { // set position of button bob buttons.x = buttons_x[index]; buttons.y = buttons_y[index]; // now select the on/off frame based on if the // button is off if (buttons_state[index]==0) buttons.curr_frame = index; else // button is on buttons.curr_frame = index+4; // draw the button Draw_BOB(&buttons, lpddsback); } // end for index static int green = 0; // display coords sprintf(buffer,"Pointer (%d,%d)",mouse_x,mouse_y); Draw_Text_GDI(buffer, 8,screen_height - 16,RGB(0,255,0),lpddsback); Draw_Text_GDI("T3D Paint Version 2.0 - Press <ESC> to Exit.",0,0,RGB(0,(green & 255),0),lpddsback); // a little animation ++green; // draw the cursor last Draw_BOB(&pointer,lpddsback); // flip the surfaces DDraw_Flip(); // sync to 30 fps Wait_Clock(30); // return success return(1); } // end Game_Main
int Game_Init(void *parms, int num_parms) { // this function is where you do all the initialization // for your game int index; // looping var char filename[80]; // used to build up files names // initialize directdraw DDraw_Init(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP); // first create the direct input object DirectInput8Create(main_instance,DIRECTINPUT_VERSION,IID_IDirectInput8, (void **)&lpdi,NULL); // create a mouse device ///////////////////////////////////// lpdi->CreateDevice(GUID_SysMouse, &lpdimouse, NULL); // set cooperation level lpdimouse->SetCooperativeLevel(main_window_handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); // set data format lpdimouse->SetDataFormat(&c_dfDIMouse); // acquire the mouse lpdimouse->Acquire(); ///////////////////////////////////////////////////////////////// // set the global mouse position mouse_x = screen_height/2; mouse_y = screen_height/2; // load the master bitmap in with all the graphics Load_Bitmap_File(&bitmap8bit, "PAINT.BMP"); Set_Palette(bitmap8bit.palette); // make sure all the surfaces are clean before starting DDraw_Fill_Surface(lpddsback, 0); DDraw_Fill_Surface(lpddsprimary, 0); // create the pointer bob Create_BOB(&pointer,mouse_x,mouse_y,32,34,1, BOB_ATTR_VISIBLE | BOB_ATTR_SINGLE_FRAME,DDSCAPS_SYSTEMMEMORY); // load the image for the pointer in Load_Frame_BOB(&pointer,&bitmap8bit,0,0,2,BITMAP_EXTRACT_MODE_CELL); // create the button bob Create_BOB(&buttons,0,0,32,34,8, BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,DDSCAPS_SYSTEMMEMORY); // load buttons in, two banks of 4, all the off's, then all the on's for (index=0; index<8; index++) Load_Frame_BOB(&buttons,&bitmap8bit,index, index%4,index/4,BITMAP_EXTRACT_MODE_CELL); // create the bitmap to hold the control panel Create_Bitmap(&cpanel,500,0,104,424); Load_Image_Bitmap(&cpanel, &bitmap8bit,150,0,BITMAP_EXTRACT_MODE_ABS); // create the drawing canvas bitmap Create_Bitmap(&canvas,0,0,500,SCREEN_HEIGHT); memset(canvas.buffer,0,canvas.width*canvas.height); canvas.attr = BITMAP_ATTR_LOADED; // clear out the canvas // memset(canvas.buffer,0,canvas.width*canvas.height); // set clipping rectangle to screen extents so mouse cursor // doens't mess up at edges RECT screen_rect = {0,0,screen_width,screen_height}; lpddclipper = DDraw_Attach_Clipper(lpddsback,1,&screen_rect); // hide the mouse ShowCursor(FALSE); // return success return(1); } // end Game_Init
int Game_Main(void *parms) { // this is the workhorse of your game it will be called // continuously in real-time this is like main() in C // all the calls for you game go here! int index; // looping var // start the timing clock Start_Clock(); // clear the drawing surface DDraw_Fill_Surface(lpddsback, 0); // lock back buffer and copy background into it DDraw_Lock_Back_Surface(); // draw background Draw_Bitmap(&background_bmp, back_buffer, back_lpitch,0); // unlock back surface DDraw_Unlock_Back_Surface(); // read keyboard DInput_Read_Keyboard(); // check the player controls // is the player turning right or left? if (keyboard_state[DIK_RIGHT]) { // there are 16 possible positions for the ship to point in if (++ship.varsI[0] >= 16) ship.varsI[0] = 0; } // end if else if (keyboard_state[DIK_LEFT]) { // there are 16 possible positions for the ship to point in if (--ship.varsI[0] < 0) ship.varsI[0] = 15; } // end if // now test for forward thrust if (keyboard_state[DIK_UP]) { // thrust ship in current direction float rad_angle = (float)ship.varsI[0]*(float)3.14159/(float)8; float xv = cos(rad_angle); float yv = sin(rad_angle); ship.varsF[0]+=xv; ship.varsF[1]+=yv; // animate the ship ship.curr_frame = ship.varsI[0]+16*(rand()%2); } // end if else // show non thrust version ship.curr_frame = ship.varsI[0]; // move ship ship.varsF[2]+=ship.varsF[0]; ship.varsF[3]+=ship.varsF[1]; // always apply friction in direction opposite current trajectory float fx = -ship.varsF[0]; float fy = -ship.varsF[1]; float length_f = sqrt(fx*fx+fy*fy); // normally we would avoid square root at all costs! // compute the frictional resitance if (fabs(length_f) > 0.1) { fx = FRICTION_FACTOR*fx/length_f; fy = FRICTION_FACTOR*fy/length_f; } // end if else fx=fy=0; // now apply friction to forward velocity ship.varsF[0]+=fx; ship.varsF[1]+=fy; //////////////////////////////////////////////////////////////////// // gravity calculation section // step 1: compute vector from black hole to ship, note that the centers // of each object are used float grav_x = (black_hole.x + black_hole.width/2) - (ship.x + ship.width/2); float grav_y = (black_hole.y + black_hole.height/2) - (ship.y + ship.height/2); float radius_squared = grav_x*grav_x + grav_y*grav_y; // equal to radius squared float length_grav = sqrt(radius_squared); // step 2: normalize the length of the vector to 1.0 grav_x = grav_x/length_grav; grav_y = grav_y/length_grav; // step 3: compute the gravity force float grav_force = (VIRTUAL_GRAVITY_CONSTANT) * (SHIP_MASS * BLACK_HOLE_MASS) / radius_squared; // step 4: apply gforce in the direction of grav_x, grav_y with the magnitude of grav_force ship.varsF[0]+=grav_x*grav_force; ship.varsF[1]+=grav_y*grav_force; //////////////////////////////////////////////////////////////////// // test if ship is off screen if (ship.varsF[2] > SCREEN_WIDTH) ship.varsF[2] = -ship.width; else if (ship.varsF[2] < -ship.width) ship.varsF[2] = SCREEN_WIDTH; if (ship.varsF[3] > SCREEN_HEIGHT) ship.varsF[3] = -ship.height; else if (ship.varsF[3] < -ship.height) ship.varsF[3] = SCREEN_HEIGHT; // test if velocity is insane if ( (ship.varsF[0]*ship.varsF[0] + ship.varsF[1]*ship.varsF[1]) > MAX_VEL) { // scale velocity down ship.varsF[0]*=.95; ship.varsF[1]*=.95; } // end if // animate the black hole Animate_BOB(&black_hole); // draw the black hole Draw_BOB(&black_hole, lpddsback); // copy floating point position to bob x,y ship.x = ship.varsF[2]; ship.y = ship.varsF[3]; // draw the ship Draw_BOB(&ship,lpddsback); // draw the title Draw_Text_GDI("GRAVITY MASS DEMO - Use Arrows to Control Ship.",10, 10,RGB(0,255,255), lpddsback); sprintf(buffer,"Friction: X=%f, Y=%f",fx, fy); Draw_Text_GDI(buffer,10,420,RGB(0,255,0), lpddsback); sprintf(buffer,"Velocity: X=%f, Y=%f",ship.varsF[0], ship.varsF[1]); Draw_Text_GDI(buffer,10,440,RGB(0,255,0), lpddsback); sprintf(buffer,"Gravity: X=%f, Y=%f",ship.varsF[2], ship.varsF[3]); Draw_Text_GDI(buffer,10,460,RGB(0,255,0), lpddsback); // flip the surfaces DDraw_Flip(); // sync to 30 fps = 1/30sec = 33 ms Wait_Clock(33); // check of user is trying to exit if (KEY_DOWN(VK_ESCAPE) || keyboard_state[DIK_ESCAPE]) { PostMessage(main_window_handle, WM_DESTROY,0,0); // stop all sounds DSound_Stop_All_Sounds(); // do a screen transition Screen_Transitions(SCREEN_DARKNESS,NULL,0); } // end if // return success return(1); } // end Game_Main
int Game_Init(void *parms = NULL, int num_parms = 0) { // this is called once after the initial window is created and // before the main event loop is entered, do all your initialization // here // create IDirectDraw interface 7.0 object and test for error if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL))) return(0); // set cooperation to full screen if (FAILED(lpdd->SetCooperativeLevel(main_window_handle, DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT))) return(0); // set display mode to 640x480x24 if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0))) return(0); // clear ddsd and set size DDRAW_INIT_STRUCT(ddsd); // enable valid fields ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.dwBackBufferCount = 1; // // request primary surface ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; // create the primary surface if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL))) return(0); ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; if(FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback))) return 0; // 把主屏和缓冲屏都填充为黑色初始化 DDraw_Fill_Surface(lpddsprimary, _RGB32BIT(0, 0,0,0)); DDraw_Fill_Surface(lpddsback, _RGB32BIT(0, 0,0,0)); // load the 24-bit image char* bmp_wc = "WarCraft24.bmp"; char* bmp_b8 = "bitmap8b.bmp"; char* bmp_b24 = "bitmap24.bmp"; char* bmp_b24e = "bitmap24_edit.bmp"; char* bmp_mo24 = "mosaic-600x.bmp"; char* bmp_ni24 = "nightelf-640x.bmp"; char* bmp_alley24 = "alley8_24bit.bmp"; // 载入背景图片 if (!Load_Bitmap_File(&bitmap, bmp_ni24)) return(0); // 创建背景表面、但实际上不是直接用背景表面来显示的、而是拷贝去缓冲表面和人物动作混合 // 后才一次性打到显示表面 // 这里头两个参数是指在屏幕的高和宽、第二个是指表面建立的地点、0指在显存建立、其它表示在 // 系统内存建立、当然速度自然是在显存建立快了、最后一个参数是是否设置为色彩键、这里设定为-1 // 也就是不设定任何色彩过滤、因为这个是背景表面、所以不需要任何透明的色彩键 lpddsbackground = DDraw_Create_Surface(640,480,0,-1); // 把bmp的内容拷贝至缓冲表面中 Bmp2Surface(lpddsbackground, SCREEN_WIDTH, SCREEN_HEIGHT); // 从现在开始创建人物动作了 if (!Load_Bitmap_File(&bitmap, "Dedsp0_24bit.bmp")) return(0); // seed random number generator // GetTickCount是一个系统启动至今的毫秒数、 // 配合srandg来产生一个随机数 srand(GetTickCount()); // initialize all the aliens // alien on level 1 of complex // //系统在调用rand()之前都会自动调用srand(),如果用户在rand()之前曾调用过srand()给参数seed指定了一个值, //那么rand()就会将seed的值作为产生伪随机数的初始值; //而如果用户在rand()前没有调用过srand(),那么rand()就会自动调用srand(1),即系统默认将1作为伪随机数的初始值。 //所以前面要调用一次srand来确保以下调用rand()的值会产生不同 // aliens[0].x = rand()%SCREEN_WIDTH; aliens[0].y = 116 - 72; aliens[0].velocity = 2+rand()%4; aliens[0].current_frame = 0; aliens[0].counter = 0; // alien on level 2 of complex aliens[1].x = rand()%SCREEN_WIDTH; aliens[1].y = 246 - 72; aliens[1].velocity = 2+rand()%4; aliens[1].current_frame = 0; aliens[1].counter = 0; // alien on level 3 of complex aliens[2].x = rand()%SCREEN_WIDTH; aliens[2].y = 382 - 72; aliens[2].velocity = 2+rand()%4; aliens[2].current_frame = 0; aliens[2].counter = 0; // now load the bitmap containing the alien imagery // then scan the images out into the surfaces of alien[0] // and copy then into the other two, be careful of reference counts! // 现在开始载入人物的动画帧图片了 if (!Load_Bitmap_File(&bitmap,"Dedsp0_24bit.bmp")) return(0); // create each surface and load bits // 初始化异形0号的三个动作帧表面、 // 其实、所有的异形动作帧表面都一样的、所以没有必要为每个异形都创建相应的动作帧、 // 所以其它异形的动作帧都指向这个异形0号的动作帧就可以了 for (int index = 0; index < 3; index++) { // create surface to hold image aliens[0].frames[index] = DDraw_Create_Surface(72,80,0); // now load bits... Scan_Image_Bitmap(&bitmap, // bitmap file to scan image data from aliens[0].frames[index], // surface to hold data index, 0); // cell to scan image from } // end for index // unload the bitmap file, we no longer need it Unload_Bitmap_File(&bitmap); // now for the tricky part. There is no need to create more surfaces with the same // data, so I'm going to copy the surface pointers member for member to each alien // however, be careful, since the reference counts do NOT go up, you still only need // to release() each surface once! for (index = 0; index < 3; index++) aliens[1].frames[index] = aliens[2].frames[index] = aliens[0].frames[index]; // return success or failure or your own return code here return(1); } // end Game_Init
int Game_Init(void *parms = NULL, int num_parms = 0) { // this is called once after the initial window is created and // before the main event loop is entered, do all your initialization // here // seed random number generator srand(GetTickCount()); // create IDirectDraw interface 7.0 object and test for error if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL))) return(0); // set cooperation to full screen if (FAILED(lpdd->SetCooperativeLevel(main_window_handle, DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT))) return(0); // set display mode to 640x480x8 if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0))) return(0); // clear ddsd and set size DDRAW_INIT_STRUCT(ddsd); // enable valid fields ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; // set the backbuffer count field to 1, use 2 for triple buffering ddsd.dwBackBufferCount = 1; // request a complex, flippable ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; // create the primary surface if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL))) return(0); // now query for attached surface from the primary surface // this line is needed by the call ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; // get the attached back buffer surface if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback))) return(0); // build up the palette data array for (int color=1; color < 255; color++) { // fill with random RGB values palette[color].peRed = rand()%256; palette[color].peGreen = rand()%256; palette[color].peBlue = rand()%256; // set flags field to PC_NOCOLLAPSE palette[color].peFlags = PC_NOCOLLAPSE; } // end for color // now fill in entry 0 and 255 with black and white palette[0].peRed = 0; palette[0].peGreen = 0; palette[0].peBlue = 0; palette[0].peFlags = PC_NOCOLLAPSE; palette[255].peRed = 255; palette[255].peGreen = 255; palette[255].peBlue = 255; palette[255].peFlags = PC_NOCOLLAPSE; // create the palette object if (FAILED(lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 | DDPCAPS_INITIALIZE, palette,&lpddpal, NULL))) return(0); // finally attach the palette to the primary surface if (FAILED(lpddsprimary->SetPalette(lpddpal))) return(0); // clear the surfaces out DDraw_Fill_Surface(lpddsprimary, 0 ); DDraw_Fill_Surface(lpddsback, 0 ); // define points of asteroid VERTEX2DF asteroid_vertices[8] = {33,-3, 9,-18, -12,-9, -21,-12, -9,6, -15,15, -3,27, 21,21}; // loop and initialize all asteroids for (int curr_index = 0; curr_index < NUM_ASTEROIDS; curr_index++) { // initialize the asteroid asteroids[curr_index].state = 1; // turn it on asteroids[curr_index].num_verts = 8; asteroids[curr_index].x0 = rand()%SCREEN_WIDTH; // position it asteroids[curr_index].y0 = rand()%SCREEN_HEIGHT; asteroids[curr_index].xv = -8 + rand()%17; asteroids[curr_index].yv = -8 + rand()%17; asteroids[curr_index].color = rand()%256; asteroids[curr_index].vlist = new VERTEX2DF [asteroids[curr_index].num_verts]; for (int index = 0; index < asteroids[curr_index].num_verts; index++) asteroids[curr_index].vlist[index] = asteroid_vertices[index]; } // end for curr_index // create sin/cos lookup table // generate the tables for (int ang = 0; ang < 360; ang++) { // convert ang to radians float theta = (float)ang*PI/(float)180; // insert next entry into table cos_look[ang] = cos(theta); sin_look[ang] = sin(theta); } // end for ang // return success or failure or your own return code here return(1); } // end Game_Init
int Game_Main(void *parms, int num_parms) { // this is the workhorse of your game it will be called // continuously in real-time this is like main() in C // all the calls for you game go here! int index; // looping var int dx,dy; // general deltas used in collision detection // check of user is trying to exit if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE)) PostMessage(main_window_handle, WM_DESTROY,0,0); // start the timing clock Start_Clock(); // clear the drawing surface DDraw_Fill_Surface(lpddsback, 0); // get joystick data lpdijoy->Poll(); // this is needed for joysticks only lpdijoy->GetDeviceState(sizeof(DIJOYSTATE2), (LPVOID)&joy_state); // lock the back buffer DDraw_Lock_Back_Surface(); // draw the background reactor image Draw_Bitmap16(&playfield, back_buffer, back_lpitch, 0); // unlock the back buffer DDraw_Unlock_Back_Surface(); // is the player moving? blaster.x+=joy_state.lX; blaster.y+=joy_state.lY; // test bounds if (blaster.x > SCREEN_WIDTH-32) blaster.x = SCREEN_WIDTH-32; else if (blaster.x < 0) blaster.x = 0; if (blaster.y > SCREEN_HEIGHT-32) blaster.y = SCREEN_HEIGHT-32; else if (blaster.y < SCREEN_HEIGHT-128) blaster.y = SCREEN_HEIGHT-128; // is player firing? if (joy_state.rgbButtons[0]) Start_Missile(); // move and draw missle Move_Missile(); Draw_Missile(); // is it time to blink eyes if ((rand()%100)==50) Set_Animation_BOB(&blaster,0); // draw blaster Animate_BOB(&blaster); Draw_BOB16(&blaster,lpddsback); // draw some text Draw_Text_GDI("(16-Bit Version) Let's Rock!!!",0,0,RGB(255,255,255),lpddsback); // display joystick and buttons 0-7 sprintf(buffer,"Joystick Stats: X-Axis=%d, Y-Axis=%d, buttons(%d,%d,%d,%d,%d,%d,%d,%d)", joy_state.lX,joy_state.lY, joy_state.rgbButtons[0], joy_state.rgbButtons[1], joy_state.rgbButtons[2], joy_state.rgbButtons[3], joy_state.rgbButtons[4], joy_state.rgbButtons[5], joy_state.rgbButtons[6], joy_state.rgbButtons[7]); Draw_Text_GDI(buffer,0,SCREEN_HEIGHT-20,RGB(255,255,50),lpddsback); // print out name of joystick sprintf(buffer, "Joystick Name & Vendor: %s",joyname); Draw_Text_GDI(buffer,0,SCREEN_HEIGHT-40,RGB(255,255,50),lpddsback); // flip the surfaces DDraw_Flip(); // sync to 30 fps Wait_Clock(30); // return success return(1); } // end Game_Main
int Game_Main(void *parms) { // this is the workhorse of your game it will be called // continuously in real-time this is like main() in C // all the calls for you game go here! static MATRIX4X4 mrot; // general rotation matrix static float plight_ang = 0, slight_ang = 0; // angles for light motion // use these to rotate objects static float x_ang = 0, y_ang = 0, z_ang = 0; // state variables for different rendering modes and help static int wireframe_mode = 1; static int backface_mode = 1; static int lighting_mode = 1; static int help_mode = 1; static int zsort_mode = -1; static int x_clip_mode = 1; static int y_clip_mode = 1; static int z_clip_mode = 1; static float hl = 300, // artificial light height ks = 1.25; // generic scaling factor to make things look good char work_string[256]; // temp string int index; // looping var // start the timing clock Start_Clock(); // clear the drawing surface DDraw_Fill_Surface(lpddsback, 0); // draw the sky Draw_Rectangle(0,0, WINDOW_WIDTH-1, WINDOW_HEIGHT-1, RGB16Bit(50,50,200), lpddsback); // draw the ground //Draw_Rectangle(0,WINDOW_HEIGHT*.38, WINDOW_WIDTH, WINDOW_HEIGHT, RGB16Bit(25,50,110), lpddsback); // read keyboard and other devices here DInput_Read_Keyboard(); // game logic here... // reset the render list Reset_RENDERLIST4DV2(&rend_list); // modes and lights // wireframe mode if (keyboard_state[DIK_W]) { // toggle wireframe mode if (++wireframe_mode > 1) wireframe_mode=0; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // backface removal if (keyboard_state[DIK_B]) { // toggle backface removal backface_mode = -backface_mode; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // lighting if (keyboard_state[DIK_L]) { // toggle lighting engine completely lighting_mode = -lighting_mode; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // toggle ambient light if (keyboard_state[DIK_A]) { // toggle ambient light if (lights2[AMBIENT_LIGHT_INDEX].state == LIGHTV2_STATE_ON) lights2[AMBIENT_LIGHT_INDEX].state = LIGHTV2_STATE_OFF; else lights2[AMBIENT_LIGHT_INDEX].state = LIGHTV2_STATE_ON; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // toggle infinite light if (keyboard_state[DIK_I]) { // toggle ambient light if (lights2[INFINITE_LIGHT_INDEX].state == LIGHTV2_STATE_ON) lights2[INFINITE_LIGHT_INDEX].state = LIGHTV2_STATE_OFF; else lights2[INFINITE_LIGHT_INDEX].state = LIGHTV2_STATE_ON; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // toggle point light if (keyboard_state[DIK_P]) { // toggle point light if (lights2[POINT_LIGHT_INDEX].state == LIGHTV2_STATE_ON) lights2[POINT_LIGHT_INDEX].state = LIGHTV2_STATE_OFF; else lights2[POINT_LIGHT_INDEX].state = LIGHTV2_STATE_ON; // toggle point light if (lights2[POINT_LIGHT2_INDEX].state == LIGHTV2_STATE_ON) lights2[POINT_LIGHT2_INDEX].state = LIGHTV2_STATE_OFF; else lights2[POINT_LIGHT2_INDEX].state = LIGHTV2_STATE_ON; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // help menu if (keyboard_state[DIK_H]) { // toggle help menu help_mode = -help_mode; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // z-sorting if (keyboard_state[DIK_Z]) { // toggle z sorting zsort_mode = -zsort_mode; Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // next animation if (keyboard_state[DIK_2]) { if (++obj_md2.anim_state >= NUM_MD2_ANIMATIONS) obj_md2.anim_state = 0; Set_Animation_MD2(&obj_md2, obj_md2.anim_state, MD2_ANIM_SINGLE_SHOT); Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // previous animation if (keyboard_state[DIK_1]) { if (--obj_md2.anim_state < 0) obj_md2.anim_state = NUM_MD2_ANIMATIONS-1; Set_Animation_MD2(&obj_md2, obj_md2.anim_state, MD2_ANIM_SINGLE_SHOT); Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // replay animation if (keyboard_state[DIK_3]) { Set_Animation_MD2(&obj_md2, obj_md2.anim_state, MD2_ANIM_SINGLE_SHOT); Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // replay animation if (keyboard_state[DIK_4]) { Set_Animation_MD2(&obj_md2, obj_md2.anim_state, MD2_ANIM_LOOP); Wait_Clock(100); // wait, so keyboard doesn't bounce } // end if // forward/backward if (keyboard_state[DIK_UP]) { // move forward if ( (cam_speed+=1) > MAX_SPEED) cam_speed = MAX_SPEED; } // end if else if (keyboard_state[DIK_DOWN]) { // move backward if ((cam_speed-=1) < -MAX_SPEED) cam_speed = -MAX_SPEED; } // end if // rotate around y axis or yaw if (keyboard_state[DIK_RIGHT]) { cam.dir.y+=5; // scroll the background Scroll_Bitmap(&background_bmp, -10); } // end if if (keyboard_state[DIK_LEFT]) { cam.dir.y-=5; // scroll the background Scroll_Bitmap(&background_bmp, 10); } // end if // scroll sky slowly Scroll_Bitmap(&background_bmp, -1); // 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; // move point light source in ellipse around game world lights2[POINT_LIGHT_INDEX].pos.x = 500*Fast_Cos(plight_ang); //lights2[POINT_LIGHT_INDEX].pos.y = 200; lights2[POINT_LIGHT_INDEX].pos.z = 500*Fast_Sin(plight_ang); // move point light source in ellipse around game world lights2[POINT_LIGHT2_INDEX].pos.x = 200*Fast_Cos(-2*plight_ang); //lights2[POINT_LIGHT2_INDEX].pos.y = 400; lights2[POINT_LIGHT2_INDEX].pos.z = 200*Fast_Sin(-2*plight_ang); if ((plight_ang+=1) > 360) plight_ang = 0; // generate camera matrix Build_CAM4DV1_Matrix_Euler(&cam, CAM_ROT_SEQ_ZYX); ////////////////////////////////////////////////////////////////////////// // the terrain // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV2(&obj_terrain); // generate rotation matrix around y axis //Build_XYZ_Rotation_MATRIX4X4(x_ang, y_ang, z_ang, &mrot); MAT_IDENTITY_4X4(&mrot); // rotate the local coords of the object Transform_OBJECT4DV2(&obj_terrain, &mrot, TRANSFORM_LOCAL_TO_TRANS,1); // perform world transform Model_To_World_OBJECT4DV2(&obj_terrain, TRANSFORM_TRANS_ONLY); // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_terrain,0); ////////////////////////////////////////////////////////////////////////// int v0, v1, v2, v3; // used to track vertices VECTOR4D pl, // position of the light po, // position of the occluder object/vertex vlo, // vector from light to object ps; // position of the shadow float rs, // radius of shadow t; // parameter t ////////////////////////////////////////////////////////////////////////// // render model, this next section draws each copy of the mech model ////////////////////////////////////////////////////////////////////////// // animate the model Animate_MD2(&obj_md2); // extract the frame of animation from vertex banks Extract_MD2_Frame(&obj_model, // pointer to destination object &obj_md2); // md2 object to extract frame from // set position of object obj_model.world_pos.x = 0; obj_model.world_pos.y = 100; obj_model.world_pos.z = 0; // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV2(&obj_model); // create identity matrix MAT_IDENTITY_4X4(&mrot); // transform the local coords of the object Transform_OBJECT4DV2(&obj_model, &mrot, TRANSFORM_LOCAL_TO_TRANS,1); // perform world transform Model_To_World_OBJECT4DV2(&obj_model, TRANSFORM_TRANS_ONLY); // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_model,0); // set position of object obj_model.world_pos.x = 0; obj_model.world_pos.y = 100; obj_model.world_pos.z = 200; // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV2(&obj_model); // create identity matrix MAT_IDENTITY_4X4(&mrot); // transform the local coords of the object Transform_OBJECT4DV2(&obj_model, &mrot, TRANSFORM_LOCAL_TO_TRANS,1); // perform world transform Model_To_World_OBJECT4DV2(&obj_model, TRANSFORM_TRANS_ONLY); // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_model,0); ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // draw all the light objects to represent the position of light sources // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV2(&obj_light_array[INDEX_RED_LIGHT_INDEX]); // set position of object to light obj_light_array[INDEX_RED_LIGHT_INDEX].world_pos = lights2[POINT_LIGHT_INDEX].pos; // create identity matrix MAT_IDENTITY_4X4(&mrot); // transform the local coords of the object Transform_OBJECT4DV2(&obj_light_array[INDEX_RED_LIGHT_INDEX], &mrot, TRANSFORM_LOCAL_TO_TRANS,1); // perform world transform Model_To_World_OBJECT4DV2(&obj_light_array[INDEX_RED_LIGHT_INDEX], TRANSFORM_TRANS_ONLY); // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_light_array[INDEX_RED_LIGHT_INDEX],0); // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV2(&obj_light_array[INDEX_YELLOW_LIGHT_INDEX]); // set position of object to light obj_light_array[INDEX_YELLOW_LIGHT_INDEX].world_pos = lights2[POINT_LIGHT2_INDEX].pos; // create identity matrix MAT_IDENTITY_4X4(&mrot); // transform the local coords of the object Transform_OBJECT4DV2(&obj_light_array[INDEX_YELLOW_LIGHT_INDEX], &mrot, TRANSFORM_LOCAL_TO_TRANS,1); // perform world transform Model_To_World_OBJECT4DV2(&obj_light_array[INDEX_YELLOW_LIGHT_INDEX], TRANSFORM_TRANS_ONLY); // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_light_array[INDEX_YELLOW_LIGHT_INDEX],0); //////////////////////////////////////////////////////////////////////////////////// // reset number of polys rendered debug_polys_rendered_per_frame = 0; debug_polys_lit_per_frame = 0; // perform rendering pass one // 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, CLIP_POLY_X_PLANE | CLIP_POLY_Y_PLANE | CLIP_POLY_Z_PLANE ); // light scene all at once if (lighting_mode==1) { Transform_LIGHTSV2(lights2, 4, &cam.mcam, TRANSFORM_LOCAL_TO_TRANS); Light_RENDERLIST4DV2_World2_16(&rend_list, &cam, lights2, 4); } // 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); // reset number of polys rendered debug_polys_rendered_per_frame = 0; // render the object if (wireframe_mode == 0) Draw_RENDERLIST4DV2_Wire16(&rend_list, back_buffer, back_lpitch); else if (wireframe_mode == 1) { // perspective mode affine texturing // set up rendering context rc.attr = RENDER_ATTR_ZBUFFER // | RENDER_ATTR_ALPHA // | RENDER_ATTR_MIPMAP // | RENDER_ATTR_BILERP | RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE; // initialize zbuffer to 0 fixed point Clear_Zbuffer(&zbuffer, (16000 << FIXP16_SHIFT)); // set up remainder of rendering context rc.video_buffer = back_buffer; rc.lpitch = back_lpitch; rc.mip_dist = 0; rc.zbuffer = (UCHAR *)zbuffer.zbuffer; rc.zpitch = WINDOW_WIDTH*4; rc.rend_list = &rend_list; rc.texture_dist = 0; rc.alpha_override = -1; // render scene Draw_RENDERLIST4DV2_RENDERCONTEXTV1_16_2(&rc); } // end if // now make second rendering pass and draw shadow // reset the render list Reset_RENDERLIST4DV2(&rend_list); ////////////////////////////////////////////////////////////////////////// // project shaded object into shadow by projecting it's vertices onto // the ground plane // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV2(&obj_model); // save the shading attributes/color of each polygon, and override them with // attributes of a shadow then restore them int pcolor[OBJECT4DV2_MAX_POLYS], // used to store color pattr[OBJECT4DV2_MAX_POLYS]; // used to store attribute // save all the color and attributes for each polygon for (int pindex = 0; pindex < obj_model.num_polys; pindex++) { // save attribute and color pattr[pindex] = obj_model.plist[pindex].attr; pcolor[pindex] = obj_model.plist[pindex].color; // set attributes for shadow rendering obj_model.plist[pindex].attr = POLY4DV2_ATTR_RGB16 | POLY4DV2_ATTR_SHADE_MODE_CONSTANT | POLY4DV2_ATTR_TRANSPARENT; obj_model.plist[pindex].color = RGB16Bit(50,50,50) + (7 << 24); } // end for pindex // create identity matrix MAT_IDENTITY_4X4(&mrot); // solve for t when the projected vertex intersects ground plane pl = lights2[POINT_LIGHT_INDEX].pos; // transform each local/model vertex of the object mesh and store result // in "transformed" vertex list, note for (int vertex=0; vertex < obj_model.num_vertices; vertex++) { POINT4D presult; // hold result of each transformation // compute parameter t0 when projected ray pierces y=0 plane VECTOR4D vi; // set position of object obj_model.world_pos.x = 0; obj_model.world_pos.y = 100; obj_model.world_pos.z = 0; // transform coordinates to worldspace right now... VECTOR4D_Add(&obj_model.vlist_local[vertex].v, &obj_model.world_pos, &vi); float t0 = -pl.y / (vi.y - pl.y); // transform point obj_model.vlist_trans[vertex].v.x = pl.x + t0*(vi.x - pl.x); obj_model.vlist_trans[vertex].v.y = 10.0; // pl.y + t0*(vi.y - pl.y); obj_model.vlist_trans[vertex].v.z = pl.z + t0*(vi.z - pl.z); obj_model.vlist_trans[vertex].v.w = 1.0; } // end for index // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_model,0); // and now second shadow object from second light source... // solve for t when the projected vertex intersects pl = lights2[POINT_LIGHT_INDEX].pos; // transform each local/model vertex of the object mesh and store result // in "transformed" vertex list for (vertex=0; vertex < obj_model.num_vertices; vertex++) { POINT4D presult; // hold result of each transformation // compute parameter t0 when projected ray pierces y=0 plane VECTOR4D vi; // set position of object obj_model.world_pos.x = 0; obj_model.world_pos.y = 100; obj_model.world_pos.z = 200; // transform coordinates to worldspace right now... VECTOR4D_Add(&obj_model.vlist_local[vertex].v, &obj_model.world_pos, &vi); float t0 = -pl.y / (vi.y - pl.y); // transform point obj_model.vlist_trans[vertex].v.x = pl.x + t0*(vi.x - pl.x); obj_model.vlist_trans[vertex].v.y = 10.0; // pl.y + t0*(vi.y - pl.y); obj_model.vlist_trans[vertex].v.z = pl.z + t0*(vi.z - pl.z); obj_model.vlist_trans[vertex].v.w = 1.0; } // end for index // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_model,0); // restore attributes and color for (pindex = 0; pindex < obj_model.num_polys; pindex++) { // save attribute and color obj_model.plist[pindex].attr = pattr[pindex]; obj_model.plist[pindex].color = pcolor[pindex]; } // end for pindex ////////////////////////////////////////////////////////////////////////// // 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, CLIP_POLY_X_PLANE | CLIP_POLY_Y_PLANE | CLIP_POLY_Z_PLANE ); // light scene all at once if (lighting_mode==1) { Transform_LIGHTSV2(lights2, 4, &cam.mcam, TRANSFORM_LOCAL_TO_TRANS); Light_RENDERLIST4DV2_World2_16(&rend_list, &cam, lights2, 4); } // 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); // render the object if (wireframe_mode == 0) Draw_RENDERLIST4DV2_Wire16(&rend_list, back_buffer, back_lpitch); else if (wireframe_mode == 1) { // perspective mode affine texturing // set up rendering context rc.attr = RENDER_ATTR_ZBUFFER | RENDER_ATTR_ALPHA // | RENDER_ATTR_MIPMAP // | RENDER_ATTR_BILERP | RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE; // initialize zbuffer to 0 fixed point //Clear_Zbuffer(&zbuffer, (16000 << FIXP16_SHIFT)); // set up remainder of rendering context rc.video_buffer = back_buffer; rc.lpitch = back_lpitch; rc.mip_dist = 0; rc.zbuffer = (UCHAR *)zbuffer.zbuffer; rc.zpitch = WINDOW_WIDTH*4; rc.rend_list = &rend_list; rc.texture_dist = 0; rc.alpha_override = -1; // render scene Draw_RENDERLIST4DV2_RENDERCONTEXTV1_16_3(&rc); } // end if // unlock the back buffer DDraw_Unlock_Back_Surface(); // draw cockpit //Draw_BOB16(&cockpit, lpddsback); // draw instructions Draw_Text_GDI("Press ESC to exit. Press <H> for Help.", 0, 0, RGB(255,255,255), 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("<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("<Z>..............Toggle Z-sorting.", 0, text_y+=12, RGB(255,255,255), lpddsback); Draw_Text_GDI("<1>,<2>..........Previous/Next Animation.", 0, text_y+=12, RGB(255,255,255), lpddsback); Draw_Text_GDI("<3>,<4>..........Play Animation Single Shot/Looped.", 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,"Lighting [%s]: Ambient=%d, Infinite=%d, Point=%d, BckFceRM [%s], Zsort[%s]", ((lighting_mode == 1) ? "ON" : "OFF"), lights2[AMBIENT_LIGHT_INDEX].state, lights2[INFINITE_LIGHT_INDEX].state, lights2[POINT_LIGHT_INDEX].state, ((backface_mode == 1) ? "ON" : "OFF"), ((zsort_mode == 1) ? "ON" : "OFF") ); Draw_Text_GDI(work_string, 0+1, WINDOW_HEIGHT-34+1, RGB(0,0,0), lpddsback); Draw_Text_GDI(work_string, 0, WINDOW_HEIGHT-34, RGB(255,255,255), lpddsback); sprintf(work_string,"Polys Rendered: %d, Polys lit: %d Anim[%d]=%s Frm=%d", debug_polys_rendered_per_frame, debug_polys_lit_per_frame, obj_md2.anim_state,md2_anim_strings[obj_md2.anim_state], obj_md2.curr_frame ); Draw_Text_GDI(work_string, 0+1, WINDOW_HEIGHT-34-2*16+1, RGB(0,0,0), lpddsback); Draw_Text_GDI(work_string, 0, WINDOW_HEIGHT-34-2*16, RGB(255,255,255), lpddsback); sprintf(work_string,"CAM [%5.2f, %5.2f, %5.2f], CELL [%d, %d]", cam.pos.x, cam.pos.y, cam.pos.z, cell_x, cell_y); Draw_Text_GDI(work_string, 0+1, WINDOW_HEIGHT-34-3*16+1, RGB(0,0,0), lpddsback); Draw_Text_GDI(work_string, 0, WINDOW_HEIGHT-34-3*16, RGB(255,255,255), 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]) { PostMessage(main_window_handle, WM_DESTROY,0,0); } // end if // return success return(1); } // end Game_Main
int Game_Init(void *parms = NULL, int num_parms = 0) { // this is called once after the initial window is created and // before the main event loop is entered, do all your initialization // here // create IDirectDraw interface 7.0 object and test for error if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL))) return(0); // set cooperation to full screen if (FAILED(lpdd->SetCooperativeLevel(main_window_handle, DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT))) return(0); // set display mode to 640x480x8 if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0))) return(0); // we need a complex surface system with a primary and backbuffer // clear ddsd and set size DDRAW_INIT_STRUCT(ddsd); // enable valid fields ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; // set the backbuffer count field to 1, use 2 for triple buffering ddsd.dwBackBufferCount = 1; // request a complex, flippable ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; // create the primary surface if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL))) return(0); // now query for attached surface from the primary surface // this line is needed by the call ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; // get the attached back buffer surface if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback))) return(0); // build up the palette data array for (int color=1; color < 255; color++) { // fill with random RGB values palette[color].peRed = rand()%256; palette[color].peGreen = rand()%256; palette[color].peBlue = rand()%256; // set flags field to PC_NOCOLLAPSE palette[color].peFlags = PC_NOCOLLAPSE; } // end for color // now fill in entry 0 and 255 with black and white palette[0].peRed = 0; palette[0].peGreen = 0; palette[0].peBlue = 0; palette[0].peFlags = PC_NOCOLLAPSE; palette[255].peRed = 255; palette[255].peGreen = 255; palette[255].peBlue = 255; palette[255].peFlags = PC_NOCOLLAPSE; // create the palette object if (FAILED(lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 | DDPCAPS_INITIALIZE, palette,&lpddpal, NULL))) return(0); // finally attach the palette to the primary surface if (FAILED(lpddsprimary->SetPalette(lpddpal))) return(0); // set clipper up on back buffer since that's where well clip RECT screen_rect= {0,0,SCREEN_WIDTH-1,SCREEN_HEIGHT-1}; lpddclipper = DDraw_Attach_Clipper(lpddsback,1,&screen_rect); // load the 8-bit image if (!Load_Bitmap_File(&bitmap,"alley8.bmp")) return(0); // load it's palette into directdraw if (FAILED(lpddpal->SetEntries(0,0,MAX_COLORS_PALETTE,bitmap.palette))) return(0); // clean the surfaces DDraw_Fill_Surface(lpddsprimary,0); DDraw_Fill_Surface(lpddsback,0); // create the buffer to hold the background lpddsbackground = DDraw_Create_Surface(640,480,0,-1); // copy the background bitmap image to the background surface // lock the surface lpddsbackground->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL); // get video pointer to primary surfce UCHAR *image_buffer = (UCHAR *)ddsd.lpSurface; // test if memory is linear if (ddsd.lPitch == SCREEN_WIDTH) { // copy memory from double buffer to primary buffer memcpy((void *)image_buffer, (void *)bitmap.buffer, SCREEN_WIDTH*SCREEN_HEIGHT); } // end if else { // non-linear // make copy of source and destination addresses UCHAR *dest_ptr = image_buffer; UCHAR *src_ptr = bitmap.buffer; // memory is non-linear, copy line by line for (int y=0; y < SCREEN_HEIGHT; y++) { // copy line memcpy((void *)dest_ptr, (void *)src_ptr, SCREEN_WIDTH); // advance pointers to next line dest_ptr+=ddsd.lPitch; src_ptr +=SCREEN_WIDTH; } // end for } // end else // now unlock the primary surface if (FAILED(lpddsbackground->Unlock(NULL))) return(0); // unload the bitmap file, we no longer need it Unload_Bitmap_File(&bitmap); // seed random number generator srand(GetTickCount()); // initialize all the aliens (in real life do this in a loop or function) // alien on level 1 of complex aliens[0].x = rand()%SCREEN_WIDTH; aliens[0].y = 116 - 72; aliens[0].velocity = 2+rand()%4; aliens[0].current_frame = 0; aliens[0].counter = 0; aliens[0].width = 72; // set real size aliens[0].height = 80; aliens[0].scale = ((float)(1+rand()%20))/10; // scale from 0.1 to 2.0 // fix up feet so they still contact floor aliens[0].y+=(72 - aliens[0].scale*72); // alien on level 2 of complex aliens[1].x = rand()%SCREEN_WIDTH; aliens[1].y = 246 - 72; aliens[1].velocity = 2+rand()%4; aliens[1].current_frame = 0; aliens[1].counter = 0; aliens[1].width = 72; // set real size aliens[1].height = 80; aliens[1].scale = ((float)(1+rand()%20))/10; // scale from 0.1 to 2.0 // fix up feet so they still contact floor aliens[1].y+=(72 - aliens[1].scale*72); // alien on level 3 of complex aliens[2].x = rand()%SCREEN_WIDTH; aliens[2].y = 382 - 72; aliens[2].velocity = 2+rand()%4; aliens[2].current_frame = 0; aliens[2].counter = 0; aliens[2].width = 72; // set real size aliens[2].height = 80; aliens[2].scale = ((float)(1+rand()%20))/10; // scale from 0.1 to 2.0 // fix up feet so they still contact floor aliens[2].y+=(72 - aliens[2].scale*72); // now load the bitmap containing the alien imagery // then scan the images out into the surfaces of alien[0] // and copy then into the other two, be careful of reference counts! // load the 8-bit image if (!Load_Bitmap_File(&bitmap,"dedsp0.bmp")) return(0); // create each surface and load bits for (int index = 0; index < 3; index++) { // create surface to hold image aliens[0].frames[index] = DDraw_Create_Surface(72,80,0); // now load bits... Scan_Image_Bitmap(&bitmap, // bitmap file to scan image data from aliens[0].frames[index], // surface to hold data index, 0); // cell to scan image from } // end for index // unload the bitmap file, we no longer need it Unload_Bitmap_File(&bitmap); // now for the tricky part. There is no need to create more surfaces with the same // data, so I'm going to copy the surface pointers member for member to each alien // however, be careful, since the reference counts do NOT go up, you still only need // to release() each surface once! for (index = 0; index < 3; index++) aliens[1].frames[index] = aliens[2].frames[index] = aliens[0].frames[index]; // return success or failure or your own return code here return(1); } // end Game_Init
int Game_Main(void *parms) { // this is the workhorse of your game it will be called // continuously in real-time this is like main() in C // all the calls for you game go here! static MATRIX4X4 mrot; // general rotation matrix // these are used to create a circling camera static float view_angle = 0; static float camera_distance = 6000; static VECTOR4D pos = {0,0,0,0}; static float tank_speed; static float turning = 0; char work_string[256]; // temp string int index; // looping var // start the timing clock Start_Clock(); // clear the drawing surface DDraw_Fill_Surface(lpddsback, 0); // draw the sky Draw_Rectangle(0,0, WINDOW_WIDTH-1, WINDOW_HEIGHT/2, RGB16Bit(0,140,192), lpddsback); // draw the ground Draw_Rectangle(0,WINDOW_HEIGHT/2, WINDOW_WIDTH-1, WINDOW_HEIGHT-1, RGB16Bit(103,62,3), lpddsback); // read keyboard and other devices here DInput_Read_Keyboard(); // game logic here... // reset the render list Reset_RENDERLIST4DV1(&rend_list); // allow user to move camera // turbo if (keyboard_state[DIK_SPACE]) tank_speed = 5*TANK_SPEED; else tank_speed = TANK_SPEED; // forward/backward if (keyboard_state[DIK_UP]) { // move forward cam.pos.x += tank_speed*Fast_Sin(cam.dir.y); cam.pos.z += tank_speed*Fast_Cos(cam.dir.y); } // end if if (keyboard_state[DIK_DOWN]) { // move backward cam.pos.x -= tank_speed*Fast_Sin(cam.dir.y); cam.pos.z -= tank_speed*Fast_Cos(cam.dir.y); } // end if // rotate if (keyboard_state[DIK_RIGHT]) { cam.dir.y+=3; // add a little turn to object if ((turning+=2) > 15) turning=15; } // end if if (keyboard_state[DIK_LEFT]) { cam.dir.y-=3; // add a little turn to object if ((turning-=2) < -15) turning=-15; } // end if else // center heading again { if (turning > 0) turning-=1; else if (turning < 0) turning+=1; } // end else // generate camera matrix Build_CAM4DV1_Matrix_Euler(&cam, CAM_ROT_SEQ_ZYX); // insert the tanks in the world for (index = 0; index < NUM_TANKS; index++) { // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV1(&obj_tank); // generate rotation matrix around y axis Build_XYZ_Rotation_MATRIX4X4(0, tanks[index].w, 0, &mrot); // rotate the local coords of the object Transform_OBJECT4DV1(&obj_tank, &mrot, TRANSFORM_LOCAL_TO_TRANS,1); // set position of tank obj_tank.world_pos.x = tanks[index].x; obj_tank.world_pos.y = tanks[index].y; obj_tank.world_pos.z = tanks[index].z; // attempt to cull object if (!Cull_OBJECT4DV1(&obj_tank, &cam, CULL_OBJECT_XYZ_PLANES)) { // if we get here then the object is visible at this world position // so we can insert it into the rendering list // perform local/model to world transform Model_To_World_OBJECT4DV1(&obj_tank, TRANSFORM_TRANS_ONLY); // insert the object into render list Insert_OBJECT4DV1_RENDERLIST4DV1(&rend_list, &obj_tank); } // end if } // end for // insert the player into the world // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV1(&obj_player); // set position of tank obj_player.world_pos.x = cam.pos.x+300*Fast_Sin(cam.dir.y); obj_player.world_pos.y = cam.pos.y-70; obj_player.world_pos.z = cam.pos.z+300*Fast_Cos(cam.dir.y); // generate rotation matrix around y axis Build_XYZ_Rotation_MATRIX4X4(0, cam.dir.y+turning, 0, &mrot); // rotate the local coords of the object Transform_OBJECT4DV1(&obj_player, &mrot, TRANSFORM_LOCAL_TO_TRANS,1); // perform world transform Model_To_World_OBJECT4DV1(&obj_player, TRANSFORM_TRANS_ONLY); // insert the object into render list Insert_OBJECT4DV1_RENDERLIST4DV1(&rend_list, &obj_player); // insert the towers in the world for (index = 0; index < NUM_TOWERS; index++) { // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV1(&obj_tower); // set position of tower obj_tower.world_pos.x = towers[index].x; obj_tower.world_pos.y = towers[index].y; obj_tower.world_pos.z = towers[index].z; // attempt to cull object if (!Cull_OBJECT4DV1(&obj_tower, &cam, CULL_OBJECT_XYZ_PLANES)) { // if we get here then the object is visible at this world position // so we can insert it into the rendering list // perform local/model to world transform Model_To_World_OBJECT4DV1(&obj_tower); // insert the object into render list Insert_OBJECT4DV1_RENDERLIST4DV1(&rend_list, &obj_tower); } // end if } // end for // seed number generator so that modulation of markers is always the same srand(13); // insert the ground markers into the world for (int index_x = 0; index_x < NUM_POINTS_X; index_x++) for (int index_z = 0; index_z < NUM_POINTS_Z; index_z++) { // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV1(&obj_marker); // set position of tower obj_marker.world_pos.x = RAND_RANGE(-100,100)-UNIVERSE_RADIUS+index_x*POINT_SIZE; obj_marker.world_pos.y = obj_marker.max_radius; obj_marker.world_pos.z = RAND_RANGE(-100,100)-UNIVERSE_RADIUS+index_z*POINT_SIZE; // attempt to cull object if (!Cull_OBJECT4DV1(&obj_marker, &cam, CULL_OBJECT_XYZ_PLANES)) { // if we get here then the object is visible at this world position // so we can insert it into the rendering list // perform local/model to world transform Model_To_World_OBJECT4DV1(&obj_marker); // insert the object into render list Insert_OBJECT4DV1_RENDERLIST4DV1(&rend_list, &obj_marker); } // end if } // end for // remove backfaces Remove_Backfaces_RENDERLIST4DV1(&rend_list, &cam); // apply world to camera transform World_To_Camera_RENDERLIST4DV1(&rend_list, &cam); // apply camera to perspective transformation Camera_To_Perspective_RENDERLIST4DV1(&rend_list, &cam); // apply screen transform Perspective_To_Screen_RENDERLIST4DV1(&rend_list, &cam); sprintf(work_string,"pos:[%f, %f, %f] heading:[%f] elev:[%f]", cam.pos.x, cam.pos.y, cam.pos.z, cam.dir.y, cam.dir.x); Draw_Text_GDI(work_string, 0, WINDOW_HEIGHT-20, RGB(0,255,0), lpddsback); // draw instructions Draw_Text_GDI("Press ESC to exit. Press Arrow Keys to Move. Space for TURBO.", 0, 0, RGB(0,255,0), lpddsback); // lock the back buffer DDraw_Lock_Back_Surface(); // render the object Draw_RENDERLIST4DV1_Wire16(&rend_list, back_buffer, back_lpitch); // unlock the back buffer DDraw_Unlock_Back_Surface(); // flip the surfaces DDraw_Flip(); // sync to 30ish fps Wait_Clock(30); // check of user is trying to exit if (KEY_DOWN(VK_ESCAPE) || keyboard_state[DIK_ESCAPE]) { PostMessage(main_window_handle, WM_DESTROY,0,0); } // end if // return success return(1); } // end Game_Main
int Game_Init(void *parms = NULL, int num_parms = 0) { // this is called once after the initial window is created and // before the main event loop is entered, do all your initialization // here // create IDirectDraw interface 7.0 object and test for error if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL))) return(0); // set cooperation to full screen if (FAILED(lpdd->SetCooperativeLevel(main_window_handle, DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT))) return(0); // set display mode to 640x480x8 if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0))) return(0); // clear ddsd and set size DDRAW_INIT_STRUCT(ddsd); // enable valid fields ddsd.dwFlags = DDSD_CAPS; // request primary surface ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; // create the primary surface if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL))) return(0); // build up the palette data array for (int color=1; color < 255; color++) { // fill with random RGB values palette[color].peRed = rand()%256; palette[color].peGreen = rand()%256; palette[color].peBlue = rand()%256; // set flags field to PC_NOCOLLAPSE palette[color].peFlags = PC_NOCOLLAPSE; } // end for color // now fill in entry 0 and 255 with black and white palette[0].peRed = 0; palette[0].peGreen = 0; palette[0].peBlue = 0; palette[0].peFlags = PC_NOCOLLAPSE; palette[255].peRed = 255; palette[255].peGreen = 255; palette[255].peBlue = 255; palette[255].peFlags = PC_NOCOLLAPSE; // create the palette object if (FAILED(lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 | DDPCAPS_INITIALIZE, palette,&lpddpal, NULL))) return(0); // finally attach the palette to the primary surface if (FAILED(lpddsprimary->SetPalette(lpddpal))) return(0); // clear the primary surface off DDraw_Fill_Surface(lpddsprimary, 0 ); // return success or failure or your own return code here return(1); } // end Game_Init