Ejemplo n.º 1
0
void Game::Step()
{
	// 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 int id = -1;

	static mat4 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 int z_buffer_mode  = -1;
	static int display_mode   = 1;
	static int bsp_backface_mode   = 1;

	char work_string[256]; // temp string

	int index; // looping var

	bspeditor::Context* context = bspeditor::Context::Instance();

	Graphics& graphics = Modules::GetGraphics();

	DIMOUSESTATE& mouse_state = t3d::Modules::GetInput().MouseState();

	// is user in editor mode or viewing mode?
	switch(context->editor_state)
	{
	case EDITOR_STATE_INIT: /////////////////////////////////////////////////
		{

			// now transition to edit mode
			context->editor_state = EDITOR_STATE_EDIT;
		} break;

	case EDITOR_STATE_EDIT: /////////////////////////////////////////////////
		{
			// start the timing clock
			Modules::GetTimer().Start_Clock();

			// clear the drawing surface 
			//DDraw_Fill_Surface(graphics.GetBackSurface(), 0);
			graphics.GetBackSurface()->Blt(NULL, gadgets->background->GetImage(), NULL, DDBLT_WAIT, NULL);

			// read keyboard and other devices here
			Modules::GetInput().ReadKeyboard();
			//DInput_Read_Mouse();

			// game logic here...

			// find nearest line 
			context->nearest_line = task->DeleteLine(mouse_state.lX, mouse_state.lY,0);

			// is user trying to press left button?
			if (mouse_state.rgbButtons[0] || mouse_state.rgbButtons[2])// && mouse_debounce[0] == 0)
			{
				// determine area click is occuring in
				if (mouse_state.lX > INTERFACE_MIN_X && mouse_state.lX < INTERFACE_MAX_X && 
					mouse_state.lY > INTERFACE_MIN_Y && mouse_state.lY < INTERFACE_MAX_Y)
				{ 
					// check for gadget
					if ((id = gadgets->Process(mouse_state.lX, mouse_state.lY, mouse_state.rgbButtons)) >= 0)
					{
						// play a sound first
						//DSound_Play(beep0_sound_id);

						// process clicks
						switch(id)
						{
						case GADGET_ID_SEGMENT_MODE_ID:
							{
								task->action = ACTION_STARTING_LINE;

							} break;

						case GADGET_ID_POLYLINE_MODE_ID:
							{
								task->action = ACTION_STARTING_POLYLINE; 
							} break;

						case GADGET_ID_DELETE_MODE_ID: 
							{
								task->action = ACTION_DELETE_LINE;
							} break;

						case GADGET_ID_CLEAR_ALL_ID:
							{
								// reset everything
								context->Reset();

							} break;

						case GADGET_ID_FLOOR_MODE_ID:
							{
								task->action = ACTION_FLOOR_MODE;
							} break;

						case GADGET_ID_WALL_TEXTURE_DEC:
							{
								if (--context->texture_index_wall < -1)
									context->texture_index_wall = -1;

							} break;

						case GADGET_ID_WALL_TEXTURE_INC:
							{
								if (++context->texture_index_wall >= NUM_TEXTURES)
									context->texture_index_wall = NUM_TEXTURES-1;

							} break;

						case GADGET_ID_WALL_HEIGHT_DEC:
							{
								if ((context->wall_height-=8) < 0)
									context->wall_height = 0;

							} break;

						case GADGET_ID_WALL_HEIGHT_INC:
							{
								context->wall_height+=8;

							} break;

						case GADGET_ID_FLOOR_TEXTURE_DEC:
							{
								if (--context->texture_index_floor < -1)
									context->texture_index_floor = -1;

							} break;

						case GADGET_ID_FLOOR_TEXTURE_INC:
							{

								if (++context->texture_index_floor >= NUM_TEXTURES)
									context->texture_index_floor = NUM_TEXTURES-1;

							} break;

						default: break;

						} // end switch

					} // end if
					else
					{

					} // end else

				} // end if interface

				// test for bsp area
				if (mouse_state.lX > BSP_MIN_X && mouse_state.lX < BSP_MAX_X && 
					mouse_state.lY > BSP_MIN_Y && mouse_state.lY < BSP_MAX_Y)
				{
					// process bsp editor area click

					// test if this is starting point or endpoint
					if (task->action == ACTION_STARTING_LINE)
					{
						// set starting field, note the offsets to center the
						// starting point in middle of cross hairs

						if (!context->snap_to_grid)
						{
							context->lines[context->total_lines].p0.x = mouse_state.lX;
							context->lines[context->total_lines].p0.y = mouse_state.lY;
						} // end if
						else
						{
							context->lines[context->total_lines].p0.x = BSP_GRID_SIZE * (int)(0.5+(float)mouse_state.lX / (float)BSP_GRID_SIZE);
							context->lines[context->total_lines].p0.y = BSP_GRID_SIZE * (int)(0.5+(float)mouse_state.lY / (float)BSP_GRID_SIZE);
						} // end if


						// remember starting line to close contour
						context->starting_line = context->total_lines;

						// set point type to ending point
						task->action = ACTION_ENDING_LINE;

						// wait for mouse button release
						// Wait_For_Mouse_Up();

					} // end if start of wall
					else
						if (task->action == ACTION_ENDING_LINE)
						{
							// check for normal left mouse click
							if (mouse_state.rgbButtons[0])
							{
								// must be the end of a wall or ending point
								if (!context->snap_to_grid)
								{
									context->lines[context->total_lines].p1.x = mouse_state.lX;
									context->lines[context->total_lines].p1.y = mouse_state.lY;
								} // end if
								else
								{
									context->lines[context->total_lines].p1.x = BSP_GRID_SIZE * (int)(0.5+(float)mouse_state.lX / (float)BSP_GRID_SIZE);
									context->lines[context->total_lines].p1.y = BSP_GRID_SIZE * (int)(0.5+(float)mouse_state.lY / (float)BSP_GRID_SIZE);
								} // end if

								// set texture id
								context->lines[context->total_lines].texture_id = context->texture_index_wall;

								// set height
								context->lines[context->total_lines].height = context->wall_height;

								// set attributes
								context->lines[context->total_lines].attr   = context->poly_attr;

								// set color
								context->lines[context->total_lines].color  = context->poly_color;

								// set task->action back to starting point
								task->action = ACTION_STARTING_LINE;

								// advance number of context->lines
								if (++context->total_lines >= MAX_LINES)
									context->total_lines = MAX_LINES - 1;

								// wait for mouse button release
								// Wait_For_Mouse_Up();
							} // end if
							else
								// check for right mouse click trying to close contour
								if (mouse_state.rgbButtons[2])
								{
									// reset, user wants to restart segment
									task->action = ACTION_STARTING_LINE;
								} // end if

						} // end else if
						else
							// test if this is starting point or endpoint
							if (task->action == ACTION_STARTING_POLYLINE)
							{
								// set starting field, note the offsets to center the
								// starting point in middle of cross hairs

								if (!context->snap_to_grid)
								{
									context->lines[context->total_lines].p0.x = mouse_state.lX;
									context->lines[context->total_lines].p0.y = mouse_state.lY;
								} // end if
								else
								{
									context->lines[context->total_lines].p0.x = BSP_GRID_SIZE * (int)(0.5+(float)mouse_state.lX / (float)BSP_GRID_SIZE);
									context->lines[context->total_lines].p0.y = BSP_GRID_SIZE * (int)(0.5+(float)mouse_state.lY / (float)BSP_GRID_SIZE);
								} // end if

								// remember starting line to close contour
								context->starting_line = context->total_lines;

								// set point type to ending point
								task->action = ACTION_ADDING_POLYLINE;

								// wait for mouse button release
								// Wait_For_Mouse_Up();

							} // end if start of wall
							else
								if (task->action == ACTION_ADDING_POLYLINE)
								{
									// check for normal left mouse click
									if (mouse_state.rgbButtons[0])
									{
										// must be the end of a wall or ending point
										if (!context->snap_to_grid)
										{
											context->lines[context->total_lines].p1.x = mouse_state.lX;
											context->lines[context->total_lines].p1.y = mouse_state.lY;
										} // end if
										else
										{
											context->lines[context->total_lines].p1.x = BSP_GRID_SIZE * (int)(0.5+(float)mouse_state.lX / (float)BSP_GRID_SIZE);
											context->lines[context->total_lines].p1.y = BSP_GRID_SIZE * (int)(0.5+(float)mouse_state.lY / (float)BSP_GRID_SIZE);
										} // end if

										// set texture id
										context->lines[context->total_lines].texture_id = context->texture_index_wall;

										// set height
										context->lines[context->total_lines].height = context->wall_height;

										// set attributes
										context->lines[context->total_lines].attr   = context->poly_attr;

										// set color
										context->lines[context->total_lines].color  = context->poly_color;

										// set task->action back to starting point
										task->action = ACTION_ADDING_POLYLINE;

										// advance number of context->lines
										if (++context->total_lines >= MAX_LINES)
											context->total_lines = MAX_LINES - 1;

										// set start point as last endpoint
										context->lines[context->total_lines].p0.x = context->lines[context->total_lines-1].p1.x;
										context->lines[context->total_lines].p0.y = context->lines[context->total_lines-1].p1.y;

										// wait for mouse button release
										// Wait_For_Mouse_Up();
									} // end if
									else
										// check for right mouse click trying to close contour
										if (mouse_state.rgbButtons[2])
										{
											// end the polyline
											task->action = ACTION_STARTING_POLYLINE;
											// Wait_For_Mouse_Up();
										} // end if

								} // end else if
								else
									if (task->action==ACTION_DELETE_LINE)
									{
										// try and delete the line nearest selected point
										task->DeleteLine(mouse_state.lX, mouse_state.lY,1);

										// wait for mouse release
										// Wait_For_Mouse_Up();

									} // end if
									else
										if (task->action==ACTION_FLOOR_MODE)
										{
											// compute cell that mouse is on
											int cell_x = (mouse_state.lX - BSP_MIN_X) / BSP_GRID_SIZE;
											int cell_y = (mouse_state.lY - BSP_MIN_Y) / BSP_GRID_SIZE;

											// drawing or erasing
											if (mouse_state.rgbButtons[0])
											{
												// set texture id
												context->floors[cell_y][cell_x] = context->texture_index_floor;
											} // end if
											else
												if (mouse_state.rgbButtons[2])
												{
													// set texture id
													context->floors[cell_y][cell_x] = -1;
												} // end if

										} // end if

				} // end if in bsp area

				// force button debounce
				if (mouse_state.rgbButtons[0])
					mouse_state.rgbButtons[0] = 0;

				if (mouse_state.rgbButtons[2])
					mouse_state.rgbButtons[2] = 0;

				//mouse_debounce[0] = 1;

			} // end if

			// debounce mouse
			//if (!mouse_state.rgbButtons[0] && mouse_debounce[0] == 1)
			//   mouse_debounce[0] = 0;

			// draw the floors
			if (context->view_floors == 1)
				task->DrawFloors(graphics.GetBackSurface());

			// lock the back buffer
			graphics.LockBackSurface();

			// draw the context->lines
			if (context->view_walls == 1)
				task->DrawLines(graphics.GetBackBuffer(), graphics.GetBackLinePitch());

			// draw the grid
			if (context->view_grid==1)
				task->DrawGrid(graphics.GetBackBuffer(), graphics.GetBackLinePitch(), _RGB32BIT(255,255,255,255), BSP_MIN_X, BSP_MIN_Y,
				BSP_GRID_SIZE, BSP_GRID_SIZE,
				BSP_CELLS_X,BSP_CELLS_Y);

			// unlock the back buffer
			graphics.UnlockBackSurface();

			// draw all the buttons
			gadgets->Draw(graphics.GetBackSurface());

			// draw the textures previews
			if (context->texture_index_wall >= 0)
			{
				// selected texture
				context->textures->SetPosition(665, 302-55);
				context->textures->SetCurrFrame(context->texture_index_wall);
				context->textures->DrawScaled(64,64,graphics.GetBackSurface());

				// get the line that mouse is closest to
				context->nearest_line = task->DeleteLine(mouse_state.lX, mouse_state.lY,0);

				// draw texture that is applied to line in secondary preview window
				if (context->nearest_line >= 0)
				{
					context->textures->SetPosition(736, 247);
					context->textures->SetCurrFrame(context->lines[context->nearest_line].texture_id);
					context->textures->DrawScaled(32,32,graphics.GetBackSurface());

					// now draw height of line
					sprintf(buffer,"%d",context->lines[context->nearest_line].height);
					graphics.DrawTextGDI(buffer, 750,188,RGB(0,255,0),graphics.GetBackSurface());      

				} // end if

			} // end if 

			// draw the floor texture preview
			if (context->texture_index_floor >= 0)
			{
				context->textures->SetPosition(665, 453);
				context->textures->SetCurrFrame(context->texture_index_floor);
				context->textures->DrawScaled(64,64,graphics.GetBackSurface());
			} // end if

			// draw the wall index
			if (context->texture_index_wall >= 0)
			{
				sprintf(buffer,"%d",context->texture_index_wall);
				graphics.DrawTextGDI(buffer, 738,336-56,RGB(0,255,0),graphics.GetBackSurface());
			} // end if
			else
			{
				graphics.DrawTextGDI("None", 738,336,RGB(0,255,0),graphics.GetBackSurface());
			} // end 

			// wall height
			sprintf(buffer,"%d",context->wall_height);
			graphics.DrawTextGDI(buffer, 688, 188,RGB(0,255,0),graphics.GetBackSurface());

			// texture index for floors
			if (context->texture_index_floor >= 0)
			{
				sprintf(buffer,"%d",context->texture_index_floor);
				graphics.DrawTextGDI(buffer, 738,488,RGB(0,255,0),graphics.GetBackSurface());
			} // end if
			else
			{
				graphics.DrawTextGDI("None", 738,488,RGB(0,255,0),graphics.GetBackSurface());
			} // end 

			// display stats
			sprintf(buffer,"WorldPos=(%d,%d). Num Walls=%d. Num Floor Tiles=%d. Total Polys=%d.",
				mouse_state.lX, mouse_state.lY, context->total_lines+1, context->num_floor_tiles, 2*(context->total_lines+1+context->num_floor_tiles));

			graphics.DrawTextGDI(buffer, 8,WINDOW_HEIGHT - 18,RGB(0,255,0),graphics.GetBackSurface());

			// flip the surfaces
			graphics.Flip(main_window_handle);

			// sync to 30ish fps
			Sleep(10);

#if 0
			// check of user is trying to exit
			if (KEY_DOWN(VK_ESCAPE) || Modules::GetInput().KeyboardState()[DIK_ESCAPE])
			{
				PostMessage(main_window_handle, WM_DESTROY,0,0);
			} // end if
#endif

		} break;

	case EDITOR_STATE_VIEW: ///////////////////////////////////////////////
		{
			// start the timing clock
			Modules::GetTimer().Start_Clock();

			// clear the drawing surface 
			graphics.FillSurface(graphics.GetBackSurface(), 0);

			// read keyboard and other devices here
			Modules::GetInput().ReadKeyboard();

			// game logic here...

			// modes and lights

			// wireframe mode
			if (Modules::GetInput().KeyboardState()[DIK_W]) 
			{
				// toggle wireframe mode
				if (++wireframe_mode > 1)
					wireframe_mode=0;
				Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
			} // end if

			// backface removal
			if (Modules::GetInput().KeyboardState()[DIK_B])
			{
				// toggle backface removal
				backface_mode = -backface_mode;
				Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
			} // end if


			// lighting
			if (Modules::GetInput().KeyboardState()[DIK_L])
			{
				// toggle lighting engine completely
				lighting_mode = -lighting_mode;
				Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
			} // end if

			LightsMgr& lights = Modules::GetGraphics().GetLights();

			// toggle ambient light
			if (Modules::GetInput().KeyboardState()[DIK_A])
			{
				// toggle ambient light
				if (lights[AMBIENT_LIGHT_INDEX].state == LIGHT_STATE_ON)
					lights[AMBIENT_LIGHT_INDEX].state = LIGHT_STATE_OFF;
				else
					lights[AMBIENT_LIGHT_INDEX].state = LIGHT_STATE_ON;

				Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
			} // end if

			// toggle point light
			if (Modules::GetInput().KeyboardState()[DIK_P])
			{
				// toggle point light
				if (lights[POINT_LIGHT_INDEX].state == LIGHT_STATE_ON)
					lights[POINT_LIGHT_INDEX].state = LIGHT_STATE_OFF;
				else
					lights[POINT_LIGHT_INDEX].state = LIGHT_STATE_ON;

				// toggle point light
				if (lights[POINT_LIGHT2_INDEX].state == LIGHT_STATE_ON)
					lights[POINT_LIGHT2_INDEX].state = LIGHT_STATE_OFF;
				else
					lights[POINT_LIGHT2_INDEX].state = LIGHT_STATE_ON;

				Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
			} // end if


			// toggle infinite light
			if (Modules::GetInput().KeyboardState()[DIK_I])
			{
				// toggle ambient light
				if (lights[INFINITE_LIGHT_INDEX].state == LIGHT_STATE_ON)
					lights[INFINITE_LIGHT_INDEX].state = LIGHT_STATE_OFF;
				else
					lights[INFINITE_LIGHT_INDEX].state = LIGHT_STATE_ON;

				Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
			} // end if

			// help menu
			if (Modules::GetInput().KeyboardState()[DIK_H])
			{
				// toggle help menu 
				help_mode = -help_mode;
				Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
			} // end if

			// z-sorting
			if (Modules::GetInput().KeyboardState()[DIK_S])
			{
				// toggle z sorting
				zsort_mode = -zsort_mode;
				Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
			} // end if

			// z buffer
			if (Modules::GetInput().KeyboardState()[DIK_Z])
			{
				// toggle z buffer
				z_buffer_mode = -z_buffer_mode;
				Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
			} // end if

			// forward/backward
			if (Modules::GetInput().KeyboardState()[DIK_UP])
			{
				// move forward
				if ( (context->cam_speed+=2) > MAX_SPEED) context->cam_speed = MAX_SPEED;
			} // end if
			else if (Modules::GetInput().KeyboardState()[DIK_DOWN])
			{
				// move backward
				if ((context->cam_speed-=2) < -MAX_SPEED) context->cam_speed = -MAX_SPEED;
			} // end if

			// rotate around y axis or yaw
			if (Modules::GetInput().KeyboardState()[DIK_RIGHT])
			{
				context->cam->DirRef().y+=10;

				// scroll the background
				background_bmp->Scroll(-10);
			} // end if

			if (Modules::GetInput().KeyboardState()[DIK_LEFT])
			{
				context->cam->DirRef().y-=10;

				// scroll the background
				background_bmp->Scroll(10);
			} // end if

			// ambient scrolling 
			static int scroll_counter = 0;
			if (++scroll_counter > 5)
			{
				// scroll the background
				background_bmp->Scroll(1);

				// reset scroll counter
				scroll_counter = 0;
			} // end if

			// move point light source in ellipse around game world
			lights[POINT_LIGHT_INDEX].pos.x = 1000*cos(DEG_TO_RAD(plight_ang));
			lights[POINT_LIGHT_INDEX].pos.y = 100;
			lights[POINT_LIGHT_INDEX].pos.z = 1000*sin(DEG_TO_RAD(plight_ang));

			// move point light source in ellipse around game world
			lights[POINT_LIGHT2_INDEX].pos.x = 500*cos(DEG_TO_RAD(-2*plight_ang));
			lights[POINT_LIGHT2_INDEX].pos.y = 200;
			lights[POINT_LIGHT2_INDEX].pos.z = 1000*sin(DEG_TO_RAD(-2*plight_ang));

			if ((plight_ang+=3) > 360)
				plight_ang = 0;

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

			// move camera
			context->cam->PosRef().x += context->cam_speed*sin(DEG_TO_RAD(context->cam->Dir().y));
			context->cam->PosRef().z += context->cam_speed*cos(DEG_TO_RAD(context->cam->Dir().y));

			// generate camera matrix
			context->cam->BuildMatrixEuler(CAM_ROT_SEQ_ZYX);

			// build the camera vector rotation matrix ////////////////////////////////
			mrot = mat4::RotateX(context->cam->Dir().x) * 
				   mat4::RotateX(context->cam->Dir().y) *
				   mat4::RotateX(context->cam->Dir().z);

			// transform the (0,0,1) vector and store it in the cam.n vector, this is now the 
			// view direction vector
			context->cam->_n = mrot * vec4(0,0,1,1);

			// normalize the viewing vector
			context->cam->_n.Normalize();

			// reset the render list
			list->Reset();

			// render the floors into polylist first

			// reset the object (this only matters for backface and object removal)
			RenderObject* obj_scene = bspeditor::Context::Instance()->obj_scene;

			obj_scene->Reset();

			// set position of floor
			obj_scene->SetWorldPos(0, 0, 0);

			// attempt to cull object   
			if (!obj_scene->Cull(*context->cam, CULL_OBJECT_XYZ_PLANES))
			{
				// create an identity to work with
				mrot = mat4::Identity();

				// rotate the local coords of the object
				obj_scene->Transform(mrot, TRANSFORM_LOCAL_TO_TRANS,1);

				// perform world transform
				obj_scene->ModelToWorld(TRANSFORM_TRANS_ONLY);

				// insert the object into render list
				list->Insert(*obj_scene,0);
			} // end if

			// reset the object (this only matters for backface and object removal)
			obj_scene->Reset();

			// set position of ceiling
			obj_scene->SetWorldPos(0, context->ceiling_height, 0);

			// attempt to cull object   
			if (!obj_scene->Cull(*context->cam, CULL_OBJECT_XYZ_PLANES))
			{
				// create an identity to work with
				mrot = mat4::Identity();

				// rotate the local coords of the object
				obj_scene->Transform(mrot, TRANSFORM_LOCAL_TO_TRANS,1);

				// perform world transform
				obj_scene->ModelToWorld(TRANSFORM_TRANS_ONLY);

				// insert the object into render list
				list->Insert(*obj_scene,0);
			} // end if

			int polycount = list->GetNumPolys();

			// insert the bsp into rendering list without culling
			context->bspfile->bsp_root->InsertionTraversal(*list, *context->cam, 1);

			// compute total number of polys inserted into list
			polycount = list->GetNumPolys() - polycount;

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

			// remove backfaces
			if (backface_mode==1)
				list->RemoveBackfaces(*context->cam);

			// apply world to camera transform
			list->WorldToCamera(*context->cam);

			// clip the polygons themselves now
			list->ClipPolys(*context->cam, ((x_clip_mode == 1) ? CLIP_POLY_X_PLANE : 0) | 
										   ((y_clip_mode == 1) ? CLIP_POLY_Y_PLANE : 0) | 
										   ((z_clip_mode == 1) ? CLIP_POLY_Z_PLANE : 0) );

			// light scene all at once 
			if (lighting_mode==1)
			{
				lights.Transform(context->cam->CameraMat(), TRANSFORM_LOCAL_TO_TRANS);
				list->LightWorld32(*context->cam);
			} // end if

			// sort the polygon list (hurry up!)
			if (zsort_mode == 1)
				list->Sort(SORT_POLYLIST_AVGZ);

			// apply camera to perspective transformation
			list->CameraToPerspective(*context->cam);

			// apply screen transform
			list->PerspectiveToScreen(*context->cam);

			// lock the back buffer
			graphics.LockBackSurface();

			// draw background
			background_bmp->Draw32(graphics.GetBackBuffer(), graphics.GetBackLinePitch(), 0);

			// reset number of polys rendered
			debug_polys_rendered_per_frame = 0;

			// render the renderinglist
			if (wireframe_mode  == 0)
				list->DrawWire32(graphics.GetBackBuffer(), graphics.GetBackLinePitch());
			else if (wireframe_mode  == 1)
			{
				RenderContext rc;

				// is z buffering enabled
				if (z_buffer_mode == 1)
				{
					// set up rendering context for 1/z buffer
					rc.attr         = RENDER_ATTR_NOBUFFER  
									//| RENDER_ATTR_ALPHA  
									//| RENDER_ATTR_MIPMAP  
									//| RENDER_ATTR_BILERP
									| RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE;


				} // end if
				else
				{    
					// set up rendering context for no zbuffer
					rc.attr         = RENDER_ATTR_NOBUFFER  
									//| RENDER_ATTR_ALPHA  
									//| RENDER_ATTR_MIPMAP  
									// | RENDER_ATTR_BILERP
									| RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE;
				} // end else

				// if z abuffer or 1/z buffer is being used then clear z buffer    
				if (rc.attr & RENDER_ATTR_ZBUFFER || rc.attr & RENDER_ATTR_WRITETHRUZBUFFER)
				{
					// clear the z buffer
					zbuffer->Clear(32000 << FIXP16_SHIFT);
				} // end if
				else if (rc.attr & RENDER_ATTR_INVZBUFFER)
				{
					// clear the 1/z buffer
					zbuffer->Clear(0 << FIXP16_SHIFT);
				} // end if

				rc.video_buffer   = graphics.GetBackBuffer();
				rc.lpitch         = graphics.GetBackLinePitch();
				rc.mip_dist       = 3500;
				rc.zbuffer        = (unsigned char*)zbuffer->Buffer();
				rc.zpitch         = WINDOW_WIDTH*4;
				rc.texture_dist   = 0;
				rc.alpha_override = -1;

				// render scene
				list->DrawContext(rc);
			} // end if

			// unlock the back buffer
			graphics.UnlockBackSurface();

			sprintf(work_string,"Lighting [%s]: Ambient=%d, Infinite=%d, BckFceRM [%s], Zsort [%s], Zbuffer [%s] vdir=[%3.2f,%3.2f,%3.2f]", 
				((lighting_mode == 1) ? "ON" : "OFF"),
				lights[AMBIENT_LIGHT_INDEX].state,
				lights[INFINITE_LIGHT_INDEX].state, 
				((backface_mode == 1) ? "ON" : "OFF"),
				((zsort_mode == 1) ? "ON" : "OFF"),
				((z_buffer_mode == 1) ? "ON" : "OFF"), context->cam->Normal().x, context->cam->Normal().y, context->cam->Normal().z);

			graphics.DrawTextGDI(work_string, 0, WINDOW_HEIGHT-34-16, RGB(0,255,0), graphics.GetBackSurface());

			// draw instructions
			graphics.DrawTextGDI("Press ESC to return to editor mode. Press <H> for Help.", 0, 0, RGB(0,255,0), graphics.GetBackSurface());

			// should we display help
			int text_y = 16;
			if (help_mode==1)
			{
				// draw help menu
				graphics.DrawTextGDI("<A>..............Toggle ambient light source.", 0, text_y+=12, RGB(255,255,255), graphics.GetBackSurface());
				graphics.DrawTextGDI("<I>..............Toggle infinite light source.", 0, text_y+=12, RGB(255,255,255), graphics.GetBackSurface());
				graphics.DrawTextGDI("<P>..............Toggle point lights.", 0, text_y+=12, RGB(255,255,255), graphics.GetBackSurface());
				graphics.DrawTextGDI("<B>..............Toggle backface removal.", 0, text_y+=12, RGB(255,255,255), graphics.GetBackSurface());
				graphics.DrawTextGDI("<S>..............Toggle Z sorting.", 0, text_y+=12, RGB(255,255,255), graphics.GetBackSurface());
				graphics.DrawTextGDI("<Z>..............Toggle Z buffering.", 0, text_y+=12, RGB(255,255,255), graphics.GetBackSurface());
				graphics.DrawTextGDI("<Z>..............Toggle Wireframe mode.", 0, text_y+=12, RGB(255,255,255), graphics.GetBackSurface());
				graphics.DrawTextGDI("<H>..............Toggle Help.", 0, text_y+=12, RGB(255,255,255), graphics.GetBackSurface());
				graphics.DrawTextGDI("<ESC>............Exit demo.", 0, text_y+=12, RGB(255,255,255), graphics.GetBackSurface());

			} // end help

			sprintf(work_string,"Polys Rendered: %d, Polys lit: %d, Polys Inserted from BSP: %d", debug_polys_rendered_per_frame, debug_polys_lit_per_frame, polycount);
			graphics.DrawTextGDI(work_string, 0, WINDOW_HEIGHT-34-16-16, RGB(0,255,0), graphics.GetBackSurface());

			sprintf(work_string,"CAM [%5.2f, %5.2f, %5.2f]",  context->cam->Pos().x, context->cam->Pos().y, context->cam->Pos().z);

			graphics.DrawTextGDI(work_string, 0, WINDOW_HEIGHT-34-16-16-16, RGB(0,255,0), graphics.GetBackSurface());

			// flip the surfaces
			graphics.Flip(main_window_handle);

			// sync to 30ish fps
			Modules::GetTimer().Wait_Clock(30);

			// check of user is trying to exit
			if (KEY_DOWN(VK_ESCAPE) || Modules::GetInput().KeyboardState()[DIK_ESCAPE])
			{
				// switch game state back to editor more
				context->editor_state = EDITOR_STATE_EDIT;
			} // end if

		} break;     

	default: break;

	} // end switch

}
Ejemplo n.º 2
0
int WINAPI WinMain(	HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow)
{

	WNDCLASS winclass;	// this will hold the class created
	HWND	 hwnd;		// generic window handle
	MSG		 msg;		// generic message
	HDC      hdc;       // generic dc
	RECT rect;
	float velocity[15];
	int ball_y[15],
		ball_x[15],
		iEndPos[15],
		index=0;
	LARGE_INTEGER a;
	__int64 b=0,c=0, diffrenceC_B=0;

	//fill in the window class stucture
	winclass.style			= CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
	winclass.lpfnWndProc	= WindowProc;
	winclass.cbClsExtra		= 0;
	winclass.cbWndExtra		= 0;
	winclass.hInstance		= hinstance;
	winclass.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
	winclass.hCursor		= LoadCursor(NULL, IDC_ARROW);
	winclass.hbrBackground	= (HBRUSH) GetStockObject(BLACK_BRUSH);
	winclass.lpszMenuName	= NULL; //MAKEINTRESOURCE(IDR_MENU1);
	winclass.lpszClassName	= WINDOW_CLASS_NAME;

	// register the window class
	if (!RegisterClass(&winclass))
		return(0);

	// create the window
	if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class
							  "Bouncing on the desktop",	 // title
							  WS_OVERLAPPEDWINDOW | WS_VISIBLE,
						 	  0,600,	   // x,y
							  WINDOW_WIDTH,  // width
						      WINDOW_HEIGHT, // height
							  NULL,	   // handle to parent 
							  NULL,	   // handle to menu
							  hinstance,// instance
							  NULL)))	// creation parms
	{
		MessageBox(hwnd, "Window Could not be Created", NULL, MB_OK); //NULL is default for Error
		return(0);
	}

	// save the window handle and instance in a global
	main_window_handle = hwnd;
	main_instance      = hinstance;

	for(index=0; index<=14; index++) //start balls at random positions, set velocity = 0
	{
		ball_y[index]= -10;
		ball_x[index]= rand()%1000;
		iEndPos[index]= rand()%900;
		velocity[index]= 0;
	}
	
	index=0; //reset index

	// enter main event loop
	while(1)
	{
		//check messages
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{ 
			// test if this is a quit message
			if (msg.message == WM_QUIT)
				break;
	
			// translate any accelerator keys
			TranslateMessage(&msg);

			// send the message to the window proc
			DispatchMessage(&msg);
		} // end if
		if(KEY_DOWN(VK_ESCAPE)) //if hit the Esc key quit the program
			PostQuitMessage(0);
		
		if(!QueryPerformanceCounter(&a))
		{
			MessageBox(hwnd, "Error on QueryPerformanceCounter()", NULL, MB_OK); //NULL is default for Error
			return(0);
		}
		else
		{
			b = c = a.QuadPart;
		}	

	   	hdc= GetDC(hwnd);
		
		//--------Begin Text Info---------------------
		SetBkMode(hdc, TRANSPARENT); //set background color
		//first create the eraser string for variable text
		SetTextColor(hdc,RGB(0,255,0)); //set text color black
		TextOut(hdc, 30, 60, buffer, strlen(buffer)); //print text
		TextOut(hdc, 30, 75, buffer2, strlen(buffer2)); //print text
		
		//unvarieing text
		SetTextColor(hdc,RGB(0,255,0)); //set text color black
		TextOut(hdc, 30, 15,"Keys 0-6 set the delay time", strlen("Keys 0-6 set the delay time")); //print text
		TextOut(hdc, 30, 30,"Left and right arrows change gravity", strlen("Left and right arrows change gravity")); //print text
		TextOut(hdc, 30, 45,"Up and down arrows change friction", strlen("Up and down arrows change friction")); //print text
		TextOut(hdc, 30, 90,"S key starts over", strlen("S key starts over")); //print text
		
		//variable text
		sprintf(buffer,"Friction= ", friction);
		sprintf(buffer2,"Gravity= ", gravity);
		TextOut(hdc, 30, 60, buffer, strlen(buffer)); //print text
		TextOut(hdc, 30, 75, buffer2, strlen(buffer2)); //print text
		//--------End Text Info-------------------------

		ReleaseDC(hwnd, hdc);
		
		
		hdc= GetWindowDC(GetDesktopWindow());
		
		//-------------Erasing ball----------------
		//fill in rect struct for erasing ball
		rect.left = ball_x[index] - BALL_RADIUS5;
		rect.right = ball_x[index] + BALL_RADIUS5;
		rect.top = ball_y[index] - BALL_RADIUS5;
		rect.bottom = ball_y[index] + BALL_RADIUS5;
		
		//Draw erasing ball in the old position
		SelectObject(hdc, red_pen5);
		SelectObject(hdc, red_brush5);
		Ellipse(hdc,rect.left, rect.top, rect.right, rect.bottom);
		
		//------------End Erasing ball----------------

		//-------------Test to see whats going on-----------
		//if the ball hits the ground, bounce back. The reason its here is because the erasing ball
		//needs the old position to erase the drawing ball.
		if(ball_y[index] >= iEndPos[index]) 
		{
			//velocity[index] = -velocity[index];
			ball_y[index] = iEndPos[index]; //need to rest the y position because of >=, the y could be > 370
		}
		
		//allows user to restart balls in a new possition if they want to
		//the reason its put here is so that if the user decides to restart, the erasing ball
		//will erase the drawing ball, and won't leave ball marks all over.
		if(startOver) 
		{
			for(index=0; index<=14; index++) //start balls at random positions, set velocity = 0
			{
				ball_y[index]= -10;
				ball_x[index]= rand()%2000;
				iEndPos[index]= rand()%900;
				velocity[index]= 0;
			}//end for loop on index
			
			startOver= false; //reset startOver back to false 
		}//end if on startOver

		//--------------End Test to see whats going on
		
		//-------------- Move the ball--------------
		velocity[index]+= gravity* ( (diffrenceC_B*0.0009)*0.02);
		velocity[index]*= friction;
		ball_y[index]+= (int) velocity[index];
		//-------------End Move the ball------------

		//---------------Draw the Ball------------------
		//Redraw the ball in its new position
	
		//fill in rect struct for drawing ball
		//ball 5
		rect.left = ball_x[index] - BALL_RADIUS5;
		rect.right = ball_x[index] + BALL_RADIUS5;
		rect.top = ball_y [index] - BALL_RADIUS5;
		rect.bottom = ball_y[index] + BALL_RADIUS5;
		
		//Draw the ball in its new spot
		SelectObject(hdc, red_pen5);
		SelectObject(hdc, red_brush5);
		Ellipse(hdc,rect.left, rect.top, rect.right, rect.bottom);
		//end ball 5

		//ball 4
		rect.left = ball_x[index] - BALL_RADIUS4;
		rect.right = ball_x[index] + BALL_RADIUS4;
		rect.top = ball_y [index] - BALL_RADIUS4;
		rect.bottom = ball_y[index] + BALL_RADIUS4;
		
		//Draw the ball in its new spot
		SelectObject(hdc, red_pen4);
		SelectObject(hdc, red_brush4);
		Ellipse(hdc,rect.left, rect.top, rect.right, rect.bottom);
		//end ball 4

		//ball 3
		rect.left = ball_x[index] - BALL_RADIUS3;
		rect.right = ball_x[index] + BALL_RADIUS3;
		rect.top = ball_y [index] - BALL_RADIUS3;
		rect.bottom = ball_y[index] + BALL_RADIUS3;
		
		//Draw the ball in its new spot
		SelectObject(hdc, red_pen3);
		SelectObject(hdc, red_brush3);
		Ellipse(hdc,rect.left, rect.top, rect.right, rect.bottom);
		//end ball 3

		//ball 2
		rect.left = ball_x[index] - BALL_RADIUS2;
		rect.right = ball_x[index] + BALL_RADIUS2;
		rect.top = ball_y [index] - BALL_RADIUS2;
		rect.bottom = ball_y[index] + BALL_RADIUS2;
		
		//Draw the ball in its new spot
		SelectObject(hdc, red_pen2);
		SelectObject(hdc, red_brush2);
		Ellipse(hdc,rect.left, rect.top, rect.right, rect.bottom);
		//end ball 2

		//ball 1
		rect.left = ball_x[index] - BALL_RADIUS1;
		rect.right = ball_x[index] + BALL_RADIUS1;
		rect.top = ball_y [index] - BALL_RADIUS1;
		rect.bottom = ball_y[index] + BALL_RADIUS1;
		
		//Draw the ball in its new spot
		SelectObject(hdc, red_pen1);
		SelectObject(hdc, red_brush1);
		Ellipse(hdc,rect.left, rect.top, rect.right, rect.bottom);
		//end ball 1
		//----------------End draw the ball---------------s

		//if index increments to 14 (or last ball) start drawing from the
		//begining again over again (meaning draw ball b0, b1,...b14 start back at b1)
		index++;
		if(index >=14)
			index=0;
		
		if(!QueryPerformanceCounter(&a))
		{
			MessageBox(hwnd, "Error on QueryPerformanceCounter()", NULL, MB_OK); //NULL is default for Error
			return(0);
		}
		else
		{
			c = a.QuadPart;
			diffrenceC_B= c-b;
		}	
		
		//slow things down a bit
		//Sleep(delay);
				
		//Release device context
		ReleaseDC(GetDesktopWindow(), hdc);
		
	} // end while

	

	// return to Windows like this
	return(msg.wParam);

} // end WinMain
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
Ejemplo n.º 5
0
// --------------------------------------------------------------------------
// main(Number of arguments, Argument values)
// Description  : This is the entry point of the program.
// Return value : SUCCESS:0  ERROR:-1
// --------------------------------------------------------------------------
int main(int argc, char **argv)
{
    // AR.Drone class
    ARDrone ardrone;

    // Initialize
    if (!ardrone.open()) {
        printf("Failed to initialize.\n");
        return -1;
    }

    // Battery
    int battery = ardrone.getBatteryPercentage();
    printf("ardrone.battery = %d [%%]\n", battery);

    // Instructions
    printf("***************************************\n");
    printf("*       CV Drone sample program       *\n");
    printf("*           - Haw To Play -           *\n");
    printf("***************************************\n");
    printf("*                                     *\n");
    printf("* - Controls -                        *\n");
    printf("*    'Space' -- Takeoff/Landing       *\n");
    printf("*    'Up'    -- Move forward          *\n");
    printf("*    'Down'  -- Move backward         *\n");
    printf("*    'Left'  -- Turn left             *\n");
    printf("*    'Right' -- Turn right            *\n");
    printf("*    'Shift+Up'    -- Move upward     *\n");
    printf("*    'Shift+Down'  -- Move downward   *\n");
    printf("*    'Shift+Left'  -- Move left       *\n");
    printf("*    'Shift+Right' -- Move right      *\n");
    printf("*                                     *\n");
    printf("* - Others -                          *\n");
    printf("*    'C'     -- Change camera         *\n");
    printf("*    'Esc'   -- Exit                  *\n");
    printf("*                                     *\n");
    printf("***************************************\n\n");

    // Main loop
    while (!GetAsyncKeyState(VK_ESCAPE)) {
        // Update
        if (!ardrone.update()) break;

        // Get an image
        IplImage *image = ardrone.getImage();

        // Take off / Landing
        if (KEY_PUSH(VK_SPACE)) {
            if (ardrone.onGround()) ardrone.takeoff();
            else                    ardrone.landing();
        }

        // Move
        double vx = 0.0, vy = 0.0, vz = 0.0, vr = 0.0;
        if (KEY_DOWN(VK_SHIFT)) {
            if (KEY_DOWN(VK_UP))    vz =  1.0;
            if (KEY_DOWN(VK_DOWN))  vz = -1.0;
            if (KEY_DOWN(VK_LEFT))  vy =  1.0;
            if (KEY_DOWN(VK_RIGHT)) vy = -1.0;
        }
        else {
            if (KEY_DOWN(VK_UP))    vx =  1.0;
            if (KEY_DOWN(VK_DOWN))  vx = -1.0;
            if (KEY_DOWN(VK_LEFT))  vr =  1.0;
            if (KEY_DOWN(VK_RIGHT)) vr = -1.0;
        }
        ardrone.move3D(vx, vy, vz, vr);

        // Change camera
        static int mode = 0;
        if (KEY_PUSH('C')) ardrone.setCamera(++mode%4);

        // Display the image
        cvShowImage("camera", image);
        cvWaitKey(1);
    }

    // See you
    ardrone.close();

    return 0;
}
Ejemplo n.º 6
0
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
static PALETTEENTRY glow = {0,0,0,PC_NOCOLLAPSE};  // used to animation red border
static int glow_count = 0, glow_dx = 5;

// 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_Bitmap(&reactor, back_buffer, back_lpitch, 0);

// unlock the back buffer
DDraw_Unlock_Back_Surface();

// get player input

// get the keyboard data
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 30 fps
Wait_Clock(30);

// return success
return(1);

} // end Game_Main
Ejemplo n.º 7
0
void Game::Step()
{
	static mat4 mrot; // general rotation matrix

	static float x_ang = 0, // these track the rotation
             y_ang = 2, // of the object
             z_ang = 0;

	Graphics& graphics = Modules::GetGraphics();

	int index; // looping var

	// start the timing clock
	Modules::GetTimer().Start_Clock();

	// clear the drawing surface 
	graphics.FillSurface(graphics.GetBackSurface(), 0);

	// read keyboard and other devices here
	Modules::GetInput().ReadKeyboard();

	// game logic here...

	// initialize the renderlist
	_obj.Reset();

	// 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; 
	mrot = mat4::RotateX(x_ang) * mat4::RotateY(y_ang) * mat4::RotateZ(z_ang);

	// rotate the local coords of single polygon in renderlist
	_obj.Transform(mrot, TRANSFORM_LOCAL_ONLY, 1);

	// perform local/model to world transform
	_obj.ModelToWorld();

	// generate camera matrix
	_cam->BuildMatrixEuler(CAM_ROT_SEQ_ZYX);

	// remove backfaces
	_obj.RemoveBackfaces(*_cam);

	// apply world to camera transform
	_obj.WorldToCamera(*_cam);

	// apply camera to perspective transformation
	_obj.CameraToPerspective(*_cam);

	// apply screen transform
	_obj.PerspectiveToScreen(*_cam);

	// draw instructions
	graphics.DrawTextGDI("Press ESC to exit. Use UP ARROW and DOWN ARROW to rotate.", 0, 0, RGB(0,255,0), graphics.GetBackSurface());

	// lock the back buffer
	graphics.LockBackSurface();

	// render the polygon list
	_obj.DrawWire32(graphics.GetBackBuffer(), graphics.GetBackLinePitch());

	// unlock the back buffer
	graphics.UnlockBackSurface();

	// flip the surfaces
	graphics.Flip(main_window_handle);

	// sync to 30ish fps
	Modules::GetTimer().Wait_Clock(30);

	// check of user is trying to exit
	if (KEY_DOWN(VK_ESCAPE) || 
		Modules::GetInput().KeyboardState()[DIK_ESCAPE])
	{
		PostMessage(main_window_handle, WM_DESTROY,0,0);
	}
}
Ejemplo n.º 8
0
void cheat_handle_stick ( struct vehicle_info *vehicle_info, struct actor_info *actor_info, float time_diff )
{
	traceLastFunc( "cheat_handle_stick()" );

	struct object_base	*base_stick, *base_self;
	struct actor_info	*actor_stick;
	struct vehicle_info *vehicle_stick;
	float				*speed_stick, *speed_self;
	float				*spin_stick, *spin_self;
	static int			id = -1;
	int					i;

	if ( KEY_PRESSED(set.key_stick) )
	{
		if ( vehicle_info != NULL )
			cheat_state->vehicle.stick ^= 1;
		else
			cheat_state->actor.stick ^= 1;
		id = actor_find( id - 1, 1, ACTOR_ALIVE | ACTOR_NOT_SAME_VEHICLE );
	}

	if ( KEY_PRESSED(set.key_stick_nearest) )
	{
		if ( vehicle_info != NULL )
			cheat_state->vehicle.stick ^= 1;
		else
			cheat_state->actor.stick ^= 1;
		id = actor_find_nearest( ACTOR_ALIVE | ACTOR_NOT_SAME_VEHICLE );
	}

	if ( (vehicle_info != NULL && cheat_state->vehicle.stick) || (actor_info != NULL && cheat_state->actor.stick) )
	{
		// remove any bad vehicle or actor stuffs
		if ( isBadPtr_GTA_pVehicle(vehicle_info) )
			vehicle_info = NULL;
		if ( isBadPtr_GTA_pPed(actor_info) )
			actor_info = NULL;

		/* check if actor has disappeared.. and if it has, switch to teh nearest */
		if ( id != -1 && actor_info_get(id, ACTOR_ALIVE) == NULL )
			id = actor_find_nearest( ACTOR_ALIVE | ACTOR_NOT_SAME_VEHICLE );

		if ( KEY_PRESSED(set.key_stick_prev) )
			id = actor_find( id, -1, ACTOR_ALIVE | ACTOR_NOT_SAME_VEHICLE );

		if ( KEY_PRESSED(set.key_stick_next) )
			id = actor_find( id, 1, ACTOR_ALIVE | ACTOR_NOT_SAME_VEHICLE );

		/* no actors to stick to */
		if ( id == -1 )
		{
			cheat_state_text( "No players found; stick disabled." );
			cheat_state->vehicle.stick = 0;
			cheat_state->actor.stick = 0;
			return;
		}

		/* get actor struct for the actor we're sticking to */
		actor_stick = actor_info_get( id, ACTOR_ALIVE | ACTOR_NOT_SAME_VEHICLE );
		if ( actor_stick == NULL )
			return;

		/* is this actor in a vehicle? */
		vehicle_stick = actor_vehicle_get( actor_stick );

		base_stick = vehicle_stick ? &vehicle_stick->base : &actor_stick->base;
		base_self = vehicle_info ? &vehicle_info->base : &actor_info->base;

		speed_stick = vehicle_stick ? vehicle_stick->speed : actor_stick->speed;
		speed_self = vehicle_info ? vehicle_info->speed : actor_info->speed;

		spin_stick = vehicle_stick ? vehicle_stick->spin : actor_stick->spin;
		spin_self = vehicle_info ? vehicle_info->spin : actor_info->spin;

		/* allow warping to work + always warp towards whatever we're sticking to...
         but only when we're in a vehicle */
		if ( KEY_PRESSED(set.key_warp_mod) && vehicle_info != NULL )
		{
			float	out[4];

			/* multiply the matrix of whatever we're sticking to with the user supplied vector */
			matrix_vect4_mult( base_stick->matrix, set.stick_vect, out );

			/* multiply the result with the negative warp-speed value, and put it in the speed vector
            (negative because we want to warp towards teh target, not away from it */
			vect3_mult( out, -set.warp_speed, speed_self );
		}

		if ( !KEY_DOWN(set.key_warp_mod) )
		{
			float	d[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
			float	accel_mult = 1.0f;
			float	out[4];

			/* handle stick movement keys */
			if ( KEY_DOWN(set.key_stick_forward) )
				d[1] += 1.0f;
			if ( KEY_DOWN(set.key_stick_backward) )
				d[1] -= 1.0f;
			if ( KEY_DOWN(set.key_stick_left) )
				d[0] -= 1.0f;
			if ( KEY_DOWN(set.key_stick_right) )
				d[0] += 1.0f;
			if ( KEY_DOWN(set.key_stick_up) )
				d[2] += 1.0f;
			if ( KEY_DOWN(set.key_stick_down) )
				d[2] -= 1.0f;
			if ( KEY_DOWN(set.key_stick_in) )
				d[3] -= 1.0f;
			if ( KEY_DOWN(set.key_stick_out) )
				d[3] += 1.0f;

			if ( !near_zero(set.stick_accel_time) )
			{
				static uint32_t time_start;

				if ( !vect4_near_zero(d) )
					time_start = ( time_start == 0 ) ? time_get() : time_start;
				else
					time_start = 0;			/* no keys pressed */

				/* acceleration */
				if ( time_start != 0 )
				{
					float	t = TIME_TO_FLOAT( time_get() - time_start );
					if ( t < set.stick_accel_time )
						accel_mult *= t / set.stick_accel_time;
				}
			}

			/* calculate new vector + dist */
			if ( !vect3_near_zero(d) && !vect3_near_zero(set.stick_vect) )
			{
				for ( i = 0; i < 3; i++ )
				{
					d[i] = set.stick_vect[i] * set.stick_vect_dist + d[i] * time_diff * 8.0f * accel_mult;
				}

				set.stick_vect_dist = vect3_length( d );
				vect3_normalize( d, set.stick_vect );
			}

			/* move towards/away from the center */
			if ( !near_zero(d[3]) )
				set.stick_vect_dist += d[3] * time_diff * 40.0f * accel_mult;

			/* Teleport vehicle detachables */
			if ( vehicle_info != NULL )
				vehicle_detachables_teleport( vehicle_info, &base_self->matrix[4 * 3], &base_stick->matrix[4 * 3] );

			matrix_copy( base_stick->matrix, base_self->matrix );
			vect3_copy( speed_stick, speed_self );
			vect3_copy( spin_stick, spin_self );

			/*base_self->interior_id = base_stick->interior_id;
         gta_interior_id_set(base_stick->interior_id);*/
			/* multiply the matrix of the target with the user supplied vector */
			matrix_vect4_mult( base_stick->matrix, set.stick_vect, out );

			/* multiply the result with the user supplied vector distance */
			vect3_mult( out, set.stick_vect_dist, out );

			/* and add it to our position */
			vect3_vect3_add( &base_self->matrix[4 * 3], out, &base_self->matrix[4 * 3] );

			if ( vehicle_info != NULL )
			{
				/* Teleport detachables again :p */
				vehicle_detachables_teleport( vehicle_info, &base_stick->matrix[4 * 3], &base_self->matrix[4 * 3] );
				vehicle_prevent_below_height( vehicle_info, set.stick_min_height );
			}
			else if ( actor_info != NULL )
			{
				// new pedFlags
				actor_info->pedFlags.bIsStanding = true;
				actor_info->pedFlags.bWasStanding = true;
				actor_info->pedFlags.bStayInSamePlace = true;
			}
		}
	}
}
Ejemplo n.º 9
0
bool CKeyDown::Right()
{
	return KEY_DOWN(VK_RIGHT);
}
Ejemplo n.º 10
0
void Game::Step()
{
	Modules::GetTimer().Step();

	// todo zz
	int debug_polys_rendered_per_frame = 0;
	int debug_polys_lit_per_frame = 0;

	static mat4 mrot;   // general rotation matrix

	// state variables for different rendering modes and help
	static bool wireframe_mode = false;
	static bool backface_mode  = true;
	static bool lighting_mode  = true;
	static bool help_mode      = true;
	static bool zsort_mode     = true;
	static bool x_clip_mode    = true;
	static bool y_clip_mode    = true;
	static bool z_clip_mode    = true;
	static bool z_buffer_mode   = true;
	static bool display_mode    = true;
	static float turning      = 0;

	char work_string[256]; // temp string

	Graphics& graphics = Modules::GetGraphics();

	// start the timing clock
	Modules::GetTimer().Start_Clock();

	// clear the drawing surface 
	graphics.FillSurface(graphics.GetBackSurface(), 0);

 	// draw the sky
 //	DrawRectangle(0,0, WINDOW_WIDTH, WINDOW_HEIGHT*.5, graphics.GetColor(180,180,220), graphics.GetBackSurface());
	graphics.GetBackSurface()->Blt(NULL, background->GetImage(), NULL, DDBLT_WAIT, NULL); 
 
	// read keyboard and other devices here
	Modules::GetInput().ReadKeyboard();

	// game logic here...

	// reset the render list
	_list->Reset();

	// modes and lights

	// wireframe mode
	if (Modules::GetInput().KeyboardState()[DIK_W])
	{
		// toggle wireframe mode
		wireframe_mode = !wireframe_mode;
		Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
	} // end if

	// backface removal
	if (Modules::GetInput().KeyboardState()[DIK_B])
	{
		// toggle backface removal
		backface_mode = !backface_mode;
		Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
	} // end if

	// lighting
	if (Modules::GetInput().KeyboardState()[DIK_L])
	{
		// toggle lighting engine completely
		lighting_mode = !lighting_mode;
		Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
	} // end if

	LightsMgr& lights = Modules::GetGraphics().GetLights();

	// toggle ambient light
	if (Modules::GetInput().KeyboardState()[DIK_A])
	{
		// toggle ambient light
		if (lights[AMBIENT_LIGHT_INDEX].state == LIGHT_STATE_ON)
			lights[AMBIENT_LIGHT_INDEX].state = LIGHT_STATE_OFF;
		else
			lights[AMBIENT_LIGHT_INDEX].state = LIGHT_STATE_ON;

		Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
	} // end if

	// toggle infinite light
	if (Modules::GetInput().KeyboardState()[DIK_I])
	{
		// toggle ambient light
		if (lights[INFINITE_LIGHT_INDEX].state == LIGHT_STATE_ON)
			lights[INFINITE_LIGHT_INDEX].state = LIGHT_STATE_OFF;
		else
			lights[INFINITE_LIGHT_INDEX].state = LIGHT_STATE_ON;

		Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
	} // end if

	// toggle point light
	if (Modules::GetInput().KeyboardState()[DIK_P])
	{
		// toggle point light
		if (lights[POINT_LIGHT_INDEX].state == LIGHT_STATE_ON)
			lights[POINT_LIGHT_INDEX].state = LIGHT_STATE_OFF;
		else
			lights[POINT_LIGHT_INDEX].state = LIGHT_STATE_ON;

		Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
	} // end if


	// toggle spot light
	if (Modules::GetInput().KeyboardState()[DIK_S])
	{
		// toggle spot light
		if (lights[SPOT_LIGHT2_INDEX].state == LIGHT_STATE_ON)
			lights[SPOT_LIGHT2_INDEX].state = LIGHT_STATE_OFF;
		else
			lights[SPOT_LIGHT2_INDEX].state = LIGHT_STATE_ON;

		Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
	} // end if


	// help menu
	if (Modules::GetInput().KeyboardState()[DIK_H])
	{
		// toggle help menu 
		help_mode = !help_mode;
		Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
	} // end if

	// z-sorting
	if (Modules::GetInput().KeyboardState()[DIK_S])
	{
		// toggle z sorting
		zsort_mode = !zsort_mode;
		Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
	} // end if

	// z buffer
	if (Modules::GetInput().KeyboardState()[DIK_Z])
	{
		// toggle z buffer
		z_buffer_mode = !z_buffer_mode;
		Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
	} // end if

	// object and camera movement

	// rotate around y axis or yaw
	if (Modules::GetInput().KeyboardState()[DIK_RIGHT])
	{
		_cam->DirRef().y+=3;
		// add a little turn to object
		if ((turning+=2) > 25)
			turning=25;
	} // end if
	else if (Modules::GetInput().KeyboardState()[DIK_LEFT])
	{
		_cam->DirRef().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

	if (Modules::GetInput().KeyboardState()[DIK_UP])
	{
		// move forward
		if ( (cam_speed+=1) > MAX_SPEED) cam_speed = MAX_SPEED;
	} // end if

	if (Modules::GetInput().KeyboardState()[DIK_DOWN])
	{
		// move backward
		if ((cam_speed-=1) < -MAX_SPEED) cam_speed = -MAX_SPEED;
	} // end if

	// move to next object
	if (Modules::GetInput().KeyboardState()[DIK_N])
	{
		if (++curr_object >= NUM_OBJECTS)
			curr_object = 0;

		// update pointer
		obj_work = obj_array[curr_object];
		Modules::GetTimer().Wait_Clock(100); // wait, so keyboard doesn't bounce
	} // 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;

	// move camera
	_cam->PosRef().x += cam_speed*sin(DEG_TO_RAD(_cam->Dir().y));
	_cam->PosRef().z += cam_speed*cos(DEG_TO_RAD(_cam->Dir().y));

	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*cos(DEG_TO_RAD(plight_ang));
	lights[POINT_LIGHT_INDEX].pos.y = 100;
	lights[POINT_LIGHT_INDEX].pos.z = 1000*sin(DEG_TO_RAD(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*cos(DEG_TO_RAD(slight_ang));
	lights[SPOT_LIGHT2_INDEX].pos.y = 200;
	lights[SPOT_LIGHT2_INDEX].pos.z = 1000*sin(DEG_TO_RAD(slight_ang));

	if ((slight_ang-=5) < 0)
		slight_ang = 360;

	obj_work->SetWorldPos(_cam->Pos().x + 75*sin(DEG_TO_RAD(_cam->Dir().y)),
						  _cam->Pos().y - 20,
						  _cam->Pos().z + 75*cos(DEG_TO_RAD(_cam->Dir().y)));

	// generate camera matrix
	_cam->BuildMatrixEuler(CAM_ROT_SEQ_ZYX);

	////////////////////////////////////////////////////////
	// insert the scenery into universe
	for (int index = 0; index < NUM_SCENE_OBJECTS; index++)
	{
		// reset the object (this only matters for backface and object removal)
		obj_scene->Reset();

		// set position of tower
		obj_scene->SetWorldPos(scene_objects[index].x,
							   scene_objects[index].y,
							   scene_objects[index].z);

		// move objects
		scene_objects[index].x+=scene_objects_vel[index].x;
		scene_objects[index].y+=scene_objects_vel[index].y;
		scene_objects[index].z+=scene_objects_vel[index].z;

		// test for out of bounds
		if (scene_objects[index].x >= UNIVERSE_RADIUS || scene_objects[index].x <= -UNIVERSE_RADIUS)
		{ 
			scene_objects_vel[index].x=-scene_objects_vel[index].x;
			scene_objects[index].x+=scene_objects_vel[index].x;
		} // end if

		if (scene_objects[index].y >= (UNIVERSE_RADIUS/2) || scene_objects[index].y <= -(UNIVERSE_RADIUS/2))
		{ 
			scene_objects_vel[index].y=-scene_objects_vel[index].y;
			scene_objects[index].y+=scene_objects_vel[index].y;
		} // end if

		if (scene_objects[index].z >= UNIVERSE_RADIUS  || scene_objects[index].z <= -UNIVERSE_RADIUS)
		{ 
			scene_objects_vel[index].z=-scene_objects_vel[index].z;
			scene_objects[index].z+=scene_objects_vel[index].z;
		} // end if

		// attempt to cull object   
		if (!obj_scene->Cull(*_cam, CULL_OBJECT_XYZ_PLANES))
		{
			mrot = mrot.Identity();

			// rotate the local coords of the object
			obj_scene->Transform(mrot, TRANSFORM_LOCAL_TO_TRANS,1);

			// perform world transform
			obj_scene->ModelToWorld(TRANSFORM_TRANS_ONLY);

			// insert the object into render list
			_list->Insert(*obj_scene, false);

		} // end if

	} // end for

	//////////////////////////////////////////////////////////////////////////
	// constant shaded water

	// reset the object (this only matters for backface and object removal)
	obj_work->Reset();

 	// generate rotation matrix around y axis
 	mrot = mat4::RotateX(-15) * mat4::RotateY(_cam->Dir().y + turning);
 
 	// rotate the local coords of the object
 	obj_work->Transform(mrot, TRANSFORM_LOCAL_TO_TRANS,true);

	// perform world transform
	obj_work->ModelToWorld(TRANSFORM_TRANS_ONLY);

	// insert the object into render list
	_list->Insert(*obj_work, false);

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

	// use these to rotate objects
	static float x_ang = 0, y_ang = 0, z_ang = 0;

 	// update rotation angles
 	if ((x_ang+=.2) > 360) x_ang = 0;
 	if ((y_ang+=.4) > 360) y_ang = 0;
 	if ((z_ang+=.8) > 360) z_ang = 0;

	// update the alpha level
	alpha_override+=alpha_inc;

	if (alpha_override > 255 || alpha_override < 0)
	{
		alpha_inc=-alpha_inc;
		alpha_override+=alpha_inc;
	} // end if

	// remove backfaces
	if (backface_mode)
		_list->RemoveBackfaces(*_cam);

	// apply world to camera transform
	_list->WorldToCamera(*_cam);

	// clip the polygons themselves now
	_list->ClipPolys(*_cam, (x_clip_mode ? CLIP_POLY_X_PLANE : 0) | 
							(y_clip_mode ? CLIP_POLY_Y_PLANE : 0) | 
							(z_clip_mode ? CLIP_POLY_Z_PLANE : 0) );

	// light scene all at once 
	if (lighting_mode)
	{
		lights.Transform(_cam->CameraMat(), TRANSFORM_LOCAL_TO_TRANS);
		_list->LightWorld32(*_cam);
	}

	// sort the polygon list (hurry up!)
	if (zsort_mode)
		_list->Sort(SORT_POLYLIST_AVGZ);

	// apply camera to perspective transformation
	_list->CameraToPerspective(*_cam);

	// apply screen transform
	_list->PerspectiveToScreen(*_cam);

	// lock the back buffer
	graphics.LockBackSurface();

	// reset number of polys rendered
	debug_polys_rendered_per_frame = 0;

	if (wireframe_mode) {
		_list->DrawWire32(graphics.GetBackBuffer(), graphics.GetBackLinePitch());
	} else {
		// set up rendering context
		RenderContext rc;
		rc.attr         = RENDER_ATTR_NOBUFFER  
						| RENDER_ATTR_ALPHA  
						| RENDER_ATTR_MIPMAP  
						| RENDER_ATTR_BILERP
						| RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE;

		rc.video_buffer   = graphics.GetBackBuffer();
		rc.lpitch         = graphics.GetBackLinePitch();
		rc.mip_dist       = 3500;
		rc.zbuffer        = (unsigned char*)zbuffer->Buffer();
		rc.zpitch         = WINDOW_WIDTH*4;
		rc.texture_dist   = 0;
		rc.alpha_override = alpha_override;

		// render scene
		_list->DrawContext(rc);
	}

	// unlock the back buffer
	graphics.UnlockBackSurface();

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

	graphics.DrawTextGDI(work_string, 0, WINDOW_HEIGHT-34, RGB(0,255,0), graphics.GetBackSurface());

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

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

	sprintf(work_string,"Polys Rendered: %d, Polys lit: %d", debug_polys_rendered_per_frame, debug_polys_lit_per_frame);
	graphics.DrawTextGDI(work_string, 0, WINDOW_HEIGHT-34-16-16, RGB(0,255,0), graphics.GetBackSurface());

	sprintf(work_string,"CAM [%5.2f, %5.2f, %5.2f]",  _cam->Pos().x, _cam->Pos().y, _cam->Pos().z);
	graphics.DrawTextGDI(work_string, 0, WINDOW_HEIGHT-34-16-16-16, RGB(0,255,0), graphics.GetBackSurface());

	sprintf(work_string,"FPS: %d", Modules::GetTimer().FPS());
	graphics.DrawTextGDI(work_string, 0, WINDOW_HEIGHT-34-16-16-16-16, RGB(0,255,0), graphics.GetBackSurface());

	// flip the surfaces
	graphics.Flip(main_window_handle);

	// sync to 30ish fps
	Modules::GetTimer().Wait_Clock(30);

	// check of user is trying to exit
	if (KEY_DOWN(VK_ESCAPE) || Modules::GetInput().KeyboardState()[DIK_ESCAPE])
	{
		PostMessage(main_window_handle, WM_DESTROY,0,0);
	} // end if

}
Ejemplo n.º 11
0
void cheat_handle_debug ( HWND wnd )
{
	static const int	data_size[4] = { 1, 2, 4, 4 };
	struct debug_info	*debug = &cheat_state->debug;
	int					move = 0, hist_chng = 0;

	if ( !cheat_state->debug_enabled )
		return;

	/* go to pointer */
	if ( KEY_PRESSED(VK_NUMPAD1) )
	{
		setDebugPointer( *(void **)debug->cursor_data );
		hist_chng = 1;
	}

	/* go back */
	if ( KEY_PRESSED(VK_NUMPAD7) )
	{
		if ( debug->hist_pos > 0 )
		{
			debug->hist_pos--;
			hist_chng = 1;
		}
		else if ( debug->hist_pos == 0 )
			setDebugPointer( (void *)NULL );
	}

	/* change data type */
	if ( KEY_PRESSED(VK_DIVIDE) )
		debug->data_type = ( debug->data_type + 1 ) % 4;

	/* inc/dec value */
	if ( KEY_DOWN(VK_ADD) || KEY_DOWN(VK_SUBTRACT) )
	{
		const int	value = KEY_DOWN( VK_ADD ) ? 1 : -1;
		uint8_t		data[4] = { 0, 0, 0, 0 };

		if ( memcpy_safe(data, debug->ptr[debug->hist_pos] + debug->offset[debug->hist_pos], data_size[debug->data_type]) )
		{
			switch ( debug->data_type )
			{
#pragma warning( disable : 4244 )

			case 0:
				( *(uint8_t *)data ) += ( uint8_t ) value;
				break;

			case 1:
				( *(uint16_t *)data ) += ( uint16_t ) value;
				break;

			case 2:
				( *(uint32_t *)data ) += ( uint32_t ) value;
				break;

			case 3:
				( *(float *)data ) += (float)value / 10.0f;
				break;
			}

			memcpy_safe( debug->ptr[debug->hist_pos] + debug->offset[debug->hist_pos], data, data_size[debug->data_type] );
		}
	}

	/* copy info to clipboard */
	if ( KEY_PRESSED(VK_MULTIPLY) )
	{
		if ( OpenClipboard(wnd) )
		{
			HGLOBAL mem = GlobalAlloc( GMEM_MOVEABLE, sizeof(debug->ptr_hist_str) );

			if ( mem != NULL )
			{
				char	*str = (char *)GlobalLock( mem );

				strlcpy( str, debug->ptr_hist_str, sizeof(debug->ptr_hist_str) );
				Log( "%s", str );
				GlobalUnlock( str );

				EmptyClipboard();

				if ( !SetClipboardData(CF_TEXT, mem) )
					Log( "SetClipboardData() %d", GetLastError() );

				/*SetClipboardData(CF_TEXT, mem);*/
			}

			CloseClipboard();
		}
		else
		{
			Log( "OpenClipboard() %d", GetLastError() );
		}
	}

	if ( KEY_PRESSED(VK_NUMPAD4) )
		move -= data_size[debug->data_type];
	if ( KEY_PRESSED(VK_NUMPAD6) )
		move += data_size[debug->data_type];
	if ( KEY_PRESSED(VK_NUMPAD8) )
		move += -16;
	if ( KEY_PRESSED(VK_NUMPAD2) )
		move += 16;
	if ( KEY_PRESSED(VK_NUMPAD9) )
		move += -160;
	if ( KEY_PRESSED(VK_NUMPAD3) )
		move += 160;

	debug->offset[debug->hist_pos] += move;

	if ( move != 0 || hist_chng )
	{
		memset( debug->modify_time, 0, DEBUG_DATA_SIZE * sizeof(uint32_t) );
		debug->data_prev_clear = 1;
	}

	for ( int i = 0; i < 9; i++ )
		KEY_CONSUME( VK_NUMPAD1 + i );
	KEY_CONSUME( VK_MULTIPLY );
	KEY_CONSUME( VK_DIVIDE );
	KEY_CONSUME( VK_ADD );
	KEY_CONSUME( VK_SUBTRACT );
}
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

static float alpha_override = 0,
             alpha_inc = .25;

// 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 int z_buffer_mode  = 1;
static int display_mode   = 1;
static float turning      = 0;
static int pass_mode      = 2;

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(0,0,0), lpddsback);
lpddsback->Blt(NULL, background.images[0], NULL, DDBLT_WAIT, NULL); 

// draw the ground
//Draw_Rectangle(0,WINDOW_HEIGHT*.5, WINDOW_WIDTH, WINDOW_HEIGHT, RGB16Bit(190,190,230), lpddsback);

// read keyboard and other devices here
DInput_Read_Keyboard();

// game logic here...

// 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;

   Wait_Clock(100); // wait, so keyboard doesn't bounce
   } // end if


// toggle spot light
if (keyboard_state[DIK_S])
   {
   // toggle spot light
   if (lights2[SPOT_LIGHT2_INDEX].state == LIGHTV2_STATE_ON)
      lights2[SPOT_LIGHT2_INDEX].state = LIGHTV2_STATE_OFF;
   else
      lights2[SPOT_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

// reflection pass mode
if (keyboard_state[DIK_N])
   {
   // toggle help menu 
   if (++pass_mode > 2) pass_mode = 0;
   Wait_Clock(100); // wait, so keyboard doesn't bounce
   } // end if

// z-sorting
if (keyboard_state[DIK_S])
   {
   // toggle z sorting
   zsort_mode = -zsort_mode;
   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
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

// 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;

// move camera
cam.pos.x += cam_speed*Fast_Sin(cam.dir.y);
cam.pos.y = 200;
cam.pos.z += cam_speed*Fast_Cos(cam.dir.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 = 100;
lights2[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
lights2[SPOT_LIGHT2_INDEX].pos.x = 1000*Fast_Cos(slight_ang);
lights2[SPOT_LIGHT2_INDEX].pos.y = 200;
lights2[SPOT_LIGHT2_INDEX].pos.z = 1000*Fast_Sin(slight_ang);

if ((slight_ang-=5) < 0)
    slight_ang = 360;

// update rotation angles
if ((x_ang+=.2) > 360) x_ang = 0;
if ((y_ang+=.4) > 360) y_ang = 0;
if ((z_ang+=.8) > 360) z_ang = 0;

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

// lock the back buffer
DDraw_Lock_Back_Surface();

// render the terrain first /////////////////////////////////
if (pass_mode >= 0)
{
// reset the render list
Reset_RENDERLIST4DV2(&rend_list);

// rotate the local coords of the object
MAT_IDENTITY_4X4(&mrot); 
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);

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

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

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

// light scene all at once 
if (lighting_mode==1)
   {
   Transform_LIGHTSV2(lights2, 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);


//   // get an identity matrix
//   MAT_IDENTITY_4X4(&mrot); 
//   mrot.M11 = -1;

   // transform the rendering list by x-z plane reflection matrix
   Transform_RENDERLIST4DV2(&rend_list, &mrot, TRANSFORM_TRANS_ONLY);  

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

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

// reset number of polys rendered
debug_polys_rendered_per_frame = 0;

// render the renderinglist
if (wireframe_mode  == 0)
   Draw_RENDERLIST4DV2_Wire16(&rend_list, back_buffer, back_lpitch);
else
if (wireframe_mode  == 1)
   {
   // initialize zbuffer to 16000 fixed point
   Clear_Zbuffer(&zbuffer, (16000 << FIXP16_SHIFT));

   // set up rendering context
   rc.attr         = RENDER_ATTR_ZBUFFER  
                     | RENDER_ATTR_ALPHA  
                     //| RENDER_ATTR_MIPMAP  
                     //| RENDER_ATTR_BILERP
                     | RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE;
   
   rc.video_buffer   = back_buffer;
   rc.lpitch         = back_lpitch;
   rc.mip_dist       = 3500;
   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(&rc);
   } // end if

} // end if
//////////////////////////////////////////////////////////

if (pass_mode >= 1)
{
// render the reflection of the objects

// reset the render list
Reset_RENDERLIST4DV2(&rend_list);

// insert the scenery into universe
for (index = 0; index < NUM_SCENE_OBJECTS; index++)
    {
    // select proper object first
    obj_work = &obj_array[(int)scene_objects[index].w];

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

    // set position of tower
    obj_work->world_pos.x = scene_objects[index].x;
    obj_work->world_pos.y = scene_objects[index].y;
    obj_work->world_pos.z = scene_objects[index].z;

    // move objects
    scene_objects[index].x+=scene_objects_vel[index].x;
    scene_objects[index].y+=scene_objects_vel[index].y;
    scene_objects[index].z+=scene_objects_vel[index].z;

    // test for out of bounds
    if (scene_objects[index].x >= UNIVERSE_RADIUS || scene_objects[index].x <= -UNIVERSE_RADIUS)
       { 
       scene_objects_vel[index].x=-scene_objects_vel[index].x;
       scene_objects[index].x+=scene_objects_vel[index].x;
       } // end if

    if (scene_objects[index].y >= (UNIVERSE_RADIUS/2) || scene_objects[index].y <= -(UNIVERSE_RADIUS/2))
       { 
       scene_objects_vel[index].y=-scene_objects_vel[index].y;
       scene_objects[index].y+=scene_objects_vel[index].y;
       } // end if

    if (scene_objects[index].z >= UNIVERSE_RADIUS  || scene_objects[index].z <= -UNIVERSE_RADIUS)
       { 
       scene_objects_vel[index].z=-scene_objects_vel[index].z;
       scene_objects[index].z+=scene_objects_vel[index].z;
       } // end if

    // attempt to cull object   
    if (!Cull_OBJECT4DV2(obj_work, &cam, CULL_OBJECT_XYZ_PLANES))
       {
       MAT_IDENTITY_4X4(&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);

       } // end if
 
    } // end for

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

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

// light scene all at once 
if (lighting_mode==1)
   {
   Transform_LIGHTSV2(lights2, 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);

// get an identity matrix
MAT_IDENTITY_4X4(&mrot); 
mrot.M11 = -1; mrot.M31 = -450;

// transform the rendering list by x-z plane reflection matrix
Transform_RENDERLIST4DV2(&rend_list, &mrot, TRANSFORM_TRANS_ONLY);  

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

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

// reset number of polys rendered
debug_polys_rendered_per_frame = 0;

// render the renderinglist
if (wireframe_mode  == 0)
   Draw_RENDERLIST4DV2_Wire16(&rend_list, back_buffer, back_lpitch);
else
if (wireframe_mode  == 1)
   {

   // set up rendering context
   rc.attr         = RENDER_ATTR_NOBUFFER  
                     | RENDER_ATTR_ALPHA  
                     //| RENDER_ATTR_MIPMAP  
                     //| RENDER_ATTR_BILERP
                     | RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE;
   
   rc.video_buffer   = back_buffer;
   rc.lpitch         = back_lpitch;
   rc.mip_dist       = 3500;
   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(&rc);
   } // end if

} // end if

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

if (pass_mode >= 2)
{
// render the objects now

// reset the render list
Reset_RENDERLIST4DV2(&rend_list);

// insert the scenery into universe
for (index = 0; index < NUM_SCENE_OBJECTS; index++)
    {
    // select proper object first
    obj_work = &obj_array[(int)scene_objects[index].w];

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

    // set position of tower
    obj_work->world_pos.x = scene_objects[index].x;
    obj_work->world_pos.y = scene_objects[index].y;
    obj_work->world_pos.z = scene_objects[index].z;

    // move objects
    scene_objects[index].x+=scene_objects_vel[index].x;
    scene_objects[index].y+=scene_objects_vel[index].y;
    scene_objects[index].z+=scene_objects_vel[index].z;

    // test for out of bounds
    if (scene_objects[index].x >= UNIVERSE_RADIUS || scene_objects[index].x <= -UNIVERSE_RADIUS)
       { 
       scene_objects_vel[index].x=-scene_objects_vel[index].x;
       scene_objects[index].x+=scene_objects_vel[index].x;
       } // end if

    if (scene_objects[index].y >= (UNIVERSE_RADIUS/2) || scene_objects[index].y <= -(UNIVERSE_RADIUS/2))
       { 
       scene_objects_vel[index].y=-scene_objects_vel[index].y;
       scene_objects[index].y+=scene_objects_vel[index].y;
       } // end if

    if (scene_objects[index].z >= UNIVERSE_RADIUS  || scene_objects[index].z <= -UNIVERSE_RADIUS)
       { 
       scene_objects_vel[index].z=-scene_objects_vel[index].z;
       scene_objects[index].z+=scene_objects_vel[index].z;
       } // end if

    // attempt to cull object   
    if (!Cull_OBJECT4DV2(obj_work, &cam, CULL_OBJECT_XYZ_PLANES))
       {
       MAT_IDENTITY_4X4(&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);

       } // end if
 
    } // end for

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

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

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

// light scene all at once 
if (lighting_mode==1)
   {
   Transform_LIGHTSV2(lights2, 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);

// get an identity matrix
//MAT_IDENTITY_4X4(&mrot); 
//mrot.M11 = -1; mrot.M31 = -400;

// transform the rendering list by x-z plane reflection matrix
Transform_RENDERLIST4DV2(&rend_list, &mrot, TRANSFORM_TRANS_ONLY);  

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

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

// reset number of polys rendered
debug_polys_rendered_per_frame = 0;

// render the renderinglist
if (wireframe_mode  == 0)
   Draw_RENDERLIST4DV2_Wire16(&rend_list, back_buffer, back_lpitch);
else
if (wireframe_mode  == 1)
   {

   // set up rendering context
   rc.attr         = RENDER_ATTR_ZBUFFER  
                     | RENDER_ATTR_ALPHA  
                     //| RENDER_ATTR_MIPMAP  
                     //| RENDER_ATTR_BILERP
                     | RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE;
   
   rc.video_buffer   = back_buffer;
   rc.lpitch         = back_lpitch;
   rc.mip_dist       = 3500;
   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(&rc);
   } // end if

} // end if

// unlock the back buffer
DDraw_Unlock_Back_Surface();

sprintf(work_string,"Lighting [%s]: Ambient=%d, Infinite=%d, Point=%d, Spot=%d, BckFceRM [%s], Zsort [%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,
                                                                                 ((backface_mode == 1) ? "ON" : "OFF"),
                                                                                 ((zsort_mode == 1) ? "ON" : "OFF"));


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

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

// should we display help
int text_y = 16;
if (help_mode==1)
    {
    // draw help menu
    Draw_Text_GDI("<A>..............Toggle ambient light source.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<I>..............Toggle infinite light source.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<P>..............Toggle point light source.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<S>..............Toggle spot light source.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<N>..............Enable next rendering pass.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<W>..............Toggle wire frame/solid mode.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<B>..............Toggle backface removal.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<S>..............Toggle Z sorting.", 0, text_y+=12, RGB(255,255,255), lpddsback);
    Draw_Text_GDI("<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]",  cam.pos.x, cam.pos.y, cam.pos.z);

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

// flip the surfaces
DDraw_Flip2();

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

// check of user is trying to exit
if (KEY_DOWN(VK_ESCAPE) || keyboard_state[DIK_ESCAPE])
    {
    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
Ejemplo n.º 14
0
void GameController::Run()
{
    Player* me = new Player(0,0,1);

    sObjMgr->CreateWorld();
    sObjMgr->Update();

    DWORD realCurrTime = 0;
    DWORD realPrevTime = GetMSTime();

    DWORD diff;

    /* Example for using the sScreenLog class */
    sScreenLog->AddTrack(&diff,ScreenLog::Track::UINT,20,30,0xFFFF0000);

//	sScreenLog->AddTrack(&me->X,ScreenLog::Track::INT,20,50,0xFFFF0000);
//	sScreenLog->AddTrack(&me->Y,ScreenLog::Track::INT,20,70,0xFFFF0000);
    while(true)
    {
        realCurrTime = GetMSTime();
        diff = GetMSTimeDiff(realPrevTime,realCurrTime);

        Player* me = sObjMgr->Me();

        ReadKeyboard();

        if(KEY_PRESSED(DIK_F))
            me->Fire();

        if(KEY_DOWN(DIK_ESCAPE))
            break;
        if(KEY_DOWN(DIK_W))
            me->SetYVelocity(-3);
        if(KEY_DOWN(DIK_S))
            me->SetYVelocity(3);
        if(KEY_DOWN(DIK_A)) {
            me->SetXVelocity(-3);
            if(KEY_DOWN(DIK_D)) {
                new Explosion(me,me->GetX()+4,me->GetY()+(me->GetHeight()/2),19,0,false);
            }
        }
        if(KEY_DOWN(DIK_D)) {
            me->SetXVelocity(3);
            if(KEY_DOWN(DIK_A)) {
                new Explosion(me,me->GetX()+me->GetWidth()-4,me->GetY()+(me->GetHeight()/2),19,0,false);
            }
        }

        /* Oops :< */
        //if(KEY_UP(DIK_W) && KEY_UP(DIK_A) && KEY_UP(DIK_S) && KEY_UP(DIK_D))
        //	{
        //	me->SetXVelocity(0);
        //	me->SetYVelocity(0);
        //	}

        if(KEY_DOWN(DIK_R))
            me->SetPos(30,70);

        if(KEY_DOWN(DIK_Q))
            me->SetAngle(me->GetAngle()+0.1f);

        if(KEY_DOWN(DIK_E))
            me->SetAngle(me->GetAngle()-0.1f);

        if(KEY_DOWN(DIK_M))
            sWorld->PrintMap();

        if(KEY_DOWN(DIK_SPACE))
        {
            me->SetXVelocity(0);
            me->SetYVelocity(0);
        }

        sObjMgr->Update(/* diff */);
        FollowUnit(me);
        Render();

        realPrevTime = realCurrTime;
    }
}
// point must be in logical
void CDrawObject::MoveHandleTo(int nHandle, CPoint point)
{
	FTLASSERT(this);

	if(KEY_DOWN(VK_SHIFT))
	{
		if(dotLine == m_objType || dotLineArrow == m_objType)
		{
			return MoveLineHandleToWithShift(nHandle, point);
		}
		else
		{
			return MoveHandleToWithShift(nHandle, point);
		}
		
	}
	CRect position = m_position;
	switch (nHandle)
	{
		case 1:
			{
				position.left = point.x;
				position.top = point.y;
			}
			break;

		case 2:
			position.top = point.y;
			break;

		case 3:
			position.right = point.x;
			position.top = point.y;
			break;

		case 4:
			position.right = point.x;
			break;

		case 5:
			{
				position.right = point.x;
				position.bottom = point.y;
			}
			break;

		case 6:
			position.bottom = point.y;
			break;

		case 7:
			position.left = point.x;
			position.bottom = point.y;
			break;

		case 8:
			position.left = point.x;
			break;
		default:
			FTLASSERT(FALSE);
			break;
	}

	MoveTo(position);
}
Ejemplo n.º 16
0
bool CKeyDown::Left()
{
	return KEY_DOWN(VK_LEFT);
}
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 int bilinear_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(250,190,80), lpddsback);
    lpddsback->Blt(NULL, background.images[0], NULL, DDBLT_WAIT, NULL);

// draw the ground
//Draw_Rectangle(0,WINDOW_HEIGHT*.5, WINDOW_WIDTH, WINDOW_HEIGHT, RGB16Bit(190,190,230), 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

// 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;

        Wait_Clock(100); // wait, so keyboard doesn't bounce
    } // end if


// toggle spot light
    if (keyboard_state[DIK_S])
    {
        // toggle spot light
        if (lights2[SPOT_LIGHT2_INDEX].state == LIGHTV2_STATE_ON)
            lights2[SPOT_LIGHT2_INDEX].state = LIGHTV2_STATE_OFF;
        else
            lights2[SPOT_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_S])
    {
        // toggle z sorting
        zsort_mode = -zsort_mode;
        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

// move to next object
    if (keyboard_state[DIK_N])
    {
        if (++curr_object >= NUM_OBJECTS)
            curr_object = 0;

        // update pointer
        obj_work = &obj_array[curr_object];
        Wait_Clock(100); // wait, so keyboard doesn't bounce
    } // end if

// toggle bilinear mode
    if (keyboard_state[DIK_B])
    {
        bilinear_mode = -bilinear_mode;

        Wait_Clock(100); // wait, so keyboard doesn't bounce
    } // 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;

// move camera
    cam.pos.x += cam_speed*Fast_Sin(cam.dir.y);
    cam.pos.z += cam_speed*Fast_Cos(cam.dir.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 = 100;
    lights2[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
    lights2[SPOT_LIGHT2_INDEX].pos.x = 1000*Fast_Cos(slight_ang);
    lights2[SPOT_LIGHT2_INDEX].pos.y = 200;
    lights2[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);

// reset BHV for culling
    BHV_Reset_Tree(&bhv_tree);

// now cull the BHV ... die polygons die!
    bhv_nodes_visited = 0;
    BHV_FrustrumCull(&bhv_tree,                 // the root of the BHV
                     &cam,                     // camera to cull relative to
                     CULL_OBJECT_XYZ_PLANES);  // clipping planes to consider

// statistic tracking
    int objects_processed = 0;

////////////////////////////////////////////////////////
// insert the scenery into universe
    for (index = 0; index < NUM_SCENE_OBJECTS; index++)
    {
        // test if container has been culled already by BHV
        if (scene_objects[index].state & OBJECT4DV2_STATE_CULLED)
            continue;

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

        objects_processed++;

        // set position of object
        obj_work->world_pos.x = scene_objects[index].pos.x;
        obj_work->world_pos.y = scene_objects[index].pos.y;
        obj_work->world_pos.z = scene_objects[index].pos.z;

        // rotate object
        if ((scene_objects[index].rot.y+=scene_objects[index].auxi[0]) >= 360)
            scene_objects[index].rot.y = 0;

        // attempt to cull object
        if (!Cull_OBJECT4DV2(obj_work, &cam, CULL_OBJECT_XYZ_PLANES))
        {
            MAT_IDENTITY_4X4(&mrot);

            // generate rotation matrix around y axis
            Build_XYZ_Rotation_MATRIX4X4(0, scene_objects[index].rot.y, 0, &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);

        } // end if

    } // end for

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

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

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

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

// light scene all at once
    if (lighting_mode==1)
    {
        Transform_LIGHTSV2(lights2, 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 renderinglist
    if (wireframe_mode  == 0)
        Draw_RENDERLIST4DV2_Wire16(&rend_list, back_buffer, back_lpitch);
    else if (wireframe_mode  == 1)
    {
        // initialize zbuffer to 16000 fixed point
        Clear_Zbuffer(&zbuffer, (000 << FIXP16_SHIFT));

        // set up rendering context
        rc.attr         = RENDER_ATTR_INVZBUFFER
                          // | RENDER_ATTR_ALPHA
                          // | RENDER_ATTR_MIPMAP
                          | (bilinear_mode==1 ? RENDER_ATTR_BILERP : 0)
                          | RENDER_ATTR_TEXTURE_PERSPECTIVE_AFFINE;

        rc.video_buffer   = back_buffer;
        rc.lpitch         = back_lpitch;
        rc.mip_dist       = 3500;
        rc.zbuffer        = (UCHAR *)zbuffer.zbuffer;
        rc.zpitch         = WINDOW_WIDTH*4;
        rc.rend_list      = &rend_list;
        rc.texture_dist   = 0;
        rc.alpha_override = 5;

        // render scene
        Draw_RENDERLIST4DV2_RENDERCONTEXTV1_16(&rc);


    } // end if

// unlock the back buffer
    DDraw_Unlock_Back_Surface();

    sprintf(work_string,"Lighting [%s]: Ambient=%d, Infinite=%d, Point=%d, Spot=%d, Zsort [%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"));

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

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

// should we display help
    int text_y = 16;
    if (help_mode==1)
    {
        // draw help menu
        Draw_Text_GDI("<A>..............Toggle ambient light source.", 0, text_y+=12, RGB(255,255,255), lpddsback);
        Draw_Text_GDI("<I>..............Toggle infinite light source.", 0, text_y+=12, RGB(255,255,255), lpddsback);
        Draw_Text_GDI("<P>..............Toggle point light source.", 0, text_y+=12, RGB(255,255,255), lpddsback);
        Draw_Text_GDI("<S>..............Toggle spot light source.", 0, text_y+=12, RGB(255,255,255), lpddsback);
        Draw_Text_GDI("<N>..............Next object.", 0, text_y+=12, RGB(255,255,255), lpddsback);
        Draw_Text_GDI("<W>..............Toggle wire frame/solid mode.", 0, text_y+=12, RGB(255,255,255), lpddsback);
        Draw_Text_GDI("<S>..............Toggle Z sorting.", 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, Object Pre-Culled by BHV: %d, Nodes visited in BHV Tree: %d",
            debug_polys_rendered_per_frame,
            debug_polys_lit_per_frame,
            NUM_SCENE_OBJECTS - objects_processed,
            bhv_nodes_visited);


    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]",  cam.pos.x, cam.pos.y, cam.pos.z);

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

// flip the surfaces
    DDraw_Flip2();

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

// check of user is trying to exit
    if (KEY_DOWN(VK_ESCAPE) || keyboard_state[DIK_ESCAPE])
    {
        PostMessage(main_window_handle, WM_DESTROY,0,0);
    } // end if

// return success
    return(1);

} // end Game_Main
Ejemplo n.º 18
0
bool CKeyDown::X()
{
	return KEY_DOWN(0x58);
}
Ejemplo n.º 19
0
// an Update() helper that handles the input
void GameWindow::HandleInput(){
	//check for escape key (to exit program)
    if (KEY_DOWN(VK_ESCAPE))
        PostMessage(m_Window, WM_DESTROY, 0, 0);
	//start game
	if(!m_bInGame){
		if(KEY_DOWN(VK_SPACE) || KEY_DOWN(VK_RETURN)){
			m_bInGame = true;
			m_pSelect->Play();
		}
	}
	else{
		//A or LeftArrow move left
		if (KEY_DOWN(VK_LEFT) || KEY_DOWN(0x41)){
			m_wPlayer.m_xVelocity = -6;
		}

		//D or RightArrow move right
		if (KEY_DOWN(VK_RIGHT) || KEY_DOWN(0x44)){
			m_wPlayer.m_xVelocity = 6;
		}
		//W or UpArrow to jump
		if(KEY_DOWN(VK_UP) || KEY_DOWN(0x57)){
			if(m_wPlayer.m_bGrounded){
				m_wPlayer.m_bGrounded = false;
				m_wPlayer.m_yVelocity = -18;
				//play sound
				m_pJump->Play();
			}
		}
		//space to cast spell
		if(KEY_DOWN(VK_SPACE)){
			//for making sure fire spell shoots in correct directions
			int vel = 1;
			//cast fire
			if(m_wPlayer.m_Spell == "Fire"){
				//(for making sure fire spell goes in correct direction
				if(m_wPlayer.m_Image == L"images\\wiz.l.png"){
					vel = -1;
				}
				//make a new projectile and shoot it
				Projectile newProj = m_wPlayer.Shoot(vel);
				if(newProj.m_bOnScreen){
					for(int i = 0; i < 10; i++){
						if(m_pProjectileList[i].m_bOnScreen == false){
							m_pProjectileList[i] = newProj;
							m_pProjectileList[i].m_bOnScreen = true;
							//play sound
							m_pShoot->Play();
							break;
						}
					}
				}
			}
			//cast dark or lightning
			else if(m_wPlayer.m_Spell == "Lightning" || (m_wPlayer.m_Spell == "Dark" && m_wPlayer.m_bGrounded)){
				Projectile newProj = m_wPlayer.Shoot(vel);
				if(newProj.m_bOnScreen){
					for(int i = 0; i < 10; i++){
						if(m_pProjectileList[i].m_bOnScreen == false){
							m_pProjectileList[i] = newProj;
							m_pProjectileList[i].m_bOnScreen = true;
							if(m_wPlayer.m_Spell == "Dark"){
								//play sound
								m_pShoot->Play();
							}
							else{
								m_pKill->Play();
							}
							break;
						}
					}
				}
			}
		}
	}
}
Ejemplo n.º 20
0
bool CKeyDown::Z()
{
	return KEY_DOWN(0x5A);
}
Ejemplo n.º 21
0
void S9xProcessEvents (bool8 block)
{
    static char prev_keystate[128];
    extern volatile char key[128];

#ifdef GRIP_SUPPORT
    ReadGrip ();
#endif

#ifdef SIDEWINDER_SUPPORT
    if (num_sidewinders)
	ReadSidewinders ();
#endif

    char key1[128];
    char *keystate = (char *) key1;
    int fn = 0;
    
    memcpy (key1, (char *) key, sizeof (key1));

#undef KEY_DOWN
#define KEY_DOWN(a) (keystate[a])
#undef KEY_PRESS
#define KEY_PRESS(a) (keystate[a] && !prev_keystate[a])
#undef KEY_WASPRESSED
#define KEY_WASPRESSED(a) (prev_keystate[a] && !keystate[a])
#undef PROCESS_KEY
#define PROCESS_KEY(k, b, v)\
if (KEY_PRESS(k)) b |= v;\
if (KEY_WASPRESSED(k)) b &= ~v;

    if (KEY_PRESS (SCANCODE_ESCAPE))
	S9xExit ();

    // Joypad 1:
    PROCESS_KEY(SCANCODE_K,		    joypads [0], SNES_RIGHT_MASK)
    PROCESS_KEY(SCANCODE_CURSORRIGHT,	    joypads [0], SNES_RIGHT_MASK)
    PROCESS_KEY(SCANCODE_H,		    joypads [0], SNES_LEFT_MASK)
    PROCESS_KEY(SCANCODE_CURSORLEFT,	    joypads [0], SNES_LEFT_MASK)
    PROCESS_KEY(SCANCODE_N,		    joypads [0], SNES_DOWN_MASK)
    PROCESS_KEY(SCANCODE_J,		    joypads [0], SNES_DOWN_MASK)
    PROCESS_KEY(SCANCODE_CURSORDOWN,	    joypads [0], SNES_DOWN_MASK)
    PROCESS_KEY(SCANCODE_U,		    joypads [0], SNES_UP_MASK)
    PROCESS_KEY(SCANCODE_CURSORUP,	    joypads [0], SNES_UP_MASK)
    PROCESS_KEY(SCANCODE_ENTER,		    joypads [0], SNES_START_MASK)
    PROCESS_KEY(SCANCODE_SPACE,		    joypads [0], SNES_SELECT_MASK)

    PROCESS_KEY(SCANCODE_A,		    joypads [0], SNES_TL_MASK)
    PROCESS_KEY(SCANCODE_V,		    joypads [0], SNES_TL_MASK)
    PROCESS_KEY(SCANCODE_Q,		    joypads [0], SNES_TL_MASK)

    PROCESS_KEY(SCANCODE_Z,		    joypads [0], SNES_TR_MASK)
    PROCESS_KEY(SCANCODE_B,		    joypads [0], SNES_TR_MASK)
    PROCESS_KEY(SCANCODE_W,		    joypads [0], SNES_TR_MASK)

    PROCESS_KEY(SCANCODE_S,		    joypads [0], SNES_X_MASK)
    PROCESS_KEY(SCANCODE_M,		    joypads [0], SNES_X_MASK)
    PROCESS_KEY(SCANCODE_E,		    joypads [0], SNES_X_MASK)

    PROCESS_KEY(SCANCODE_X,		    joypads [0], SNES_Y_MASK)
    PROCESS_KEY(SCANCODE_COMMA,		    joypads [0], SNES_Y_MASK)
    PROCESS_KEY(SCANCODE_R,		    joypads [0], SNES_Y_MASK)

    PROCESS_KEY(SCANCODE_D,		    joypads [0], SNES_A_MASK)
    PROCESS_KEY(SCANCODE_PERIOD,	    joypads [0], SNES_A_MASK)
    PROCESS_KEY(SCANCODE_T,		    joypads [0], SNES_A_MASK)

    PROCESS_KEY(SCANCODE_C,		    joypads [0], SNES_B_MASK)
    PROCESS_KEY(SCANCODE_SLASH,		    joypads [0], SNES_B_MASK)
    PROCESS_KEY(SCANCODE_Y,		    joypads [0], SNES_B_MASK)
    
    // Joypad 2:
//    PROCESS_KEY(SCANCODE_CURSORRIGHT,	    joypads [1], SNES_RIGHT_MASK)
//    PROCESS_KEY(SCANCODE_CURSORLEFT,	    joypads [1], SNES_LEFT_MASK)
//    PROCESS_KEY(SCANCODE_CURSORDOWN,	    joypads [1], SNES_DOWN_MASK)
//    PROCESS_KEY(SCANCODE_CURSORUP,	    joypads [1], SNES_UP_MASK)
    PROCESS_KEY(SCANCODE_KEYPADENTER,	    joypads [0], SNES_START_MASK)
    PROCESS_KEY(SCANCODE_KEYPADPLUS,	    joypads [0], SNES_SELECT_MASK)
    PROCESS_KEY(SCANCODE_INSERT,	    joypads [0], SNES_X_MASK)
    PROCESS_KEY(SCANCODE_REMOVE,	    joypads [0], SNES_Y_MASK)
    PROCESS_KEY(SCANCODE_HOME,		    joypads [0], SNES_A_MASK)
    PROCESS_KEY(SCANCODE_END,		    joypads [0], SNES_B_MASK)
    PROCESS_KEY(SCANCODE_PAGEUP,	    joypads [0], SNES_TL_MASK)
    PROCESS_KEY(SCANCODE_PAGEDOWN,	    joypads [0], SNES_TR_MASK)
    
    if (KEY_PRESS (SCANCODE_0))
	Settings.DisableHDMA = !Settings.DisableHDMA;
    if (KEY_PRESS (SCANCODE_1))
	PPU.BG_Forced ^= 1;
    if (KEY_PRESS (SCANCODE_2))
	PPU.BG_Forced ^= 2;
    if (KEY_PRESS (SCANCODE_3))
	PPU.BG_Forced ^= 4;
    if (KEY_PRESS (SCANCODE_4))
	PPU.BG_Forced ^= 8;
    if (KEY_PRESS (SCANCODE_5))
	PPU.BG_Forced ^= 16;
    if (KEY_PRESS (SCANCODE_6))
	Settings.SwapJoypads = !Settings.SwapJoypads;
    if (KEY_PRESS (SCANCODE_7))
    {
	if (IPPU.Controller == SNES_SUPERSCOPE)
	    show_mouse (NULL);
	S9xNextController ();
	if (IPPU.Controller == SNES_SUPERSCOPE)
	    show_mouse (screen);
    }
    if (KEY_PRESS (SCANCODE_8))
	Settings.BGLayering = !Settings.BGLayering;
    if (KEY_PRESS (SCANCODE_9))
	if (Settings.SixteenBit)
	    Settings.Transparency = !Settings.Transparency;

    if (KEY_PRESS(SCANCODE_TAB))
	superscope_turbo = !superscope_turbo;
    PROCESS_KEY(SCANCODE_GRAVE, superscope_pause, 1);

    if (KEY_PRESS(SCANCODE_F1))
	fn = 1;
    if (KEY_PRESS(SCANCODE_F2))
	fn = 2;
    if (KEY_PRESS(SCANCODE_F3))
	fn = 3;
    if (KEY_PRESS(SCANCODE_F4))
	fn = 4;
    if (KEY_PRESS(SCANCODE_F5))
	fn = 5;
    if (KEY_PRESS(SCANCODE_F6))
	fn = 6;
    if (KEY_PRESS(SCANCODE_F7))
	fn = 7;
    if (KEY_PRESS(SCANCODE_F8))
	fn = 8;
    if (KEY_PRESS(SCANCODE_F9))
	fn = 9;
    if (KEY_PRESS(SCANCODE_F10))
	fn = 10;
    if (KEY_PRESS(SCANCODE_F11))
	fn = 11;
    if (KEY_PRESS(SCANCODE_F12))
	fn = 12;
	
    if (fn > 0)
    {
	if (!KEY_DOWN(SCANCODE_LEFTALT) && !KEY_DOWN(SCANCODE_LEFTSHIFT))
	{
	    if (fn == 11)
	    {
		S9xLoadSnapshot (S9xChooseFilename (TRUE));
	    }
	    else if (fn == 12)
	    {
		Snapshot (S9xChooseFilename (FALSE));
	    }
	    else
	    {
		char def [PATH_MAX];
		char filename [PATH_MAX];
		char drive [_MAX_DRIVE];
		char dir [_MAX_DIR];
		char ext [_MAX_EXT];

		_splitpath (Memory.ROMFilename, drive, dir, def, ext);
		sprintf (filename, "%s%s%s.%03d",
			 S9xGetSnapshotDirectory (), SLASH_STR, def,
			 fn - 1);
		S9xLoadSnapshot (filename);
	    }
	}
	else if (KEY_DOWN(SCANCODE_LEFTALT))
	{
	    if (fn >= 4)
		S9xToggleSoundChannel (fn - 4);
#ifdef DEBUGGER
	    else if (fn == 1)
		CPU.Flags |= DEBUG_MODE_FLAG;
#endif
	    else if (fn == 2)
		S9xLoadSnapshot (S9xChooseFilename (TRUE));
	    else if (fn == 3)
		Snapshot (S9xChooseFilename (FALSE));
	}
	else
	{
	    char def [PATH_MAX];
	    char filename [PATH_MAX];
	    char drive [_MAX_DRIVE];
	    char dir [_MAX_DIR];
	    char ext [_MAX_EXT];

	    _splitpath (Memory.ROMFilename, drive, dir, def, ext);
	    sprintf (filename, "%s%s%s.%03d",
		     S9xGetSnapshotDirectory (), SLASH_STR, def,
		     fn - 1);
	    Snapshot (filename);
	}
    }

    if (KEY_PRESS (SCANCODE_BREAK) || KEY_PRESS (SCANCODE_BREAK_ALTERNATIVE) ||
	KEY_PRESS (SCANCODE_SCROLLLOCK))
	Settings.Paused ^= 1;

    if (KEY_PRESS (SCANCODE_PRINTSCREEN))
	SaveScreenshot ();

    if (KEY_PRESS (SCANCODE_MINUS))
    {
	if (Settings.SkipFrames <= 1)
	    Settings.SkipFrames = AUTO_FRAMERATE;
	else
	if (Settings.SkipFrames != AUTO_FRAMERATE)
	    Settings.SkipFrames--;
    }

    if (KEY_PRESS (SCANCODE_EQUAL))
    {
	if (Settings.SkipFrames == AUTO_FRAMERATE)
	    Settings.SkipFrames = 1;
	else
	if (Settings.SkipFrames < 10)
	    Settings.SkipFrames++;
    }
	
    memcpy (prev_keystate, keystate, sizeof (prev_keystate));

    if (block)
	__dpmi_yield ();
}
Ejemplo n.º 22
0
bool CKeyDown::Space()
{
	return KEY_DOWN(VK_SPACE);
}
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
Ejemplo n.º 24
0
bool CKeyDown::Esc()
{
	return KEY_DOWN(VK_ESCAPE);
}
Ejemplo n.º 25
0
//28.
// the entry point for any Windows program
//29.
int WINAPI WinMain(HINSTANCE hInstance,
                   //30.
                   HINSTANCE hPrevInstance,
                   //31.
                   LPSTR lpCmdLine,
                   //32.
                   int nCmdShow)
//33.
{
    //34.
    HWND hWnd;
    //35.
    WNDCLASSEX wc;
    //36.

    //37.
    ZeroMemory(&wc, sizeof(WNDCLASSEX));
    //38.

    //39.
    wc.cbSize = sizeof(WNDCLASSEX);
    //40.
    wc.style = CS_HREDRAW | CS_VREDRAW;
    //41.
    wc.lpfnWndProc = WindowProc;
    //42.
    wc.hInstance = hInstance;
    //43.
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    //44.
    // wc.hbrBackground = (HBRUSH)COLOR_WINDOW; // not needed any more
    //45.
    wc.lpszClassName = "WindowClass";
    //46.

    //47.
    RegisterClassEx(&wc);
    //48.

    //49.
    hWnd = CreateWindowEx(NULL,
                          //50.
                          "WindowClass",
                          //51.
                          "Our Direct3D Program",
                          //52.
                          WS_EX_TOPMOST | WS_POPUP, // fullscreen values
                          //53.
                          0, 0, // the starting x and y positions should be 0
                          //54.
                          SCREEN_WIDTH, SCREEN_HEIGHT, // set the window to 640 x 480
                          //55.
                          NULL,
                          //56.
                          NULL,
                          //57.
                          hInstance,
                          //58.
                          NULL);
    //59.

    //60.
    ShowWindow(hWnd, nCmdShow);
    //61.

    //62.
    // set up and initialize Direct3D
    //63.
    initD3D(hWnd);
    //64.

    //65.
    // enter the main loop:
    //66.

    //67.
    MSG msg;
    //68.

    //69.
    while(TRUE)
        //70.
    {
        //71.
        while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
            //72.
        {
            //73.
            TranslateMessage(&msg);
            //74.
            DispatchMessage(&msg);
            //75.
        }
        //76.

        //77.
        if(msg.message == WM_QUIT)
            //78.
            break;
        //79.

        //80.
        render_frame();
        //81.

        //82.
        // check the 'escape' key
        //83.
        if(KEY_DOWN(VK_ESCAPE))
            //84.
            PostMessage(hWnd, WM_DESTROY, 0, 0);
        //85.
    }
    //86.

    //87.
    // clean up DirectX and COM
    //88.
    cleanD3D();
    //89.

    //90.
    return msg.wParam;
    //91.
}
Ejemplo n.º 26
0
bool CKeyDown::Up()
{
	return KEY_DOWN(VK_UP);
}
Ejemplo n.º 27
0
// --------------------------------------------------------------------------
// main(Number of arguments, Value of arguments)
// This is the main function.
// Return value Success:0 Error:-1
// --------------------------------------------------------------------------
int main(int argc, char **argv)
{
    // AR.Drone class
    ARDrone ardrone;

    // Initialize
    if (!ardrone.open()) {
        printf("Failed to initialize.\n");
        return -1;
    }

    // Main loop
    while (!GetAsyncKeyState(VK_ESCAPE)) {
        // Update your AR.Drone
        if (!ardrone.update()) break;

        // Get an image
        IplImage *image = ardrone.getImage();

        // Battery
        printf("ardrone.battery = %d [��] (�c���%d��)\n", battery, 12*battery/100);

        // Take off / Landing
        if (KEY_PUSH(VK_SPACE)) {
            if (ardrone.onGround()) ardrone.takeoff();
            else                    ardrone.landing();
        }

        // Emergency stop
        if (KEY_PUSH(VK_RETURN)) ardrone.emergency();

        // AR.Drone is flying
        if (!ardrone.onGround()) {
            double x = 0.0, y = 0.0, z = 0.0, r = 0.0;

            // Keyboard
            if (KEY_DOWN(VK_UP))    x =  0.5;
            if (KEY_DOWN(VK_DOWN))  x = -0.5;
            if (KEY_DOWN(VK_LEFT))  r =  0.5;
            if (KEY_DOWN(VK_RIGHT)) r = -0.5;
            if (KEY_DOWN('Q'))      z =  0.5;
            if (KEY_DOWN('A'))      z = -0.5;

            // Joypad
            JOYINFOEX JoyInfoEx;
            JoyInfoEx.dwSize = sizeof(JOYINFOEX);
            JoyInfoEx.dwFlags = JOY_RETURNALL;

            // Get joypad infomations
            if (joyGetPosEx(0, &JoyInfoEx) == JOYERR_NOERROR) {
                int y_pad = -((int)JoyInfoEx.dwXpos - 0x7FFF) / 32512.0*100.0;
                int x_pad = -((int)JoyInfoEx.dwYpos - 0x7FFF) / 32512.0*100.0;
                int r_pad = -((int)JoyInfoEx.dwZpos - 0x7FFF) / 32512.0*100.0;
                int z_pad =  ((int)JoyInfoEx.dwRpos - 0x7FFF) / 32512.0*100.0;

                printf("X = %d  ", x_pad);
                printf("Y = %d  ", y_pad);
                printf("Z = %d  ", z_pad);
                printf("R = %d\n", r_pad);

                x = 0.5 * x_pad / 100;
                y = 0.5 * y_pad / 100;
                z = 0.5 * z_pad / 100;
                r = 0.5 * r_pad / 100;

                if (JoyInfoEx.dwButtons & JOY_BUTTON1) ardrone.takeoff();
                if (JoyInfoEx.dwButtons & JOY_BUTTON2) ardrone.landing();
            }

            // Move
		    ardrone.move3D(x, y, z, r);
        }


        // Display the image
        cvShowImage("camera", image);
        cvWaitKey(1);
    }

    // See you
    ardrone.close();

    return 0;
}
Ejemplo n.º 28
0
bool CKeyDown::Down()
{
	return KEY_DOWN(VK_DOWN);
}
Ejemplo n.º 29
0
void  Render()
{
   Matrix mat,mat1,mat2;
   Bulid_XYZ_RotationMatrix(mat1,0.0,0.0,g_roty);
   BuildTranslateMatrix(mat2,0.0,0.0,g_tranz);
   static bool bDrawNonTextureCube=false;
   if(KEY_DOWN(VK_F1))
   {
	   //Draw the color cube. don't use texture
	   bDrawNonTextureCube = !bDrawNonTextureCube;
   }
 
   int icount = g_RenderManager.RenderObjectSize();
   for(int i = 0; i < icount;++i)
   {
       CRenderObject *pobj = g_RenderManager[i];
	   POLYGONLIST &polygonlist = pobj->m_PolyGonList;
	   int polygonsize = polygonlist.size();
	   for( int j = 0; j < polygonsize;++j)
	   {
		   POLYGON &polygon = polygonlist[j];
		   if(bDrawNonTextureCube)
			   polygon.state &= ~OBJECT_HAS_TEXTURE;
		   else 
			   polygon.state |= OBJECT_HAS_TEXTURE;
	   }
	  
	   pobj->Transform(mat1);//transform local
	   pobj->world_pos *= mat2;
	  
   }
   //local->world,world->camera,camera->screen
   static bool bEnableLighting = false;
   static bool bEableBackfaceRemove =false;
   static bool bEnableInvZBuffer = false;
   if(KEY_DOWN(VK_HOME))
   {
	   //user press p
	   for(int i=0; i< g_lights.GetLightsCount();++i)
	   {
		   CLight* pLight = g_lights.GetLight(i);
		    pLight->EnableLight();
		 /*  if(pLight->GetLightType() == CLight::kAmbientLight)
		   {
			   pLight->EnableLight();
			   break;
		   }*/
	   }
	   bEnableLighting = true;
	   
   }
   else if(KEY_DOWN(VK_END))
   {
	   bEnableLighting = false;
   }
   else if(KEY_DOWN(VK_F2))
   {
	   bEableBackfaceRemove = true;
   }
   else if(KEY_DOWN(VK_F3))
   {
	   bEableBackfaceRemove = false;
   }
   else if(KEY_DOWN(VK_F4))
   {
	   bEnableInvZBuffer = true;
   }
   else if(KEY_DOWN(VK_F5))
   {
	   bEnableInvZBuffer = false;
   }
   if(bEnableInvZBuffer)
    ZBuffer::GetInstance()->Clear(0);
   else
    ZBuffer::GetInstance()->Clear((1<<30)-1);

   g_RenderManager.Render(bEnableLighting,bEableBackfaceRemove,!bEnableInvZBuffer);
   g_fps++;
}
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

static int delay = 30; // initial delay per frame

// start the timing clock
DWORD start_time = Start_Clock();

// 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();

// read keyboard
DInput_Read_Keyboard();

// update delay
if (keyboard_state[DIK_RIGHT]) 
   delay+=5;
else
if (delay > 5 && keyboard_state[DIK_LEFT]) 
   delay-=5;


// draw the ship
ship.x = ship.varsF[SHIP_X_POS]+0.5;
ship.y = ship.varsF[SHIP_Y_POS]+0.5;
ship.curr_frame = 0;
Draw_BOB(&ship, lpddsback);

// draw shadow
ship.curr_frame = 1;
ship.x-=64;
ship.y+=128;
Draw_BOB(&ship, lpddsback);

// draw the title
Draw_Text_GDI("(16-Bit Version) Time Based Kinematic Motion DEMO, Press <ESC> to Exit.",10, 10,RGB(255,255,255), lpddsback);

sprintf(buffer, "Frame rate = %f, use <RIGHT>, <LEFT> arrows to change load", 1000*1/(float)delay );
Draw_Text_GDI(buffer,10, 25,RGB(255,255,255), lpddsback);

sprintf(buffer,"Ship Velocity is %f pixels/sec",1000*ship.varsF[SHIP_X_VEL]);
Draw_Text_GDI(buffer,10, 40,RGB(255,255,255), lpddsback);

// this models the load in the game
Wait_Clock(delay);

// flip the surfaces
DDraw_Flip();

// move the ship based on time //////////////////////////////////
// x = x + v*dt

// compute dt
float dt = Get_Clock() - start_time; // in milliseconds

// move based on 30 pixels per seconds or .03 pixels per millisecond
ship.varsF[SHIP_X_POS]+=(ship.varsF[SHIP_X_VEL]*dt);

// test for off screen
if (ship.varsF[SHIP_X_POS] > screen_width+ship.width)
   ship.varsF[SHIP_X_POS] = -ship.width;

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

// 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();
    } // end if

// return success
return(1);

} // end Game_Main