www.pudn.com > IntroductionTo3DGameEngineDesign.rar > GameInput.cs


using System; 
using System.Collections; 
using System.Drawing; 
using Microsoft.DirectX.DirectInput; 
using Microsoft.DirectX; 
 
namespace GameEngine 
{ 
		#region delegates 
		public delegate void ButtonAction(); 
		public delegate void AxisAction(int nCount); 
		#endregion 
 
	///  
	/// Summary description for GameInput. 
	/// This class encapsulates the interface to the keyboard and mouse.  It provides 
	/// a unified interface for the game engine where the status of any of these input devices 
	/// may be polled.  More importantly it provides the capability to invoke a supplied method 
	/// whenever a mapped keyboard or mouse button is pressed. 
	///  
	public class GameInput : IDisposable 
	{ 
		#region Attributes 
		public  bool           m_bInitialized  = false; 
 
		private KeyboardState  m_keydata       = null; 
		private MouseState     m_mousedata     = new MouseState(); 
		private JoystickState  m_joystick      = new JoystickState(); 
		private int            m_NumPov        = 0; 
		private Device         KeyboardDev     = null; 
		private Device         MouseDev        = null; 
		private Device         JoystickDev     = null; 
		private bool           m_bJoystickSet  = false; 
		private ArrayList      m_ActionMap     = new ArrayList(); 
		private ArrayList      m_AxisActionMap = new ArrayList(); 
		private int            m_MouseX        = 0; 
		private int            m_MouseY        = 0; 
		private int            m_MouseZ        = 0; 
		private static Point   m_MousePoint; 
		private System.Windows.Forms.Form m_form = null;		 
			#endregion 
 
		struct Mapping  
		{ 
			public int key; 
			public ButtonAction action; 
			public bool bOnTransition; 
		} 
 
		struct AxisMapping  
		{ 
			public int key; 
			public AxisAction action; 
		} 
 
		///  
		/// return a reference to the DirectInput device 
		///  
		///  
		public Point GetMousePoint() 
		{ 
			return m_MousePoint; 
		} 
 
		public GameInput(System.Windows.Forms.Form form) 
		{ 
			m_form = form; 
 
			try 
			{ 
 
				m_MousePoint = new Point(); 
				m_MousePoint.X = 400; 
				m_MousePoint.Y = 300; 
 
				// create the keyboard device 
				KeyboardDev = new Device( SystemGuid.Keyboard ); 
				KeyboardDev.SetCooperativeLevel( m_form, CooperativeLevelFlags.NoWindowsKey | CooperativeLevelFlags.NonExclusive | CooperativeLevelFlags.Foreground); 
				KeyboardDev.SetDataFormat(DeviceDataFormat.Keyboard); 
 
				// create the mouse device 
				MouseDev = new Device( SystemGuid.Mouse ); 
				MouseDev.SetCooperativeLevel( m_form, CooperativeLevelFlags.Exclusive | CooperativeLevelFlags.Foreground); 
				MouseDev.SetDataFormat(DeviceDataFormat.Mouse); 
 
				// Enumerate joysticks in the system. 
				foreach(DeviceInstance instance in Manager.GetDevices(DeviceClass.GameControl, EnumDevicesFlags.AttachedOnly)) 
				{ 
					// Create the device.  Just pick the first one 
					JoystickDev = new Device( instance.InstanceGuid ); 
					break; 
				} 
				if ( JoystickDev != null ) 
				{ 
					// Create the device. 
					// Set the cooperative level for the device. 
					JoystickDev.SetCooperativeLevel( m_form, CooperativeLevelFlags.Exclusive | CooperativeLevelFlags.Foreground); 
					// Set the data format to the Joystick pre-defined format. 
					JoystickDev.SetDataFormat(DeviceDataFormat.Joystick); 
 
					// Now find out how many POV's the device has 
					// for displaying info in the UI thread. 
					m_NumPov = JoystickDev.Caps.NumberPointOfViews; 
					m_bJoystickSet = true; 
					try 
					{ 
						JoystickDev.Acquire(); 
					} 
					catch{} 
				} 
			} 
			catch {} 
 
		} 
 
		// poll method 
		public void Poll() 
		{ 
		KeyboardState oldkeydata = null; 
 
		// Bool flag that is set when it's ok 
		// to get device state information. 
		bool bKeyboardOk = false; 
		bool bMouseOk = false; 
		bool bJoystickOk = false; 
			 
 
			MouseState oldmousedata = new MouseState(); 
			JoystickState oldjoystickdata = new JoystickState(); 
 
			oldkeydata = m_keydata; 
 
			// get keyboard data 
			try 
			{ 
				KeyboardDev.Poll(); 
				bKeyboardOk = true; 
			} 
			catch(InputException ex) 
			{ 
				// Check to see if either the app 
				// needs to acquire the device, or 
				// if the app lost the device to another 
				// process. 
				if ( (ex is NotAcquiredException)  ) 
				{ 
					try 
					{ 
						// Reacquire the device. 
						KeyboardDev.Acquire(); 
						// Set the flag for now. 
						bKeyboardOk = true; 
					} 
					catch(InputException ex2) 
					{								 
						if ( ex2 is OtherApplicationHasPriorityException) 
						{	// Something very odd happened. 
							Console.AddLine("An unknown error has occcurred. This app won't be able to process device info."); 
						} 
						// Failed to aquire the device. 
						// This could be because the app 
						// doesn't have focus. 
						bKeyboardOk = false; 
					} 
				} 
				else 
				{ 
					KeyboardDev = new Device( SystemGuid.Keyboard ); 
					KeyboardDev.SetCooperativeLevel( m_form, CooperativeLevelFlags.NoWindowsKey | CooperativeLevelFlags.NonExclusive | CooperativeLevelFlags.Foreground); 
					KeyboardDev.SetDataFormat(DeviceDataFormat.Keyboard); 
				} 
			} 
 
			// get mouse data 
			try 
			{ 
				MouseDev.Poll(); 
				bMouseOk = true; 
			} 
			catch(InputException ex) 
			{ 
				// Check to see if either the app 
				// needs to acquire the device, or 
				// if the app lost the device to another 
				// process. 
				if ( (ex is NotAcquiredException) ) 
				{ 
					try 
					{ 
						// Reacquire the device. 
						MouseDev.Acquire(); 
						// Set the flag for now. 
						bMouseOk = true; 
//						Console.AddLine("had to reacquire the mouse"); 
					} 
					catch(InputException ex2) 
					{								 
						if ( ex2 is OtherApplicationHasPriorityException ) 
						{	// Something very odd happened. 
							System.Diagnostics.Debug.WriteLine("An unknown error has occcurred. This app won't be able to process device info. " + ex2.ErrorString); 
						} 
						// Failed to aquire the device. 
						// This could be because the app 
						// doesn't have focus. 
						bMouseOk = false; 
					} 
				} 
				else 
				{ 
					System.Diagnostics.Debug.WriteLine(ex.ErrorString); 
					MouseDev.Dispose(); 
					MouseDev = new Device( SystemGuid.Mouse ); 
					MouseDev.SetCooperativeLevel( m_form, CooperativeLevelFlags.Exclusive | CooperativeLevelFlags.Foreground); 
					MouseDev.SetDataFormat(DeviceDataFormat.Mouse); 
				} 
			} 
 
			// get joystick data 
			try 
			{ 
				if ( m_bJoystickSet )  
				{ 
					JoystickDev.Poll(); 
					bJoystickOk = true; 
				} 
			} 
			catch(InputException ex) 
			{ 
				// Check to see if either the app 
				// needs to acquire the device, or 
				// if the app lost the device to another 
				// process. 
				if ( (ex is NotAcquiredException) ) 
				{ 
					try 
					{ 
						if ( JoystickDev != null ) 
						{ 
							// Create the device. 
							// Set the cooperative level for the device. 
							JoystickDev.SetCooperativeLevel( m_form, CooperativeLevelFlags.Exclusive | CooperativeLevelFlags.Foreground); 
							// Set the data format to the Joystick pre-defined format. 
							JoystickDev.SetDataFormat(DeviceDataFormat.Joystick); 
 
							// Now find out how many POV's the device has 
							// for displaying info in the UI thread. 
							m_NumPov = JoystickDev.Caps.NumberPointOfViews; 
							m_bJoystickSet = true; 
						} 
						// Reacquire the device. 
						JoystickDev.Acquire(); 
						// Set the flag for now. 
						bJoystickOk = true; 
					} 
					catch(InputException ex2) 
					{								 
						if (  ex2 is OtherApplicationHasPriorityException ) 
						{	// Something very odd happened. 
							Console.AddLine("An unknown error has occcurred. This app won't be able to process device info."); 
						} 
						// Failed to aquire the device. 
						// This could be because the app 
						// doesn't have focus. 
						bJoystickOk = false; 
					} 
				} 
				else  
				{ 
					if ( JoystickDev != null ) 
					{ 
						// Create the device. 
						// Set the cooperative level for the device. 
						JoystickDev.SetCooperativeLevel( m_form, CooperativeLevelFlags.Exclusive | CooperativeLevelFlags.Foreground); 
						// Set the data format to the Joystick pre-defined format. 
						JoystickDev.SetDataFormat(DeviceDataFormat.Joystick); 
 
						// Now find out how many POV's the device has 
						// for displaying info in the UI thread. 
						m_NumPov = JoystickDev.Caps.NumberPointOfViews; 
						m_bJoystickSet = true; 
						// Reacquire the device. 
						try 
						{ 
							JoystickDev.Acquire(); 
						} 
						catch{} 
 
						// Set the flag for now. 
						bJoystickOk = true; 
					} 
				} 
			} 
			if (bJoystickOk == true) 
			{ 
				// Get the state of the device 
				try	{ m_joystick = JoystickDev.CurrentJoystickState; } 
					// Catch any exceptions. None will be handled here,  
					// any device re-aquisition will be handled above.	 
				catch(DirectXException){} 
			} 
 
			try  
			{ 
			    if ( bKeyboardOk ) 
				{ 
				   m_keydata = KeyboardDev.GetCurrentKeyboardState(); 
				} 
			    if ( bMouseOk ) 
				{ 
				    m_mousedata = MouseDev.CurrentMouseState; 
					m_MouseX += m_mousedata.X; 
					m_MouseY += m_mousedata.Y; 
					m_MouseZ += m_mousedata.Z; 
 
					m_MousePoint.X += m_mousedata.X; 
					m_MousePoint.Y += m_mousedata.Y; 
 
				} 
 
				// call any axis actions 
				foreach ( AxisMapping map in m_AxisActionMap ) 
				{ 
					switch ( map.key )  
					{ 
						case 0: 
							map.action(m_mousedata.X); 
							break; 
						case 1: 
							map.action(m_mousedata.Y); 
							break; 
						case 2: 
							map.action(m_mousedata.Z); 
							break; 
						case 3: 
							map.action(m_joystick.X); 
							break; 
						case 4: 
							map.action(m_joystick.X); 
							break; 
						case 5: 
							map.action(m_joystick.X); 
							break; 
					} 
				} 
 
				// only process the action map if the console is not visible 
				if ( !GameEngine.Console.IsVisible ) 
				{ 
					foreach ( Mapping map in m_ActionMap )  
					{ 
						// if this is against the keyboard 
						if ( map.key < 256 )  
						{ 
							if ( m_keydata[(Key)map.key]  )  
							{ 
								if ( !map.bOnTransition || oldkeydata[(Key)map.key]  )  
								{ 
									map.action(); 
								} 
							} 
						}  
						else if ( map.key < 264 )  // space for 8 mouse buttons 
						{ 
							if ( (m_mousedata.GetMouseButtons()[map.key-256] & 0x80) != 0 )  
							{ 
								if ( !map.bOnTransition || (oldmousedata.GetMouseButtons()[map.key-256] & 0x80) == 0 )  
								{ 
									map.action(); 
								} 
							} 
						} 
						else  // joystick buttons 
						{ 
							if ( (m_joystick.GetButtons()[map.key-264] & 0x80) != 0 )  
							{ 
								if ( !map.bOnTransition || (oldjoystickdata.GetButtons()[map.key-264] & 0x80) == 0 )  
								{ 
									map.action(); 
								} 
							} 
						} 
					} 
				} 
			} 
			catch {} 
		} 
 
		public bool IsMouseButtonDown( int nButton ) 
		{ 
			return (m_mousedata.GetMouseButtons()[nButton] & 0x80) != 0; 
		} 
 
		// Check if any buttons were pressed 
		public bool IsKeyPressed() 
		{ 
			bool bPressed = false; 
 
///TODO			foreach ( byte b in m_keydata )  
//			{ 
//				if ( (b & 0x80) > 0 ) bPressed = true; 
//			} 
			return bPressed; 
		} 
 
		// Check if any buttons were pressed 
		public bool IsKeyPressed(Key key) 
		{ 
			bool bPressed = false; 
			try  
			{ 
				bPressed = m_keydata[key] ; 
			} 
			catch 
			{ 
			} 
 
			return bPressed; 
		} 
 
		// method to map a key to an action 
		public void MapKeyboardAction( Key key, ButtonAction proc, bool bTransition ) 
		{ 
			Mapping map = new Mapping(); 
			map.key = (int)key; 
			map.action = proc; 
			map.bOnTransition = bTransition; 
			m_ActionMap.Add(map); 
		} 
 
		// method to map a mouse button to an action 
		public void MapMouseButtonAction( int nButton, ButtonAction proc, bool bTransition ) 
		{ 
			Mapping map = new Mapping(); 
			map.key = nButton + 256; 
			map.action = proc; 
			map.bOnTransition = bTransition; 
			m_ActionMap.Add(map); 
		} 
 
		// method to map a joystick button to an action 
		public void MapJoystickButtonAction( int nButton, ButtonAction proc, bool bTransition ) 
		{ 
			Mapping map = new Mapping(); 
			map.key = nButton + 264; 
			map.action = proc; 
			map.bOnTransition = bTransition; 
			m_ActionMap.Add(map); 
		} 
 
		// method to map a mouse axis to an action 
		public void MapMouseAxisAction( int nAxis, AxisAction proc ) 
		{ 
			AxisMapping map = new AxisMapping(); 
			map.key = nAxis; 
			map.action = proc; 
			m_AxisActionMap.Add(map); 
		} 
 
		// method to map a joystick axis to an action 
		public void MapJoystickAxisAction( int nAxis, AxisAction proc ) 
		{ 
			AxisMapping map = new AxisMapping(); 
			map.key = nAxis + 3; 
			map.action = proc; 
			m_AxisActionMap.Add(map); 
		} 
 
		public void UnMapKeyboardAction( Key key ) 
		{ 
			foreach ( Mapping map in m_ActionMap )  
			{ 
				if ( map.key == (int)key )  
				{ 
					m_ActionMap.Remove(map); 
				} 
			} 
		} 
 
		public void UnMapMouseButtonAction( int nButton ) 
		{ 
			foreach ( Mapping map in m_ActionMap )  
			{ 
				if ( map.key == (nButton + 256) )  
				{ 
					m_ActionMap.Remove(map); 
				} 
			} 
		} 
 
		public void UnMapMouseAxisAction( int nAxis ) 
		{ 
			foreach ( AxisMapping map in m_AxisActionMap )  
			{ 
				if ( map.key == nAxis )  
				{ 
					m_AxisActionMap.Remove(map); 
				} 
			} 
		} 
 
		public void UnMapJoystickButtonAction( int nButton ) 
		{ 
			foreach ( Mapping map in m_ActionMap )  
			{ 
				if ( map.key == (nButton + 264) )  
				{ 
					m_ActionMap.Remove(map); 
				} 
			} 
		} 
 
		public void UnMapJoystickAxisAction( int nAxis ) 
		{ 
			foreach ( AxisMapping map in m_AxisActionMap )  
			{ 
				if ( map.key == (nAxis+3) )  
				{ 
					m_AxisActionMap.Remove(map); 
				} 
			} 
		} 
 
		public void ClearActionMaps() 
		{ 
			m_ActionMap.Clear(); 
			m_AxisActionMap.Clear(); 
		} 
 
 
		///  
		/// Get the current mouse X value 
		///  
		public int GetMouseX() 
		{ 
			int nResult = m_MouseX; 
 
			m_MouseX = 0; 
			return nResult; 
		} 
 
		///  
		/// Get the current mouse Y value 
		///  
		public int GetMouseY() 
		{ 
			int nResult = m_MouseY; 
 
			m_MouseY = 0; 
			return nResult; 
		} 
 
		///  
		/// Get the current mouse Z value (mouse wheel) 
		///  
		public int GetMouseZ() 
		{ 
			int nResult = m_MouseZ; 
 
			m_MouseZ = 0; 
			return nResult; 
		} 
 
		///  
		/// Get joystick axis data 
		///  
		public int GetJoystickX( ) 
		{ 
			if ( m_bJoystickSet )  
			{ 
				return m_joystick.X; 
			}  
			else  
			{ 
				return 0; 
			} 
		} 
 
		///  
		/// Get normalized joystick axis data 
		///  
		public float GetJoystickNormalX( ) 
		{ 
			if ( m_bJoystickSet )  
			{ 
				return (float)m_joystick.X/(float)short.MaxValue; 
			}  
			else  
			{ 
				return 0; 
			} 
		} 
 
		///  
		/// Get joystick axis data 
		///  
		public int GetJoystickY( ) 
		{ 
			if ( m_bJoystickSet )  
			{ 
				return m_joystick.Y; 
			}  
			else  
			{ 
				return 0; 
			} 
		} 
 
		///  
		/// Get normalized joystick axis data 
		///  
		public float GetJoystickNormalY( ) 
		{ 
			if ( m_bJoystickSet )  
			{ 
				return (float)m_joystick.Y/(float)short.MaxValue; 
			}  
			else  
			{ 
				return 0; 
			} 
		} 
 
		///  
		/// Get joystick axis data 
		///  
		public int GetJoystickZ( ) 
		{ 
			if ( m_bJoystickSet )  
			{ 
				return m_joystick.Z; 
			}  
			else  
			{ 
				return 0; 
			} 
		} 
 
		///  
		/// Get joystick button data 
		///  
		public bool GetJoystickButton( int nIndex ) 
		{ 
			if ( m_bJoystickSet && nIndex < 32 )  
			{ 
				return m_joystick.GetButtons()[nIndex] != 0; 
			}  
			else  
			{ 
				return false; 
			} 
		} 
 
		///  
		/// Get joystick slider data 
		///  
		public int GetJoystickSlider( int nIndex ) 
		{ 
			if ( m_bJoystickSet && nIndex < 2 )  
			{ 
				return m_joystick.GetSlider()[nIndex]; 
			}  
			else  
			{ 
				return 0; 
			} 
		} 
 
		//Dispose method 
		public void Dispose() 
		{ 
			KeyboardDev.Unacquire(); 
			KeyboardDev.Dispose(); 
			MouseDev.Unacquire(); 
			MouseDev.Dispose(); 
			if ( m_bJoystickSet )  
			{ 
				JoystickDev.Unacquire(); 
				JoystickDev.Dispose(); 
			} 
		} 
 
	} 
}