/// <summary>Gets the input induced camera offset, based on mouse position or game pad state.</summary> /// <returns>The offset based on player input.</returns> private Vector2 GetInputInducedOffset() { Vector2 offset; offset.X = 0; offset.Y = 0; // Get viewport, for mouse position scaling and offset scaling. var viewport = _graphics.Viewport; var offsetScale = new Vector2(viewport.Width, viewport.Height).Length() / 6f; var inputManager = (InputManager)_services.GetService(typeof(InputManager)); var mouse = inputManager.GetMouse(); // If we have a game pad attached, get the stick tilt. if (Settings.Instance.EnableGamepad) { foreach (var gamepad in inputManager.GamePads) { if (gamepad.IsAttached) { offset = GamePadHelper.GetLook(gamepad); // Only use the first gamepad we can find. break; } } } else if (mouse != null) { // Otherwise use the mouse. var state = mouse.GetState(); // Get the relative position of the mouse to the ship and // apply some factoring to it (so that the maximum distance // of cursor to ship is not half the screen size). if (state.X >= 0 && state.X < viewport.Width) { offset.X = ((state.X / (float)viewport.Width) - 0.5f) * 2; } if (state.Y >= 0 && state.Y < viewport.Height) { offset.Y = ((state.Y / (float)viewport.Height) - 0.5f) * 2; } } // Normalize the vector. This way we get some 'dead area' when controlling with the mouse // in the corners of the screen (where the offset length won't change), but we get the same // effect as we'd get it with the game pad, keeping it fair in how far players can look. if (offset.LengthSquared() > 1) { offset.Normalize(); } return(XnaUnitConversion.ToSimulationUnits(offset * offsetScale)); }
public override void Update(GameTime gameTime) { base.Update(gameTime); // Rescan input devices periodically, e.g. to accept newly connected gamepads. if ((DateTime.UtcNow - _lastInputDeviceScan).TotalSeconds > InputDeviceScanInterval) { AttachListeners(); _lastInputDeviceScan = DateTime.UtcNow; } // Disregard the rest if we're not connected. if (!IsConnected) { // Reset periodic update values. _accelerationDirection = Directions.None; _accelerationVector = Vector2.Zero; _accelerationChanged = DateTime.MinValue; _targetRotation = 0; _rotationChanged = DateTime.MinValue; _lastUpdate = DateTime.MinValue; return; } // Handle game pad input that we can't properly handle via events. if (Settings.Instance.EnableGamepad && _gamePad != null && _gamePad.IsAttached) { // Handle movement of the left stick, which controls our movement. var gamepadAcceleration = GamePadHelper.GetAcceleration(_gamePad); if (gamepadAcceleration != _previousGamepadAcceleration) { _accelerationVector = gamepadAcceleration; _accelerationChanged = DateTime.UtcNow; } _previousGamepadAcceleration = gamepadAcceleration; // Handle movement of the right stick, which controls our direction. var gamepadLook = GamePadHelper.GetLook(_gamePad); if (gamepadLook != _previousGamepadLook && gamepadLook != Vector2.Zero) { _targetRotation = (float)Math.Atan2(gamepadLook.Y, gamepadLook.X); _rotationChanged = DateTime.UtcNow; } _previousGamepadLook = gamepadLook; } // See if we want to re-orientate the ship and whether the acceleration // changed. Only check every so often, as slight delays here will not be // as noticeable, due to the ship's slow turn/acceleration speed. if ((DateTime.UtcNow - _lastUpdate).TotalMilliseconds > AnalogPollInterval) { // Has the mouse moved since the last update? if (_rotationChanged >= _lastUpdate) { // Yes, push command. BeginCommand(GameCommand.Rotate); } // Has the acceleration changed since the last update? if (_accelerationChanged >= _lastUpdate) { // Yes, push command. BeginCommand(GameCommand.Accelerate); } _lastUpdate = DateTime.UtcNow; } }