Example #1
0
        private void Transition_3_TargetCenter()
        {
            _state = TutorialState.TargetCenter;

            _cannon5.RotateTo(_cannon4);

            if (FloatMath.DiffRadiansAbs(_cannon2.Rotation.ActualValue, FloatMath.RAD_POS_090) < FloatMath.RAD_POS_060)
            {
                _cannon2.Rotation.Set(FloatMath.RAD_POS_180);
            }

            SetInfoBox(L10N.T(L10NImpl.STR_TUT_INFO3));

            AddTouchAnimation(_cannon2, _cannon3);
        }
Example #2
0
        private bool OnCollision(Fixture fixtureA, Fixture fixtureB, Contact contact)
        {
            if (!Alive || IsDying || RemoteState != RemoteBulletState.Normal || PredictionState != RemoteBulletState.Normal)
            {
                return(false);
            }

            #region RemoteBullet
            var otherBullet = fixtureB.UserData as RemoteBullet;
            if (otherBullet != null)
            {
                if (otherBullet.Fraction == Fraction)
                {
                    return(true);
                }
                if (!otherBullet.Alive)
                {
                    return(false);
                }

                if (otherBullet.Scale / Scale >= 2f && !otherBullet.Fraction.IsNeutral)
                {
                    // split other
                    otherBullet.PredictKill(RemoteBulletState.Dying_Instant);
                    PredictKill(RemoteBulletState.Dying_Explosion);
                    MainGame.Inst.GDSound.PlayEffectCollision();
                    return(false);
                }
                else if (Scale / otherBullet.Scale >= 2f && Fraction.IsNeutral)
                {
                    // split me
                    otherBullet.PredictKill(RemoteBulletState.Dying_Explosion);
                    PredictKill(RemoteBulletState.Dying_Instant);
                    MainGame.Inst.GDSound.PlayEffectCollision();
                    return(false);
                }
                else
                {
                    otherBullet.PredictKill(RemoteBulletState.Dying_Explosion);
                    PredictKill(RemoteBulletState.Dying_Explosion);
                    MainGame.Inst.GDSound.PlayEffectCollision();
                    return(false);
                }
            }
            #endregion

            #region Cannon
            var otherCannon = fixtureB.UserData as Cannon;
            if (otherCannon != null)
            {
                if (otherCannon.Fraction == Fraction)
                {
                    // stupid approximation to prevent source cannon coll (lifetime > 0.5s)
                    if (Lifetime > 0.5f || fixtureB == otherCannon.PhysicsFixtureBase)
                    {
                        if (otherCannon.IsLaser && otherCannon.CannonHealth.TargetValue >= 1f)
                        {
                            MainGame.Inst.GDSound.PlayEffectReflect();
                            return(true);
                        }
                        else
                        {
                            PredictKill(RemoteBulletState.Dying_ShrinkFast);
                            otherCannon.ApplyBoost();
                            MainGame.Inst.GDSound.PlayEffectBoost();
                        }
                    }
                }
                else                 // if (otherCannon.Fraction != this.Fraction)
                {
                    PredictKill(RemoteBulletState.Dying_Fade);
                    otherCannon.TakeDamage(Fraction, Scale);
                    MainGame.Inst.GDSound.PlayEffectHit();
                }

                return(false);
            }
            #endregion

            #region VoidWall
            var otherVoidWall = fixtureB.UserData as VoidWall;
            if (otherVoidWall != null)
            {
                PredictKill(RemoteBulletState.Dying_Explosion);
                MainGame.Inst.GDSound.PlayEffectCollision();
                return(false);
            }
            #endregion

            #region VoidCircle
            var otherVoidCircle = fixtureB.UserData as VoidCircle;
            if (otherVoidCircle != null)
            {
                PredictKill(RemoteBulletState.Dying_Explosion);
                MainGame.Inst.GDSound.PlayEffectCollision();
                return(false);
            }
            #endregion

            #region Shield
            var otherShield = fixtureB.UserData as ShieldCollisionMarker;
            if (otherShield != null)
            {
                if (!otherShield.Active)
                {
                    return(false);
                }

                PredictKill(RemoteBulletState.Dying_Explosion);
                MainGame.Inst.GDSound.PlayEffectCollision();
                return(false);
            }
            #endregion

            #region GlassBlock
            var otherGlassBlock = fixtureB.UserData as GlassBlock;
            if (otherGlassBlock != null)
            {
                MainGame.Inst.GDSound.PlayEffectGlass();
                return(true);
            }
            #endregion

            #region Portal
            var otherPortal = fixtureB.UserData as Portal;
            if (otherPortal != null)
            {
                var inPortal = otherPortal;

                Vector2 normal;
                FixedArray2 <Vector2> t;
                contact.GetWorldManifold(out normal, out t);

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

                if (!hit)
                {
                    // back-side hit
                    PredictKill(RemoteBulletState.Dying_Explosion);
                    return(false);
                }

                if (inPortal.Links.Count == 0)
                {
                    // void portal
                    PredictKill(RemoteBulletState.Dying_ShrinkFast);
                    return(false);
                }

                PredictKill(RemoteBulletState.Dying_ShrinkFast);
                return(false);
            }
            #endregion

            #region MirrorBlock
            var otherMirrorBlock = fixtureB.UserData as MirrorBlock;
            if (otherMirrorBlock != null)
            {
                MainGame.Inst.GDSound.PlayEffectReflect();
                return(true);
            }
            #endregion

            #region MirrorCircle
            var otherMirrorCircle = fixtureB.UserData as MirrorCircle;
            if (otherMirrorCircle != null)
            {
                MainGame.Inst.GDSound.PlayEffectReflect();
                return(true);
            }
            #endregion

            #region RefractionMarker
            var otherRefractionMarker1 = fixtureB.UserData as MarkerRefractionEdge;
            if (otherRefractionMarker1 != null)
            {
                return(false);
            }
            var otherRefractionMarker2 = fixtureB.UserData as MarkerRefractionCorner;
            if (otherRefractionMarker2 != null)
            {
                return(false);
            }
            #endregion

            #region BorderMarker
            var otherBorderMarker = fixtureB.UserData as MarkerCollisionBorder;
            if (otherBorderMarker != null)
            {
                if (GDOwner.WrapMode == GameWrapMode.Reflect)
                {
                    return(true);
                }
                return(false);
            }
            #endregion

            return(false);
        }
Example #3
0
        protected override void OnUpdate(GDGameScreen screen, SAMTime gameTime, InputState istate)
        {
            if (_state >= TutorialState.TargetFirstNeutral)
            {
                _cannon1.CannonHealth.SetForce(1);
            }
            if (_state >= TutorialState.TargetCenter)
            {
                _cannon2.CannonHealth.SetForce(1);
            }
            if (_state >= TutorialState.AttackEnemy)
            {
                _cannon3.CannonHealth.SetForce(1);
            }

            _s1_blinkTimer += gameTime.ElapsedSeconds;

            switch (_state)
            {
            case TutorialState.Start:
                Transition_1_ShootFirstNeutral();
                break;

            case TutorialState.TargetFirstNeutral:
                if (_cannon2.Fraction != _fracNeutral)
                {
                    _cannon2.CannonHealth.SetForce(0f);
                    _cannon2.SetFraction(_fracNeutral);
                }
                _infobox.Background = _infobox.Background.WithColor(ColorMath.Blend(FlatColors.Concrete, FlatColors.Orange, FloatMath.PercSin(_s1_blinkTimer * 4f)));
                if (FloatMath.DiffRadiansAbs(_cannon1.Rotation.ActualValue, FloatMath.RAD_POS_270) < FloatMath.RAD_POS_060)
                {
                    Transition_2_ShootingFirstNeutral();
                }
                break;

            case TutorialState.ShootingFirstNeutral:
                _infobox.Background = _infobox.Background.WithColor(FlatColors.Concrete);
                if (FloatMath.IsOne(_cannon2.CannonHealth.ActualValue))
                {
                    Transition_3_TargetCenter();
                }
                break;

            case TutorialState.TargetCenter:
                if (FloatMath.DiffRadiansAbs(_cannon2.Rotation.ActualValue, FloatMath.RAD_000) < FloatMath.RAD_POS_060)
                {
                    Transition_4_BoostWhileShootingCenter();
                }
                break;

            case TutorialState.BoostWhileShootingCenter:
                _cannon3.ForceResetBarrelCharge();                         // no shooting enemy for now
                _cannon4.ForceResetBarrelCharge();                         // no shooting me    for now
                _cannon3.Rotation.Set(FloatMath.RAD_POS_090);
                var cap3 = _cannon3.Fraction == _fracPlayer && FloatMath.IsOne(_cannon3.CannonHealth.ActualValue);
                var cap4 = _cannon4.Fraction == _fracComputer && FloatMath.IsOne(_cannon4.CannonHealth.ActualValue);
                if (cap3 && _cannon4.Fraction == _fracComputer)
                {
                    _cannon4.CannonHealth.Set(1);
                }
                if (cap3 && cap4)
                {
                    Transition_5_AttackEnemy();
                }
                break;

            case TutorialState.AttackEnemy:
                _cannon4.CannonHealth.SetForce(1);
                if (FloatMath.DiffRadiansAbs(_cannon3.Rotation.ActualValue, FloatMath.RAD_000) < FloatMath.RAD_POS_060)
                {
                    Transition_6_ChangeGameSpeed();
                }
                break;

            case TutorialState.ChangeGameSpeed:
                _cannon4.CannonHealth.SetForce(1);
                if (_screen.GameSpeedMode > GameSpeedModes.SUPERSLOW)
                {
                    Transition_7_CaptureEnemy();
                }
                break;

            case TutorialState.CaptureEnemy:
                _infobox.Background = _infobox.Background.WithColor(ColorMath.Blend(FlatColors.Alizarin, FlatColors.SunFlower, FloatMath.PercSin(_s1_blinkTimer * 6f)));
                if (FloatMath.IsOne(_cannon4.CannonHealth.ActualValue) && _cannon4.Fraction == _fracPlayer)
                {
                    Transition_8_WinGame();
                }
                break;

            case TutorialState.WinGame:
                _infobox.Background = _infobox.Background.WithColor(ColorMath.Blend(FlatColors.Emerald, FlatColors.Concrete, FloatMath.PercSin(_s1_blinkTimer * 4f)));
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Example #4
0
        private List <Tuple <BulletPathBlueprint, float> > FindBulletPaths(LevelBlueprint lvl, World wBase, World wCollision, int sourceID, FPoint rcStart, List <Tuple <Vector2, Vector2> > sourcerays, float startRadians, float cannonRadians, int remainingRecasts)
        {
            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  = RayCastBullet(wBase, rcStart, rcEnd);
            var traceResult2 = RayCastBullet(wCollision, rcStart, rcEnd);

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

            if (traceResult == null)
            {
                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 GlassBlockBlueprint;

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

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

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

            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(FindBulletPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pVec.ToAngle(), cannonRadians, remainingRecasts - 1));
            }

            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(FindBulletPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pVec.ToAngle(), cannonRadians, remainingRecasts - 1));
            }

            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 fBlackhole = traceResult.Item1.UserData as BlackHoleBlueprint;

            if (fBlackhole != null)
            {
                return(none);                // Black holes are _not_ correctly calculated in this preprocessor
            }

            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 + (traceResult.Item2 - cIn).Rotate(rot) * stretch;

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

                    var sub = FindBulletPaths(lvl, wBase, wCollision, sourceID, newStart, rays, newAngle, cannonRadians, remainingRecasts - 1);
                    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(FindBulletPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pVec.ToAngle(), cannonRadians, remainingRecasts - 1));
                }
                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(FindBulletPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pVec.ToAngle(), cannonRadians, remainingRecasts - 1));
                }
                throw new Exception("Unsupported WrapMode: " + lvl.WrapMode);
            }

            throw new Exception("Unknown rayTrace resturn ficture: " + traceResult.Item1.UserData);
        }
Example #5
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);
        }
Example #6
0
        // test of rays hit each other
        private bool RayParallality(FPoint v1s, FPoint v1e, float v1d, FPoint v2s, FPoint v2e, float v2d, bool reflTolerant, out FPoint intersect, out float u)
        {
            var a1 = (v1e - v1s).ToAngle();
            var a2 = (v2e - v2s).ToAngle();

            var maxAngle = reflTolerant ? FloatMath.RAD_POS_004 : FloatMath.RAD_POS_090;

            if (FloatMath.DiffRadiansAbs(a1, a2) < maxAngle)
            {
                // same direction

                var u1 = v2s.ProjectOntoLine(v1s, v1e);
                var u2 = v1s.ProjectOntoLine(v2s, v2e);

                if (u1 > 0 && u1 < 1)
                {
                    intersect = Math2D.PointOnLine(u1, v1s, v1e);
                    u         = u1;
                    return(true);
                }
                if (u2 > 0 && u2 < 1)
                {
                    intersect = v1s;
                    u         = 0;
                    return(true);
                }
            }
            else if (FloatMath.DiffRadiansAbs(a1 + FloatMath.RAD_POS_180, a2) < maxAngle)
            {
                var u1s = FloatMath.Clamp(v2e.ProjectOntoLine(v1s, v1e), 0f, 1f);
                var u1e = FloatMath.Clamp(v2s.ProjectOntoLine(v1s, v1e), 0f, 1f);
                var u2s = FloatMath.Clamp(v1e.ProjectOntoLine(v2s, v2e), 0f, 1f);
                var u2e = FloatMath.Clamp(v1s.ProjectOntoLine(v2s, v2e), 0f, 1f);

                var v1rs = (u1s == 0) ? v1s : Math2D.PointOnLine(u1s, v1s, v1e);
                var v1re = (u1e == 1) ? v1e : Math2D.PointOnLine(u1e, v1s, v1e);
                var v2rs = (u2s == 0) ? v2s : Math2D.PointOnLine(u2s, v2s, v2e);
                var v2re = (u1e == 1) ? v2e : Math2D.PointOnLine(u2e, v2s, v2e);

                var distStart = (v1rs - v2re).LengthSquared();
                var distEnd   = (v1re - v2rs).LengthSquared();

                if (distStart < RAY_WIDTH * RAY_WIDTH && distEnd < RAY_WIDTH * RAY_WIDTH)
                {
                    var pc = FPoint.MiddlePoint(v1s, v2s);

                    pc = pc + (v1s - v2s).WithLength((v1d - v2d) / 2f);

                    var pcu1 = pc.ProjectOntoLine(v1s, v1e);
                    if (pcu1 < 0)
                    {
                        pc = v1s;
                    }
                    if (pcu1 > 1)
                    {
                        pc = v1e;
                    }

                    var pcu2 = pc.ProjectOntoLine(v2s, v2e);
                    if (pcu2 < 0)
                    {
                        pc = v2s;
                    }
                    if (pcu2 > 1)
                    {
                        pc = v2e;
                    }

                    intersect = pc;
                    u         = pc.ProjectOntoLine(v1s, v1e);
                    return(true);
                }
                else if (distStart < RAY_WIDTH * RAY_WIDTH)
                {
                    var drStart = FloatMath.Sqrt(distStart);
                    var drEnd   = FloatMath.Sqrt(distEnd);
                    var perc    = (RAY_WIDTH - drStart) / (drEnd - drStart);

                    u1e = u1s + (u1e - u1s) * perc;
                    u2s = u2e + (u2s - u2e) * perc;

                    v1re = Math2D.PointOnLine(u1e, v1s, v1e);
                    v2rs = Math2D.PointOnLine(u2s, v2s, v2e);

                    var v1rd = v1d + u1s * (v1e - v1s).Length();
                    var v2rd = v2d + u2s * (v2e - v2s).Length();



                    var pc = FPoint.MiddlePoint(v1rs, v2rs);

                    pc = pc + (v1rs - v2rs).WithLength((v1rd - v2rd) / 2f);

                    var pcu1 = pc.ProjectOntoLine(v1rs, v1re);
                    if (pcu1 < u1s)
                    {
                        pc = v1rs;
                    }
                    if (pcu1 > u1e)
                    {
                        pc = v1re;
                    }

                    var pcu2 = pc.ProjectOntoLine(v2rs, v2re);
                    if (pcu2 < u2s)
                    {
                        pc = v2rs;
                    }
                    if (pcu2 > u2e)
                    {
                        pc = v2re;
                    }

                    intersect = pc;
                    u         = pc.ProjectOntoLine(v1s, v1e);
                    return(true);
                }
                else if (distEnd < RAY_WIDTH * RAY_WIDTH)
                {
                    var drStart = FloatMath.Sqrt(distStart);
                    var drEnd   = FloatMath.Sqrt(distEnd);
                    var perc    = (RAY_WIDTH - drEnd) / (drStart - drEnd);

                    u1s = u1e + (u1s - u1e) * perc;
                    u2e = u2s + (u2e - u2s) * perc;

                    v1rs = Math2D.PointOnLine(u1s, v1s, v1e);
                    v2re = Math2D.PointOnLine(u2e, v2s, v2e);

                    var v1rd = v1d + u1s * (v1e - v1s).Length();
                    var v2rd = v2d + u2s * (v2e - v2s).Length();



                    var pc = FPoint.MiddlePoint(v1rs, v2rs);

                    pc = pc + (v1rs - v2rs).WithLength((v1rd - v2rd) / 2f);

                    var pcu1 = pc.ProjectOntoLine(v1rs, v1re);
                    if (pcu1 < u1s)
                    {
                        pc = v1rs;
                    }
                    if (pcu1 > u1e)
                    {
                        pc = v1re;
                    }

                    var pcu2 = pc.ProjectOntoLine(v2rs, v2re);
                    if (pcu2 < u2s)
                    {
                        pc = v2rs;
                    }
                    if (pcu2 > u2e)
                    {
                        pc = v2re;
                    }

                    intersect = pc;
                    u         = pc.ProjectOntoLine(v1s, v1e);
                    return(true);
                }
            }



            intersect = FPoint.Zero;
            u         = float.NaN;

            return(false);
        }
Example #7
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>"));
            }
        }
Example #8
0
        private bool OnCollision(Fixture fixtureA, Fixture fixtureB, Contact contact)
        {
            if (!Alive || IsDying)
            {
                return(false);
            }

            #region Bullet
            var otherBullet = fixtureB.UserData as Bullet;
            if (otherBullet != null)
            {
                if (otherBullet.Fraction == Fraction)
                {
                    return(true);
                }
                if (!otherBullet.Alive)
                {
                    return(false);
                }

                if (otherBullet.Scale / Scale >= 2f && !otherBullet.Fraction.IsNeutral)
                {
                    // split other
                    otherBullet.SplitDestruct();
                    MutualDestruct();
                    MainGame.Inst.GDSound.PlayEffectCollision();
                    return(false);
                }
                else if (Scale / otherBullet.Scale >= 2f && Fraction.IsNeutral)
                {
                    // split me
                    otherBullet.MutualDestruct();
                    SplitDestruct();
                    MainGame.Inst.GDSound.PlayEffectCollision();
                    return(false);
                }
                else
                {
                    otherBullet.MutualDestruct();
                    MutualDestruct();
                    MainGame.Inst.GDSound.PlayEffectCollision();
                    return(false);
                }
            }
            #endregion

            #region Cannon
            var otherCannon = fixtureB.UserData as Cannon;
            if (otherCannon != null)
            {
                if (otherCannon.Fraction == Fraction)
                {
                    // if Source barrel then ignore collision
                    if (otherCannon != Source || fixtureB == otherCannon.PhysicsFixtureBase)
                    {
                        if (otherCannon.IsLaser && otherCannon.CannonHealth.ActualValue >= 1f)
                        {
                            MainGame.Inst.GDSound.PlayEffectReflect();
                            return(true);
                        }
                        else
                        {
                            DisintegrateIntoFriend();
                            otherCannon.ApplyBoost();
                            MainGame.Inst.GDSound.PlayEffectBoost();
                        }
                    }
                }
                else                 // if (otherCannon.Fraction != this.Fraction)
                {
                    if (otherCannon != Source || fixtureB == otherCannon.PhysicsFixtureBase)
                    {
                        DisintegrateIntoEnemy();
                        otherCannon.TakeDamage(Fraction, Scale);
                        MainGame.Inst.GDSound.PlayEffectHit();
                    }
                }

                return(false);
            }
            #endregion

            #region VoidWall
            var otherVoidWall = fixtureB.UserData as VoidWall;
            if (otherVoidWall != null)
            {
                DisintegrateIntoVoidObject();
                MainGame.Inst.GDSound.PlayEffectCollision();
                return(false);
            }
            #endregion

            #region VoidCircle
            var otherVoidCircle = fixtureB.UserData as VoidCircle;
            if (otherVoidCircle != null)
            {
                DisintegrateIntoVoidObject();
                MainGame.Inst.GDSound.PlayEffectCollision();
                return(false);
            }
            #endregion

            #region Shield
            var otherShield = fixtureB.UserData as ShieldCollisionMarker;
            if (otherShield != null)
            {
                if (otherShield.Source == Source)
                {
                    return(false);
                }
                if (!otherShield.Active)
                {
                    return(false);
                }

                DisintegrateIntoVoidObject();
                MainGame.Inst.GDSound.PlayEffectCollision();
                return(false);
            }
            #endregion

            #region GlassBlock
            var otherGlassBlock = fixtureB.UserData as GlassBlock;
            if (otherGlassBlock != null)
            {
                MainGame.Inst.GDSound.PlayEffectGlass();
                return(true);
            }
            #endregion

            #region Portal
            var otherPortal = fixtureB.UserData as Portal;
            if (otherPortal != null)
            {
                var inPortal = otherPortal;

                Vector2 normal;
                FixedArray2 <Vector2> t;
                contact.GetWorldManifold(out normal, out t);

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

                if (!hit)
                {
                    // back-side hit
                    DisintegrateIntoVoidObject();
                    return(false);
                }

                if (inPortal.Links.Count == 0)
                {
                    // void portal
                    DisintegrateIntoPortal();
                    return(false);
                }

                var velocity = ConvertUnits.ToDisplayUnits(PhysicsBody.LinearVelocity);

                for (int i = 0; i < _ignoredPortals.Count; i++)
                {
                    if (_ignoredPortals[i].Entity == inPortal)
                    {
                        _ignoredPortals[i].LastCollidedCycle = MonoSAMGame.GameCycleCounter;

                        if (FloatMath.DiffRadiansAbs(velocity.ToAngle(), inPortal.Normal) > FloatMath.RAD_POS_090)
                        {
                            // prevent tunneling
                            Alive = false;
                            return(false);
                        }

                        return(false);
                    }
                }

                foreach (var outportal in inPortal.Links)
                {
                    var stretch = outportal.Length / inPortal.Length;

                    var rot    = outportal.Normal - inPortal.Normal + FloatMath.RAD_POS_180;
                    var projec = ConvertUnits.ToDisplayUnits(PhysicsBody.Position).ProjectOntoLine(inPortal.Position, inPortal.VecDirection);

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

                    var b = new Bullet(GDOwner, Source, newStart, newVelocity, Scale * stretch, Fraction)
                    {
                        Lifetime = Lifetime
                    };
                    b._ignoredPortals.Add(new CollisionIgnorePortal()
                    {
                        Entity = outportal, LastCollidedCycle = MonoSAMGame.GameCycleCounter
                    });
                    b.AddOperation(new BulletGrowOperation(0.15f));
                    Owner.Entities.AddEntity(b);
                }
                DisintegrateIntoPortal();
                return(false);
            }
            #endregion

            #region MirrorBlock
            var otherMirrorBlock = fixtureB.UserData as MirrorBlock;
            if (otherMirrorBlock != null)
            {
                MainGame.Inst.GDSound.PlayEffectReflect();
                return(true);
            }
            #endregion

            #region MirrorCircle
            var otherMirrorCircle = fixtureB.UserData as MirrorCircle;
            if (otherMirrorCircle != null)
            {
                MainGame.Inst.GDSound.PlayEffectReflect();
                return(true);
            }
            #endregion

            #region RefractionMarker
            var otherRefractionMarker1 = fixtureB.UserData as MarkerRefractionEdge;
            if (otherRefractionMarker1 != null)
            {
                return(false);
            }
            var otherRefractionMarker2 = fixtureB.UserData as MarkerRefractionCorner;
            if (otherRefractionMarker2 != null)
            {
                return(false);
            }
            #endregion

            #region BorderMarker
            var otherBorderMarker = fixtureB.UserData as MarkerCollisionBorder;
            if (otherBorderMarker != null)
            {
                if (GDOwner.WrapMode == GameWrapMode.Reflect)
                {
                    return(true);
                }
                return(false);
            }
            #endregion

            // wud ???
            SAMLog.Error("Collision", string.Format("Bullet collided with unkown fixture: {0}", fixtureB.UserData ?? "<NULL>"));
            return(false);
        }
Example #9
0
            public bool Run(KIController ki)
            {
                if (_runDirect != null)
                {
                    var target = _runDirect();
                    if (target != null)
                    {
                        var rot = FloatMath.PositiveAtan2(target.Position.Y - ki.Cannon.Position.Y, target.Position.X - ki.Cannon.Position.X);

                        ki.Cannon.KITarget = target;

                        if (ki.MinimumRotationalDelta > 0 && FloatMath.DiffRadiansAbs(rot, ki.Cannon.Rotation.TargetValue) < ki.MinimumRotationalDelta)
                        {
                            ki.LastKIFunction = "Ign[" + Name + "]";
                            return(true);
                        }

                        ki.Cannon.Rotation.Set(rot);
                        ki.LastKIFunction = Name;

                        return(true);
                    }
                }
                else if (_runPrecalc != null)
                {
                    var target = _runPrecalc();
                    if (target != null)
                    {
                        ki.Cannon.KITarget = target.TargetCannon;

                        if (ki.MinimumRotationalDelta > 0 && FloatMath.DiffRadiansAbs(target.CannonRotation, ki.Cannon.Rotation.TargetValue) < ki.MinimumRotationalDelta)
                        {
                            ki.LastKIFunction = "Ign[" + Name + "]";
                            return(true);
                        }

                        ki.Cannon.Rotation.Set(target.CannonRotation);
                        ki.LastKIFunction = Name;

                        return(true);
                    }
                }
                else if (_runAntiLaser != null)
                {
                    var ray = _runAntiLaser();
                    if (ray != null)
                    {
                        var target = ki.Cannon.Position.MirrorAt(FPoint.MiddlePoint(ray.Start, ray.End));
                        var rot    = target.ToAngle(ki.Cannon.Position);

                        ki.Cannon.KITarget = null;

                        if (ki.MinimumRotationalDelta > 0 && FloatMath.DiffRadiansAbs(rot, ki.Cannon.Rotation.TargetValue) < ki.MinimumRotationalDelta / 4f)
                        {
                            ki.LastKIFunction = "Ign[" + Name + "]";
                            return(true);
                        }

                        ki.Cannon.Rotation.Set(rot);
                        ki.LastKIFunction = Name;

                        return(true);
                    }
                    return(false);
                }
                else if (_runGeneric != null)
                {
                    _runGeneric();
                    return(true);
                }
                else if (_runCustom != null)
                {
                    var f = _runCustom();
                    if (f != null)
                    {
                        var rot = f.Value;

                        if (ki.MinimumRotationalDelta > 0 && FloatMath.DiffRadiansAbs(rot, ki.Cannon.Rotation.TargetValue) < ki.MinimumRotationalDelta / 4f)
                        {
                            ki.LastKIFunction = "Ign[" + Name + "]";
                            return(true);
                        }

                        ki.Cannon.Rotation.Set(rot);
                        ki.LastKIFunction = Name;

                        return(true);
                    }
                    return(false);
                }

                ki.Cannon.KITarget = null;
                return(false);
            }
Example #10
0
        private List <Tuple <List <Vector2>, ICannonBlueprint, float> > FindBulletPaths(LevelBlueprint lvl, World world, int sourceID, FPoint spawnPoint, Vector2 spawnVeloc, List <Vector2> fullpath, float scale, float lifetime)
        {
            var none = new List <Tuple <List <Vector2>, ICannonBlueprint, float> >();         // path, cannon, quality

            fullpath = fullpath.ToList();

            object  collisionUserObject = null;
            Contact collisionContact    = null;

            var farseerBullet = BodyFactory.CreateCircle(world, ConvertUnits.ToSimUnits(scale * Bullet.BULLET_DIAMETER / 2), 1, ConvertUnits2.ToSimUnits(spawnPoint), BodyType.Dynamic, null);

            farseerBullet.LinearVelocity = ConvertUnits.ToSimUnits(spawnVeloc);
            farseerBullet.CollidesWith   = Category.All;
            farseerBullet.Restitution    = 1f;                       // Bouncability, 1=bounce always elastic
            farseerBullet.AngularDamping = 1f;                       // Practically no angular rotation
            farseerBullet.Friction       = 0f;
            farseerBullet.LinearDamping  = 0f;                       // no slowing down
            farseerBullet.OnCollision   += (fa, fb, cobj) =>
            {
                collisionUserObject = fb.UserData;
                collisionContact    = cobj;
                if (fb.UserData is GlassBlockBlueprint)
                {
                    return(true);
                }
                if (fb.UserData is MirrorBlockBlueprint)
                {
                    return(true);
                }
                if (fb.UserData is MirrorCircleBlueprint)
                {
                    return(true);
                }
                if (fb.UserData is MarkerCollisionBorder)
                {
                    return(true);
                }
                return(false);
            };
            farseerBullet.AngularVelocity = 0;

            fullpath.Add(spawnPoint.ToVec2D());

            for (;;)
            {
                collisionUserObject = null;

                foreach (var bh in lvl.BlueprintBlackHoles)
                {
                    var pp       = ConvertUnits.ToDisplayUnits(farseerBullet.Position) - new Vector2(bh.X, bh.Y);
                    var force    = bh.Power / pp.LengthSquared();
                    var vecForce = pp.WithLength(force);
                    farseerBullet.ApplyForce(ConvertUnits.ToSimUnits(vecForce));
                }

                world.Step(1 / SIMULATION_UPS);                 // x UPS
                lifetime += 1 / SIMULATION_UPS;
                fullpath.Add(ConvertUnits2.ToDisplayUnitsPoint(farseerBullet.Position).ToVec2D());

                if (collisionUserObject is PortalBlueprint)
                {
                    var veloc = ConvertUnits.ToDisplayUnits(farseerBullet.LinearVelocity);

                    world.RemoveBody(farseerBullet);
                    var fPortal = (PortalBlueprint)collisionUserObject;

                    Vector2 normal;
                    FixedArray2 <Vector2> t;
                    collisionContact.GetWorldManifold(out normal, out t);

                    bool hit = FloatMath.DiffRadiansAbs(normal.ToAngle(), FloatMath.ToRadians(fPortal.Normal)) < FloatMath.RAD_POS_001;

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

                    var dat = new List <Tuple <List <Vector2>, ICannonBlueprint, float> >();
                    foreach (var outportal in lvl.BlueprintPortals.Where(p => p.Side != fPortal.Side && p.Group == fPortal.Group))
                    {
                        var stretch = outportal.Length / fPortal.Length;

                        var cIn              = new FPoint(fPortal.X, fPortal.Y);
                        var cOut             = new FPoint(outportal.X, outportal.Y);
                        var cInVecNormal     = Vector2.UnitX.RotateDeg(fPortal.Normal);
                        var cInVecDirection  = cInVecNormal.RotateWithLength(FloatMath.RAD_POS_090, fPortal.Length / 2f);
                        var cOutVecNormal    = Vector2.UnitX.RotateDeg(outportal.Normal);
                        var cOutVecDirection = cOutVecNormal.RotateWithLength(FloatMath.RAD_POS_090, outportal.Length / 2f);

                        var rot    = FloatMath.ToRadians(outportal.Normal - fPortal.Normal) + FloatMath.RAD_POS_180;
                        var projec = ConvertUnits.ToDisplayUnits(farseerBullet.Position).ProjectOntoLine(cIn, cInVecDirection);

                        var newVelocity = ConvertUnits.ToDisplayUnits(farseerBullet.LinearVelocity).Rotate(rot);
                        var newStart    = cOut + cOutVecDirection * (-projec) + cOutVecNormal * (Portal.WIDTH / 2f) + newVelocity.WithLength(scale * Bullet.BULLET_DIAMETER / 2 + 4);

                        var sub = FindBulletPaths(lvl, world, sourceID, newStart, newVelocity, fullpath, scale * stretch, lifetime);
                        dat.AddRange(sub);
                    }
                    return(dat);
                }

                if (collisionUserObject is ICannonBlueprint)
                {
                    world.RemoveBody(farseerBullet);
                    var tgcannon = (ICannonBlueprint)collisionUserObject;

                    if (tgcannon.CannonID == sourceID)
                    {
                        return(none);
                    }

                    var quality = Math2D.LinePointDistance(ConvertUnits2.ToDisplayUnitsPoint(farseerBullet.Position), ConvertUnits2.ToDisplayUnitsPoint(farseerBullet.Position) + ConvertUnits.ToDisplayUnits(farseerBullet.LinearVelocity), new FPoint(tgcannon.X, tgcannon.Y));

                    return(new List <Tuple <List <Vector2>, ICannonBlueprint, float> > {
                        Tuple.Create(fullpath, tgcannon, quality)
                    });
                }


                bool oow = (farseerBullet.Position.X < 0 - 64) || (farseerBullet.Position.Y < 0 - 64) || (farseerBullet.Position.X > ConvertUnits.ToSimUnits(lvl.LevelWidth) + 64) || (farseerBullet.Position.Y > ConvertUnits.ToSimUnits(lvl.LevelHeight) + 64);
                bool ool = (lifetime >= Bullet.MAXIMUM_LIFETIME * LIFETIME_FAC);

                //if (collisionUserObject != null || oow || ool)
                //{
                //	world.RemoveBody(farseerBullet);
                //	return new List<Tuple<List<Vector2>, CannonBlueprint, float>> { Tuple.Create(fullpath, new CannonBlueprint(farseerBullet.Position.X, farseerBullet.Position.Y, 64, 1, 0, FloatMath.GetRangedIntRandom(0, 9999999)), 1f) };
                //}

                if (collisionUserObject is VoidWallBlueprint)
                {
                    world.RemoveBody(farseerBullet); return(none);
                }
                if (collisionUserObject is VoidCircleBlueprint)
                {
                    world.RemoveBody(farseerBullet); return(none);
                }
                if (collisionUserObject is BlackHoleBlueprint)
                {
                    world.RemoveBody(farseerBullet); return(none);
                }

                if (oow || ool)
                {
                    world.RemoveBody(farseerBullet); return(none);
                }

                if (lvl.WrapMode == LevelBlueprint.WRAPMODE_DONUT)
                {
                    var pbullet = ConvertUnits.ToDisplayUnits(farseerBullet.Position);

                    pbullet.X = (pbullet.X + lvl.LevelWidth) % lvl.LevelWidth;
                    pbullet.Y = (pbullet.Y + lvl.LevelHeight) % lvl.LevelHeight;

                    farseerBullet.Position = ConvertUnits.ToSimUnits(pbullet);
                }
            }
        }