MonoGameのカメラを作る

提供: MonoBook
ナビゲーションに移動 検索に移動

カメラクラスを作っておくと捗る。

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Input;

    public class Camera : GameComponent
    {
        public Camera(Game game) : base(game)
        {
            _aspectRatio = game.GraphicsDevice.Viewport.AspectRatio;

            UpdateProjection();
            UpdateView();

            this.Enabled = true;
        }

        /// <summary>
        /// カメラの位置
        /// </summary>
        public Vector3 Position
        {
            get { return _position; }
            set { _position = value; UpdateView(); }
        }

        private Vector3 _position = new Vector3(0, 10, 10);

        /// <summary>
        /// カメラの焦点
        /// </summary>
        public Vector3 Target
        {
            get { return _target; }
            set { _target = value; UpdateView(); }
         }

        private Vector3 _target = Vector3.Zero;

        /// <summary>
        /// カメラの向き
        /// </summary>
        /// <value>The direction.</value>
        public Vector3 Direction
        {
            get
            {
                return Vector3.Normalize(this.Position - this.Target);
            }
            set
            {
                var norm = Vector3.Normalize(value);
                this.Target = this.Position + norm;
            }
        }

        /// <summary>
        /// カメラの上(傾き)
        /// フライトシミュレーターなどで飛行機が傾けばカメラも傾くアレ。
        /// ラジアンではなく度で指定する。
        /// </summary>
        public float Angle {
            get { return _angle; }
            set { _angle = value; UpdateView(); }
        }

        private float _angle = 0;

        /// <summary>
        /// この距離より近いオブジェクトが描画されなくなる。
        /// </summary>
        /// <value>The near plane distance.</value>
        public float NearPlaneDistance { 
            get { return _nearPlaneDistance; } 
            set { _nearPlaneDistance = value; UpdateProjection(); } 
        }

        private float _nearPlaneDistance = 0.1f;

        /// <summary>
        /// この距離より遠いオブジェクトが描画されなくなる。
        /// </summary>
        /// <value>The far plane distance.</value>
        public float FarPlaneDistance {
            get { return _farPlaneDistance; } 
            set { _farPlaneDistance = value; UpdateProjection(); } 
        }

        private float _farPlaneDistance = 10000f;

        /// <summary>
        /// カメラの視野角(1〜179)
        /// 肉眼は46度くらいらしい(諸説ある)。
        /// 超広角レンズ、または魚眼レンズ - 最大180度の画角(それよりさらに広いものもある)
        /// 広角レンズ - 一般に 100度から60度
        /// 標準レンズ - 一般に 50度から 25度
        /// 望遠レンズ - 一般に 15度から 10度
        /// 超望遠レンズ - 一般に 8度から 1度
        /// </summary>
        /// <value>The field of view.</value>
        public float FieldOfView { 
            get { return _fieldOfView; } 
            set 
            {
                if (value <= 0)
                {
                    _fieldOfView = 0.01f;
                }
                else if (180 <= value)
                {
                    _fieldOfView = 179.99f;
                }
                else
                {
                    _fieldOfView = value;
                }
                UpdateProjection();
            }
        }

        private float _fieldOfView = 46;

        /// <summary>
        /// カメラのアスペクト比
        /// </summary>
        /// <value>The aspect ratio.</value>
        public float AspectRatio { 
            get { return _aspectRatio; } 
            set { _aspectRatio = value; UpdateProjection(); }
        }

        private float _aspectRatio;

        // --------------------------------

        public Matrix View { get { return _view; } }

        private Matrix _view;

        public Matrix Projection { get { return _projection; } }

        private Matrix _projection;

        public Matrix ViewProjection { get { return _view * _projection; } }


        private void UpdateProjection()
        {
            //var viewport = this.Game.GraphicsDevice.Viewport;
            //_projection = Matrix.CreateOrthographicOffCenter(
            //    (viewport.Width / -2) * _aspectRatio,
            //    (viewport.Width / +2) * _aspectRatio,
            //    (viewport.Height / -2),
            //    (viewport.Height / +2),
            //    _nearPlaneDistance,
            //    _farPlaneDistance);

            var fieldOfViewRadian = MathHelper.ToRadians(_fieldOfView);

            _projection = Matrix.CreatePerspectiveFieldOfView(
                fieldOfViewRadian,
                _aspectRatio,
                _nearPlaneDistance,
                _farPlaneDistance);
        }

        private void UpdateView()
        {
            var radian = MathHelper.ToRadians(this.Angle);
            var rotate = Matrix.CreateRotationZ(radian);
            var upVector = Vector3.Transform(Vector3.Up, rotate);
            _view = Matrix.CreateLookAt(this.Position, Target, upVector);
        }

        public override void Update(GameTime gameTime)
        {
            if (this.Enabled)
            {
                this.UpdateView();
            }
            base.Update(gameTime);
        }
    }

関連項目[編集 | ソースを編集]