예제 #1
0
        public void TickCollisions(TickCollisionsEvent _)
        {
            // TODO: Do this via collision detection instead.
            // TODO: Clean this up.
            // Keeps sword rested on the ground.
            if (this.stateMachine_.IsOnGround)
            {
                var bladeFromGroundY = -(this.playerRigidbody_.CenterY -
                                         this.playerRigidbody_.BottomY);
                bladeFromGroundY -= MathF.Abs(
                    TrigMath.LenDegY(this.handDis_, this.handDeg_));

                var minAngle = MathF.Acos(bladeFromGroundY / this.bladeLength_) /
                               MathF.PI *
                               180;

                var diffToGround = TrigMath.DifferenceInDegrees(this.swordDeg_, 270);
                if (FloatMath.Abs(diffToGround) <= minAngle)
                {
                    this.swordDeg_ = 270 + FloatMath.Sign(diffToGround) * minAngle;

                    if (FloatMath.Abs(this.swordDevVel_) > 2)
                    {
                        this.swordDevVel_ *= -.5f;
                    }
                    else
                    {
                        this.swordDevVel_ = 0;
                    }
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Returns the intersection point of the given lines.
        /// Returns Empty if the lines do not intersect.
        /// Source: http://mathworld.wolfram.com/Line-LineIntersection.html
        ///         https://stackoverflow.com/a/385828/1761622
        /// </summary>
        public static bool LineIntersection(FPoint v1, FPoint v2, FPoint v3, FPoint v4, out FPoint intersec)
        {
            float a = Det2(v1.X - v2.X, v1.Y - v2.Y, v3.X - v4.X, v3.Y - v4.Y);

            if (FloatMath.Abs(a) < FloatMath.EPSILON)
            {
                intersec = FPoint.Zero; return(false);
            }                                                                                               // Lines are parallel

            float d1 = Det2(v1.X, v1.Y, v2.X, v2.Y);
            float d2 = Det2(v3.X, v3.Y, v4.X, v4.Y);
            float x  = Det2(d1, v1.X - v2.X, d2, v3.X - v4.X) / a;
            float y  = Det2(d1, v1.Y - v2.Y, d2, v3.Y - v4.Y) / a;

            intersec = new FPoint(x, y);

            if (x < FloatMath.Min(v1.X, v2.X) - FloatMath.EPSILON || x > FloatMath.Max(v1.X, v2.X) + FloatMath.EPSILON)
            {
                return(false);
            }
            if (y < FloatMath.Min(v1.Y, v2.Y) - FloatMath.EPSILON || y > FloatMath.Max(v1.Y, v2.Y) + FloatMath.EPSILON)
            {
                return(false);
            }
            if (x < FloatMath.Min(v3.X, v4.X) - FloatMath.EPSILON || x > FloatMath.Max(v3.X, v4.X) + FloatMath.EPSILON)
            {
                return(false);
            }
            if (y < FloatMath.Min(v3.Y, v4.Y) - FloatMath.EPSILON || y > FloatMath.Max(v3.Y, v4.Y) + FloatMath.EPSILON)
            {
                return(false);
            }

            return(true);
        }
예제 #3
0
        private void TickCollisions_(TickCollisionsEvent _)
        {
            var initXSpd      = FloatMath.Abs(this.playerRigidbody_.XVelocity);
            var collidedTypes = this.collider_.TickCollisions();

            if ((collidedTypes & LevelTileTypes.LEFT_WALL) != 0 ||
                (collidedTypes & LevelTileTypes.RIGHT_WALL) != 0)
            {
                if (initXSpd > 1)
                {
                    this.playerSounds_.PlayBumpWallSound();
                }
            }

            // If falling while meant to be on the ground, then switch to falling state.
            if (this.stateMachine_.IsOnGround && this.rigidbody_.YVelocity > 0)
            {
                this.stateMachine_.State    = PlayerState.INITIALLY_FALLING_OFF_LEDGE;
                this.initiallyFallingTimer_ = 3;
            }

            if (this.stateMachine_.State == PlayerState.WALL_SLIDING &&
                this.rigidbody_.YVelocity > 0)
            {
                this.playerRigidbody_.YAcceleration =
                    PlayerConstants.WALL_SLIDING_GRAVITY;
            }
            else
            {
                this.playerRigidbody_.YAcceleration = PlayerConstants.GRAVITY;
            }
        }
예제 #4
0
        public static bool LineIntersectionExt(FPoint v1s, FPoint v1e, FPoint v2s, FPoint v2e, float epsilon, out FPoint intersec, out float u1, out float u2)
        {
            float a = Det2(v1s.X - v1e.X, v1s.Y - v1e.Y, v2s.X - v2e.X, v2s.Y - v2e.Y);

            if (FloatMath.Abs(a) < FloatMath.EPSILON)
            {
                intersec = FPoint.Zero; u1 = u2 = Single.NaN; return(false);
            }                                                                                                                     // Lines are parallel

            float d1 = Det2(v1s.X, v1s.Y, v1e.X, v1e.Y);
            float d2 = Det2(v2s.X, v2s.Y, v2e.X, v2e.Y);
            float x  = Det2(d1, v1s.X - v1e.X, d2, v2s.X - v2e.X) / a;
            float y  = Det2(d1, v1s.Y - v1e.Y, d2, v2s.Y - v2e.Y) / a;

            intersec = new FPoint(x, y);

            var v1len = (v1e - v1s).Length();
            var v2len = (v2e - v2s).Length();

            u1 = ((x - v1s.X) * (v1e.X - v1s.X) + (y - v1s.Y) * (v1e.Y - v1s.Y)) / ((v1e.X - v1s.X) * (v1e.X - v1s.X) + (v1e.Y - v1s.Y) * (v1e.Y - v1s.Y));
            u2 = ((x - v2s.X) * (v2e.X - v2s.X) + (y - v2s.Y) * (v2e.Y - v2s.Y)) / ((v2e.X - v2s.X) * (v2e.X - v2s.X) + (v2e.Y - v2s.Y) * (v2e.Y - v2s.Y));

            if (u1 < (0 - (epsilon / v1len)) || u1 > (1 + (epsilon / v1len)))
            {
                return(false);
            }
            if (u2 < (0 - (epsilon / v2len)) || u2 > (1 + (epsilon / v2len)))
            {
                return(false);
            }

            return(true);
        }
예제 #5
0
        private IGamepad?FindFirstTouchedGamepad_()
        {
            foreach (var gamepad in this.gamepads_)
            {
                foreach (var analogStick in gamepad.AnalogSticks)
                {
                    var rawAxes = analogStick.RawAxes;
                    if (FloatMath.Abs(rawAxes.X) > GamepadConstants.DEADZONE ||
                        FloatMath.Abs(rawAxes.Y) > GamepadConstants.DEADZONE)
                    {
                        return(gamepad);
                    }
                }

                foreach (var button in gamepad.Buttons)
                {
                    if (button.IsDown)
                    {
                        return(gamepad);
                    }
                }
            }

            return(null);
        }
        private void UpdateDrag(SAMTime gameTime, InputState istate)
        {
            if (dragMode == DragMode.Node)
            {
                var delta = (istate.GamePointerPositionOnMap.X - mouseStartPos);

                isActiveDragging |= FloatMath.Abs(delta) > MIN_DRAG;
                if (!isActiveDragging)
                {
                    return;
                }

                _values[dragAnchor].SetDirect(offsetStart + delta);

                for (int i = dragAnchor - 1; i >= 0; i--)
                {
                    _values[i].Set(_values[i + 1].TargetValue - DIST_X);
                    _values[i].ValueMin = float.MinValue;
                    _values[i].ValueMax = _values[i + 1].Value - MIN_DIST_X;
                }
                for (int i = dragAnchor + 1; i < _nodes.Length; i++)
                {
                    _values[i].Set(_values[i - 1].TargetValue + DIST_X);
                    _values[i].ValueMin = _values[i - 1].Value + MIN_DIST_X;
                    _values[i].ValueMax = float.MaxValue;
                }

                if (gameTime.TotalElapsedSeconds - dragStartTime > CLICK_CANCEL_TIME || FloatMath.Abs(delta) > CLICK_CANCEL_DIST)
                {
                    _nodes[dragAnchor].CancelClick();
                }

                dragStartTime = gameTime.TotalElapsedSeconds;
            }
            else if (dragMode == DragMode.Global)
            {
                var delta = (istate.GamePointerPositionOnMap.X - mouseStartPos);

                isActiveDragging |= FloatMath.Abs(delta) > MIN_DRAG;
                if (!isActiveDragging)
                {
                    return;
                }

                for (int i = 0; i < _nodes.Length; i++)
                {
                    _values[i].Set(offsetStart + delta + i * DIST_X);
                    _values[i].ValueMin = (i == 0)               ? float.MinValue : _values[i - 1].Value + MIN_DIST_X;
                    _values[i].ValueMax = (i + 1 == _nodes.Length) ? float.MaxValue : _values[i + 1].Value - MIN_DIST_X;
                }
            }

            UpdateOffsets(gameTime, istate);
            _sleep = false;
        }
예제 #7
0
        public virtual void TakeLaserDamage(Fraction source, LaserRay ray, float dmg)
        {
#if DEBUG
            if (DebugSettings.Get("ImmortalCannons"))
            {
                _attackingRaysCollector.Add(ray); return;
            }
#endif

            if (source.IsNeutral)
            {
                if (dmg > 0f)
                {
                    ResetChargeAndBooster();
                }
            }
            else if (Fraction.IsNeutral)
            {
                if (dmg > 0f)
                {
                    counterAttackingLasersFriends++;

                    _attackingRaysCollector.Add(ray);

                    SetFraction(source);
                    CannonHealth.Set(dmg / Scale);
                    CannonHealth.Limit(0f, 1f);
                }
            }
            else
            {
                if (dmg > 0)
                {
                    counterAttackingLasersEnemy++;
                }

                _attackingRaysCollector.Add(ray);

                CannonHealth.Dec(dmg / Scale);

                if (FloatMath.IsZero(CannonHealth.TargetValue))
                {
                    // Never tell me the odds

                    SetFraction(Fraction.GetNeutral());
                }
                else if (CannonHealth.TargetValue < 0)
                {
                    SetFraction(source);
                    CannonHealth.Set(FloatMath.Abs(CannonHealth.TargetValue));
                }

                CannonHealth.Limit(0f, 1f);
            }
        }
예제 #8
0
        public void ProcessInputs(ProcessInputsEvent _)
        {
            var secondaryAnalogStick = this.gamepad_[AnalogStickType.SECONDARY];
            var secStickX            = secondaryAnalogStick.RawAxes.X;
            var secStickY            = secondaryAnalogStick.RawAxes.Y;

            var secStickMag = TrigMath.DistanceBetween(0, 0, secStickX, secStickY);

            if (secStickMag < GamepadConstants.DEADZONE)
            {
                secStickMag = 0;
            }

            var wasShieldOut = this.isShieldOut_;

            this.isShieldOut_ = secStickMag > 0;

            if (this.isShieldOut_)
            {
                var secStickDeg = TrigMath.DegreesBetween(0, 0, secStickX, secStickY);

                var toHandDeg = secStickDeg;

                var maxHorizontalHandDis = this.playerRigidbody_.Width / 2 + 2;
                var maxVerticalHandDis   = this.playerRigidbody_.Height / 2 + 2;
                var maxHandDis           =
                    FloatMath.Abs(
                        TrigMath.LenDegX(maxHorizontalHandDis, secStickDeg)) +
                    FloatMath.Abs(
                        TrigMath.LenDegY(maxVerticalHandDis, secStickDeg));

                var toHandDis = maxHandDis * secStickMag;

                if (!wasShieldOut)
                {
                    this.handDis_ = toHandDis;
                    this.handDeg_ = toHandDeg;
                }
                else
                {
                    var accFactor = 3;

                    this.handDis_ += (toHandDis - this.handDis_) / accFactor;
                    this.handDeg_ +=
                        TrigMath.DifferenceInDegrees(toHandDeg, this.handDeg_) /
                        accFactor;
                }
            }
        }
        private void TickAnimations_(TickAnimationEvent _)
        {
            if (this.stateMachine_.IsMovingUprightOnGround ||
                this.stateMachine_.IsMovingDuckedOnGround)
            {
                this.distanceToNextFootstep_ -=
                    FloatMath.Abs(this.rigidbody_.XVelocity);
            }

            if (this.distanceToNextFootstep_ <= 0)
            {
                var isUpright = this.stateMachine_.IsMovingUprightOnGround;
                this.PlayAtRandomPitch_(isUpright
                                    ? this.footstepHeavy_
                                    : this.footstepLight_);

                this.distanceToNextFootstep_ += this.distanceBetweenFootsteps_;
            }
        }
예제 #10
0
        public virtual void TakeDamage(Fraction source, float sourceScale)
        {
#if DEBUG
            if (DebugSettings.Get("ImmortalCannons"))
            {
                return;
            }
#endif

            if (source.IsNeutral)
            {
                ResetChargeAndBooster();
            }
            else if (Fraction.IsNeutral)
            {
                SetFraction(source);
                CannonHealth.Set((sourceScale * HEALTH_HIT_GEN) / Scale);
                CannonHealth.Limit(0f, 1f);
            }
            else
            {
                CannonHealth.Dec((sourceScale * HEALTH_HIT_DROP) / Scale);

                if (FloatMath.IsZero(CannonHealth.TargetValue))
                {
                    // Never tell me the odds

                    SetFraction(Fraction.GetNeutral());
                }
                else if (CannonHealth.TargetValue < 0)
                {
                    SetFraction(source);
                    CannonHealth.Set(FloatMath.Abs(CannonHealth.TargetValue));
                }

                CannonHealth.Limit(0f, 1f);
            }
        }
예제 #11
0
        private void RemoveUntrusted(List <Tuple <BulletPathBlueprint, float> >[] rayClock)
        {
            List <Tuple <int, Tuple <BulletPathBlueprint, float> > > rems = new List <Tuple <int, Tuple <BulletPathBlueprint, float> > >();

            for (int ideg = 0; ideg < RESOLUTION; ideg++)
            {
                var ddeg = (ideg * 1f / RESOLUTION) * 360;

                foreach (var ray in rayClock[ideg])
                {
                    bool fault = false;
                    for (int ideg2 = 0; ideg2 < RESOLUTION; ideg2++)
                    {
                        var ddeg2 = (ideg2 * 1f / RESOLUTION) * 360;

                        if (ideg2 == ideg || FloatMath.Abs(FloatMath.DiffModulo(ddeg, ddeg2, 360)) > TRUSTANGLE)
                        {
                            continue;
                        }

                        if (rayClock[ideg2].All(r => r.Item1.TargetCannonID != ray.Item1.TargetCannonID))
                        {
                            fault = true;
                        }
                    }
                    if (fault)
                    {
                        rems.Add(Tuple.Create(ideg, ray));
                    }
                }
            }

            foreach (var rem in rems)
            {
                rayClock[rem.Item1].Remove(rem.Item2);
            }
        }
예제 #12
0
        private List <Tuple <BulletPathBlueprint, float> > FindLaserPaths(LevelBlueprint lvl, World wBase, World wCollision, int sourceID, FPoint rcStart, List <Tuple <Vector2, Vector2> > sourcerays, float startRadians, float cannonRadians, int remainingRecasts, bool inGlassBlock, object objIgnore)
        {
            var none = new List <Tuple <BulletPathBlueprint, float> >();

            if (remainingRecasts <= 0)
            {
                return(none);
            }

            var rays = sourcerays.ToList();

            var rcEnd = rcStart + new Vector2(2048, 0).Rotate(startRadians);

            var traceResult  = RayCastLaser(wBase, rcStart, rcEnd, objIgnore);
            var traceResult2 = RayCastLaser(wCollision, rcStart, rcEnd, objIgnore);

            if (traceResult2 != null && traceResult != null && traceResult2.Item1.UserData != traceResult.Item1.UserData)
            {
                // Dirty hit
                return(none);
            }

            if (traceResult == null)
            {
                return(none);
            }

            foreach (var r in rays)
            {
                if (Math2D.LineIntersectionExt(rcStart, traceResult.Item2, r.Item1.ToFPoint(), r.Item2.ToFPoint(), -0.1f, out _, out _, out _))
                {
                    return(none);
                }
            }


            var fCannon = traceResult.Item1.UserData as ICannonBlueprint;

            if (fCannon != null)
            {
                if (fCannon.CannonID == sourceID)
                {
                    return(none);
                }

                var quality = Math2D.LinePointDistance(rcStart, traceResult.Item2, new FPoint(fCannon.X, fCannon.Y));
                rays.Add(Tuple.Create(rcStart.ToVec2D(), traceResult.Item2.ToVec2D()));
                var path = new BulletPathBlueprint(fCannon.CannonID, cannonRadians, rays.ToArray());
                return(new List <Tuple <BulletPathBlueprint, float> > {
                    Tuple.Create(path, quality)
                });
            }

            var fGlassBlock = traceResult.Item1.UserData as MarkerRefractionEdge;

            if (fGlassBlock != null)
            {
                rays.Add(Tuple.Create(rcStart.ToVec2D(), traceResult.Item2.ToVec2D()));

                var pNewStart = traceResult.Item2;

                var normal = traceResult.Item3;
                var aIn    = (rcStart - rcEnd).ToAngle() - normal.ToAngle();

                // sin(aIn) / sin(aOut) = currRefractIdx / Glass.RefractIdx

                var n = inGlassBlock ? (GlassBlockBlueprint.REFRACTION_INDEX / 1f) : (1f / GlassBlockBlueprint.REFRACTION_INDEX);

                var sinaOut = FloatMath.Sin(aIn) * n;

                var dat = new List <Tuple <BulletPathBlueprint, float> >();

                var isRefracting = sinaOut <1 && sinaOut> -1;
                var isReflecting = FloatMath.Abs(aIn) > LaserNetwork.MIN_REFRACT_ANGLE && (!inGlassBlock || (inGlassBlock && !isRefracting));

                if (isRefracting)                 // refraction
                {
                    // refraction

                    var aOut          = FloatMath.Asin(sinaOut);
                    var pRefractAngle = (-normal).ToAngle() + aOut;

                    var sub = FindLaserPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pRefractAngle, cannonRadians, remainingRecasts - 1, !inGlassBlock, fGlassBlock);
                    dat.AddRange(sub);
                }

                if (isReflecting)
                {
                    // reflection

                    var pReflectVec = Vector2.Reflect(rcEnd - rcStart, traceResult.Item3);

                    var sub = FindLaserPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pReflectVec.ToAngle(), cannonRadians, remainingRecasts - 1, !inGlassBlock, fGlassBlock);
                    dat.AddRange(sub);
                }

                return(dat);
            }

            var fGlassBlockCorner = traceResult.Item1.UserData as MarkerRefractionCorner;

            if (fGlassBlockCorner != null)
            {
                if (NO_LASER_CORNER_HITS)
                {
                    return(none);
                }

                rays.Add(Tuple.Create(rcStart.ToVec2D(), traceResult.Item2.ToVec2D()));

                var pNewStart = traceResult.Item2;

                var dat = new List <Tuple <BulletPathBlueprint, float> >();

                if (!inGlassBlock)
                {
                    // reflection

                    var pReflectVec = Vector2.Reflect(rcEnd - rcStart, traceResult.Item3);

                    var sub = FindLaserPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pReflectVec.ToAngle(), cannonRadians, remainingRecasts - 1, !inGlassBlock, fGlassBlockCorner);
                    dat.AddRange(sub);
                }

                return(dat);
            }

            var fMirrorBlock = traceResult.Item1.UserData as MirrorBlockBlueprint;

            if (fMirrorBlock != null)
            {
                rays.Add(Tuple.Create(rcStart.ToVec2D(), traceResult.Item2.ToVec2D()));

                var pNewStart = traceResult.Item2;
                var pVec      = Vector2.Reflect(rcEnd - rcStart, traceResult.Item3);

                return(FindLaserPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pVec.ToAngle(), cannonRadians, remainingRecasts - 1, inGlassBlock, fMirrorBlock));
            }

            var fMirrorCircle = traceResult.Item1.UserData as MirrorCircleBlueprint;

            if (fMirrorCircle != null)
            {
                rays.Add(Tuple.Create(rcStart.ToVec2D(), traceResult.Item2.ToVec2D()));

                var pNewStart = traceResult.Item2;
                var pVec      = Vector2.Reflect(rcEnd - rcStart, traceResult.Item3);

                return(FindLaserPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pVec.ToAngle(), cannonRadians, remainingRecasts - 1, inGlassBlock, fMirrorCircle));
            }

            var fVoidWall = traceResult.Item1.UserData as VoidWallBlueprint;

            if (fVoidWall != null)
            {
                return(none);
            }

            var fVoidCircle = traceResult.Item1.UserData as VoidCircleBlueprint;

            if (fVoidCircle != null)
            {
                return(none);
            }

            var fPortal = traceResult.Item1.UserData as PortalBlueprint;

            if (fPortal != null)
            {
                bool hit = FloatMath.DiffRadiansAbs(traceResult.Item3.ToAngle(), FloatMath.ToRadians(fPortal.Normal)) < FloatMath.RAD_POS_005;

                if (!hit)
                {
                    return(none);
                }

                rays.Add(Tuple.Create(rcStart.ToVec2D(), traceResult.Item2.ToVec2D()));

                var dat = new List <Tuple <BulletPathBlueprint, float> >();
                foreach (var outportal in lvl.BlueprintPortals.Where(p => p.Side != fPortal.Side && p.Group == fPortal.Group))
                {
                    var cIn  = new FPoint(fPortal.X, fPortal.Y);
                    var cOut = new FPoint(outportal.X, outportal.Y);

                    var rot     = FloatMath.ToRadians(outportal.Normal - fPortal.Normal + 180);
                    var stretch = outportal.Length / fPortal.Length;

                    var newAngle = FloatMath.NormalizeAngle(startRadians + rot);
                    var newStart = cOut + stretch * (traceResult.Item2 - cIn).Rotate(rot);

                    newStart = newStart.MirrorAtNormal(cOut, Vector2.UnitX.Rotate(FloatMath.ToRadians(outportal.Normal)));

                    var sub = FindLaserPaths(lvl, wBase, wCollision, sourceID, newStart, rays, newAngle, cannonRadians, remainingRecasts - 1, inGlassBlock, outportal);
                    dat.AddRange(sub);
                }
                return(dat);
            }

            var fBorder = traceResult.Item1.UserData as MarkerCollisionBorder;

            if (fBorder != null)
            {
                if (lvl.WrapMode == LevelBlueprint.WRAPMODE_DONUT)
                {
                    rays.Add(Tuple.Create(rcStart.ToVec2D(), traceResult.Item2.ToVec2D()));

                    var pNewStartX = traceResult.Item2.X;
                    var pNewStartY = traceResult.Item2.Y;
                    switch (fBorder.Side)
                    {
                    case FlatAlign4.NN: pNewStartY += lvl.LevelHeight; break;

                    case FlatAlign4.EE: pNewStartX -= lvl.LevelWidth; break;

                    case FlatAlign4.SS: pNewStartY -= lvl.LevelHeight; break;

                    case FlatAlign4.WW: pNewStartX += lvl.LevelWidth; break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                    var pVec      = rcEnd - rcStart;
                    var pNewStart = new FPoint(pNewStartX, pNewStartY);

                    return(FindLaserPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pVec.ToAngle(), cannonRadians, remainingRecasts - 1, inGlassBlock, fBorder));
                }
                else if (lvl.WrapMode == LevelBlueprint.WRAPMODE_SOLID)
                {
                    rays.Add(Tuple.Create(rcStart.ToVec2D(), traceResult.Item2.ToVec2D()));

                    var pNewStart = traceResult.Item2;
                    var pVec      = Vector2.Reflect(rcEnd - rcStart, traceResult.Item3);

                    return(FindLaserPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pVec.ToAngle(), cannonRadians, remainingRecasts - 1, inGlassBlock, fBorder));
                }
                throw new Exception("Unsupported WrapMode: " + lvl.WrapMode);
            }

            throw new Exception("Unknown rayTrace resturn ficture: " + traceResult.Item1.UserData);
        }
예제 #13
0
        private void RecalcFromRay(LaserSource src, FPoint istart, FPoint iend, int idepth, bool iinglass, object iignore, LaserRay isrc, float idist, bool nofault)
        {
            Stack <Tuple <FPoint, FPoint, int, bool, object, LaserRay, float> > remaining = new Stack <Tuple <FPoint, FPoint, int, bool, object, LaserRay, float> >();

            remaining.Push(Tuple.Create(istart, iend, idepth, iinglass, iignore, isrc, idist));

            while (remaining.Any())
            {
                var pop = remaining.Pop();

                var start     = pop.Item1;
                var end       = pop.Item2;
                var depth     = pop.Item3;
                var inglass   = pop.Item4;
                var ignore    = pop.Item5;
                var source    = pop.Item6;
                var startdist = pop.Item7;

                if (src.Lasers.Count + 1 >= MAX_LASER_PER_SOURCE)
                {
                    continue;
                }
                if (depth >= MAX_LASER_RAYCOUNT)
                {
                    continue;
                }
                if (!start.IsValid)
                {
                    continue;
                }
                if (!end.IsValid)
                {
                    continue;
                }
                if (start.EpsilonEquals(end, FloatMath.EPSILON6))
                {
                    continue;
                }

                var result = RayCast(start, end, ignore);

                #region OOB
                if (result == null)
                {
                    var ray = new LaserRay(start, end, source, LaserRayTerminator.OOB, depth, inglass, ignore, null, startdist, null, src.Type);
                    src.Lasers.Add(ray);
                    if (TestForLaserCollision(src, ray, nofault))
                    {
                        continue;
                    }

                    continue;
                }
                #endregion

                #region Cannon
                var resultCannon = result.Item1.UserData as Cannon;
                if (resultCannon != null)
                {
                    var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Target, depth, inglass, ignore, resultCannon, startdist, resultCannon, src.Type);
                    src.Lasers.Add(ray);
                    if (TestForLaserCollision(src, ray, nofault))
                    {
                        continue;
                    }

                    continue;
                }
                #endregion

                #region GlassBlockRefraction
                var resultGlassBlockRefrac = result.Item1.UserData as MarkerRefractionEdge;
                if (resultGlassBlockRefrac != null)
                {
                    var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Glass, depth, inglass, ignore, resultGlassBlockRefrac, startdist, null, src.Type);
                    src.Lasers.Add(ray);
                    if (TestForLaserCollision(src, ray, nofault))
                    {
                        continue;
                    }

                    // sin(aIn) / sin(aOut) = currRefractIdx / Glass.RefractIdx
                    var aIn = (start - end).ToAngle() - result.Item3.ToAngle();
                    var n   = inglass ? (GlassBlock.REFRACTION_INDEX / 1f) : (1f / GlassBlock.REFRACTION_INDEX);

                    var sinaOut = FloatMath.Sin(aIn) * n;

                    var isRefracting = sinaOut <1 && sinaOut> -1;
                    var isReflecting = FloatMath.Abs(aIn) > MIN_REFRACT_ANGLE && (!inglass || (inglass && !isRefracting));

                    if (isRefracting)                     // refraction
                    {
                        var aOut          = FloatMath.Asin(sinaOut);
                        var pRefractAngle = (-result.Item3).ToAngle() + aOut;

                        remaining.Push(Tuple.Create(result.Item2, result.Item2 + new Vector2(_rayLength, 0).Rotate(pRefractAngle), depth + 1, !inglass, (object)resultGlassBlockRefrac, ray, startdist + ray.Length));
                    }

                    if (isReflecting)
                    {
                        var reflect_end = result.Item2 + Vector2.Reflect(end - start, result.Item3).WithLength(_rayLength);
                        remaining.Push(Tuple.Create(result.Item2, reflect_end, depth + 1, inglass, (object)resultGlassBlockRefrac, ray, startdist + ray.Length));
                    }

                    continue;
                }
                #endregion

                #region GlassBlockRefraction (Corner)
                var resultGlassCornerRefrac = result.Item1.UserData as MarkerRefractionCorner;
                if (resultGlassCornerRefrac != null)
                {
                    var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.VoidObject, depth, inglass, ignore, resultGlassCornerRefrac, startdist, null, src.Type);
                    src.Lasers.Add(ray);
                    if (TestForLaserCollision(src, ray, nofault))
                    {
                        continue;
                    }

                    // sin(aIn) / sin(aOut) = currRefractIdx / Glass.RefractIdx
                    var aIn = (start - end).ToAngle() - result.Item3.ToAngle();
                    var n   = inglass ? (GlassBlock.REFRACTION_INDEX / 1f) : (1f / GlassBlock.REFRACTION_INDEX);

                    var sinaOut = FloatMath.Sin(aIn) * n;

                    var isRefracting = sinaOut <1 && sinaOut> -1;
                    if (isRefracting)                     // refraction
                    {
                        // No refrac in corner
                    }

                    if (!inglass)
                    {
                        var reflect_end = result.Item2 + Vector2.Reflect(end - start, result.Item3).WithLength(_rayLength);
                        remaining.Push(Tuple.Create(result.Item2, reflect_end, depth + 1, inglass, (object)resultGlassCornerRefrac, ray, startdist + ray.Length));
                        continue;
                    }
                    else
                    {
                        // No funtime in corner
                        continue;
                    }
                }
                #endregion

                #region MirrorBlock
                var resultMirrorBlock = result.Item1.UserData as MirrorBlock;
                if (resultMirrorBlock != null)
                {
                    var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Mirror, depth, inglass, ignore, resultMirrorBlock, startdist, null, src.Type);
                    src.Lasers.Add(ray);
                    if (TestForLaserCollision(src, ray, nofault))
                    {
                        continue;
                    }

                    var reflect_end = result.Item2 + Vector2.Reflect(end - start, result.Item3).WithLength(_rayLength);
                    remaining.Push(Tuple.Create(result.Item2, reflect_end, depth + 1, inglass, (object)resultMirrorBlock, ray, startdist + ray.Length));
                    continue;
                }
                #endregion

                #region MirrorCircle
                var resultMirrorCircle = result.Item1.UserData as MirrorCircle;
                if (resultMirrorCircle != null)
                {
                    var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Mirror, depth, inglass, ignore, resultMirrorCircle, startdist, null, src.Type);
                    src.Lasers.Add(ray);
                    if (TestForLaserCollision(src, ray, nofault))
                    {
                        continue;
                    }

                    var reflect_end = result.Item2 + Vector2.Reflect(end - start, result.Item3).WithLength(_rayLength);
                    remaining.Push(Tuple.Create(result.Item2, reflect_end, depth + 1, inglass, (object)resultMirrorCircle, ray, startdist + ray.Length));
                    continue;
                }
                #endregion

                #region VoidWall
                var resultVoidWall = result.Item1.UserData as VoidWall;
                if (resultVoidWall != null)
                {
                    var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.VoidObject, depth, inglass, ignore, resultVoidWall, startdist, null, src.Type);
                    src.Lasers.Add(ray);
                    if (TestForLaserCollision(src, ray, nofault))
                    {
                        continue;
                    }

                    continue;
                }
                #endregion

                #region VoidCircle
                var resultVoidCircle = result.Item1.UserData as VoidCircle;
                if (resultVoidCircle != null)
                {
                    var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.VoidObject, depth, inglass, ignore, resultVoidCircle, startdist, null, src.Type);
                    src.Lasers.Add(ray);
                    if (TestForLaserCollision(src, ray, nofault))
                    {
                        continue;
                    }

                    continue;
                }
                #endregion

                #region Shield
                var resultShield = result.Item1.UserData as ShieldCollisionMarker;
                if (resultShield != null)
                {
                    if (resultShield.Active)
                    {
                        var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Target, depth, inglass, ignore, resultShield, startdist, resultShield.Source, src.Type);
                        src.Lasers.Add(ray);
                        if (TestForLaserCollision(src, ray, nofault))
                        {
                            continue;
                        }

                        continue;
                    }
                    else if (src.Type == RayType.Shield && src.LaserFraction == resultShield.Source.Fraction)
                    {
                        var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Target, depth, inglass, ignore, resultShield, startdist, resultShield.Source, src.Type);
                        src.Lasers.Add(ray);
                        if (TestForLaserCollision(src, ray, nofault))
                        {
                            continue;
                        }

                        continue;
                    }
                    else
                    {
                        continue;
                    }
                }
                #endregion

                #region Portal
                var resultPortal = result.Item1.UserData as Portal;
                if (resultPortal != null)
                {
                    var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Portal, depth, inglass, ignore, resultPortal, startdist, null, src.Type);
                    src.Lasers.Add(ray);
                    if (TestForLaserCollision(src, ray, nofault))
                    {
                        continue;
                    }

                    var  inPortal = resultPortal;
                    var  normal   = result.Item3;
                    bool hit      = FloatMath.DiffRadiansAbs(normal.ToAngle(), inPortal.Normal) < FloatMath.RAD_POS_001;

                    if (!hit)
                    {
                        continue;                           // back-side hit
                    }
                    if (inPortal.Links.Count == 0)
                    {
                        continue;                                                // void portal
                    }
                    foreach (var outportal in inPortal.Links)
                    {
                        var rot    = outportal.Normal - inPortal.Normal + FloatMath.RAD_POS_180;
                        var projec = result.Item2.ProjectOntoLine(inPortal.Position, inPortal.VecDirection);

                        var newVelocity = (end - start).Rotate(rot);
                        var newStart    = outportal.Position + outportal.VecDirection * (-projec) + outportal.VecNormal * (Portal.WIDTH / 2f);

                        var newEnd = newStart + newVelocity.WithLength(_rayLength);

                        remaining.Push(Tuple.Create(newStart, newEnd, depth + 1, false, (object)outportal, ray, startdist + ray.Length));
                    }
                    continue;
                }
                #endregion

                #region Border
                var resultBorderMarker = result.Item1.UserData as MarkerCollisionBorder;
                if (resultBorderMarker != null)
                {
                    if (_wrapMode == GameWrapMode.Reflect)
                    {
                        var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Mirror, depth, inglass, ignore, resultBorderMarker, startdist, null, src.Type);
                        src.Lasers.Add(ray);
                        if (TestForLaserCollision(src, ray, nofault))
                        {
                            continue;
                        }

                        var reflect_end = result.Item2 + Vector2.Reflect(end - start, result.Item3).WithLength(_rayLength);
                        remaining.Push(Tuple.Create(result.Item2, reflect_end, depth + 1, inglass, (object)resultBorderMarker, ray, startdist + ray.Length));
                        continue;
                    }
                    else if (_wrapMode == GameWrapMode.Donut)
                    {
                        var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Portal, depth, inglass, ignore, resultBorderMarker, startdist, null, src.Type);
                        src.Lasers.Add(ray);
                        if (TestForLaserCollision(src, ray, nofault))
                        {
                            continue;
                        }

                        var pNewStartX = result.Item2.X;
                        var pNewStartY = result.Item2.Y;
                        switch (resultBorderMarker.Side)
                        {
                        case FlatAlign4.NN: pNewStartY += _screen.Blueprint.LevelHeight; break;

                        case FlatAlign4.EE: pNewStartX -= _screen.Blueprint.LevelWidth; break;

                        case FlatAlign4.SS: pNewStartY -= _screen.Blueprint.LevelHeight; break;

                        case FlatAlign4.WW: pNewStartX += _screen.Blueprint.LevelWidth; break;

                        default:
                            SAMLog.Error("LASER::EnumSwitch_RFR", "value: " + resultBorderMarker.Side);
                            break;
                        }

                        var newStart = new FPoint(pNewStartX, pNewStartY);
                        var newEnd   = newStart + (end - start);

                        remaining.Push(Tuple.Create(newStart, newEnd, depth + 1, inglass, (object)null, ray, startdist + ray.Length));
                        continue;
                    }
                    else
                    {
                        SAMLog.Error("LASER::UnknownWrap", "Unknown wrapmode: " + _wrapMode);
                    }

                    continue;
                }
                #endregion

                #region Bullet
                var resultBullet = result.Item1.UserData as Bullet;
                if (resultBullet != null)
                {
                    var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.BulletTerm, depth, inglass, ignore, resultBullet, startdist, null, src.Type);
                    ray.TerminatorBullet = resultBullet;
                    src.Lasers.Add(ray);
                    if (TestForLaserCollision(src, ray, nofault))
                    {
                        continue;
                    }

                    continue;
                }
                #endregion

                #region RemoteBullet
                var resultRemoteBullet = result.Item1.UserData as RemoteBullet;
                if (resultRemoteBullet != null)
                {
                    var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.BulletTerm, depth, inglass, ignore, resultRemoteBullet, startdist, null, src.Type);
                    ray.TerminatorBullet = resultRemoteBullet;
                    src.Lasers.Add(ray);
                    if (TestForLaserCollision(src, ray, nofault))
                    {
                        continue;
                    }

                    continue;
                }
                #endregion

                // wud ???
                SAMLog.Error("LASER::UnknownFixture", string.Format("Ray collided with unkown fixture: {0}", result?.Item1?.UserData ?? "<NULL>"));
            }
        }
예제 #14
0
        private void ProcessScheduledHorizontalMovement_()
        {
            var heldXAxis     = this.HeldXAxis;
            var isRunning     = this.IsRunning;
            var isTryingToRun = FloatMath.Abs(heldXAxis) > .5f;

            var heldXAxisSign = FinMath.Sign(heldXAxis);

            float?targetXVelocity = null;
            float xAcceleration   = 0;

            if (this.StateMachine.CanMoveUprightOnGround)
            {
                var maxGroundXVelocity =
                    isRunning
                ? PlayerConstants.UPRIGHT_MAX_FAST_XSPD
                : PlayerConstants.UPRIGHT_MAX_SLOW_XSPD;
                var groundAcceleration =
                    isTryingToRun
                ? PlayerConstants.GROUND_UPRIGHT_FAST_XACC
                : PlayerConstants.GROUND_UPRIGHT_SLOW_XACC;
                var reactionFraction =
                    heldXAxisSign == -FinMath.Sign(this.Rigidbody.XVelocity)
                ? PlayerConstants.GROUND_REACTION_FRAC
                : 1;

                targetXVelocity = maxGroundXVelocity * heldXAxis;
                xAcceleration   = groundAcceleration * reactionFraction * heldXAxisSign;

                // If holding a direction on the ground, we're either turning, running, or walking.
                if (heldXAxisSign != 0)
                {
                    this.StateMachine.State = reactionFraction != 1
                                        ? PlayerState.TURNING
                                        : isTryingToRun
                                            ? PlayerState.RUNNING
                                            : PlayerState.WALKING;
                }
                // If not holding a direction on the ground but velocity is not zero, we're stopping.
                else if (FinMath.Abs(this.Rigidbody.XVelocity) > .001)
                {
                    this.StateMachine.State = PlayerState.STOPPING;
                }
            }
            else if (this.StateMachine.CanMoveDuckedOnGround)
            {
                var maxGroundXVelocity =
                    isRunning
                ? PlayerConstants.DUCKED_MAX_FAST_XSPD
                : PlayerConstants.DUCKED_MAX_SLOW_XSPD;
                var groundAcceleration =
                    isTryingToRun
                ? PlayerConstants.GROUND_DUCKED_FAST_XACC
                : PlayerConstants.GROUND_DUCKED_SLOW_XACC;

                targetXVelocity = maxGroundXVelocity * heldXAxis;
                xAcceleration   = groundAcceleration * heldXAxisSign;

                // If holding a direction on the ground, we're either turning, running, or walking.
                if (heldXAxisSign != 0)
                {
                    this.StateMachine.State = PlayerState.DUCKWALKING;
                }
            }
            else if (this.StateMachine.CanMoveInAir)
            {
                var maxAirXVelocity =
                    isRunning
                ? PlayerConstants.UPRIGHT_MAX_FAST_XSPD
                : PlayerConstants.UPRIGHT_MAX_SLOW_XSPD;
                var airAcceleration =
                    isTryingToRun
                ? PlayerConstants.AIR_FAST_XACC
                : PlayerConstants.AIR_SLOW_XACC;

                targetXVelocity = maxAirXVelocity * heldXAxis;
                xAcceleration   = airAcceleration * heldXAxisSign;
            }

            this.Rigidbody.TargetXVelocity = targetXVelocity;
            this.Rigidbody.XAcceleration   = xAcceleration;
        }
예제 #15
0
 public static FSize Diff(FPoint a, FPoint b)
 {
     return(new FSize(FloatMath.Abs(a.X - b.X), FloatMath.Abs(a.Y - b.Y)));
 }
예제 #16
0
 public static float LinePointDistance(FPoint p1, FPoint p2, FPoint point)
 {
     return(FloatMath.Abs(CrossProduct(p1, p2, point) / (p2 - p1).Length()));
 }
예제 #17
0
 public static float ManhattenLength(this Vector2 v)
 {
     return(FloatMath.Abs(v.X) + FloatMath.Abs(v.Y));
 }
예제 #18
0
 public static FSize ToAbsFSize(this Vector2 p)
 {
     return(new FSize(FloatMath.Abs(p.X), FloatMath.Abs(p.Y)));
 }
예제 #19
0
        private void TickAnimation_(TickAnimationEvent _)
        {
            var xVel = this.playerRigidbody_.XVelocity;

            var xVelSign = MathF.Sign(xVel);

            if (xVelSign != 0)
            {
                this.xDir_ = xVelSign;
            }

            var isStanding    = this.stateMachine_.State == PlayerState.STANDING;
            var isWalking     = this.stateMachine_.State == PlayerState.WALKING;
            var isRealRunning = this.stateMachine_.State == PlayerState.RUNNING;

            if (isStanding)
            {
                this.frameFraction_.Value += .01f;
            }

            if (isWalking)
            {
                var walkFraction = FloatMath.Abs(this.playerRigidbody_.XVelocity) /
                                   PlayerConstants.UPRIGHT_MAX_SLOW_XSPD;
                var animationSpeed = FloatMath.Max(.01f, .02f * walkFraction);

                this.frameFraction_.Value += animationSpeed;
            }

            if (isRealRunning)
            {
                var runFraction = FloatMath.Abs(this.playerRigidbody_.XVelocity) /
                                  PlayerConstants.UPRIGHT_MAX_FAST_XSPD;
                var animationSpeed = FloatMath.Max(.01f, .04f * runFraction);

                this.frameFraction_.Value += animationSpeed;
            }

            var frameFraction = this.frameFraction_.Value;
            var frameAngle    = this.frameFraction_.Value * 360;

            var hipWidth      = PlayerConstants.HSIZE * .6f;
            var backHipWidth  = .4f * hipWidth;
            var frontHipWidth = hipWidth - backHipWidth;

            if (isStanding)
            {
                this.hipCenter_.Transform.RelativeDeg = 0;
                this.hipLeft_.Transform.Length        = frontHipWidth;
                this.hipRight_.Transform.Length       = backHipWidth;

                var leanAngle = this.OscillateAround_(15, 15, frameAngle);

                this.upperLegLeft_.Transform.RelativeDeg  = 90 + leanAngle;
                this.upperLegRight_.Transform.RelativeDeg = -90 + leanAngle;

                this.lowerLegLeft_.Transform.RelativeDeg  = -leanAngle;
                this.lowerLegRight_.Transform.RelativeDeg = -leanAngle;
            }


            if (isWalking)
            {
                var hipAngle = TrigMath.LenDegX(15, -20 + frameAngle);
                this.hipCenter_.Transform.RelativeDeg = hipAngle;

                this.hipLeft_.Transform.Length =
                    frontHipWidth * this.OscillateAround_(1, .5f, hipAngle + 180);
                this.hipRight_.Transform.Length =
                    backHipWidth * this.OscillateAround_(1, .5f, hipAngle);

                var upperLegRange = 20;
                this.upperLegLeft_.Transform.RelativeDeg =
                    90 + TrigMath.LenDegX(upperLegRange / 2, frameAngle);
                this.upperLegRight_.Transform.RelativeDeg =
                    -90 + TrigMath.LenDegX(upperLegRange / 2, frameAngle + 180);

                var lowerLegAngle = -15 + frameAngle;
                var lowerLegRange = 30;
                this.lowerLegLeft_.Transform.RelativeDeg =
                    -lowerLegRange / 2 +
                    TrigMath.LenDegX(lowerLegRange / 2, lowerLegAngle);
                this.lowerLegRight_.Transform.RelativeDeg =
                    -lowerLegRange / 2 +
                    TrigMath.LenDegX(lowerLegRange / 2, lowerLegAngle + 180);
            }


            if (isRealRunning)
            {
                var hipAngle = TrigMath.LenDegX(15, -45 + frameAngle);
                this.hipCenter_.Transform.RelativeDeg = hipAngle;

                this.hipLeft_.Transform.Length =
                    frontHipWidth * this.OscillateAround_(1, .5f, hipAngle + 180);
                this.hipRight_.Transform.Length =
                    backHipWidth * this.OscillateAround_(1, .5f, hipAngle);

                this.upperLegLeft_.Transform.RelativeDeg =
                    180 + this.CalcUpperBoneAngle_(frameFraction, false);
                this.upperLegRight_.Transform.RelativeDeg =
                    this.CalcUpperBoneAngle_(frameFraction, true);

                this.lowerLegLeft_.Transform.RelativeDeg =
                    this.CalcLowerBoneAngle_(frameFraction, false);
                this.lowerLegRight_.Transform.RelativeDeg =
                    this.CalcLowerBoneAngle_(frameFraction, true);
            }

            // TODO: Should this happen automatically?
            this.ForEachBone_(bone => bone.UpdateMatrices());

            var leftHeight =
                FloatMath.Abs(TrigMath.LenDegY(this.upperLegLeft_.Transform.Length,
                                               this.upperLegLeft_.Transform
                                               .GlobalDeg)) +
                FloatMath.Abs(TrigMath.LenDegY(this.lowerLegLeft_.Transform.Length,
                                               this.lowerLegLeft_.Transform
                                               .GlobalDeg));
            var rightHeight =
                FloatMath.Abs(TrigMath.LenDegY(this.upperLegRight_.Transform.Length,
                                               this.upperLegRight_.Transform
                                               .GlobalDeg)) +
                FloatMath.Abs(TrigMath.LenDegY(this.lowerLegRight_.Transform.Length,
                                               this.lowerLegRight_.Transform
                                               .GlobalDeg));

            this.legHeight_ = FloatMath.Max(leftHeight, rightHeight);
        }
예제 #20
0
 public bool EpsilonEquals(FPoint other, float eps = FloatMath.EPSILON)
 {
     return(FloatMath.Abs(X - other.X) <= eps && FloatMath.Abs(Y - other.Y) <= eps);
 }
예제 #21
0
 public static bool EpsilonEquals(this Vector2 vector2, Vector2 other, float eps = 0.00001f)
 {
     return(FloatMath.Abs(vector2.X - other.X) <= eps && FloatMath.Abs(vector2.Y - other.Y) <= eps);
 }
예제 #22
0
        private void ProcessManualInputs_()
        {
            var secondaryAnalogStick = this.gamepad_[AnalogStickType.SECONDARY];
            var secStickX            = secondaryAnalogStick.RawAxes.X;
            var secStickY            = secondaryAnalogStick.RawAxes.Y;

            var secStickMag = TrigMath.DistanceBetween(0, 0, secStickX, secStickY);

            if (secStickMag < GamepadConstants.DEADZONE)
            {
                secStickMag = 0;
            }
            var secStickDeg = TrigMath.DegreesBetween(0, 0, secStickX, secStickY);

            var isResting = secStickMag == 0;

            // TODO: Detect arcs?

            /*if (isResting) {
             * var xVel = this.playerRigidbody_.XVelocity;
             * if (xVel != 0) {
             *  var sign = FloatMath.Sign(xVel);
             *
             *  this.handDis_ = this.maxHandDis_;
             *
             *  if (this.stateMachine_.State == PlayerState.WALKING) {
             *    this.handDeg_ = 90 - sign * (90 + 45);
             *    this.swordDeg_ = 90 - sign * 45;
             *  } else if (this.stateMachine_.State == PlayerState.RUNNING) {
             *    this.handDeg_ = 90 + sign * (90 + 22);
             *    this.swordDeg_ = 90 + sign * (90 + 22);
             *  }
             * }
             * return;
             * }*/

            // Stick moves hands to lift sword. Angle needs to be closer to have
            // more of an effect.
            var diffToHeld =
                TrigMath.DifferenceInDegrees(secStickDeg, this.handDeg_);
            var normalizedDiffToHeld = MathF.Abs(diffToHeld / 180);

            var moveFactor = 1 - normalizedDiffToHeld;

            var diffToTop = TrigMath.DifferenceInDegrees(90, this.handDeg_);
            var isLifting = FloatMath.Sign(diffToTop) == FloatMath.Sign(diffToHeld);

            var moveForce  = 0f;
            var liftFactor = secStickMag * MathF.Pow(moveFactor, 5); // 4, 6, 7

            if (isLifting)
            {
                var liftForce = .6f * diffToHeld * liftFactor;   // .5f
                moveForce = liftForce;
            }
            else
            {
                var dropFactor = secStickMag;
                var dropForce  = .8f * diffToHeld * dropFactor;
                moveForce = dropForce;
            }

            var initDiffToGround   = TrigMath.DifferenceInDegrees(270, this.handDeg_);
            var gravitationalForce = 3 * FloatMath.Sign(initDiffToGround);

            var forceOnHands = moveForce + gravitationalForce;

            // TODO: Use euler method?
            this.handDegVel_ += forceOnHands;
            this.handDeg_    += this.handDegVel_;

            var minAngle          = 45;
            var finalDiffToGround = TrigMath.DifferenceInDegrees(this.handDeg_, 270);

            if (FloatMath.Abs(finalDiffToGround) < minAngle)
            {
                this.handDeg_ = 270 + FloatMath.Sign(finalDiffToGround) * minAngle;

                if (FloatMath.Abs(this.handDegVel_) > 2)
                {
                    this.handDegVel_ *= -.5f;
                }
                else
                {
                    this.handDegVel_ = 0;
                }
            }

            // TODO: This line should theoretically not be here??
            //this.handDeg_ += diffToHeld * liftFactor;
            this.handDeg_ %= 360;

            // TODO: Keep this value when the player lets go of the stick
            this.handDis_ = 16 * secStickMag;

            // TODO: Should be based on velocity instead.
            // If lifting sword, sword angle lags behind.
            //this.swordDeg_ = this.handDeg_;
            var swordDegAccFac = 1 / (1 + MathF.Abs(this.handDegVel_));

            this.swordDeg_ +=
                TrigMath.DifferenceInDegrees(this.handDeg_, this.swordDeg_) * swordDegAccFac;
        }
예제 #23
0
        public LineSegment(FPoint start, FPoint end)
        {
            startPoint = start;
            endPoint   = end;

            direction = (end - start).Normalized();

            Length    = (end - start).Length();
            Boundings = new FRectangle(FloatMath.Min(startPoint.X, endPoint.X), FloatMath.Min(startPoint.Y, endPoint.Y), FloatMath.Abs(startPoint.X - endPoint.X), FloatMath.Abs(startPoint.Y - endPoint.Y));
        }