void CSG_Doc_SVG::Draw_Rectangle(const CSG_Rect &r, int Fill_Color, int Line_Color, double Line_Width) { Draw_Rectangle(r.Get_XMin(), r.Get_YMin(), r.Get_XMax(), r.Get_YMax(), Fill_Color, Line_Color, Line_Width) ; }
void Draw_FilledRectangle(int x0, int y0, int width, int height, int backgroundColor, int borderColor, int Draw_Border) { // Draw background for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { DRAW_PIXEL(x0 + x, y0 + y, backgroundColor); } } // Draw border if (Draw_Border) Draw_Rectangle(x0, y0, width, height, borderColor); }
IplImage* Harrlike::DetectSaveROI() { if(m_justSet) { IplImage* small_image; CvMemStorage* storage = cvCreateMemStorage(0);//default:64k byte CvSeq* faces = NULL; /*Smallize to boost the speed of detection*/ if( m_PyrDown ) { if(m_srcImage->nChannels == 1) small_image = cvCreateImage( cvSize(m_srcImage->width/2,m_srcImage->height/2), IPL_DEPTH_8U, 1 ); else small_image = cvCreateImage( cvSize(m_srcImage->width/2,m_srcImage->height/2), IPL_DEPTH_8U, 3 ); cvPyrDown( m_srcImage, small_image, CV_GAUSSIAN_5x5 ); scale = 2; } else small_image = m_srcImage; faces = cvHaarDetectObjects( small_image, cascade, storage, 1.2, 2 , CV_HAAR_DO_CANNY_PRUNING ); /* Draw all faces with rectangle */ if(faces!=NULL) { Draw_Rectangle(faces,scale); SaveROI(m_OriginalImage,faces); if( small_image != m_srcImage )cvReleaseImage( &small_image ); cvClearSeq(faces); cvReleaseImage( &small_image ); cvReleaseMemStorage( &storage ); return m_normalizeImage; } else { printf("m_Number %d can't be foundd!\n"); return NULL; } /*cvNamedWindow( "test", 0 ); cvShowImage( "test", m_srcImage ); cvSaveImage("Face_Detect1.jpg",m_srcImage); cvWaitKey(0);*/ } return NULL; }
void Draw_Blocks(void) { // this function draws all the blocks in row major form int x1 = BLOCK_ORIGIN_X, // used to track current position y1 = BLOCK_ORIGIN_Y; // draw all the blocks for (int row=0; row < NUM_BLOCK_ROWS; row++) { // reset column position x1 = BLOCK_ORIGIN_X; // draw this row of blocks for (int col=0; col < NUM_BLOCK_COLUMNS; col++) { // draw next block (if there is one) if (blocks[row][col]!=0) { // draw block Draw_Rectangle(x1-4,y1+4, x1+BLOCK_WIDTH-4,y1+BLOCK_HEIGHT+4,0); Draw_Rectangle(x1,y1,x1+BLOCK_WIDTH, y1+BLOCK_HEIGHT,blocks[row][col]); } // end if // advance column position x1+=BLOCK_X_GAP; } // end for col // advance to next row position y1+=BLOCK_Y_GAP; } // end for row } // end Draw_Blocks
void Draw_Projectiles(void) { // this function draws all the projectiles for (int index=0; index < NUM_PROJECTILES; index++) { // is this one alive? if (missiles[index].state==1) { Draw_Rectangle(missiles[index].x-1,missiles[index].y-1, missiles[index].x+1,missiles[index].y+1, 249, lpddsback); } // end if } // end for index } // end Draw_Projectiles
void SCR_DrawDevStats (void) { Colour_t colour_dark = { 0, 0, 0, 0.5f }; char str[40]; int y = 25-9; //9=number of lines to print int x = 0; //margin if (!devstats.value) return; GL_SetCanvas (CANVAS_BOTTOMLEFT); Draw_Rectangle(x,y*8,152,72, colour_dark); //dark rectangle sprintf (str, "devstats |Curr Peak"); Draw_String(x, (y++) * 8 - x, str); sprintf (str, "---------+---------"); Draw_String(x, (y++) * 8 - x, str); sprintf (str, "Edicts |%4i %4i", dev_stats.edicts, dev_peakstats.edicts); Draw_String(x, (y++) * 8 - x, str); sprintf (str, "Packet |%4i %4i", dev_stats.packetsize, dev_peakstats.packetsize); Draw_String(x, (y++) * 8 - x, str); sprintf (str, "Visedicts|%4i %4i", dev_stats.visedicts, dev_peakstats.visedicts); Draw_String(x, (y++) * 8 - x, str); sprintf (str, "Efrags |%4i %4i", dev_stats.efrags, dev_peakstats.efrags); Draw_String(x, (y++) * 8 - x, str); sprintf (str, "Dlights |%4i %4i", dev_stats.dlights, dev_peakstats.dlights); Draw_String(x, (y++) * 8 - x, str); sprintf (str, "Beams |%4i %4i", dev_stats.beams, dev_peakstats.beams); Draw_String(x, (y++) * 8 - x, str); sprintf (str, "Tempents |%4i %4i", dev_stats.tempents, dev_peakstats.tempents); Draw_String(x, (y++) * 8 - x, str); }
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_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_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); #if 1 // draw the sky //Draw_Rectangle(0,0, WINDOW_WIDTH-1, WINDOW_HEIGHT/2, 166, lpddsback); //Draw_Rectangle(0,WINDOW_HEIGHT/2, WINDOW_WIDTH-1, WINDOW_HEIGHT-1, rgblookup[RGB16Bit565(115,42,16)], lpddsback); //Draw_Rectangle(0,0, WINDOW_WIDTH-1, WINDOW_HEIGHT/2, rgblookup[RGB16Bit565(0,140,192)], lpddsback); //Draw_Rectangle(0,0, WINDOW_WIDTH-1, WINDOW_HEIGHT/2, RGB16Bit(0,140,192), lpddsback); Draw_Rectangle(0,0, WINDOW_WIDTH, WINDOW_HEIGHT/2, RGB16Bit(0,35,50), lpddsback); // draw the ground //Draw_Rectangle(0,WINDOW_HEIGHT/2, WINDOW_WIDTH-1, WINDOW_HEIGHT-1, 28, lpddsback); //Draw_Rectangle(0,WINDOW_HEIGHT/2, WINDOW_WIDTH-1, WINDOW_HEIGHT-1, rgblookup[RGB16Bit565(115,42,16)], lpddsback); //Draw_Rectangle(0,WINDOW_HEIGHT/2, WINDOW_WIDTH-1, WINDOW_HEIGHT-1, RGB16Bit(103,62,3), lpddsback); 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); // 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) > 25) turning=25; } // end if if (keyboard_state[DIK_LEFT]) { cam.dir.y-=3; // add a little turn to object if ((turning-=2) < -25) turning=-25; } // end if else // center heading again { if (turning > 0) turning-=1; else if (turning < 0) turning+=1; } // end else // 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 = 4000*Fast_Cos(plight_ang); lights[POINT_LIGHT_INDEX].pos.y = 200; lights[POINT_LIGHT_INDEX].pos.z = 4000*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 = 2000*Fast_Cos(slight_ang); lights[SPOT_LIGHT2_INDEX].pos.y = 200; lights[SPOT_LIGHT2_INDEX].pos.z = 2000*Fast_Sin(slight_ang); if ((slight_ang-=5) < 0) slight_ang = 360; // generate camera matrix Build_CAM4DV1_Matrix_Euler(&cam, CAM_ROT_SEQ_ZYX); // insert the player into the world // reset the object (this only matters for backface and object removal) Reset_OBJECT4DV2(&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 static int turn=0; Build_XYZ_Rotation_MATRIX4X4(1, cam.dir.y+turning, 2, &mrot); // rotate the local coords of the object Transform_OBJECT4DV2(&obj_player, &mrot, TRANSFORM_LOCAL_TO_TRANS,1); // perform world transform Model_To_World_OBJECT4DV2(&obj_player, TRANSFORM_TRANS_ONLY); //Light_OBJECT4DV2_World16(&obj_player, &cam, lights, 4); // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_player,0); #if 1 ////////////////////////////////////////////////////////// // 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_OBJECT4DV2(&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_OBJECT4DV2(&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_OBJECT4DV2(&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_OBJECT4DV2(&obj_tank, TRANSFORM_TRANS_ONLY); //Light_OBJECT4DV2_World16(&obj_tank, &cam, lights, 4); // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_tank,0); } // end if } // end for //////////////////////////////////////////////////////// // 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_OBJECT4DV2(&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_OBJECT4DV2(&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_OBJECT4DV2(&obj_tower); //Light_OBJECT4DV2_World16(&obj_tower, &cam, lights, 4); // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_tower,0); } // end if } // end for /////////////////////////////////////////////////////////////// // seed number generator so that modulation of markers is always the same srand(13); static int mcount = 0, mdir = 2; mcount+=mdir; if (mcount > 200 || mcount < -200) { mdir=-mdir; mcount+=mdir; } // 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_OBJECT4DV2(&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[0] + 50*Fast_Sin(index_x*10+Fast_Sin(index_z)+mcount); obj_marker.world_pos.z = RAND_RANGE(-100,100)-UNIVERSE_RADIUS+index_z*POINT_SIZE; // attempt to cull object if (!Cull_OBJECT4DV2(&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_OBJECT4DV2(&obj_marker); //Light_OBJECT4DV2_World16(&obj_marker, &cam, lights, 4); // insert the object into render list Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_marker,0); } // end if } // end for //////////////////////////////////////////////////////////////////////// #endif // 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,"pos:[%f, %f, %f] heading:[%f] elev:[%f], polys[%d]", cam.pos.x, cam.pos.y, cam.pos.z, cam.dir.y, cam.dir.x, debug_polys_rendered_per_frame); Draw_Text_GDI(work_string, 0, WINDOW_HEIGHT-20, RGB(0,255,0), lpddsback); 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("<RIGHT ARROW>....Rotate player right.", 0, text_y+=12, RGB(255,255,255), lpddsback); Draw_Text_GDI("<LEFT ARROW>.....Rotate player left.", 0, text_y+=12, RGB(255,255,255), lpddsback); Draw_Text_GDI("<UP ARROW>.......Move player forward.", 0, text_y+=12, RGB(255,255,255), lpddsback); Draw_Text_GDI("<DOWN ARROW>.....Move player backward.", 0, text_y+=12, RGB(255,255,255), lpddsback); Draw_Text_GDI("<SPACE BAR>......Turbo.", 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); #endif // 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) { // 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; // 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 FreakOut::Game_Main(void *parms,HWND main_window_handle) { // 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! char buffer[80]; // used to print text // what state is the game in? if (game_state == GAME_STATE_INIT) { // initialize everything here graphics DD_Init(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP); // seed the random number generator // so game is different each play srand(Start_Clock()); // set the paddle position here to the middle bottom paddle_x = PADDLE_START_X; paddle_y = PADDLE_START_Y; // set ball position and velocity ball_x = 8+rand()%(SCREEN_WIDTH-16); ball_y = BALL_START_Y; ball_dx = -4 + rand()%(8+1); ball_dy = 6 + rand()%2; // transition to start level state game_state = GAME_STATE_START_LEVEL; } // end if //////////////////////////////////////////////////////////////// else if (game_state == GAME_STATE_START_LEVEL) { // get a new level ready to run // initialize the blocks Init_Blocks(); // reset block counter blocks_hit = 0; // transition to run state game_state = GAME_STATE_RUN; } // end if /////////////////////////////////////////////////////////////// else if (game_state == GAME_STATE_RUN) { // start the timing clock Start_Clock(); // clear drawing surface for the next frame of animation Draw_Rectangle(0,0,SCREEN_WIDTH-1, SCREEN_HEIGHT-1,200); // move the paddle if (KEY_DOWN(VK_RIGHT)) { // move paddle to right paddle_x+=8; // make sure paddle doesn't go off screen if (paddle_x > (SCREEN_WIDTH-PADDLE_WIDTH)) paddle_x = SCREEN_WIDTH-PADDLE_WIDTH; } // end if else if (KEY_DOWN(VK_LEFT)) { // move paddle to right paddle_x-=8; // make sure paddle doesn't go off screen if (paddle_x < 0) paddle_x = 0; } // end if // draw blocks Draw_Blocks(); // move the ball ball_x+=ball_dx; ball_y+=ball_dy; // keep ball on screen, if the ball hits the edge of // screen then bounce it by reflecting its velocity if (ball_x > (SCREEN_WIDTH - BALL_SIZE) || ball_x < 0) { // reflect x-axis velocity ball_dx=-ball_dx; // update position ball_x+=ball_dx; } // end if // now y-axis if (ball_y < 0) { // reflect y-axis velocity ball_dy=-ball_dy; // update position ball_y+=ball_dy; } // end if else // penalize player for missing the ball if (ball_y > (SCREEN_HEIGHT - BALL_SIZE)) { // reflect y-axis velocity ball_dy=-ball_dy; // update position ball_y+=ball_dy; // minus the score score-=100; } // end if // next watch out for ball velocity getting out of hand if (ball_dx > 8) ball_dx = 8; else if (ball_dx < -8) ball_dx = -8; // test if ball hit any blocks or the paddle Process_Ball(); // draw the paddle and shadow Draw_Rectangle(paddle_x-8, paddle_y+8, paddle_x+PADDLE_WIDTH-8, paddle_y+PADDLE_HEIGHT+8,0); Draw_Rectangle(paddle_x, paddle_y, paddle_x+PADDLE_WIDTH, paddle_y+PADDLE_HEIGHT,PADDLE_COLOR); // draw the ball Draw_Rectangle(ball_x-4, ball_y+4, ball_x+BALL_SIZE-4, ball_y+BALL_SIZE+4, 0); Draw_Rectangle(ball_x, ball_y, ball_x+BALL_SIZE, ball_y+BALL_SIZE, 255); // draw the info sprintf(buffer,"F R E A K O U T Score %d Level %d",score,level); Draw_Text_GDI(buffer, 8,SCREEN_HEIGHT-16, 127); // flip the surfaces DD_Flip(); // sync to 33ish fps Wait_Clock(30); // check of user is trying to exit if (KEY_DOWN(VK_ESCAPE)) { // send message to windows to exit PostMessage(main_window_handle, WM_DESTROY,0,0); // set exit state game_state = GAME_STATE_SHUTDOWN; } // end if } // end if /////////////////////////////////////////////////////////////// else if (game_state == GAME_STATE_SHUTDOWN) { // in this state shut everything down and release resources DD_Shutdown(); // switch to exit state game_state = GAME_STATE_EXIT; } // end if // return success return(1); } // end Game_Main