/// <summary>
        /// Modifies the zoom if the camera is in perspective mode
        /// </summary>
        protected virtual void PerformPerspectiveZoom()
        {
            if (!UsePerspectiveZoom || (TargetController == null))
            {
                return;
            }

            float characterSpeed  = Mathf.Abs(TargetController.Speed.x);
            float currentVelocity = Mathf.Max(characterSpeed, CharacterSpeed.x);
            float targetZoom      = MMMaths.Remap(currentVelocity, CharacterSpeed.x, CharacterSpeed.y, PerspectiveZoom.x, PerspectiveZoom.y);

            _currentZoom = Mathf.Lerp(_currentZoom, targetZoom, Time.deltaTime * PerspectiveZoomSpeed);
            SetPerspectiveZoom(_currentZoom);
        }
        /// <summary>
        /// Modifies the orthographic zoom
        /// </summary>
        protected virtual void PerformOrthographicZoom()
        {
            if (!UseOrthographicZoom || (TargetController == null))
            {
                return;
            }

            float characterSpeed  = Mathf.Abs(TargetController.Speed.x);
            float currentVelocity = Mathf.Max(characterSpeed, CharacterSpeed.x);
            float targetZoom      = MMMaths.Remap(currentVelocity, CharacterSpeed.x, CharacterSpeed.y, OrthographicZoom.x, OrthographicZoom.y);

            _currentZoom = Mathf.Lerp(_currentZoom, targetZoom, Time.deltaTime * OrthographicZoomSpeed);
            _virtualCamera.m_Lens.OrthographicSize = _currentZoom;
        }
Exemple #3
0
        protected virtual void Decide()
        {
            _timeToNextDecision    = Random.Range(DecisionTimeRange.x, DecisionTimeRange.y);
            _lastDecisionTimeStamp = Time.time;
            int dice = MMMaths.RollADice(2);

            if (dice == 2)
            {
                TryToMove();
            }
            else
            {
                StopMoving();
            }
        }
        /// <summary>
        /// Every frame, we check if we're crouched and if we still should be
        /// </summary>
        public override void ProcessAbility()
        {
            base.ProcessAbility();

            // if we don't have a model, we do nothing and exit
            if ((_model == null) || (_characterFly == null))
            {
                return;
            }

            // determines and applies the rotation based on the controller speed
            _currentAngle             = MMMaths.Remap(_controller.Speed.x, 0f, _characterFly.FlySpeed, 0f, MaximumAllowedAngle);
            _newRotation              = Quaternion.Euler(_currentAngle * Vector3.forward);
            _model.transform.rotation = Quaternion.Lerp(_model.transform.rotation, _newRotation, CharacterRotationSpeed * Time.deltaTime);
        }
        protected virtual void Sort()
        {
            Followers = FindObjectsOfType <Follower>();

            // fill the bag
            var   shuffleBag = new ShuffleBag(40);
            int   amount     = 1;
            float minValue   = -2f;
            float maxValue   = 2f;
            float newValue   = 0f;

            for (int i = 0; i < 40; i++)
            {
                newValue = MMMaths.Remap(i, 0, 40, minValue, maxValue);
                if (newValue == 0f)
                {
                    newValue = 2.2f;
                }
                shuffleBag.Add(newValue, amount);
            }

            float followOffset = 1f;

            foreach (Follower follower in Followers)
            {
                _newPosition   = follower.transform.position;
                _newPosition.z = shuffleBag.Next() * 1.5f + Random.Range(0.01f, 0.04f);

                follower.transform.position = _newPosition;
                int dice = MMMaths.RollADice(4);

                float offset = shuffleBag.Next();
                if (offset > 0f)
                {
                    offset += 2.5f;
                }
                else
                {
                    offset -= 2.5f;
                }
                follower.gameObject.GetComponentNoAlloc <MMFollowTarget>().SetXOffset(offset);


                follower.gameObject.GetComponentNoAlloc <MMFollowTarget>().FollowPositionSpeed = Random.Range(3f, 10f);

                followOffset += 0.2f;
            }
        }
Exemple #6
0
        /// <summary>
        /// Determines the weapon rotation based on the current aim direction
        /// </summary>
        protected override void DetermineWeaponRotation()
        {
            if (_currentAim != Vector3.zero)
            {
                if (_direction != Vector3.zero)
                {
                    CurrentAngle         = Mathf.Atan2(_currentAim.y, _currentAim.x) * Mathf.Rad2Deg;
                    CurrentAngleAbsolute = Mathf.Atan2(_currentAimAbsolute.y, _currentAimAbsolute.x) * Mathf.Rad2Deg;
                    if (RotationMode == RotationModes.Strict4Directions || RotationMode == RotationModes.Strict8Directions)
                    {
                        CurrentAngle = MMMaths.RoundToClosest(CurrentAngle, _possibleAngleValues);
                    }
                    if (RotationMode == RotationModes.Strict2Directions)
                    {
                        CurrentAngle = 0f;
                    }

                    // we add our additional angle
                    CurrentAngle += _additionalAngle;

                    // we clamp the angle to the min/max values set in the inspector
                    if (_weapon.Owner.Orientation2D != null)
                    {
                        if (_weapon.Owner.Orientation2D.IsFacingRight)
                        {
                            CurrentAngle = Mathf.Clamp(CurrentAngle, MinimumAngle, MaximumAngle);
                        }
                        else
                        {
                            CurrentAngle = Mathf.Clamp(CurrentAngle, -MaximumAngle, -MinimumAngle);
                        }
                    }
                    else
                    {
                        CurrentAngle = Mathf.Clamp(CurrentAngle, MinimumAngle, MaximumAngle);
                    }

                    _lookRotation = Quaternion.Euler(CurrentAngle * Vector3.forward);
                    RotateWeapon(_lookRotation);
                }
            }
            else
            {
                CurrentAngle = 0f;
                RotateWeapon(_initialRotation);
            }
            MMDebug.DebugDrawArrow(this.transform.position, _currentAimAbsolute.normalized, Color.green);
        }
Exemple #7
0
        /// <summary>
        /// Rotates the cone, interpolating the rotation if needed
        /// </summary>
        /// <param name="direction"></param>
        protected virtual void AimAt(Vector3 direction)
        {
            if (Interpolate)
            {
                _newAim = MMMaths.Lerp(_newAim, direction, InterpolateRate, Time.deltaTime);
            }
            else
            {
                _newAim = direction;
            }

            _angle         = MMMaths.AngleBetween(this.transform.right, _newAim);
            _eulerAngles.y = -_angle;

            _coneOfVision2D.SetDirectionAndAngles(_newAim, _eulerAngles);
        }
Exemple #8
0
        protected virtual MMRadioReceiver InstantiateBlock(Vector3 newPosition, string newName)
        {
            // instantiating the block and setting its name
            _receiver      = Instantiate(GroundPrefabToInstantiate, newPosition, Quaternion.identity, ParentContainer);
            _receiver.name = newName;

            // setting its receiver settings
            float distanceToDancer = Vector3.Distance(Dancer.transform.position + DancerOffset, newPosition);
            float maxDistance      = Mathf.Max(NumberOfColumns * Depth, NumberOfRows * Width) / 2f;
            float remappedDistance = MMMaths.Remap(distanceToDancer, 0f, maxDistance, 0f, 1f);
            float newAmplitude     = Amplitude.Evaluate(remappedDistance);
            float random           = Random.Range(MinRandom, MaxRandom);

            newAmplitude *= random;
            newAmplitude *= AmplitudeMultiplier;

            int channel = Random.Range(0, 2);

            _receiver.MinRandomLevelMultiplier = newAmplitude;
            _receiver.MaxRandomLevelMultiplier = newAmplitude;
            _receiver.GenerateRandomLevelMultiplier();
            _receiver.Channel = channel;

            // setting its material
            float randomMaterial = Random.Range(0f, 100f);

            if (randomMaterial < 80f)
            {
                _receiver.GetComponent <MeshRenderer>().material = GroundMaterial;
            }
            else
            {
                if (randomMaterial < 90f)
                {
                    _receiver.GetComponent <MeshRenderer>().material = GroundMaterialAlt1;
                }
                else
                {
                    _receiver.GetComponent <MeshRenderer>().material = GroundMaterialAlt2;
                }
            }

            // setting its position
            _receiver.transform.position = newPosition;

            return(_receiver);
        }
Exemple #9
0
 /// <summary>
 /// Determines the direction of the ray we have to cast
 /// </summary>
 protected virtual void DetermineDirection()
 {
     if (RandomSpread)
     {
         _randomSpreadDirection = MMMaths.RandomVector3(-Spread, Spread);
         Quaternion spread = Quaternion.Euler(_randomSpreadDirection);
         _randomSpreadDirection = (Mode == Modes.ThreeD) ? spread * transform.forward : spread * transform.right;
         if (RotateWeaponOnSpread)
         {
             this.transform.rotation = this.transform.rotation * spread;
         }
     }
     else
     {
         _randomSpreadDirection = (Mode == Modes.ThreeD) ? transform.forward : transform.right;
     }
 }
Exemple #10
0
        /// <summary>
        /// Applies fall damage
        /// </summary>
        /// <param name="distance"></param>
        protected virtual void ApplyDamage(float distance)
        {
            int damageToApply = (int)Mathf.Round(MMMaths.Remap(distance, MinimumDamageFallHeight, MaximumDamageFallHeight,
                                                               (float)MinimumDamage, (float)MaximumDamage));

            if (ClampedDamage)
            {
                damageToApply = (int)Mathf.Clamp(damageToApply, (float)MinimumDamage, (float)MaximumDamage);
            }

            if (!_startFeedbackIsPlaying)
            {
                PlayAbilityStartFeedbacks();
            }
            _health.Damage(damageToApply, this.gameObject, 0.2f, 0.2f);
            _damageThisFrame = true;
        }
Exemple #11
0
        /// <summary>
        /// Draws on the scene view cubes to show the minimum and maximum gaps, for tweaking purposes.
        /// </summary>
        protected virtual void OnDrawGizmosSelected()
        {
            DrawClamps();

            GUIStyle style = new GUIStyle();

            // we rotate the Gizmos matrix to have the gap cubes aligned to our spawner's rotation
            Gizmos.matrix = transform.localToWorldMatrix;

            // Draws a cube showing the minimum gap
            Gizmos.color = Color.yellow;
            Gizmos.DrawWireCube(Vector3.zero, MinimumGap);

            // Draws a cube showing the maximum gap
            Gizmos.color = Color.red;
            Gizmos.DrawWireCube(Vector3.zero, MaximumGap);

            // we reset our matrix rotation as to not affect other gizmo calls
            Gizmos.matrix = Matrix4x4.identity;

            // if the minimumGap cube ain't null, we draw it around our object to show the minimum gap that'll be applied to a spawned object
            if (MinimumGap != Vector3.zero)
            {
                style.normal.textColor = Color.yellow;
                Vector3 labelPosition = transform.position + (Mathf.Abs(MinimumGap.y / 2) + 1) * Vector3.up + Vector3.left;
                labelPosition = MMMaths.RotatePointAroundPivot(labelPosition, transform.position, transform.rotation.eulerAngles);
                                #if UNITY_EDITOR
                UnityEditor.Handles.Label(labelPosition, "Minimum Gap", style);
                                #endif
            }

            // if the maximumGap cube ain't null, we draw it around our object to show the maximum gap that'll be applied to a spawned object
            if (MaximumGap != Vector3.zero)
            {
                style.normal.textColor = Color.red;
                Vector3 labelPosition = transform.position + (-Mathf.Abs(MaximumGap.y / 2) + 1) * Vector3.up + Vector3.left;
                labelPosition = MMMaths.RotatePointAroundPivot(labelPosition, transform.position, transform.rotation.eulerAngles);
                                #if UNITY_EDITOR
                UnityEditor.Handles.Label(labelPosition, "Maximum Gap", style);
                                #endif
            }

            // we draw an arrow showing the direction of the spawns
            MMDebug.DrawGizmoArrow(transform.position, transform.rotation * Vector3.left * 10, Color.green);
        }
Exemple #12
0
 /// <summary>
 /// Determines the direction of the ray we have to cast
 /// </summary>
 protected virtual void DetermineDirection()
 {
     _direction = Flipped ? -transform.right : transform.right;
     if (RandomSpread)
     {
         _randomSpreadDirection = MMMaths.RandomVector3(-Spread, Spread);
         Quaternion spread = Quaternion.Euler(_randomSpreadDirection);
         _randomSpreadDirection = spread * _direction;
         if (RotateWeaponOnSpread)
         {
             this.transform.rotation = this.transform.rotation * spread;
         }
     }
     else
     {
         _randomSpreadDirection = _direction;
     }
 }
Exemple #13
0
        /// <summary>
        /// Determines the weapon rotation based on the current aim direction
        /// </summary>
        protected override void DetermineWeaponRotation()
        {
            if (ReticleMovesWithSlopes)
            {
                AimAt(_slopeTargetPosition);
                return;
            }

            if (Unrestricted3DAim)
            {
                AimAt(this.transform.position + _weaponAimCurrentAim);
                return;
            }

            if (_weaponAimCurrentAim != Vector3.zero)
            {
                if (_direction != Vector3.zero)
                {
                    CurrentAngle = Mathf.Atan2(_weaponAimCurrentAim.z, _weaponAimCurrentAim.x) * Mathf.Rad2Deg;
                    if (RotationMode == RotationModes.Strict4Directions || RotationMode == RotationModes.Strict8Directions)
                    {
                        CurrentAngle = MMMaths.RoundToClosest(CurrentAngle, _possibleAngleValues);
                    }

                    // we add our additional angle
                    CurrentAngle += _additionalAngle;

                    // we clamp the angle to the min/max values set in the inspector

                    CurrentAngle = Mathf.Clamp(CurrentAngle, MinimumAngle, MaximumAngle);
                    CurrentAngle = -CurrentAngle + 90f;

                    _lookRotation = Quaternion.Euler(CurrentAngle * Vector3.up);

                    RotateWeapon(_lookRotation);
                }
            }
            else
            {
                CurrentAngle = 0f;
                RotateWeapon(_initialRotation);
            }
        }
        /// <summary>
        /// Computes the relative speeds
        /// </summary>
        protected virtual void ComputeRelativeSpeeds()
        {
            _newSpeed = (this.transform.position - _positionLastFrame) / Time.deltaTime;

            // relative speed
            if (_characterHandleWeapon == null)
            {
                _relativeSpeed = MovementRotatingModel.transform.InverseTransformVector(_newSpeed);
            }
            else
            {
                _relativeSpeed = WeaponRotatingModel.transform.InverseTransformVector(_newSpeed);
            }

            // remapped speed
            if (_characterRun != null)
            {
                _remappedSpeed.x = MMMaths.Remap(_relativeSpeed.x, 0f, _characterRun.RunSpeed, 0f, 1f);
                _remappedSpeed.y = MMMaths.Remap(_relativeSpeed.y, 0f, _characterRun.RunSpeed, 0f, 1f);
                _remappedSpeed.z = MMMaths.Remap(_relativeSpeed.z, 0f, _characterRun.RunSpeed, 0f, 1f);
            }

            // relative speed normalized
            _relativeSpeedNormalized = _relativeSpeed.normalized;

            // RotationSpeed
            if (Mathf.Abs(_modelAnglesYLastFrame - ModelAngles.y) > 1f)
            {
                _rotationSpeed = Mathf.Abs(_modelAnglesYLastFrame - ModelAngles.y);
            }
            else
            {
                _rotationSpeed -= Time.time * RotationSpeedResetSpeed;
            }
            if (_rotationSpeed <= 0f)
            {
                _rotationSpeed = 0f;
            }

            _modelAnglesYLastFrame = ModelAngles.y;
            _positionLastFrame     = this.transform.position;
        }
Exemple #15
0
    protected virtual void Decide()
    {
        _timeToNextDecision    = Random.Range(DecisionTimeRange.x, DecisionTimeRange.y);
        _lastDecisionTimeStamp = Time.time;

        int dice = MMMaths.RollADice(5);

        if (dice == 1)
        {
            PickNewTarget();
        }
        if (dice == 2)
        {
            StopMoving();
        }
        if ((dice == 3) || (dice == 4) || (dice == 5))
        {
            StartMoving();
        }
    }
Exemple #16
0
        /// <summary>
        /// Applies the offset specified in the inspector
        /// </summary>
        protected virtual void ApplyOffset()
        {
            _weaponAttachmentOffset = WeaponAttachmentOffset;

            if (Flipped)
            {
                _weaponAttachmentOffset.x = -WeaponAttachmentOffset.x;
            }

            if (_characterGravity != null)
            {
                _weaponAttachmentOffset = MMMaths.RotateVector2(_weaponAttachmentOffset, _characterGravity.GravityAngle);
            }
            // we apply the offset
            if (transform.parent != null)
            {
                _weaponOffset      = transform.parent.position + _weaponAttachmentOffset;
                transform.position = _weaponOffset;
            }
        }
        /// <summary>
        /// Rotates the target object, interpolating the rotation if needed
        /// </summary>
        /// <param name="direction"></param>
        protected virtual void AimAt(Vector3 direction)
        {
            if (Interpolate)
            {
                _newAim = MMMaths.Lerp(_newAim, direction, InterpolateRate, Time.deltaTime);
            }
            else
            {
                _newAim = direction;
            }

            switch (Axis)
            {
            case PossibleAxis.Forward:
                GameObjectToAim.transform.forward = _newAim;
                break;

            case PossibleAxis.Right:
                GameObjectToAim.transform.right = _newAim;
                break;
            }
        }
        protected virtual void Transition(bool entering, Vector2 gravityDirection)
        {
            float gravityAngle = 180 - MMMaths.AngleBetween(Vector2.up, gravityDirection);

            if (TransitionForcesMode == TransitionForcesModes.Nothing)
            {
                return;
            }
            if (TransitionForcesMode == TransitionForcesModes.Reset)
            {
                return;
                //_controller.SetForce(Vector2.zero);
                //_movement.ChangeState(CharacterStates.MovementStates.Idle);
            }
            if (TransitionForcesMode == TransitionForcesModes.Adapt)
            {
                // the angle is calculated depending on if the player enters or exits a zone and takes _previousGravityAngle as parameter if you glide over from one zone to another
                float rotationAngle = entering ? _previousGravityAngle - gravityAngle : gravityAngle - _defaultGravityAngle;
                return;
                //_controller.SetForce(Quaternion.Euler(0, 0, rotationAngle) * _controller.Speed);
            }
            _previousGravityAngle = entering ? gravityAngle : _defaultGravityAngle;
        }
Exemple #19
0
        /// <summary>
        /// Follows the target, lerping the position or not based on what's been defined in the inspector
        /// </summary>
        protected virtual void FollowTargetPosition()
        {
            if (Target == null)
            {
                return;
            }

            if (!FollowPosition)
            {
                return;
            }

            var pos            = Target.position;
            var targetPosition = new Vector3(pos.x, pos.y, this.transform.position.z);

            _newTargetPosition = targetPosition + Offset;

            float trueDistance = 0f;

            _direction   = (_newTargetPosition - this.transform.position).normalized;
            trueDistance = Vector3.Distance(this.transform.position, _newTargetPosition);

            _speed = (_speed < FollowPositionSpeed) ? _speed + FollowAcceleration * Time.deltaTime : FollowPositionSpeed;

            float interpolatedDistance = trueDistance;

            if (InterpolatePosition)
            {
                interpolatedDistance = MMMaths.Lerp(0f, trueDistance, _speed, Time.deltaTime);
                this.transform.Translate(_direction * interpolatedDistance, Space.World);
            }
            else
            {
                this.transform.Translate(_direction * interpolatedDistance, Space.World);
            }
        }
Exemple #20
0
    protected virtual void Spawn()
    {
        if (EnemiesSpawned >= MaxEnemies)
        {
            return;
        }

        _lastSpawnAt = Time.time;
        _nextSpawnIn = Random.Range(SpawnFrequencyMin, SpawnFrequencyMax);

        GameObject nextGameObject = ObjectPooler.GetPooledGameObject();

        if (nextGameObject != null)
        {
            nextGameObject.transform.position = MMMaths.RandomVector3(MinTargetRange, MaxTargetRange);
            nextGameObject.gameObject.SetActive(true);

            EnemiesSpawned++;
        }
        else
        {
            MMDebug.DebugLogTime("pooled object is null");
        }
    }
Exemple #21
0
        /// <summary>
        /// Casts rays to the sides of the character, from its center axis.
        /// If we hit a wall/slope, we check its angle and move or not according to it.
        /// </summary>
        protected override void CastRaysToTheSides(float raysDirection)
        {
            // we determine the origin of our rays
            _horizontalRayCastFromBottom = (_boundsBottomRightCorner + _boundsBottomLeftCorner) / 2;
            _horizontalRayCastToTop      = (_boundsTopLeftCorner + _boundsTopRightCorner) / 2;
            _horizontalRayCastFromBottom = _horizontalRayCastFromBottom + (Vector2)transform.up * _obstacleHeightTolerance;
            _horizontalRayCastToTop      = _horizontalRayCastToTop - (Vector2)transform.up * _obstacleHeightTolerance;

            // we determine the length of our rays
            float horizontalRayLength = Mathf.Abs(_speed.x * Time.deltaTime) + _boundsWidth / 2 + RayOffset * 2;

            // we resize our storage if needed
            if (_sideHitsStorage.Length != NumberOfHorizontalRays)
            {
                _sideHitsStorage = new RaycastHit2D[NumberOfHorizontalRays];
            }

            SetTemporaryLayer();

            // we cast rays to the sides
            for (int i = 0; i < NumberOfHorizontalRays; i++)
            {
                Vector2 rayOriginPoint = Vector2.Lerp(_horizontalRayCastFromBottom, _horizontalRayCastToTop, (float)i / (float)(NumberOfHorizontalRays - 1));

                // if we were grounded last frame and if this is our first ray, we don't cast against one way platforms
                if (State.WasGroundedLastFrame && i == 0)
                {
                    _sideHitsStorage[i] = MMDebug.RayCast(rayOriginPoint, raysDirection * (transform.right), horizontalRayLength, PlatformMask, MMColors.Indigo, Parameters.DrawRaycastsGizmos);
                }
                else
                {
                    _sideHitsStorage[i] = MMDebug.RayCast(rayOriginPoint, raysDirection * (transform.right), horizontalRayLength, PlatformMask & ~OneWayPlatformMask & ~MovingOneWayPlatformMask, MMColors.Indigo, Parameters.DrawRaycastsGizmos);
                }
                // if we've hit something
                if (_sideHitsStorage[i].distance > 0)
                {
                    // if this collider is on our ignore list, we break
                    if (_sideHitsStorage[i].collider == _ignoredCollider)
                    {
                        break;
                    }

                    // we determine and store our current lateral slope angle
                    float hitAngle = Mathf.Abs(Vector2.Angle(_sideHitsStorage[i].normal, transform.up));

                    if (OneWayPlatformMask.MMContains(_sideHitsStorage[i].collider.gameObject))
                    {
                        if (hitAngle > 90)
                        {
                            break;
                        }
                    }

                    // we check if this is our movement direction
                    if (_movementDirection == raysDirection)
                    {
                        State.LateralSlopeAngle = hitAngle;
                    }

                    // if the lateral slope angle is higher than our maximum slope angle, then we've hit a wall, and stop x movement accordingly
                    if (hitAngle > Parameters.MaximumSlopeAngle)
                    {
                        if (raysDirection < 0)
                        {
                            State.IsCollidingLeft        = true;
                            State.DistanceToLeftCollider = _sideHitsStorage[i].distance;
                        }
                        else
                        {
                            State.IsCollidingRight        = true;
                            State.DistanceToRightCollider = _sideHitsStorage[i].distance;
                        }

                        if (_movementDirection == raysDirection)
                        {
                            CurrentWallCollider = _sideHitsStorage[i].collider.gameObject;
                            State.SlopeAngleOK  = false;

                            float distance = MMMaths.DistanceBetweenPointAndLine(_sideHitsStorage[i].point, _horizontalRayCastFromBottom, _horizontalRayCastToTop);
                            if (raysDirection <= 0)
                            {
                                _newPosition.x = -distance
                                                 + _boundsWidth / 2
                                                 + RayOffset * 2;
                            }
                            else
                            {
                                _newPosition.x = distance
                                                 - _boundsWidth / 2
                                                 - RayOffset * 2;
                            }

                            // if we're in the air, we prevent the character from being pushed back.
                            if (!State.IsGrounded && (Speed.y != 0))
                            {
                                _newPosition.x = 0;
                            }

                            _contactList.Add(_sideHitsStorage[i]);
                            _speed.x = 0;
                        }

                        break;
                    }
                }
            }

            SetOriginalLayer();
        }
Exemple #22
0
        /// <summary>
        /// Every frame, we cast a number of rays below our character to check for platform collisions
        /// </summary>
        protected override void CastRaysBelow()
        {
            _friction = 0;

            if (_newPosition.y < -_smallValue)
            {
                State.IsFalling = true;
            }
            else
            {
                State.IsFalling = false;
            }

            if ((Parameters.Gravity > 0) && (!State.IsFalling))
            {
                State.IsCollidingBelow = false;
                return;
            }

            float rayLength = (_boundsHeight / 2) + RayOffset;

            if (State.OnAMovingPlatform)
            {
                rayLength *= 2;
            }

            if (_newPosition.y < 0)
            {
                rayLength += Mathf.Abs(_newPosition.y);
            }

            _verticalRayCastFromLeft  = (_boundsBottomLeftCorner + _boundsTopLeftCorner) / 2;
            _verticalRayCastToRight   = (_boundsBottomRightCorner + _boundsTopRightCorner) / 2;
            _verticalRayCastFromLeft += (Vector2)transform.up * RayOffset;
            _verticalRayCastToRight  += (Vector2)transform.up * RayOffset;
            _verticalRayCastFromLeft += (Vector2)transform.right * _newPosition.x;
            _verticalRayCastToRight  += (Vector2)transform.right * _newPosition.x;

            if (_belowHitsStorage.Length != NumberOfVerticalRays)
            {
                _belowHitsStorage = new RaycastHit2D[NumberOfVerticalRays];
            }

            _raysBelowLayerMaskPlatforms = PlatformMask;

            _raysBelowLayerMaskPlatformsWithoutOneWay    = PlatformMask & ~MidHeightOneWayPlatformMask & ~OneWayPlatformMask & ~MovingOneWayPlatformMask;
            _raysBelowLayerMaskPlatformsWithoutMidHeight = _raysBelowLayerMaskPlatforms & ~MidHeightOneWayPlatformMask;

            // if what we're standing on is a mid height oneway platform, we turn it into a regular platform for this frame only
            if (StandingOnLastFrame != null)
            {
                _savedBelowLayer = StandingOnLastFrame.layer;
                if (MidHeightOneWayPlatformMask.MMContains(StandingOnLastFrame.layer))
                {
                    StandingOnLastFrame.layer = LayerMask.NameToLayer("Platforms");
                }
            }

            // if we were grounded last frame, and not on a one way platform, we ignore any one way platform that would come in our path.
            if (State.WasGroundedLastFrame)
            {
                if (StandingOnLastFrame != null)
                {
                    if (!MidHeightOneWayPlatformMask.MMContains(StandingOnLastFrame.layer))
                    {
                        _raysBelowLayerMaskPlatforms = _raysBelowLayerMaskPlatformsWithoutMidHeight;
                    }
                }
            }

            // stairs management
            if (State.WasGroundedLastFrame)
            {
                if (StandingOnLastFrame != null)
                {
                    if (StairsMask.MMContains(StandingOnLastFrame.layer))
                    {
                        // if we're still within the bounds of the stairs
                        if (StandingOnCollider.bounds.Contains(_colliderBottomCenterPosition))
                        {
                            _raysBelowLayerMaskPlatforms = _raysBelowLayerMaskPlatforms & ~OneWayPlatformMask | StairsMask;
                        }
                    }
                }
            }

            if (State.OnAMovingPlatform && (_newPosition.y > 0))
            {
                _raysBelowLayerMaskPlatforms = _raysBelowLayerMaskPlatforms & ~OneWayPlatformMask;
            }

            float smallestDistance      = float.MaxValue;
            int   smallestDistanceIndex = 0;
            bool  hitConnected          = false;

            SetTemporaryLayer();

            for (int i = 0; i < NumberOfVerticalRays; i++)
            {
                Vector2 rayOriginPoint = Vector2.Lerp(_verticalRayCastFromLeft, _verticalRayCastToRight, (float)i / (float)(NumberOfVerticalRays - 1));

                if ((_newPosition.y > 0) && (!State.WasGroundedLastFrame))
                {
                    _belowHitsStorage[i] = MMDebug.RayCast(rayOriginPoint, -transform.up, rayLength, _raysBelowLayerMaskPlatformsWithoutOneWay, Color.blue, Parameters.DrawRaycastsGizmos);
                }
                else
                {
                    _belowHitsStorage[i] = MMDebug.RayCast(rayOriginPoint, -transform.up, rayLength, _raysBelowLayerMaskPlatforms, Color.blue, Parameters.DrawRaycastsGizmos);
                }

                float distance = MMMaths.DistanceBetweenPointAndLine(_belowHitsStorage [smallestDistanceIndex].point, _verticalRayCastFromLeft, _verticalRayCastToRight);

                if (_belowHitsStorage[i])
                {
                    if (_belowHitsStorage[i].collider == _ignoredCollider)
                    {
                        continue;
                    }

                    hitConnected          = true;
                    State.BelowSlopeAngle = Vector2.Angle(_belowHitsStorage[i].normal, transform.up);
                    _crossBelowSlopeAngle = Vector3.Cross(transform.up, _belowHitsStorage [i].normal);
                    if (_crossBelowSlopeAngle.z < 0)
                    {
                        State.BelowSlopeAngle = -State.BelowSlopeAngle;
                    }

                    if (_belowHitsStorage[i].distance < smallestDistance)
                    {
                        smallestDistanceIndex = i;
                        smallestDistance      = _belowHitsStorage[i].distance;
                    }
                }

                if (distance < _smallValue)
                {
                    break;
                }
            }

            SetOriginalLayer();

            if (hitConnected)
            {
                StandingOn         = _belowHitsStorage[smallestDistanceIndex].collider.gameObject;
                StandingOnCollider = _belowHitsStorage [smallestDistanceIndex].collider;

                // if the character is jumping onto a (1-way) platform but not high enough, we do nothing
                if (
                    !State.WasGroundedLastFrame &&
                    (smallestDistance < _boundsHeight / 2) &&
                    (
                        OneWayPlatformMask.MMContains(StandingOn.layer)
                        ||
                        MovingOneWayPlatformMask.MMContains(StandingOn.layer)
                    )
                    )
                {
                    State.IsCollidingBelow = false;
                    return;
                }

                State.IsFalling        = false;
                State.IsCollidingBelow = true;


                // if we're applying an external force (jumping, jetpack...) we only apply that
                if (_externalForce.y > 0 && _speed.y > 0)
                {
                    _newPosition.y         = _speed.y * Time.deltaTime;
                    State.IsCollidingBelow = false;
                }
                // if not, we just adjust the position based on the raycast hit
                else
                {
                    float distance = MMMaths.DistanceBetweenPointAndLine(_belowHitsStorage [smallestDistanceIndex].point, _verticalRayCastFromLeft, _verticalRayCastToRight);

                    _newPosition.y = -distance
                                     + _boundsHeight / 2
                                     + RayOffset;
                }

                if (!State.WasGroundedLastFrame && _speed.y > 0)
                {
                    _newPosition.y += _speed.y * Time.deltaTime;
                }

                if (Mathf.Abs(_newPosition.y) < _smallValue)
                {
                    _newPosition.y = 0;
                }

                // we check if whatever we're standing on applies a friction change
                _frictionTest = _belowHitsStorage[smallestDistanceIndex].collider.gameObject.MMGetComponentNoAlloc <SurfaceModifier>();
                if (_frictionTest != null)
                {
                    _friction = _belowHitsStorage[smallestDistanceIndex].collider.GetComponent <SurfaceModifier>().Friction;
                }

                // we check if the character is standing on a moving platform
                _movingPlatformTest = _belowHitsStorage[smallestDistanceIndex].collider.gameObject.MMGetComponentNoAlloc <MMPathMovement>();
                if (_movingPlatformTest != null && State.IsGrounded)
                {
                    _movingPlatform = _movingPlatformTest.GetComponent <MMPathMovement>();
                }
                else
                {
                    DetachFromMovingPlatform();
                }
            }
            else
            {
                State.IsCollidingBelow = false;
                if (State.OnAMovingPlatform)
                {
                    DetachFromMovingPlatform();
                }
            }

            if (StickToSlopes)
            {
                StickToSlope();
            }
        }
 protected virtual void Shake()
 {
     _remappedTimeSinceStart = MMMaths.Remap(Time.time - _shakeStartedTimestamp, 0f, ShakeDuration, 0f, 1f);
     _chromaticAberration.intensity.value = ShakeIntensity.Evaluate(_remappedTimeSinceStart);
 }
Exemple #24
0
        /// <summary>
        /// Instantiates cubes to form a ground and randomizes their settings
        /// </summary>
        protected virtual void GenerateGround()
        {
            int counter            = 0;
            List <GameObject> list = new List <GameObject>();

            for (int i = 0; i < ParentContainer.transform.childCount; i++)
            {
                list.Add(ParentContainer.transform.GetChild(i).gameObject);
            }
            foreach (GameObject child in list)
            {
                counter++;
                if (Application.isPlaying)
                {
                    Destroy(child.gameObject);
                }
                else
                {
                    DestroyImmediate(child.gameObject);
                }
            }

            _counter = 0;
            // we instantiate our ground grid
            for (int i = 0; i < NumberOfRows; i++)
            {
                for (int j = 0; j < NumberOfColumns; j++)
                {
                    _wipPosition.x = i * Width;
                    _wipPosition.y = 0;
                    _wipPosition.z = j * Depth;
                    _wipPosition  += Offset;
                    _wipName       = "GroundBlock_" + _counter;
                    InstantiateBlock(_wipPosition, _wipName);
                    _counter++;
                }
            }

            // we generate some floating cubes too
            for (int i = 0; i < NumberOfRows; i++)
            {
                for (int j = 0; j < NumberOfColumns; j++)
                {
                    _wipPosition.x = i * Width;
                    _wipPosition.y = Random.Range(MinHeight, MaxHeight);
                    _wipPosition.z = j * Depth;
                    _wipPosition  += Offset;

                    if ((MMMaths.Chance(FloatingBlockChance)) && (Vector3.Distance(_wipPosition, Dancer.transform.position) > MinDistanceToDancer))
                    {
                        _wipName  = "AirBlock_" + _counter;
                        _receiver = InstantiateBlock(_wipPosition, _wipName);

                        _receiver.transform.localScale      = _receiver.transform.localScale * Random.Range(MinScale, MaxScale);
                        _receiver.MinRandomLevelMultiplier *= 3f;
                        _receiver.MaxRandomLevelMultiplier *= 3f;

                        MMAutoRotate autoRotate = _receiver.gameObject.AddComponent <MMAutoRotate>();
                        autoRotate.RotationSpeed = new Vector3(0f, 100f, 0f);

                        _counter++;
                    }
                }
            }
        }
Exemple #25
0
 void Update()
 {
     BaseUpdate();
     Flyer.transform.position = MMMaths.RotatePointAroundPivot(Flyer.transform.position, Pivot.transform.position, perAngle);
 }
Exemple #26
0
 public bool Teleport(Vector2 destination, float maxRetryDistance)
 {
     return(this.Teleport(destination,
                          (MMMaths.Vector3ToVector2(base.transform.position) - destination).normalized, maxRetryDistance));
 }
 /// <summary>
 /// Called when turning, rotates the snake's head, changes its direction, plays a feedback
 /// </summary>
 public virtual void Turn()
 {
     TurnFeedback?.PlayFeedbacks();
     Direction = MMMaths.RotateVector2(Direction, 90f);
     this.transform.Rotate(new Vector3(0f, 0f, 90f));
 }
        /// <summary>
        /// Finds the closest gravity point and changes the gravity if needed
        /// </summary>
        protected virtual void ComputeGravityPoints()
        {
            // if we're not affected by gravity points, we do nothing and exit
            if (!SubjectToGravityPoints)
            {
                return;
            }
            // if we're in a gravity zone, we do nothing and exit
            if (_inAGravityZone)
            {
                return;
            }

            // we grab the closest gravity point
            _closestGravityPoint = GetClosestGravityPoint();

            // if it's not null
            if (_closestGravityPoint != null)
            {
                // our new gravity point becomes the closest if we didn't have one already, otherwise we stay on the last gravity point met for now
                _newGravityPoint = (_lastGravityPoint == null) ? _closestGravityPoint : _lastGravityPoint;
                // if we've got a new gravity point
                if ((_lastGravityPoint != _closestGravityPoint) && (_lastGravityPoint != null))
                {
                    // if we haven't entered a new gravity point in a while, we switch to that new gravity point
                    if (Time.time - _entryTimeStampPoints >= InactiveBufferDuration)
                    {
                        _entryTimeStampPoints = Time.time;
                        _newGravityPoint      = _closestGravityPoint;
                        Transition(true, _newGravityPoint.transform.position - _controller.ColliderCenterPosition);
                        StartRotating();
                    }
                }
                // if we didn't have a gravity point last time, we switch to this new one
                if (_lastGravityPoint == null)
                {
                    if (Time.time - _entryTimeStampPoints >= InactiveBufferDuration)
                    {
                        _entryTimeStampPoints = Time.time;
                        _newGravityPoint      = _closestGravityPoint;
                        Transition(true, _newGravityPoint.transform.position - _controller.ColliderCenterPosition);
                        StartRotating();
                    }
                }
                // we override our gravity
                _gravityPointDirection = _newGravityPoint.transform.position - _controller.ColliderCenterPosition;
                float gravityAngle = 180 - MMMaths.AngleBetween(Vector2.up, _gravityPointDirection);
                _gravityOverridden    = true;
                _overrideGravityAngle = gravityAngle;
                _lastGravityPoint     = _newGravityPoint;
            }
            else
            {
                // if we don't have a gravity point in range, our gravity is not overridden
                if (Time.time - _entryTimeStampPoints >= InactiveBufferDuration)
                {
                    if (_lastGravityPoint != null)
                    {
                        Transition(false, _newGravityPoint.transform.position - _controller.ColliderCenterPosition);
                        StartRotating();
                    }
                    _entryTimeStampPoints = Time.time;
                    _gravityOverridden    = false;
                    _lastGravityPoint     = null;
                }
            }
        }
Exemple #29
0
        public override GameObject SpawnProjectile(Vector3 spawnPosition, int projectileIndex, int totalProjectiles,
                                                   bool triggerObjectActivation = true)
        {
            /// we get the next object in the pool and make sure it's not null
            GameObject nextGameObject = ObjectPooler.GetPooledGameObject();

            // mandatory checks
            if (nextGameObject == null)
            {
                return(null);
            }
            if (nextGameObject.GetComponent <MMPoolableObject>() == null)
            {
                throw new Exception(gameObject.name + " is trying to spawn objects that don't have a PoolableObject component.");
            }
            // we position the object
            nextGameObject.transform.position = spawnPosition;
            if (_projectileSpawnTransform != null)
            {
                nextGameObject.transform.position = _projectileSpawnTransform.position;
            }
            // we set its direction

            Projectile projectile = nextGameObject.GetComponent <Projectile>();

            if (projectile != null)
            {
                projectile.SetDamage((int)(DamageCaused * _damageMultiplier));
                projectile.SetWeapon(this);
                if (Owner != null)
                {
                    projectile.SetOwner(Owner.gameObject);
                }
            }
            // we activate the object
            nextGameObject.gameObject.SetActive(true);

            if (projectile != null)
            {
                if (RandomSpread)
                {
                    _randomSpreadDirection.x = UnityEngine.Random.Range(-Spread.x, Spread.x);
                    _randomSpreadDirection.y = UnityEngine.Random.Range(-Spread.y, Spread.y);
                    _randomSpreadDirection.z = UnityEngine.Random.Range(-Spread.z, Spread.z);
                }
                else
                {
                    if (totalProjectiles > 1)
                    {
                        _randomSpreadDirection.x = MMMaths.Remap(projectileIndex, 0, totalProjectiles - 1, -Spread.x, Spread.x);
                        _randomSpreadDirection.y = MMMaths.Remap(projectileIndex, 0, totalProjectiles - 1, -Spread.y, Spread.y);
                        _randomSpreadDirection.z = MMMaths.Remap(projectileIndex, 0, totalProjectiles - 1, -Spread.z, Spread.z);
                    }
                    else
                    {
                        _randomSpreadDirection = Vector3.zero;
                    }
                }

                Quaternion spread = Quaternion.Euler(_randomSpreadDirection);

                if (Owner == null)
                {
                    projectile.SetDirection(spread * transform.forward, transform.rotation, true);
                }
                else
                {
                    if (Owner.CharacterDimension == Character.CharacterDimensions.Type3D)
                    {
                        projectile.SetDirection(spread * transform.forward, transform.rotation, true);
                    }
                    else
                    {
                        Vector3 newDirection = (spread * transform.right) * (Flipped ? -1 : 1);
                        if (Owner.Orientation2D != null)
                        {
                            projectile.SetDirection(newDirection, transform.rotation, Owner.Orientation2D.IsFacingRight);
                        }
                        else
                        {
                            projectile.SetDirection(newDirection, transform.rotation, true);
                        }
                    }
                }

                if (RotateWeaponOnSpread)
                {
                    this.transform.rotation = this.transform.rotation * spread;
                }
            }

            if (triggerObjectActivation)
            {
                if (nextGameObject.GetComponent <MMPoolableObject>() != null)
                {
                    nextGameObject.GetComponent <MMPoolableObject>().TriggerOnSpawnComplete();
                }
            }
            return(nextGameObject);
        }
        /// <summary>
        /// Computes the current aim direction
        /// </summary>
        protected virtual void GetCurrentAim()
        {
            if (_weapon.Owner == null)
            {
                return;
            }

            if ((_weapon.Owner.LinkedInputManager == null) && (_weapon.Owner.CharacterType == Character.CharacterTypes.Player))
            {
                return;
            }

            switch (AimControl)
            {
            case AimControls.Off:
                if (_weapon.Owner == null)
                {
                    return;
                }

                _currentAim = Vector2.right;
                _direction  = Vector2.right;
                if (_characterGravity != null)
                {
                    _currentAim = _characterGravity.transform.right;
                    _direction  = _characterGravity.transform.right;
                }
                break;

            case AimControls.Script:
                _currentAim = (_weapon.Owner.IsFacingRight) ? _currentAim : -_currentAim;
                _direction  = -(transform.position - _currentAim);
                break;

            case AimControls.PrimaryMovement:
                if (_weapon.Owner == null)
                {
                    return;
                }

                if (_weapon.Owner.IsFacingRight)
                {
                    _currentAim = _weapon.Owner.LinkedInputManager.PrimaryMovement;
                    _direction  = transform.position + _currentAim;
                }
                else
                {
                    _currentAim = -_weapon.Owner.LinkedInputManager.PrimaryMovement;
                    _direction  = -(transform.position - _currentAim);
                }

                if (_characterGravity != null)
                {
                    _currentAim = MMMaths.RotateVector2(_currentAim, _characterGravity.GravityAngle);
                    if (_characterGravity.ShouldReverseInput())
                    {
                        _currentAim = -_currentAim;
                    }
                }
                break;

            case AimControls.SecondaryMovement:
                if (_weapon.Owner == null)
                {
                    return;
                }

                if (_weapon.Owner.IsFacingRight)
                {
                    _currentAim = _weapon.Owner.LinkedInputManager.SecondaryMovement;
                    _direction  = transform.position + _currentAim;
                }
                else
                {
                    _currentAim = -_weapon.Owner.LinkedInputManager.SecondaryMovement;
                    _direction  = -(transform.position - _currentAim);
                }
                break;

            case AimControls.Mouse:
                if (_weapon.Owner == null)
                {
                    return;
                }

                _mousePosition   = Input.mousePosition;
                _mousePosition.z = 10;


                _direction   = Camera.main.ScreenToWorldPoint(_mousePosition);
                _direction.z = transform.position.z;

                if (_weapon.Owner.IsFacingRight)
                {
                    _currentAim = _direction - transform.position;
                }
                else
                {
                    _currentAim = transform.position - _direction;
                }
                break;
            }
        }