Advertisement
Guest User

Camera2D

a guest
Apr 9th, 2010
844
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 17.60 KB | None | 0 0
  1. using System;
  2. using FarseerGames.FarseerPhysics.Dynamics;
  3. using Microsoft.Xna.Framework;
  4. using Microsoft.Xna.Framework.Input;
  5. using Microsoft.Xna.Framework.Graphics;
  6. using FarseerGames.FarseerPhysics.Collisions;
  7.  
  8. namespace AmazingGadgets
  9. {
  10.     public class Camera2D
  11.     {
  12.         Vector2 _position = Vector2.Zero;
  13.         Vector2 _origPosition = Vector2.Zero;
  14.         Vector2 _targetPosition = Vector2.Zero;
  15.         float _moveRate = 1;
  16.         float _rotation = 0;
  17.         float _origRotation = 0;
  18.         float _targetRotation = 0;
  19.         float _zoom = 1;
  20.         float _origZoom = 1;
  21.         float _targetZoom = 1;
  22.         float _zoomRate = 0.01f;
  23.         float _maxZoom = 4;
  24.         float _minZoom = 0.25f;
  25.         float _rotationRate = 0.01f;
  26.         float _transition;
  27.         bool _transitioning = false;
  28.         const float _transitionSpeed = 0.01f;
  29.         const float _smoothingSpeed = 0.15f;
  30.         bool positionUnset = true;
  31.         bool _zoomUnset = true;
  32.         bool _rotationUnset = true;
  33.         Vector2 _size;
  34.         Vector2 _minPosition = Vector2.Zero;
  35.         Vector2 _maxPosition = Vector2.Zero;
  36.         Body _trackingBody;
  37.         Func<InputHelper, bool> _zoomIn = (InputHelper input) =>
  38.         {
  39.             return input.IsCurPress(Buttons.DPadUp);
  40.         };
  41.         Func<InputHelper, bool> _zoomOut = (InputHelper input) =>
  42.         {
  43.             return input.IsCurPress(Buttons.DPadDown);
  44.         };
  45.  
  46.         Func<Camera2D, bool> _clampingEnabled = (Camera2D camera) =>
  47.         {
  48.             return (camera._minPosition != camera._maxPosition);
  49.         };
  50.  
  51.         Func<InputHelper, Camera2D, float> _horizontalCameraMovement =
  52.             (InputHelper input, Camera2D camera) =>
  53.         {
  54.             return (input.RightStickPosition.X * camera._moveRate) * camera._zoom;
  55.         };
  56.  
  57.         Func<InputHelper, Camera2D, float> _verticalCameraMovement =
  58.             (InputHelper input, Camera2D camera) =>
  59.         {
  60.             return (input.RightStickPosition.Y * camera._moveRate) * camera.Zoom;
  61.         };
  62.  
  63.         Func<InputHelper, bool> _rotateLeft = (InputHelper input) =>
  64.         {
  65.             return false;
  66.         };
  67.  
  68.         Func<InputHelper, bool> _rotateRight = (InputHelper input) =>
  69.         {
  70.             return false;
  71.         };
  72.  
  73.         Func<InputHelper, bool> _resetCamera = (InputHelper input) =>
  74.         {
  75.             return input.IsCurPress(Buttons.RightStick);
  76.         };
  77.  
  78.  
  79.         /// <summary>
  80.         /// The constructor for the Camera2D class.
  81.         /// </summary>
  82.         /// <param name="size">
  83.         /// the size of the camera's view when at zoom = 1. This is usually
  84.         /// set to the viewport's size.
  85.         /// </param>
  86.         public Camera2D(Vector2 size)
  87.         {
  88.             _size = size;
  89.         }
  90.         /// <summary>
  91.         /// The current position of the camera.
  92.         /// </summary>
  93.         public Vector2 Position
  94.         {
  95.             get { return _position; }
  96.             set
  97.             {
  98.                 if (positionUnset == true)
  99.                 {
  100.                     _origPosition = value;
  101.                     positionUnset = false;
  102.                 }
  103.                 _position = value;
  104.                 _targetPosition = value;
  105.             }
  106.         }
  107.         /// <summary>
  108.         /// The current rotation of the camera in radians.
  109.         /// </summary>
  110.         public float Rotation
  111.         {
  112.             get { return _rotation; }
  113.             set
  114.             {
  115.                 if (_rotationUnset == true)
  116.                 {
  117.                     _origRotation = value;
  118.                     _rotationUnset = false;
  119.                 }
  120.                 _rotation = value;
  121.                 _targetRotation = value;
  122.             }
  123.         }
  124.         /// <summary>
  125.         /// The current zoom of the camera. This is a value indicating
  126.         /// how far zoomed in or out the camera is. To get the actual
  127.         /// current size of the camera view, see CurSize.
  128.         /// </summary>
  129.         public float Zoom
  130.         {
  131.             get { return _zoom; }
  132.             set
  133.             {
  134.                 if (_zoomUnset == true)
  135.                 {
  136.                     _origZoom = value;
  137.                     _zoomUnset = false;
  138.                 }
  139.                 _zoom = value;
  140.                 _targetZoom = value;
  141.             }
  142.         }
  143.         /// <summary>
  144.         /// the furthest zoomed in the camera can be. Larger numbers
  145.         /// are further zoomed in.
  146.         /// </summary>
  147.         public float MaxZoom
  148.         {
  149.             get { return _maxZoom; }
  150.             set { _maxZoom = value; }
  151.         }
  152.         /// <summary>
  153.         /// The futhest zoomed out that the camera can be. Smaller numbers
  154.         /// are further zoomed out.
  155.         /// </summary>
  156.         public float MinZoom
  157.         {
  158.             get { return _minZoom; }
  159.             set { _minZoom = value; }
  160.         }
  161.         /// <summary>
  162.         /// The amount that the camera rotates (in radians) in one timestep.
  163.         /// </summary>
  164.         public float RotationRate
  165.         {
  166.             get { return _rotationRate; }
  167.             set { _rotationRate = value; }
  168.         }
  169.         /// <summary>
  170.         /// The amount that the camera zooms in or out in one timestep.
  171.         /// </summary>
  172.         public float ZoomRate
  173.         {
  174.             get { return _zoomRate; }
  175.             set { _zoomRate = value; }
  176.         }
  177.         /// <summary>
  178.         /// The rate at which the camera moves in one timestep.
  179.         /// </summary>
  180.         public float MoveRate
  181.         {
  182.             get { return _moveRate; }
  183.             set { _moveRate = value; }
  184.         }
  185.         /// <summary>
  186.         /// A vector representing the size of the camera when zoom is at 1.
  187.         /// </summary>
  188.         public Vector2 Size
  189.         {
  190.             get { return _size; }
  191.             //i think changing the camera size on the fly
  192.             //would screw up stuff
  193.             //set { _size = value; }
  194.         }
  195.         /// <summary>
  196.         /// a vector representing the current size of the camera view.
  197.         /// Expressed as: Size * (1 / zoom).
  198.         /// </summary>
  199.         public Vector2 CurSize
  200.         {
  201.             get { return Vector2.Multiply(_size, 1 / _zoom); }
  202.         }
  203.         /// <summary>
  204.         /// A matrix representing the camera's current position, rotation, and zoom.
  205.         /// Feed this to SpriteBatch.Begin (or use it in your matrix calculations for
  206.         /// drawing 2D polygons)
  207.         /// </summary>
  208.         public Matrix CameraMatrix
  209.         {
  210.             get
  211.             {
  212.                 return Matrix.Identity *
  213.                       Matrix.CreateTranslation(new Vector3(-_position, 0)) *
  214.                       Matrix.CreateScale(_zoom) *
  215.                       Matrix.CreateRotationZ(_rotation) *
  216.                       Matrix.CreateTranslation(new Vector3(_size / 2, 0));
  217.             }
  218.         }
  219.         /// <summary>
  220.         /// The furthest up, and the furthest left the camera can go.
  221.         /// if this value equals maxPosition, then no clamping will be
  222.         /// applied (unless you override that function).
  223.         /// </summary>
  224.         public Vector2 MinPosition
  225.         {
  226.             get { return _minPosition; }
  227.             set { _minPosition = value; }
  228.         }
  229.         /// <summary>
  230.         /// the furthest down, and the furthest right the camera will go.
  231.         /// if this value equals minPosition, then no clamping will be
  232.         /// applied (unless you override that function).
  233.         /// </summary>
  234.         public Vector2 MaxPosition
  235.         {
  236.             get { return _maxPosition; }
  237.             set { _maxPosition = value; }
  238.         }
  239.         /// <summary>
  240.         /// the body that this camera is currently tracking.
  241.         /// Null if not tracking any.
  242.         /// </summary>
  243.         public Body TrackingBody
  244.         {
  245.             get { return _trackingBody; }
  246.             set { _trackingBody = value; }
  247.         }
  248.         /// <summary>
  249.         /// a function that is called to determine if the user wants
  250.         /// to zoom in.
  251.         /// </summary>
  252.         public Func<InputHelper, bool> ZoomIn
  253.         {
  254.             get { return _zoomIn; }
  255.             set { _zoomIn = value; }
  256.         }
  257.         /// <summary>
  258.         /// a function that is called to determine whether the user wants
  259.         /// to zoom out.
  260.         /// </summary>
  261.         public Func<InputHelper, bool> ZoomOut
  262.         {
  263.             get { return _zoomOut; }
  264.             set { _zoomOut = value; }
  265.         }
  266.         /// <summary>
  267.         /// a function that determines whether clamping is currently enabled
  268.         /// for this camera.
  269.         /// </summary>
  270.         public Func<Camera2D, bool> ClampingEnabled
  271.         {
  272.             get { return _clampingEnabled; }
  273.             set { _clampingEnabled = value; }
  274.         }
  275.         /// <summary>
  276.         /// a function that is called to determine the amount of horizontal
  277.         /// movement that the user is requesting that the camera be moved
  278.         /// by.
  279.         /// </summary>
  280.         public Func<InputHelper, Camera2D, float> HorizontalCameraMovement
  281.         {
  282.             get { return _horizontalCameraMovement; }
  283.             set { _horizontalCameraMovement = value; }
  284.         }
  285.         /// <summary>
  286.         /// a function that is called to determine the amount of vertical
  287.         /// movement that the user is requesting that the camera be moved
  288.         /// by.
  289.         /// </summary>
  290.         public Func<InputHelper, Camera2D, float> VerticalCameraMovement
  291.         {
  292.             get { return _verticalCameraMovement; }
  293.             set { _verticalCameraMovement = value; }
  294.         }
  295.         /// <summary>
  296.         /// a function that is called to determine if the user wants to
  297.         /// rotate the camera left.
  298.         /// </summary>
  299.         public Func<InputHelper, bool> RotateLeft
  300.         {
  301.             get { return _rotateLeft; }
  302.             set { _rotateLeft = value; }
  303.         }
  304.         /// <summary>
  305.         /// a function that is called to determine if the user wants to rotate
  306.         /// the camera right.
  307.         /// </summary>
  308.         public Func<InputHelper, bool> RotateRight
  309.         {
  310.             get { return _rotateRight; }
  311.             set { _rotateRight = value; }
  312.         }
  313.         /// <summary>
  314.         /// A function that is called to determine if the user is requesting
  315.         /// that the camera be reset to it's original parameters.
  316.         /// </summary>
  317.         public Func<InputHelper, bool> ResetCamera
  318.         {
  319.             get { return _resetCamera; }
  320.             set { _resetCamera = value; }
  321.         }
  322.  
  323.  
  324.         /// <summary>
  325.         /// Moves the camera forward one timestep.
  326.         /// </summary>
  327.         /// <param name="input">
  328.         /// the an InputHelper input representing the current
  329.         /// input state.
  330.         /// </param>
  331.         public void Update(InputHelper input)
  332.         {
  333.             if (!_transitioning)
  334.             {
  335.                 if (_trackingBody == null)
  336.                 {
  337.                     if (_clampingEnabled(this))
  338.                         _targetPosition = Vector2.Clamp(_position + new Vector2(
  339.                                 _horizontalCameraMovement(input, this),
  340.                                 _verticalCameraMovement(input, this)),
  341.                                 _minPosition,
  342.                                 _maxPosition);
  343.                     else
  344.                         _targetPosition += new Vector2(
  345.                             _horizontalCameraMovement(input, this),
  346.                             _verticalCameraMovement(input, this));
  347.                 }
  348.                 else
  349.                 {
  350.                     if (_clampingEnabled(this))
  351.                         _targetPosition = Vector2.Clamp(
  352.                             _trackingBody.Position,
  353.                             _minPosition,
  354.                             _maxPosition);
  355.                     else
  356.                         _targetPosition = _trackingBody.Position;
  357.                 }
  358.                 if (_zoomIn(input))
  359.                     _targetZoom = Math.Min(_maxZoom, _zoom + _zoomRate);
  360.                 if (_zoomOut(input))
  361.                     _targetZoom = Math.Max(_minZoom, _zoom - _zoomRate);
  362.                 //these might need to be swapped
  363.                 if (_rotateLeft(input))
  364.                     _targetRotation = (_rotation + _rotationRate) % (float)(Math.PI * 2);
  365.                 if (_rotateRight(input))
  366.                     _targetRotation = (_rotation - _rotationRate) % (float)(Math.PI * 2);
  367.                 if (input.IsCurPress(Buttons.RightStick))
  368.                 {
  369.                     _transitioning = true;
  370.                     _targetPosition = _origPosition;
  371.                     _targetRotation = _origRotation;
  372.                     _targetZoom = _origZoom;
  373.                     _trackingBody = null;
  374.                 }
  375.             }
  376.             else if (_transition < 1)
  377.             {
  378.                 _transition += _transitionSpeed;
  379.             }
  380.             if (_transition >= 1f ||
  381.                 (_position == _origPosition &&
  382.                 _rotation == _origRotation &&
  383.                 _zoom == _origZoom))
  384.             {
  385.                 _transition = 0;
  386.                 _transitioning = false;
  387.             }
  388.             _position = Vector2.SmoothStep(_position, _targetPosition, _smoothingSpeed);
  389.             _rotation = MathHelper.SmoothStep(_rotation, _targetRotation, _smoothingSpeed);
  390.             _zoom = MathHelper.SmoothStep(_zoom, _targetZoom, _smoothingSpeed);
  391.         }
  392.  
  393.         /// <summary>
  394.         /// tells you if drawing the texture will actually draw onscreen.
  395.         /// </summary>
  396.         /// <param name="tex">
  397.         /// the texture to check.
  398.         /// </param>
  399.         /// <param name="position">
  400.         /// the position of the texture's center.
  401.         /// </param>
  402.         /// <param name="origin">
  403.         /// a Vector2 equaling half of the texture's size.
  404.         /// </param>
  405.         /// <param name="rotation">
  406.         /// the rotation of the texture, in radians.
  407.         /// </param>
  408.         /// <returns>
  409.         /// a bool indicating whether you should draw this texture.
  410.         /// </returns>
  411.         public bool ShouldDraw(Texture2D tex, Vector2 position, Vector2 origin, float rotation)
  412.         {
  413.             Matrix textureMatrix = Matrix.CreateRotationZ(rotation) * Matrix.CreateTranslation(new Vector3(position, 0));
  414.             Vector2 topLeft = Vector2.Transform(-origin, textureMatrix);
  415.             Vector2 topRight = Vector2.Transform(new Vector2(origin.X, -origin.Y), textureMatrix);
  416.             Vector2 botLeft = Vector2.Transform(new Vector2(-origin.X, origin.Y), textureMatrix);
  417.             Vector2 botRight = Vector2.Transform(origin, textureMatrix);
  418.             AABB texAABB = new AABB();
  419.             if (rotation >= 0 && rotation <= MathHelper.PiOver2)
  420.                 texAABB = new AABB(new Vector2(botLeft.X, topLeft.Y), new Vector2(topRight.X, botRight.Y));
  421.             else if (rotation > MathHelper.PiOver2 && rotation <= MathHelper.Pi)
  422.                 texAABB = new AABB(new Vector2(botRight.X, botLeft.Y), new Vector2(topLeft.X, topRight.Y));
  423.             else if (rotation > MathHelper.Pi && rotation <= (MathHelper.Pi + MathHelper.PiOver2))
  424.                 texAABB = new AABB(new Vector2(botRight.X, topRight.Y), new Vector2(botLeft.X, topLeft.Y));
  425.             else if (rotation > (MathHelper.Pi + MathHelper.PiOver2) && rotation <= MathHelper.TwoPi)
  426.                 texAABB = new AABB(new Vector2(topLeft.X, topRight.Y), new Vector2(botRight.X, botLeft.Y));
  427.  
  428.  
  429.             Matrix simpleCameraMatrix = Matrix.Identity *
  430.                 Matrix.CreateTranslation(new Vector3(-_position, 0)) *
  431.                 Matrix.CreateRotationZ(_rotation) *
  432.                 Matrix.CreateTranslation(new Vector3(-_size / 2, 0));
  433.             Vector2 camOrigin = (_size * (1 / _zoom));
  434.             topLeft = Vector2.Transform(-camOrigin, simpleCameraMatrix);
  435.             topRight = Vector2.Transform(new Vector2(camOrigin.X, -camOrigin.Y), simpleCameraMatrix);
  436.             botLeft = Vector2.Transform(new Vector2(-camOrigin.X, camOrigin.Y), simpleCameraMatrix);
  437.             botRight = Vector2.Transform(camOrigin, simpleCameraMatrix);
  438.             AABB camAABB = new AABB();
  439.             if (rotation >= 0 && rotation <= MathHelper.PiOver2)
  440.                 camAABB = new AABB(new Vector2(botLeft.X, topLeft.Y), new Vector2(topRight.X, botRight.Y));
  441.             else if (rotation > MathHelper.PiOver2 && rotation <= MathHelper.Pi)
  442.                 camAABB = new AABB(new Vector2(botRight.X, botLeft.Y), new Vector2(topLeft.X, topRight.Y));
  443.             else if (rotation > MathHelper.Pi && rotation <= (MathHelper.Pi + MathHelper.PiOver2))
  444.                 camAABB = new AABB(new Vector2(botRight.X, topRight.Y), new Vector2(botLeft.X, topLeft.Y));
  445.             else if (rotation > (MathHelper.Pi + MathHelper.PiOver2) && rotation <= MathHelper.TwoPi)
  446.                 camAABB = new AABB(new Vector2(topLeft.X, topRight.Y), new Vector2(botRight.X, botLeft.Y));
  447.  
  448.             if (camAABB.Contains(texAABB.Min) || camAABB.Contains(texAABB.Max))
  449.                 return true;
  450.             return false;
  451.         }
  452.  
  453.         /// <summary>
  454.         /// Given a position in screen coordiantes, will convert it to world coordinates.
  455.         /// </summary>
  456.         /// <param name="position"></param>
  457.         /// <returns></returns>
  458.         public Vector2 ToWorldLocation(Vector2 position)
  459.         {
  460.             return Vector2.Transform(position, Matrix.Invert(CameraMatrix));
  461.         }
  462.     }
  463. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement