XNA 2D Camera Engine That Follows Sprite

前端 未结 4 523
猫巷女王i
猫巷女王i 2020-12-12 11:56

What is the best way to create a parallax effect in an XNA game? I would like the camera to follow my sprite as it moves across the world, that way I can build in effects li

4条回答
  •  青春惊慌失措
    2020-12-12 13:01

    So I figured it out using a combination of the tutorials above and have created the class below. It tweens towards your target and follows it around. Try it out.

    public interface IFocusable
    {
        Vector2 Position { get; }
    }
    
    public interface ICamera2D
    {
        /// 
        /// Gets or sets the position of the camera
        /// 
        /// The position.
        Vector2 Position { get; set; }
    
        /// 
        /// Gets or sets the move speed of the camera.
        /// The camera will tween to its destination.
        /// 
        /// The move speed.
        float MoveSpeed { get; set; }
    
        /// 
        /// Gets or sets the rotation of the camera.
        /// 
        /// The rotation.
        float Rotation { get; set; }
    
        /// 
        /// Gets the origin of the viewport (accounts for Scale)
        ///         
        /// The origin.
        Vector2 Origin { get; }
    
        /// 
        /// Gets or sets the scale of the Camera
        /// 
        /// The scale.
        float Scale { get; set; }
    
        /// 
        /// Gets the screen center (does not account for Scale)
        /// 
        /// The screen center.
        Vector2 ScreenCenter { get; }
    
        /// 
        /// Gets the transform that can be applied to 
        /// the SpriteBatch Class.
        /// 
        /// 
        /// The transform.
        Matrix Transform { get; }
    
        /// 
        /// Gets or sets the focus of the Camera.
        /// 
        /// 
        /// The focus.
        IFocusable Focus { get; set; }
    
        /// 
        /// Determines whether the target is in view given the specified position.
        /// This can be used to increase performance by not drawing objects
        /// directly in the viewport
        /// 
        /// The position.
        /// The texture.
        /// 
        ///     true if the target is in view at the specified position; otherwise, false.
        /// 
        bool IsInView(Vector2 position, Texture2D texture);
    }
    
    public class Camera2D : GameComponent, ICamera2D
    {
        private Vector2 _position;
        protected float _viewportHeight;
        protected float _viewportWidth;
    
        public Camera2D(Game game)
            : base(game)
        {}
    
        #region Properties
    
        public Vector2 Position
        {
            get { return _position; }
            set { _position = value; }
        }
        public float Rotation { get; set; }
        public Vector2 Origin { get; set; }
        public float Scale { get; set; }
        public Vector2 ScreenCenter { get; protected set; }
        public Matrix Transform { get; set; }
        public IFocusable Focus { get; set; }
        public float MoveSpeed { get; set; }
    
        #endregion
    
        /// 
        /// Called when the GameComponent needs to be initialized. 
        /// 
        public override void Initialize()
        {
            _viewportWidth = Game.GraphicsDevice.Viewport.Width;
            _viewportHeight = Game.GraphicsDevice.Viewport.Height;
    
            ScreenCenter = new Vector2(_viewportWidth/2, _viewportHeight/2);
            Scale = 1;
            MoveSpeed = 1.25f;
    
            base.Initialize();
        }
    
        public override void Update(GameTime gameTime)
        {
            // Create the Transform used by any
            // spritebatch process
            Transform = Matrix.Identity*
                        Matrix.CreateTranslation(-Position.X, -Position.Y, 0)*
                        Matrix.CreateRotationZ(Rotation)*
                        Matrix.CreateTranslation(Origin.X, Origin.Y, 0)*
                        Matrix.CreateScale(new Vector3(Scale, Scale, Scale));
    
            Origin = ScreenCenter / Scale;
    
            // Move the Camera to the position that it needs to go
            var delta = (float) gameTime.ElapsedGameTime.TotalSeconds;
    
            _position.X += (Focus.Position.X - Position.X) * MoveSpeed * delta;
            _position.Y += (Focus.Position.Y - Position.Y) * MoveSpeed * delta;
    
            base.Update(gameTime);
        }
    
        /// 
        /// Determines whether the target is in view given the specified position.
        /// This can be used to increase performance by not drawing objects
        /// directly in the viewport
        /// 
        /// The position.
        /// The texture.
        /// 
        ///     true if [is in view] [the specified position]; otherwise, false.
        /// 
        public bool IsInView(Vector2 position, Texture2D texture)
        {
            // If the object is not within the horizontal bounds of the screen
    
            if ( (position.X + texture.Width) < (Position.X - Origin.X) || (position.X) > (Position.X + Origin.X) )
                return false;
    
            // If the object is not within the vertical bounds of the screen
            if ((position.Y + texture.Height) < (Position.Y - Origin.Y) || (position.Y) > (Position.Y + Origin.Y))
                return false;
    
            // In View
            return true;
        }
    }
    

    And Here is how you would use it with SpriteBatch:

    spriteBatch.Begin(SpriteBlendMode.AlphaBlend,
                      SpriteSortMode.FrontToBack,
                      SaveStateMode.SaveState,
                      Camera.Transform);
    spriteBatch.Draw(_heliTexture,
                     _heliPosition,
                     heliSourceRectangle,
                     Color.White,
                     0.0f,
                     new Vector2(0,0),
                     0.5f,
                     SpriteEffects.FlipHorizontally,
                     0.0f);
    spriteBatch.End();
    

    Let Me know if this helps you out, and thanks to StackOverflow and the community. W00t!

提交回复
热议问题