using System; using FarseerPhysics; using FarseerPhysics.DebugViews; using FarseerPhysics.Dynamics; using FarseerPhysics.Dynamics.Joints; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Input; using FarseerPhysics.SamplesFramework; using Axios.Engine; namespace GameStateManagement { public class PhysicsGameScreen : GameScreen { public Camera2D Camera; protected DebugViewXNA DebugView; public World World; private float _agentForce; private float _agentTorque; private FixedMouseJoint _fixedMouseJoint; private Body _userAgent; public bool UseSecondStep = false; protected PhysicsGameScreen() { TransitionOnTime = TimeSpan.FromSeconds(0.75); TransitionOffTime = TimeSpan.FromSeconds(0.75); #if DEBUG EnableCameraControl = true; HasCursor = true; #else EnableCameraControl = false; HasCursor = false; #endif _userAgent = null; World = null; Camera = null; DebugView = null; } public bool EnableCameraControl { get; set; } protected void SetUserAgent(Body agent, float force, float torque) { _userAgent = agent; _agentForce = force; _agentTorque = torque; } public override void Activate(bool instancePreserved) { if (!instancePreserved) { base.Activate(instancePreserved); //We enable diagnostics to show get values for our performance counters. FarseerPhysics.Settings.EnableDiagnostics = true; if (World == null) { World = new World(Vector2.Zero); } else { World.Clear(); } if (DebugView == null) { if (!Axios.Settings.ScreenSaver) { ContentManager man = new ContentManager(this.ScreenManager.Game.Services, "Content"); DebugView = new DebugViewXNA(World); DebugView.RemoveFlags(DebugViewFlags.Shape); DebugView.RemoveFlags(DebugViewFlags.Joint); DebugView.DefaultShapeColor = Color.White; DebugView.SleepingShapeColor = Color.LightGray; DebugView.LoadContent(ScreenManager.GraphicsDevice, man); } } if (Camera == null) { Camera = new Camera2D(ScreenManager.GraphicsDevice); } else { Camera.ResetCamera(); } // Loading may take a while... so prevent the game from "catching up" once we finished loading ScreenManager.Game.ResetElapsedTime(); } } public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen) { if (!coveredByOtherScreen && !otherScreenHasFocus && ScreenState != GameStateManagement.ScreenState.TransitionOff) { // variable time step but never less then 30 Hz if (UseSecondStep) World.Step(Math.Min((float)gameTime.ElapsedGameTime.TotalSeconds, (1f / 30f))); else World.Step((float)(gameTime.ElapsedGameTime.TotalMilliseconds * 0.001)); } else { World.Step(0f); } Camera.Update(gameTime); base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen); } public virtual void CleanUp() { } public override void HandleInput(GameTime gameTime, InputState input) { #if DEBUG // Control debug view PlayerIndex player; if (input.IsNewButtonPress(Buttons.Start, ControllingPlayer.Value, out player)) { EnableOrDisableFlag(DebugViewFlags.Shape); EnableOrDisableFlag(DebugViewFlags.DebugPanel); EnableOrDisableFlag(DebugViewFlags.PerformanceGraph); EnableOrDisableFlag(DebugViewFlags.Joint); EnableOrDisableFlag(DebugViewFlags.ContactPoints); EnableOrDisableFlag(DebugViewFlags.ContactNormals); EnableOrDisableFlag(DebugViewFlags.Controllers); } if (input.IsNewKeyPress(Keys.F1, ControllingPlayer.Value, out player)) { EnableOrDisableFlag(DebugViewFlags.Shape); } if (input.IsNewKeyPress(Keys.F2, ControllingPlayer.Value, out player)) { EnableOrDisableFlag(DebugViewFlags.DebugPanel); EnableOrDisableFlag(DebugViewFlags.PerformanceGraph); } if (input.IsNewKeyPress(Keys.F3, ControllingPlayer.Value, out player)) { EnableOrDisableFlag(DebugViewFlags.Joint); } if (input.IsNewKeyPress(Keys.F4, ControllingPlayer.Value, out player)) { EnableOrDisableFlag(DebugViewFlags.ContactPoints); EnableOrDisableFlag(DebugViewFlags.ContactNormals); } if (input.IsNewKeyPress(Keys.F5, ControllingPlayer.Value, out player)) { EnableOrDisableFlag(DebugViewFlags.PolygonPoints); } if (input.IsNewKeyPress(Keys.F6, ControllingPlayer.Value, out player)) { EnableOrDisableFlag(DebugViewFlags.Controllers); } if (input.IsNewKeyPress(Keys.F7, ControllingPlayer.Value, out player)) { EnableOrDisableFlag(DebugViewFlags.CenterOfMass); } if (input.IsNewKeyPress(Keys.F8, ControllingPlayer.Value, out player)) { EnableOrDisableFlag(DebugViewFlags.AABB); } #endif if (_userAgent != null) { HandleUserAgent(input); } if (EnableCameraControl) { HandleCamera(input, gameTime); } if (HasCursor) { HandleCursor(input); } PlayerIndex i; if (input.IsNewButtonPress(Buttons.Back, PlayerIndex.One, out i) || input.IsNewKeyPress(Keys.Escape, PlayerIndex.One, out i)) { //if (this.ScreenState == GameStateManagement.ScreenState.Active && this.TransitionPosition == 0 && this.TransitionAlpha == 1) //{ //Give the screens a chance to transition CleanUp(); ExitScreen(); //} } base.HandleInput(gameTime, input); } public virtual void HandleCursor(InputState input) { PlayerIndex player; Vector2 position = Camera.ConvertScreenToWorld(input.Cursor); if ((input.IsNewButtonPress(Buttons.A, PlayerIndex.One, out player) || input.IsNewMouseButtonPress(MouseButtons.LeftButton)) && _fixedMouseJoint == null) { Fixture savedFixture = World.TestPoint(position); if (savedFixture != null && savedFixture.UserData is SimpleAxiosGameObject && ((SimpleAxiosGameObject)(savedFixture.UserData)).AllowAutomaticMouseJoint) { Body body = savedFixture.Body; _fixedMouseJoint = new FixedMouseJoint(body, position); _fixedMouseJoint.MaxForce = 1000.0f * body.Mass; World.AddJoint(_fixedMouseJoint); body.Awake = true; } } if ((input.IsNewButtonRelease(Buttons.A, ControllingPlayer.Value, out player) || input.IsNewMouseButtonRelease(MouseButtons.LeftButton)) && _fixedMouseJoint != null) { World.RemoveJoint(_fixedMouseJoint); _fixedMouseJoint = null; } if (_fixedMouseJoint != null) { _fixedMouseJoint.WorldAnchorB = position; } } private void HandleCamera(InputState input, GameTime gameTime) { Vector2 camMove = Vector2.Zero; if (input.CurrentKeyboardStates[0].IsKeyDown(Keys.Up)) { camMove.Y -= 10f * (float)gameTime.ElapsedGameTime.TotalSeconds; } if (input.CurrentKeyboardStates[0].IsKeyDown(Keys.Down)) { camMove.Y += 10f * (float)gameTime.ElapsedGameTime.TotalSeconds; } if (input.CurrentKeyboardStates[0].IsKeyDown(Keys.Left)) { camMove.X -= 10f * (float)gameTime.ElapsedGameTime.TotalSeconds; } if (input.CurrentKeyboardStates[0].IsKeyDown(Keys.Right)) { camMove.X += 10f * (float)gameTime.ElapsedGameTime.TotalSeconds; } if (input.CurrentKeyboardStates[0].IsKeyDown(Keys.PageUp)) { Camera.Zoom += 5f * (float)gameTime.ElapsedGameTime.TotalSeconds * Camera.Zoom / 20f; } if (input.CurrentKeyboardStates[0].IsKeyDown(Keys.PageDown)) { Camera.Zoom -= 5f * (float)gameTime.ElapsedGameTime.TotalSeconds * Camera.Zoom / 20f; } if (camMove != Vector2.Zero) { Camera.MoveCamera(camMove); } PlayerIndex i; if (input.IsNewKeyPress(Keys.Home, PlayerIndex.One, out i)) { Camera.ResetCamera(); } } private void HandleUserAgent(InputState input) { Vector2 force = _agentForce * new Vector2(input.CurrentGamePadStates[0].ThumbSticks.Right.X, -input.CurrentGamePadStates[0].ThumbSticks.Right.Y); float torque = _agentTorque * (input.CurrentGamePadStates[0].Triggers.Right - input.CurrentGamePadStates[0].Triggers.Left); _userAgent.ApplyForce(force); _userAgent.ApplyTorque(torque); float forceAmount = _agentForce * 0.6f; force = Vector2.Zero; torque = 0; if (input.CurrentKeyboardStates[0].IsKeyDown(Keys.A)) { force += new Vector2(-forceAmount, 0); } if (input.CurrentKeyboardStates[0].IsKeyDown(Keys.S)) { force += new Vector2(0, forceAmount); } if (input.CurrentKeyboardStates[0].IsKeyDown(Keys.D)) { force += new Vector2(forceAmount, 0); } if (input.CurrentKeyboardStates[0].IsKeyDown(Keys.W)) { force += new Vector2(0, -forceAmount); } if (input.CurrentKeyboardStates[0].IsKeyDown(Keys.Q)) { torque -= _agentTorque; } if (input.CurrentKeyboardStates[0].IsKeyDown(Keys.E)) { torque += _agentTorque; } _userAgent.ApplyForce(force); _userAgent.ApplyTorque(torque); } private void EnableOrDisableFlag(DebugViewFlags flag) { if ((DebugView.Flags & flag) == flag) { DebugView.RemoveFlags(flag); } else { DebugView.AppendFlags(flag); } } public override void Draw(GameTime gameTime) { Matrix projection = Camera.SimProjection; Matrix view = Camera.SimView; if (!Axios.Settings.ScreenSaver) DebugView.RenderDebugData(ref projection, ref view); base.Draw(gameTime); } } }