1. 程式人生 > >貪吃小怪獸介紹之位置同步

貪吃小怪獸介紹之位置同步

類似GAnimation,來一套GTransform,傳入的資料全為整數,GTranform也是全整數計算,速度快,沒誤差,計算攻擊範圍更爽。在計算旋轉角度的時候使用Atan2來計算,Atan2(y,x)可以獲得點(x,y)與x軸的夾角,返回的是一個(-pi,pi)的單精度浮點數,轉化為整數的角度值然後自己寫插值,GTransform一直保留一個整數的當前Y軸的旋轉角度,計算出目標角度後再計算DeltaAngle,再插值。至於位置同步,GTransform一直是整數計算,GTransform.Position獲取的是整數,然後再轉化成浮點數交給檢視呈現,因為我一直是整數計算,所以沒有誤差。附上程式碼。

注意:客戶端的輸入在發給伺服器前已經轉化為整數,保留的有效位數可以修改配置管理器的值,我預設是保留2位小數。

 //計算旋轉移動
    public class GTransform : IComponent
    {
        public int RoSpeed = 8;//這個越大旋轉的越慢,因為是除數
        private Point3 _pos;
        private Vector3 _eulerAngle;
        private int _curEulerY;
        private Player _player;
        private Point3 _scale;

        public void Release()
        {
            this.LogWarning(StringUtils.NotFinishLog);
            _player = null;
        }

        public void Init(object arg = null)
        {
            GTransformInitArgs args = (GTransformInitArgs) arg;
            if (args == null)
            {
                this.LogError("Init() Arg Should Be GTransformInitArgs!");
                return;
            }
            _player = args.DataEntity;
            _pos = new Point3
            {
                X = args.X,
                Y = args.Y,
                Z = args.Z
            };
            _eulerAngle = Vector3.zero;
            _curEulerY = 0;
            _scale = args.Scale;
        }

        public void AddScale(int delta)
        {
            _scale.X += delta;
            _scale.Y += delta;
            _scale.Z += delta;
        }

        public Point3 Position
        {
            get { return _pos; }
        }

        public Point3 Scale
        {
            get { return _scale; }
        }

        public Quaternion Rotation
        {
            get
            {
                return Quaternion.Euler(_eulerAngle);
            }
        }

        public void UpdateFrame(FClientKey fk = null)
        {
            //TODO 修改Player的pos和rotation
            if (fk.MoveX != 0 || fk.MoveY != 0)
            {
                int nextY = (int) (Mathf.Atan2(fk.MoveX, fk.MoveY) * 180 / Mathf.PI);
                nextY = (nextY + 360) % 360;
                _curEulerY = (_curEulerY + 360) % 360;
                int deltaAngle = nextY - _curEulerY;
                //選擇的角度肯定不會大於180的,如果大於180說明應該選擇對頂角的角度
                if (Mathf.Abs(deltaAngle) > 180)
                {
                    if (deltaAngle > 0)
                        deltaAngle -= 360;
                    else
                        deltaAngle += 360;
                }
                _curEulerY += (deltaAngle) / RoSpeed;
                if (_curEulerY > 180) _curEulerY -= 360;
                _eulerAngle.y = _curEulerY;
            }
            _pos.X += fk.MoveX;
            _pos.Z += fk.MoveY;

        }

        public void SetPosition(Point3 pos)
        {
            _pos = pos;

        }
    }