Ejemplo n.º 1
0
        public override Node Update(GameTime gameTime)
        {
            CAN_MOVE_UP    = true;
            CAN_MOVE_DOWN  = true;
            CAN_MOVE_LEFT  = true;
            CAN_MOVE_RIGHT = true;

            CAN_GRAB_L = false;
            CAN_GRAB_R = false;

            //CAN_WALL_JUMP = false;

            _deltaX = _x - _oldX;
            _deltaY = _y - _oldY;

            UpdateRect();

            if (!_isMove)
            {
                if (_status == Status.IS_LAND)
                {
                    DecelerateX(2f);
                }
                else
                {
                    DecelerateX(2f);
                }
            }

            // Lateral Move State
            _isPush = false;
            _isMove = false;
            _onMove = false;

            // Jump Move State
            //_onJump = false;
            //_onFall = false;



            //_sumVector.X = Geo.GetVector(_angleMove.X).X;
            //_sumVector.Y = Geo.GetVector(_angleMove.Y).Y;

            _sumVector = Geo.GetVector(_angleMove.X) * _velocity.X + Geo.GetVector(_angleMove.Y) * _velocity.Y;

            if (MOVE_LEFT && MOVE_RIGHT)
            {
                _sumVector.X = 0f;
            }

            //_finalVector.X = _sumVector.X * _velocity.X;
            //_finalVector.Y = _sumVector.Y * _velocity.Y;

            _finalVector = _sumVector;

            //_finalVector.X = Geo.GetVector(_angleMove.X).X * _velocity.X;
            //_finalVector.Y = Geo.GetVector(_angleMove.Y).Y * _velocity.Y;

            #region Collisions Test

            if (_hSpots.Count > 0)
            {
                // Reset all collide point to false !
                for (int i = 0; i < _hSpots.Count; i++)
                {
                    _cPoints[i]._isContact = false;

                    _cPoints[i]._hotPoint = _hSpots[i];

                    _cPoints[i]._pos = XY + _hSpots[i] + _finalVector;

                    _cPoints[i]._mapX = (int)(_cPoints[i]._pos.X / _tileW);
                    _cPoints[i]._mapY = (int)(_cPoints[i]._pos.Y / _tileH);

                    _cPoints[i]._offset = new Vector2(_cPoints[i]._mapX * _tileW, _cPoints[i]._mapY * _tileH);

                    _cPoints[i]._tile = _map2D.Get(_cPoints[i]._mapX, _cPoints[i]._mapY);

                    //_CollidePointInPolygon = false;

                    if (null != _cPoints[i]._tile)
                    {
                        // check the tileset if collide in polygon
                        if (_tileMapLayer._tileSets.ContainsKey(_cPoints[i]._tile._id))
                        {
                            TileSet tileset = _tileMapLayer._tileSets[_cPoints[i]._tile._id];

                            _cPoints[i]._polygon = tileset._polygonCollision;

                            if (_cPoints[i]._polygon != null)
                            {
                                // get polygon[] in the tile where is the contactPoint of the global Tileset
                                _cPoints[i].GetLineContact(_cPoints[i]._offset, _cPoints[i]._polygon);

                                _cPoints[i]._isContact =
                                    Collision2D.PointInPolygon(_cPoints[i]._pos, _cPoints[i]._polygon, _cPoints[i]._polygon.Length, _cPoints[i]._offset) &&
                                    _cPoints[i]._tile._isCollidable &&
                                    _cPoints[i]._tile._passLevel > PASS_LEVEL; // && _contactPoints[i]._successRaycast;
                            }
                        }
                    }
                }

                // Point Test

                // Up Top
                #region Contact : UP / TOP
                if (_cPoints[(int)HSpots.UL]._isContact && _status == Status.IS_JUMP)
                {
                    CAN_MOVE_UP = false;
                    //_topY = _topY_L = _contactPoints[(int)HotPoints.UL]._mapY * _tileH + _tileH + _rect.Height / 2 + 2;
                    _topY = _topY_L = _cPoints[(int)HSpots.UL]._pointContact.Y + _rect.Height / 2 + 2;
                }
                if (_cPoints[(int)HSpots.UR]._isContact && _status == Status.IS_JUMP)
                {
                    CAN_MOVE_UP = false;
                    //_topY = _topY_R = _contactPoints[(int)HotPoints.UR]._mapY * _tileH + _tileH + _rect.Height / 2 + 2;
                    _topY = _topY_R = _cPoints[(int)HSpots.UR]._pointContact.Y + _rect.Height / 2 + 2;
                }

                if (_cPoints[(int)HSpots.UL]._isContact && _cPoints[(int)HSpots.UR]._isContact && _status == Status.IS_JUMP)
                {
                    if (_topY_L > _topY_R)
                    {
                        _topY = _topY_L;
                    }
                    else
                    {
                        _topY = _topY_R;
                    }
                }
                #endregion

                #region Contact : DOWN / BOTTOM
                if (_cPoints[(int)HSpots.DL]._isContact)
                {
                    CAN_MOVE_DOWN = false;

                    _landLineA = _landLineA_L = _cPoints[(int)HSpots.DL]._polygon[0] + _cPoints[(int)HSpots.DL]._offset;
                    _landLineB = _landLineB_L = _cPoints[(int)HSpots.DL]._polygon[1] + _cPoints[(int)HSpots.DL]._offset;

                    _landRadian = _landRadian_L = Geo.GetRadian(_landLineA, _landLineB);

                    //_pointLandCollision = _pointLandCollision_L = Collision2D.LineLineIntersection(_landLineA, _landLineB, _contactPoints[(int)HotPoints.DL]._pos, _contactPoints[(int)HotPoints.DL]._pos + _contactPoints[(int)HotPoints.DL]._raycast);
                    _pointLandCollision = _pointLandCollision_L = _cPoints[(int)HSpots.DL]._pointContact;

                    _landY = _landY_L = _pointLandCollision_L.Y - _rect.Height / 2 - 2;
                }


                if (_cPoints[(int)HSpots.DR]._isContact)
                {
                    CAN_MOVE_DOWN = false;

                    _landLineA = _landLineA_R = _cPoints[(int)HSpots.DR]._polygon[0] + _cPoints[(int)HSpots.DR]._offset;
                    _landLineB = _landLineB_R = _cPoints[(int)HSpots.DR]._polygon[1] + _cPoints[(int)HSpots.DR]._offset;

                    _landRadian = _landRadian_R = Geo.GetRadian(_landLineA, _landLineB);

                    //_pointLandCollision = _pointLandCollision_R = Collision2D.LineLineIntersection(_landLineA, _landLineB, _contactPoints[(int)HotPoints.DR]._pos, _contactPoints[(int)HotPoints.DR]._pos + _contactPoints[(int)HotPoints.DR]._raycast);
                    _pointLandCollision = _pointLandCollision_R = _cPoints[(int)HSpots.DR]._pointContact;

                    _landY = _landY_R = _pointLandCollision_R.Y - _rect.Height / 2 - 2;
                }
                #endregion

                #region Contact : LEFT & RIGHT
                // Limit Side Move
                // LEFT
                if (_cPoints[(int)HSpots.LU]._isContact && MOVE_LEFT)
                {
                    CAN_MOVE_LEFT = false;
                    //_sideL = _contactPoints[(int)HotPoints.LU]._mapX * _tileW + _tileW + _rect.Width / 2 + 2;
                    _sideL = _cPoints[(int)HSpots.LU]._pointContact.X + _rect.Width / 2 + 2;
                }
                if (_cPoints[(int)HSpots.LD]._isContact && MOVE_LEFT)
                {
                    CAN_MOVE_LEFT = false;
                    //_sideL = _contactPoints[(int)HotPoints.LD]._mapX * _tileW + _tileW + _rect.Width / 2 + 2;
                    _sideL = _cPoints[(int)HSpots.LD]._pointContact.X + _rect.Width / 2 + 2;
                }
                // RIGHT
                if (_cPoints[(int)HSpots.RU]._isContact && MOVE_RIGHT)
                {
                    CAN_MOVE_RIGHT = false;
                    //_sideR = _contactPoints[(int)HotPoints.RU]._mapX * _tileW - _rect.Width / 2 - 2;
                    _sideR = _cPoints[(int)HSpots.RU]._pointContact.X - _rect.Width / 2 - 2;
                }
                if (_cPoints[(int)HSpots.RD]._isContact && MOVE_RIGHT)
                {
                    CAN_MOVE_RIGHT = false;
                    //_sideR = _contactPoints[(int)HotPoints.RD]._mapX * _tileW - _rect.Width / 2 - 2;
                    _sideR = _cPoints[(int)HSpots.RD]._pointContact.X - _rect.Width / 2 - 2;
                }

                // Type Slope = 3
                if (_cPoints[(int)HSpots.LU]._tile != null)
                {
                    if (!_cPoints[(int)HSpots.LU]._isContact && _cPoints[(int)HSpots.LU]._tile._type == 3 && MOVE_LEFT) // && _contactPoints[(int)CPoint.DL]._isContact
                    {
                        //CAN_MOVE_DOWN = false;

                        _landLineA = _landLineA_L = _cPoints[(int)HSpots.LU]._polygon[0] + _cPoints[(int)HSpots.LU]._offset;
                        _landLineB = _landLineB_L = _cPoints[(int)HSpots.LU]._polygon[1] + _cPoints[(int)HSpots.LU]._offset;

                        _landRadian = _landRadian_L = Geo.GetRadian(_landLineA, _landLineB);

                        if (_cPoints[(int)HSpots.DL]._isContact)
                        {
                            CAN_MOVE_DOWN = false;

                            _pointLandCollision = _pointLandCollision_L = Collision2D.LineLineIntersection(_landLineA, _landLineB, _cPoints[(int)HSpots.DL]._pos, _cPoints[(int)HSpots.DL]._pos + _cPoints[(int)HSpots.DL]._raycast);
                            //_pointLandCollision = _pointLandCollision_L = _cPoints[(int)HSpots.DL]._pointContact;
                            _landY = _landY_L = _pointLandCollision_L.Y - _rect.Height / 2 - 2;
                        }
                    }
                }

                if (_cPoints[(int)HSpots.RU]._tile != null)
                {
                    if (!_cPoints[(int)HSpots.RU]._isContact && _cPoints[(int)HSpots.RU]._tile._type == 3 && MOVE_RIGHT) // && _contactPoints[(int)CPoint.DL]._isContact
                    {
                        //CAN_MOVE_DOWN = false;

                        _landLineA = _landLineA_R = _cPoints[(int)HSpots.RU]._polygon[0] + _cPoints[(int)HSpots.RU]._offset;
                        _landLineB = _landLineB_R = _cPoints[(int)HSpots.RU]._polygon[1] + _cPoints[(int)HSpots.RU]._offset;

                        _landRadian = _landRadian_R = Geo.GetRadian(_landLineA, _landLineB);

                        if (_cPoints[(int)HSpots.DR]._isContact)
                        {
                            CAN_MOVE_DOWN = false;

                            _pointLandCollision = _pointLandCollision_R = Collision2D.LineLineIntersection(_landLineA, _landLineB, _cPoints[(int)HSpots.DR]._pos, _cPoints[(int)HSpots.DR]._pos + _cPoints[(int)HSpots.DR]._raycast);
                            //_pointLandCollision = _pointLandCollision_R = _cPoints[(int)HSpots.DR]._pointContact;
                            _landY = _landY_R = _pointLandCollision_R.Y - _rect.Height / 2 - 2;
                        }
                    }
                }

                // Choose best LandY Left or Right
                //if (MOVE_LEFT && _contactPoints[(int)CPoint.DL]._isContact)
                if (_cPoints[(int)HSpots.DL]._isContact && _cPoints[(int)HSpots.DR]._isContact)
                {
                    //Console.Write("< BOTH LAND L & R >");

                    if (_pointLandCollision_L.Y < _pointLandCollision_R.Y)
                    //if (_landY_L < _landY_R)
                    {
                        _pointLandCollision = _pointLandCollision_L;

                        _landLineA  = _landLineA_L;
                        _landLineB  = _landLineB_L;
                        _landRadian = _landRadian_L;
                        //_landY_R = _landY = _landY_L;
                        _landY = _landY_L;

                        _contactPointDown = _cPoints[(int)HSpots.DL];
                    }
                    else //if (MOVE_RIGHT && _contactPoints[(int)CPoint.DR]._isContact)
                    if (_pointLandCollision_L.Y > _pointLandCollision_R.Y)
                    {
                        _pointLandCollision = _pointLandCollision_R;

                        _landLineA  = _landLineA_R;
                        _landLineB  = _landLineB_R;
                        _landRadian = _landRadian_R;
                        //_landY_L = _landY = _landY_R;
                        _landY = _landY_R;

                        _contactPointDown = _cPoints[(int)HSpots.DR];
                    }
                }

                #endregion

                #region Contact : GRAB LEDGE

                if (CAN_MOVE_UP && CAN_MOVE_DOWN && !CAN_MOVE_LEFT &&
                    _cPoints[(int)HSpots.EL]._isContact &&
                    Math.Abs(_cPoints[(int)HSpots.EL]._pos.Y - _cPoints[(int)HSpots.EL]._firstline.B.Y) <= 8)
                {
                    TileMap tileU = _map2D.Get(_cPoints[(int)HSpots.EL]._mapX, _cPoints[(int)HSpots.EL]._mapY - 1);

                    bool climbable = false;

                    if (tileU == null)
                    {
                        climbable = true;
                    }
                    else if (tileU._id != Const.NoIndex) // test is tile at up is empty or not, if not then test is climbable on Left
                    {
                        if (tileU._tileSet._properties.ContainsKey("ClimbR"))
                        {
                            climbable = true;
                        }
                    }
                    else
                    {
                        climbable = true;
                    }

                    if (climbable && !CAN_GRAB_L)
                    {
                        CAN_GRAB_L = true;

                        _grabY = _cPoints[(int)HSpots.EL]._firstline.B.Y - _hSpots[(int)HSpots.EL].Y;

                        _ledgeGrip.X = _cPoints[(int)HSpots.EL]._firstline.B.X;
                        _ledgeGrip.Y = _cPoints[(int)HSpots.EL]._firstline.B.Y;
                    }
                }

                if (CAN_MOVE_UP && CAN_MOVE_DOWN && !CAN_MOVE_RIGHT &&
                    _cPoints[(int)HSpots.ER]._isContact &&
                    Math.Abs(_cPoints[(int)HSpots.ER]._pos.Y - _cPoints[(int)HSpots.ER]._firstline.A.Y) <= 8)
                {
                    TileMap tileU = _map2D.Get(_cPoints[(int)HSpots.ER]._mapX, _cPoints[(int)HSpots.ER]._mapY - 1);

                    bool climbable = false;

                    if (tileU == null)
                    {
                        climbable = true;
                    }
                    else if (tileU._id != Const.NoIndex) // test is tile at up is empty or not, if not then test is climbable on Left
                    {
                        if (tileU._tileSet._properties.ContainsKey("ClimbL"))
                        {
                            climbable = true;
                        }
                    }
                    else
                    {
                        climbable = true;
                    }

                    if (climbable && !CAN_GRAB_R)
                    {
                        CAN_GRAB_R = true;

                        _grabY = _cPoints[(int)HSpots.ER]._firstline.A.Y - _hSpots[(int)HSpots.ER].Y;

                        _ledgeGrip.X = _cPoints[(int)HSpots.ER]._firstline.A.X;
                        _ledgeGrip.Y = _cPoints[(int)HSpots.ER]._firstline.A.Y;
                    }
                }
                #endregion
            }

            #endregion

            #region CAN MOVE TEST & Pre Collision Raycast

            if (!CAN_MOVE_DOWN)
            {
                if (_status != Status.IS_LAND)
                {
                    _preCollisionRayCastY = (_y + _finalVector.Y) - _landY;
                    _finalVector.Y       -= _preCollisionRayCastY;

                    //_y = _landY ;
                    //_finalVector.Y = 0;

                    Land();
                }
            }
            if (!CAN_MOVE_UP)
            {
                Console.WriteLine("!! Touch Top !!");
                _preCollisionRayCastY = (_y + _finalVector.Y) - _topY;
                _finalVector.Y       -= _preCollisionRayCastY;
            }

            if (!CAN_MOVE_LEFT)
            //if (_contactPoints[(int)HotPoints.LU]._isContact || _contactPoints[(int)HotPoints.LD]._isContact)
            {
                _preCollisionRayCastX = (_x + _finalVector.X) - _sideL;
                _finalVector.X       -= _preCollisionRayCastX;

                if (MOVE_LEFT)
                {
                    _isPush = true;

                    if (!CAN_WALL_JUMP_R && _status == Status.IS_FALL && CAN_MOVE_UP && _cPoints[(int)HSpots.EL]._isContact)
                    {
                        Console.WriteLine("CAN WALL JUMP R");

                        _onCanWallJump  = true;
                        CAN_WALL_JUMP_R = true;
                    }
                }
            }
            if (!CAN_MOVE_RIGHT)
            //if (_contactPoints[(int)HotPoints.RU]._isContact || _contactPoints[(int)HotPoints.RD]._isContact)
            {
                _preCollisionRayCastX = (_x + _finalVector.X) - _sideR;
                _finalVector.X       -= _preCollisionRayCastX;

                if (MOVE_RIGHT)
                {
                    _isPush = true;

                    if (!CAN_WALL_JUMP_L && _status == Status.IS_FALL && CAN_MOVE_UP && _cPoints[(int)HSpots.ER]._isContact)
                    {
                        Console.WriteLine("CAN WALL JUMP L");

                        _onCanWallJump  = true;
                        CAN_WALL_JUMP_L = true;
                    }
                }
            }


            if (((CAN_GRAB_L && !CAN_MOVE_LEFT) || (CAN_GRAB_R && !CAN_MOVE_RIGHT)) && _isPush && _status == Status.IS_FALL)
            {
                _preCollisionRayCastY = (_y + _finalVector.Y) - _grabY;
                _finalVector.Y       -= _preCollisionRayCastY;

                //Console.WriteLine($"---------------------> _grabY = {_grabY} _preCollisionRayCastY = {_preCollisionRayCastY}");
                if (CAN_GRAB_L)
                {
                    Grab(ref IS_GRAB_L);
                }
                if (CAN_GRAB_R)
                {
                    Grab(ref IS_GRAB_R);
                }
            }


            #endregion

            #region Status

            if (_status == Status.IS_FALL)
            {
                float factor = 1f;

                if (((CAN_WALL_JUMP_L && _cPoints[(int)HSpots.ER]._isContact) || (CAN_WALL_JUMP_R && _cPoints[(int)HSpots.EL]._isContact)) && _isPush && CAN_MOVE_UP)
                {
                    factor = .05f; // Slow down when grip wall
                }

                _velocity.Y += _acceleration.Y * factor;

                if (_velocity.Y >= _speedMax.Y)
                {
                    _velocity.Y = _speedMax.Y;
                }
            }

            if (_status == Status.IS_LAND && _velocity.Y == 0)
            {
                if (CAN_MOVE_DOWN)
                {
                    Fall();
                }

                //_contactX = _x - _contactDown._mapX * _tileW; _contactY = _contactDown._mapY * _tileH;

                //_contactY = -((_contactY - _landLineA.Y) + (_landLineB.Y - _landLineA.Y) / (_landLineA.X - _landLineB.X) * _contactX) ;

                //_contactY = _contactY + _contactDown._mapY * _tileH;

                //Console.WriteLine($"_contactX = {_contactX} : {_contactY}");

                //if (_contactDown._isContact)
                //    _y = _contactY - _rect.Height / 2 - 2;
            }

            if (_status == Status.IS_GRAB)
            {
                ++_ticGrab;

                if (_ticGrab >= _tempoGrab)
                {
                    _ticGrab = _tempoGrab;

                    if (CAN_GRAB_L)
                    {
                        CAN_GRAB_L = false; CAN_CLIMB_L = true;
                    }
                    if (CAN_GRAB_R)
                    {
                        CAN_GRAB_R = false; CAN_CLIMB_R = true;
                    }


                    if (!_isPush) // When release button push then readyToClimb !
                    {
                        _readyToClimb = true;

                        if (MOVE_UP)
                        {
                            Console.WriteLine($"Climb < {IS_GRAB_L} - {IS_GRAB_R} > : MOVE_UP");

                            if (IS_GRAB_L)
                            {
                                Climb(-1);
                            }
                            if (IS_GRAB_R)
                            {
                                Climb(1);
                            }
                        }

                        if (MOVE_DOWN)
                        {
                            Fall();
                        }
                    }
                    else if (MOVE_JUMP)
                    {
                        Console.WriteLine($"Climb < {IS_GRAB_L} - {IS_GRAB_R} > : MOVE_JUMP");

                        _readyToClimb = true;

                        if (IS_GRAB_L)
                        {
                            Climb(-1);
                        }
                        if (IS_GRAB_R)
                        {
                            Climb(1);
                        }
                    }
                }
            }

            if (_status == Status.IS_CLIMB)
            {
                if (AUTO_UP)
                {
                    _y += -4f;

                    ++_ticAutoUp;
                    if (_ticAutoUp > _rect.Height / 4)
                    {
                        _ticAutoUp   = 0;
                        _ticAutoMove = 0;
                        AUTO_UP      = false;
                        AUTO_MOVE    = true;
                    }
                }
                if (AUTO_MOVE)
                {
                    _y += -.5f;

                    ++_ticAutoMove;
                    if (_ticAutoMove > _rect.Width / 4)
                    {
                        AUTO_MOVE          = false;
                        _directionAutoMove = 0;

                        //Fall();
                        SetStatus(Status.IS_LAND);
                    }

                    if (_directionAutoMove < 0)
                    {
                        _landRadian = Geo.GetRadian(_cPoints[(int)HSpots.EL]._firstline.B, _cPoints[(int)HSpots.EL]._firstline.A);
                        MoveL();
                    }
                    if (_directionAutoMove > 0)
                    {
                        _landRadian = Geo.GetRadian(_cPoints[(int)HSpots.ER]._firstline.A, _cPoints[(int)HSpots.ER]._firstline.B);
                        MoveR();
                    }
                }
            }

            if (_status == Status.IS_JUMP)
            {
                _velocity.Y += -_deceleration.Y;

                if (_velocity.Y <= 0 || !CAN_MOVE_UP)
                {
                    Fall();
                }
            }

            #endregion

            #region Jump Helper when left Land or Grab

            if (_onFall && _status == Status.IS_FALL && (_oldStatus == Status.IS_LAND || (_status == Status.IS_GRAB && !_isPush)))
            {
                _isJustFall  = true;
                _ticJustFall = 0;
                //Console.Write("<Just Fall from land >");
            }

            if (_isJustFall)
            {
                //if (!CAN_MOVE_UP)
                //{
                //    _isJustFall = false;
                //    SetStatus(Status.IS_FALL); Fall();
                //}

                if (MOVE_JUMP && !_onJump) // second chance to jump
                {
                    Console.WriteLine("Helper Jump !");

                    SetStatus(Status.IS_LAND);
                    Jump(_speedMax.Y);
                }

                ++_ticJustFall;
                if (_ticJustFall > _maxTicJustFall)
                {
                    //Console.Write("< Stop jump helper >");
                    _isJustFall  = false;
                    _ticJustFall = 0;
                }
            }


            if (_onCanWallJump)
            {
                Console.WriteLine("ON Can Wall Jump !");
                _onCanWallJump = false;

                _velocity.Y = 0f;
            }


            #endregion

            #region Trigger

            if (_onLand)
            {
                _onLand = false;

                _velocity.Y = 0;
                _velocity.X = 0;
            }

            if (_onFall)
            {
                _onFall      = false;
                _angleMove.Y = Geo.RAD_D;

                _velocity.X = 0;
                _velocity.Y = 0;
            }

            if (_onJump)
            {
                _onJump = false;
            }

            if (_onGrab)
            {
                _onGrab = false;
                //_isJustGrab = true;
                _velocity.Y = 0;
            }

            if (_onClimb)
            {
                _onClimb = false;
                //System.Console.Write("< ON_CLIMB >");
            }

            #endregion

            _oldX = _x;
            _oldY = _y;

            _x += _finalVector.X; //* (float)gameTime.ElapsedGameTime.TotalSeconds * 100;
            _y += _finalVector.Y; //* (float)gameTime.ElapsedGameTime.TotalSeconds * 100;

            MOVE_UP    = false;
            MOVE_DOWN  = false;
            MOVE_LEFT  = false;
            MOVE_RIGHT = false;

            MOVE_JUMP = false;
            MOVE_FALL = false;

            return(base.Update(gameTime));
        }