// X:\jsc.svn\core\ScriptCoreLib\JavaScript\BCLImplementation\System\Threading\Tasks\Task\Task.Delay.cs

        public static Task Delay(int millisecondsDelay)
        {
            //Console.WriteLine("enter __Task.Delay");

            var x = new TaskCompletionSource<object>();


            var timer = new Timer(millisecondsDelay);

            timer.timer +=
                delegate
                {
                    timer.stop();

                    //Console.WriteLine("continue __Task.Delay");
                    x.SetResult(null);
                };

            timer.start();

            //Console.WriteLine("exit __Task.Delay");
            return x.Task;
        }
		public KeyboardButton(Stage s, int fps)
		{
			var t = new Timer(fps);

			t.timer +=
				delegate
				{
					if (a)
					{
						a = false;
						t.stop();
						return;
					}

					if (this.Tick != null)
						this.Tick();
				};

			this.ForceKeyDown =
				delegate
				{
					a = false;

					if (this.Down != null)
						this.Down();

					if (!t.running)
					{
						if (this.Tick != null)
							this.Tick();

						t.start();
					}
				};

			s.keyDown +=
				e =>
				{

					if (CheckButton(e.keyCode, e.keyLocation, false))
					{
						this.ForceKeyDown();
					}
				};


			this.ForceKeyUp =
				delegate
				{
					if (this.Up != null)
						this.Up();

					a = true;
				};

			s.keyUp +=
				  e =>
				  {

					  if (CheckButton(e.keyCode, e.keyLocation, true))
					  {
						  this.ForceKeyUp();
					  }
				  };
		}
        private static int CreateWalkingDummy_Walk(Texture64[][] Walk, SpriteInfoExtended s, int WalkingAnimationFrame, Timer t)
        {
            #region dead people do not walk
            if (s.Health <= 0)
            {
                t.stop();
                return WalkingAnimationFrame;
            }
            #endregion


            if (!s.AIEnabled)
                return WalkingAnimationFrame;

            WalkingAnimationFrame = t.currentCount % Walk.Length;

            s.Frames = Walk[WalkingAnimationFrame];
            return WalkingAnimationFrame;
        }
        public FlashTowerDefenseSized(int DefaultWidth, int DefaultHeight)
        {

            var bg = new Sprite { x = 0, y = 0 };

            //bg.graphics.beginFill(0xffffff);
            //bg.graphics.beginFill(0x808080);
            //bg.graphics.drawRect(0, 0, Width / 2, Height);



            var warzone = new Sprite { x = 0, y = 0 };

            warzone.graphics.beginFill(ColorWhite);
            warzone.graphics.drawRect(-OffscreenMargin, -OffscreenMargin, DefaultWidth + 2 * OffscreenMargin, DefaultHeight + 2 * OffscreenMargin);

            warzone.mouseChildren = false;


            GetWarzone = () => warzone;

            bg.AttachTo(GetWarzone());
            warzone.AttachTo(this);

            #region create aim
            this.Aim = new Shape();

            Aim.graphics.lineStyle(4, 0, 1);

            Aim.graphics.moveTo(-8, 0);
            Aim.graphics.lineTo(8, 0);

            Aim.graphics.moveTo(0, -8);
            Aim.graphics.lineTo(0, 8);

            Aim.filters = new[] { new DropShadowFilter() };
            Aim.AttachTo(GetWarzone());
            #endregion


            #region BlurWarzoneOnHover
            this.BlurWarzoneOnHover =
                (txt, HideAim) =>
                {


                    txt.mouseOver +=

                        delegate
                        {
                            if (!txt.mouseEnabled)
                                return;

                            txt.textColor = ColorBlue;
                            txt.filters = null;

                            if (CanFire)
                            {
                                warzone.filters = new[] { new BlurFilter() };

                                if (HideAim)
                                    Aim.visible = false;
                            }
                        };

                    txt.mouseOut +=
                        delegate
                        {

                            txt.filters = new[] { new BlurFilter() };
                            txt.textColor = ColorBlack;

                            if (CanFire)
                            {
                                warzone.filters = null;

                                if (HideAim)
                                    Aim.visible = true;
                            }
                        };
                };
            #endregion


            #region ScoreBoard
            var ScoreBoard = new TextField
            {
                x = 24,
                y = 24,

                defaultTextFormat = new TextFormat
                {
                    size = 12
                },
                autoSize = TextFieldAutoSize.LEFT,
                text = "Defend yourself by shooting those mad sheep.",
                filters = new[] { new BlurFilter() },
                selectable = false,
            };

            //ScoreBoard.AttachTo(this);


            BlurWarzoneOnHover(ScoreBoard, true);
            #endregion



            Action<double, Action> Times =
                (m, h) => (DefaultWidth * DefaultHeight * m).Times(h);

            Action<double, Func<BitmapAsset>> AddDoodads =
                (m, GetImage) => Times(m, () => GetImage().AttachTo(bg).SetCenteredPosition(DefaultWidth.Random(), DefaultHeight.Random()));

            AddDoodads(0.0001, () => Images.grass1.ToBitmapAsset());
            AddDoodads(0.00005, () => Images.bump2.ToBitmapAsset());

            Action StartIngameMusic =
                delegate
                {
                    if (this.IngameMusic != null)
                        this.IngameMusic.stop();

                    this.IngameMusic = Sounds.snd_world.ToSoundAsset().play(0, 999, new SoundTransform(IngameMusicVolume));
                };

            StartIngameMusic();

            Func<Animation> AddCactus = () =>
                new Animation(null, Images.img_cactus)
                {
                    FrameRate = 1000 / 7,
                    AnimationEnabled = true
                };




            Action<double> AddCactusAt = y =>
                {
                    var x = DefaultWidth.Random();

                    AddCactus().AttachTo(GetWarzone()).MoveTo(
                        x, y + Math.Cos(x + y) * DefaultHeight * 0.03);
                };

            (3 + 3.Random()).Times(AddCactusAt.FixParam(DefaultHeight * 0.06));
            (3 + 3.Random()).Times(AddCactusAt.FixParam(DefaultHeight * 0.94));

            PrebuiltTurret = new Animation(Images.img_turret1_gunfire_180, Images.img_turret1_gunfire_180_frames);

            PrebuiltTurret.x = (DefaultWidth - PrebuiltTurret.width) * 0.9;
            PrebuiltTurret.y = (DefaultHeight - PrebuiltTurret.height) / 2;

            PrebuiltTurret.AttachTo(GetWarzone());

            #region Messages
            var ActiveMessages = new List<TextField>();
            var ShowMessageNow = default(Action<string, Action>);

            ShowMessageNow =
                (MessageText, Done) =>
                {

                    var p = new TextField
                    {
                        textColor = ColorWhite,
                        background = true,
                        backgroundColor = ColorBlack,
                        filters = new[] { new GlowFilter(ColorBlack) },
                        autoSize = TextFieldAutoSize.LEFT,
                        text = MessageText,
                        mouseEnabled = false
                    };

                    var y = DefaultHeight - p.height - 32;

                    p.AddTo(ActiveMessages).AttachTo(this).MoveTo((DefaultWidth - p.width) / 2, DefaultHeight);

                    Sounds.snd_message.ToSoundAsset().play();

                    var MessagesToBeMoved = (from TheMessage in ActiveMessages select new { TheMessage, y = TheMessage.y - TheMessage.height }).ToArray();



                    (1000 / 24).AtInterval(
                        t =>
                        {
                            foreach (var i in MessagesToBeMoved)
                            {
                                if (i.TheMessage.y > i.y)
                                    i.TheMessage.y -= 4;

                            }

                            p.y -= 4;

                            if (p.y < y)
                            {
                                t.stop();

                                if (Done != null)
                                    Done();

                                9000.AtDelayDo(
                                    () => p.RemoveFrom(ActiveMessages).FadeOutAndOrphanize(1000 / 24, 0.21)
                                );
                            }
                        }
                    );
                };


            var QueuedMessages = new Queue<string>();

            this.ShowMessage =
                Text =>
                {
                    if (QueuedMessages.Count > 0)
                    {
                        QueuedMessages.Enqueue(Text);
                        return;
                    }

                    // not busy
                    QueuedMessages.Enqueue(Text);

                    var NextQueuedMessages = default(Action);

                    NextQueuedMessages =
                        () => ShowMessageNow(QueuedMessages.Peek(),
                            delegate
                            {
                                QueuedMessages.Dequeue();

                                if (QueuedMessages.Count > 0)
                                    NextQueuedMessages();
                            }
                        );

                    NextQueuedMessages();
                };
            #endregion

            var StatusBar = new Sprite
            {
                mouseEnabled = false,
                mouseChildren = false,
            }.MoveTo(DefaultWidth - 96, DefaultHeight - 64).AttachTo(this);



            #region  WeaponBar
            var WeaponBar = new Sprite
            {
            }.AttachTo(StatusBar);


            var AmmoAvatar = new Sprite().MoveTo(38, 24).AttachTo(WeaponBar);

            Images.Avatars.avatars_ammo.ToBitmapAsset().MoveToCenter().AttachTo(AmmoAvatar);

            var AmmoText = new TextField
            {
                defaultTextFormat = new TextFormat
                {
                    bold = true,
                    size = 20,
                    font = "_sans"
                },
                text = "200000",
                filters = new[] { new GlowFilter(ColorBlack, 0.5) },
                autoSize = TextFieldAutoSize.RIGHT,
                x = 0,
                width = 0
            }.AttachTo(AmmoAvatar);




            var WeaponAvatar = new Sprite().AttachTo(WeaponBar);
            #endregion

            var CurrentTarget = default(Point);
            var CurrentTargetTimer = default(Timer);

            #region Ego
            Ego = new PlayerWarrior
                {
                    filters = new[] { new GlowFilter(ColorGreen) }
                };

            EgoIsOnTheField = () => Ego.parent != null;
            EgoIsAlive = () => Ego.IsAlive;

            Func<bool> EgoCanManTurret = () => !PrebuiltTurretInUse; // look up if there is somebody else in it
            Func<bool> EgoIsCloseToTurret = () => new Point { x = Ego.x - PrebuiltTurret.x, y = Ego.y - PrebuiltTurret.y }.length < 32;

            var EgoAimDistance = 48;
            var EgoAimMoveSpeed = 0.1;
            var EgoMoveSpeed = 3.0;
            var EgoMoveToMouseTarget = false;

            UpdateEgoAim =
                delegate
                {
                    Aim.MoveTo(Ego.x + Math.Cos(EgoAimDirection) * EgoAimDistance, Ego.y + Math.Sin(EgoAimDirection) * EgoAimDistance);
                };


            EgoMovedSlowTimer = new Timer(200, 1);

            Ego.FoundNewWeapon +=
                weapon => ShowMessage("You found " + weapon.Name);

            Ego.FoundMoreAmmo +=
                weapon => ShowMessage("Got ammo for " + weapon.Name);



            Action Reorder =
                delegate
                {
#if Z
                    GetWarzone().Children().OrderBy(i => (double)i.y).
                       ForEach(
                        (k, i) =>
                            k.parent.setChildIndex(k, i)
                    );
#endif

                };

            Action ReorderThrottle = Reorder.ThrottleTo(1000);

            var EgoMoveUpTimer = (1000 / 30).AtInterval(
                delegate
                {
                    if (EgoMoveToMouseTarget)
                    {
                        var p = new Point { x = CurrentTarget.x - Ego.x, y = CurrentTarget.y - Ego.y };

                        if (p.length <= EgoMoveSpeed)
                        {
                            // run one the pointer
                            return;
                        }

                        Ego.MoveToArc(p.GetRotation(), EgoMoveSpeed);
                    }
                    else
                        Ego.MoveToArc(EgoAimDirection, EgoMoveSpeed);

                    Ego.x = Math.Min(Math.Max(Ego.x, 0), DefaultWidth);
                    Ego.y = Math.Min(Math.Max(Ego.y, 0), DefaultHeight);
                    ReorderThrottle();

                    UpdateEgoAim();

                    EgoMovedSlowTimer.start();

                    // we moved now let's check for boxes
                    foreach (var BoxToTake in
                                     from ss in Boxes
                                     where new Point { x = Ego.x - ss.x, y = Ego.y - ss.y }.length < 32
                                     select ss)
                    {
                        BoxToTake.RemoveFrom(Boxes).Orphanize();

                        Sounds.sound20.ToSoundAsset().play();

                        if (BoxToTake.WeaponInside == null)
                        {
                            // add stuff, so the player doesn't get bored:D
                            // maybe implment them too? see Diablo.
                            var PowerUps = new[] { 
                                // gta
                                "Double Damage", 
                                "Fast Reload", 
                                "Respect",
                                "Armour",

                                // diablo
                                "Defense", 
                                "Mana", 
                                "Dexerity", 
                                "Experience", 
                                "Stamina", 
                                "Strength", 
                                "Life", 
                                "Replenish Life" 
                            };


                            ShowMessage("+1 " + PowerUps.Random());
                        }
                        else
                        {
                            Ego.AddWeapon(BoxToTake.WeaponInside);
                        }

                        if (NetworkTakeCrate != null)
                            NetworkTakeCrate(BoxToTake.NetworkId);
                    }
                });

            EgoMoveUpTimer.stop();

            var EgoAimMoveTimer = (1000 / 30).AtInterval(
                 delegate
                 {
                     EgoAimDirection += EgoAimMoveSpeed * EgoMoveSpeed;

                     if (EgoAimDirection < 0)
                         EgoAimDirection += Math.PI * 4;

                     EgoAimDirection %= Math.PI * 2;

                     UpdateEgoAim();
                 });
            EgoAimMoveTimer.stop();


            #endregion


            Ego.CurrentWeaponChanged +=
                delegate
                {
                    Sounds.SelectWeapon.ToSoundAsset().play();

                    if (WeaponAvatar.numChildren > 0)
                        WeaponAvatar.getChildAt(0).Orphanize();

                    Ego.CurrentWeapon.Type.Avatar.ToBitmapAsset().MoveToCenter().AttachTo(WeaponAvatar);
                    WeaponBar.filters = new[] { new GlowFilter(Ego.CurrentWeapon.Color) };
                };

            Ego.CurrentWeaponAmmoChanged += () => AmmoText.text = "" + Ego.CurrentWeapon.Ammo;

            SetDefaultWeapon();

            Ego.Die +=
                () =>
                {
                    ShowMessage("Meeeediiic!");
                    ShowMessage("You died a painful death");

                    PlayerWarrior.AutoResurrectDelay.AtDelayDo(
                        delegate
                        {
                            Ego.Revive();

                            if (EgoResurrect != null)
                                EgoResurrect();
                        }
                    );
                };

            #region HealthBar
            var HealthBar = new Sprite
            {
                filters = new[] { new GlowFilter(ColorRed) }
            }.MoveTo(-20, 0).AttachTo(StatusBar);

            var Hearts = new[] 
            {
                Images.Avatars.avatars_heart.ToBitmapAsset().MoveToArc(20.DegreesToRadians(), 90).AttachTo(HealthBar),
                Images.Avatars.avatars_heart.ToBitmapAsset().MoveToArc(7.DegreesToRadians(), 90).AttachTo(HealthBar),
                Images.Avatars.avatars_heart.ToBitmapAsset().MoveToArc(353.DegreesToRadians(), 90).AttachTo(HealthBar),
                Images.Avatars.avatars_heart.ToBitmapAsset().MoveToArc(340.DegreesToRadians(), 90).AttachTo(HealthBar),
            };

            var EgoHeartBeat = default(SoundChannel);

            Ego.HealthChanged +=
                delegate
                {
                    if (EgoHeartBeat == null)
                    {
                        EgoHeartBeat = Sounds.heartbeat3.ToSoundAsset().play();
                        EgoHeartBeat.soundComplete +=
                            e =>
                            {
                                EgoHeartBeat = null;
                            };
                    }

                    if (Ego.Health > 0)
                    {

                        var z = (Ego.Health / Ego.MaxHealth) * Hearts.Length;
                        var f = Math.Floor(z).ToInt32();
                        var a = z % 1;

                        for (int i = 0; i < f; i++)
                        {
                            Hearts[i].alpha = 1;
                        }

                        if (f < Hearts.Length)
                        {
                            Hearts[f].alpha = a;

                            for (int i = f + 1; i < Hearts.Length; i++)
                            {
                                Hearts[i].alpha = 0;
                            }

                        }
                    }
                    else
                    {
                        for (int i = 0; i < Hearts.Length; i++)
                        {
                            Hearts[i].alpha = 0;
                        }
                    }

                    //ShowMessage("h: " + f + " " + a);
                };

            #endregion

            var PrebuiltTurretSound = default(SoundChannel);

            var runaways = 0;
            var score = 0;

            Action UpdateScoreBoard =
                delegate
                {
                    if (!CanFire) return;

                    ScoreBoard.text =
                        new
                        {
                            runaways,
                            gore = (100 * (double)BadGuys.Count(i => !i.IsAlive) / (double)BadGuys.Count()).Round() + "%",
                            score,
                            level = CurrentLevel
                        }.ToString();
                };

            Action<Point> DoMachineGunFire =
                e =>
                {
                    if (Ego.CurrentWeapon.Ammo <= 0)
                        return;


                    Ego.CurrentWeapon.Ammo--;



                    var DamagePointOfOrigin = new Point { x = PrebuiltTurret.x, y = PrebuiltTurret.y };
                    var DamageDirection = new Point { x = e.x - PrebuiltTurret.x, y = e.y - PrebuiltTurret.y }.GetRotation();

                    DoSomeDamage(DamagePointOfOrigin, DamageDirection, WeaponInfo.Machinegun);

                    if (Ego.CurrentWeapon.Ammo <= 0)
                    {
                        Sounds.OutOfAmmo.ToSoundAsset().play();
                        PrebuiltTurret.AnimationEnabled = false;
                        return;
                    }
                };



            PrebuiltTurret.AnimationEnabledChanged +=
                delegate
                {

                    if (PrebuiltTurret.AnimationEnabled)
                    {
                        if (PrebuiltTurretSound == null)
                            PrebuiltTurretSound = Sounds.gunfire.ToSoundAsset().play(0, 999);

                        PrebuiltTurret.filters = new[] { new GlowFilter() };
                    }
                    else
                    {
                        if (PrebuiltTurretSound != null)
                            PrebuiltTurretSound.stop();

                        PrebuiltTurretSound = null;
                        PrebuiltTurret.filters = null;
                    }

                };

            GetWarzone().mouseDown +=
                e =>
                {
                    if (!CanFire) return;

                    // the turret cannot fire without a man behind it
                    if (EgoIsOnTheField())
                        return;

                    if (Ego.CurrentWeapon.Ammo <= 0)
                    {
                        Sounds.OutOfAmmo.ToSoundAsset().play();
                        return;
                    }


                    PrebuiltTurret.AnimationEnabled = true;

                    var p = new Point
                    {
                        x = e.stageX,
                        y = e.stageY,
                    };

                    CurrentTarget = this.globalToLocal(p);


                    CurrentTargetTimer =
                        (1000 / 10).AtInterval(
                            delegate
                            {
                                if (!PrebuiltTurret.AnimationEnabled)
                                {
                                    CurrentTargetTimer.stop();

                                    return;
                                }

                                DoMachineGunFire(CurrentTarget);
                            }
                        );

                };

            GetWarzone().mouseUp +=
                 e =>
                 {
                     PrebuiltTurret.AnimationEnabled = false;
                 };

            GetWarzone().mouseOut +=
                delegate
                {
                    PrebuiltTurret.AnimationEnabled = false;
                };

            GetWarzone().mouseMove +=
                e =>
                {
                    if (!CanFire)
                        return;

                    var p = new Point
                    {
                        x = e.stageX,
                        y = e.stageY,
                    };

                    CurrentTarget = this.globalToLocal(p);


                    if (EgoIsOnTheField())
                    {
                        Mouse.show();
                        return;
                    }


                    Mouse.hide();

                    Aim.x = CurrentTarget.x;
                    Aim.y = CurrentTarget.y;
                };





            Func<double> GetEntryPointY = () => (DefaultHeight * 0.8).FixedRandom() + DefaultHeight * 0.1;



            #region AttachRules
            Func<Actor, Actor> AttachRules =
                a =>
                {
                    if (a == null)
                        throw new Exception("AttachRules");

                    var an = a;

                    //Console.WriteLine("attached KilledByLocalPlayer");


                    a.KilledByLocalPlayer +=
                        delegate
                        {
                            //Console.WriteLine("KilledByLocalPlayer: " + an.ScoreValue);

                            if (NetworkAddKillScore != null)
                                NetworkAddKillScore(an.ScoreValue);
                        };

                    if (a.NetworkId == 0)
                    {
                        a.NetworkId = int.MaxValue.FixedRandom();

                        if (0.5.ByChance())
                        {
                            a.Crate = new Crate
                                {
                                    NetworkId = int.MaxValue.FixedRandom()
                                }.AddTo(Boxes);

                            if (0.7.ByChance())
                            {
                                // add random weapon, note that this is
                                // not a fixed random, so each player
                                // gets different weapon
                                a.Crate.WeaponInside = Weapon.PredefinedWeapons.Random().Clone();
                            }
                        }
                    }

                    a.CorpseAndBloodGone += () => BadGuys.Remove(a);
                    a.Moved +=
                        delegate
                        {
                            if (a.x > (DefaultWidth + OffscreenMargin))
                            {
                                a.Crate = null;

                                a.RemoveFrom(BadGuys).Orphanize();

                                if (CanFire)
                                {
                                    WaveEndCountdown--;
                                    runaways++;

                                    ScoreBoard.textColor = ColorRed;
                                    UpdateScoreBoard();
                                }

                                a.IsAlive = false;
                                // this one was able to run away
                            }
                        };





                    a.Die +=
                        delegate
                        {
                            WaveEndCountdown--;

                            score += a.ScoreValue;
                            UpdateScoreBoard();


                            if (a.Crate != null)
                            {
                                a.Crate.MoveTo(a.x, a.y).AttachTo(GetWarzone());
                            }
                        };

                    a.AttachTo(GetWarzone()).AddTo(BadGuys);

                    if (a.PlayHelloSound != null)
                        a.PlayHelloSound();

                    return a;
                };
            #endregion

            Action EgoTakeNextWeapon = () => Ego.CurrentWeapon = Ego.OtherWeaponsLikeCurrent.Next(i => i == Ego.CurrentWeapon);
            Action EgoTakePreviousWeapon = () => Ego.CurrentWeapon = Ego.OtherWeaponsLikeCurrent.Previous(i => i == Ego.CurrentWeapon);






            GetWarzone().mouseWheel +=
                e =>
                {
                    if (e.delta > 0)
                        EgoTakeNextWeapon();
                    else
                        EgoTakePreviousWeapon();
                };

            var EgoMoveToMouseTargetAntiDoubleClick = default(Timer);

            GetWarzone().mouseDown +=
                e =>
                {
                    if (!EgoIsOnTheField())
                        return;

                    if (!EgoIsAlive())
                        return;

                    var pp = new Point
                    {
                        x = e.stageX,
                        y = e.stageY,
                    };

                    CurrentTarget = this.globalToLocal(pp);

                    var p = new Point { x = CurrentTarget.x - Ego.x, y = CurrentTarget.y - Ego.y };

                    EgoAimDirection = p.GetRotation();



                    UpdateEgoAim();

                    EgoMoveToMouseTarget = true;

                    EgoMoveToMouseTargetAntiDoubleClick =
                        200.AtDelayDo(
                        delegate
                        {
                            if (!EgoIsAlive())
                            {
                                Ego.RunAnimation = false;
                                EgoMoveUpTimer.stop();
                                return;
                            }

                            if (!EgoMoveToMouseTarget)
                                return;

                            Ego.RunAnimation = true;
                            EgoMoveSpeed = 2.5;
                            EgoMoveUpTimer.start();
                        }
                    );
                };


            GetWarzone().mouseMove +=
                e =>
                {
                    if (!EgoMoveToMouseTarget)
                        return;

                    if (!EgoIsOnTheField())
                        return;

                    if (!EgoIsAlive())
                        return;

                    var pp = new Point
                    {
                        x = e.stageX,
                        y = e.stageY,
                    };

                    CurrentTarget = this.globalToLocal(pp);

                    var p = new Point { x = CurrentTarget.x - Ego.x, y = CurrentTarget.y - Ego.y };


                    EgoAimDirection = p.GetRotation();


                    UpdateEgoAim();
                };

            GetWarzone().mouseUp +=
                e =>
                {
                    if (!EgoMoveToMouseTarget)
                        return;

                    if (!EgoIsAlive())
                        return;

                    if (EgoMoveToMouseTargetAntiDoubleClick != null)
                    {
                        EgoMoveToMouseTargetAntiDoubleClick.stop();
                        EgoMoveToMouseTargetAntiDoubleClick = null;
                    }

                    EgoMoveUpTimer.stop();
                    Ego.RunAnimation = false;
                    EgoMoveToMouseTarget = false;
                };

            GetWarzone().doubleClickEnabled = true;
            GetWarzone().doubleClick +=
              e =>
              {
                  if (!EgoIsOnTheField())
                      return;

                  if (!EgoIsAlive())
                      return;

                  var pp = new Point
                  {
                      x = e.stageX,
                      y = e.stageY,
                  };

                  CurrentTarget = this.globalToLocal(pp);


                  EgoAimDirection = new Point { x = CurrentTarget.x - Ego.x, y = CurrentTarget.y - Ego.y }.GetRotation();

                  UpdateEgoAim();

                  EgoDoFireWeapon();
              };

            Action StageIsReady =
                delegate
                {

                    //stage.scaleMode = StageScaleMode.NO_BORDER;

                    // multiplay ?


                    var WeaponShortcutButtons = new[]
                    {
                        Keyboard.NUMBER_1,
                        Keyboard.NUMBER_2,
                        Keyboard.NUMBER_3,
                        Keyboard.NUMBER_4,
                        Keyboard.NUMBER_5,
                        Keyboard.NUMBER_6,
                        Keyboard.NUMBER_7,
                        Keyboard.NUMBER_8,
                        Keyboard.NUMBER_9,
                        Keyboard.NUMBER_0,
                    }.Select(
                        (Button, Index) =>
                            new KeyboardButton(stage)
                            {
                                Buttons = new[] { Button },
                                Filter = EgoIsAlive,
                                Up = () => Ego.CurrentWeapon = Ego.OtherWeaponsLikeCurrent.AtOrDefault(Index, Ego.CurrentWeapon)
                            }
                    ).ToArray();

                    var KeySpace = new KeyboardButton(stage)
                     {
                         Buttons = new[] { Keyboard.SPACE },
                         Filter = EgoIsOnTheField.And(EgoIsAlive),
                         Up =
                             delegate
                             {
                                 // car brakes, open door, take item

                                 // Add Ammo

                                 foreach (var BarrelToTake in this.Barrels.Where(i => (i.ToPoint() - Ego.ToPoint()).length < 32))
                                 {
                                     Sounds.sound20.ToSoundAsset().play();
                                     Ego.AddWeapon(BarrelToTake.ExplosiveMaterialType);
                                     BarrelToTake.RemoveFrom(Barrels).Orphanize();

                                     if (NetworkUndeployExplosiveBarrel != null)
                                         NetworkUndeployExplosiveBarrel(BarrelToTake.NetworkId);

                                 }
                             }
                     };


                    var KeyLeft = new KeyboardButton(stage)
                    {
                        Groups = new[]
                        {
                            MovementWASD[Keyboard.A],
                            MovementArrows[Keyboard.LEFT],
                        },
                        Filter = EgoIsOnTheField.And(EgoIsAlive),
                        Down =
                            delegate
                            {
                                EgoAimMoveSpeed = -0.1;
                                EgoAimMoveTimer.start();
                            },
                        Up = EgoAimMoveTimer.stop,
                    };

                    var KeyRight = new KeyboardButton(stage)
                    {
                        Groups = new[]
                        {
                            MovementWASD[Keyboard.D],
                            MovementArrows[Keyboard.RIGHT],
                        },
                        Filter = EgoIsOnTheField.And(EgoIsAlive),
                        Down =
                            delegate
                            {
                                EgoAimMoveSpeed = +0.1;
                                EgoAimMoveTimer.start();
                            },
                        Up = EgoAimMoveTimer.stop,
                    };

                    var KeyUp = new KeyboardButton(stage)
                    {
                        Groups = new[]
                        {
                            MovementWASD[Keyboard.W],
                            MovementArrows[Keyboard.UP],
                        },
                        Filter = EgoIsOnTheField.And(EgoIsAlive),
                        Down =
                            delegate
                            {
                                if (!Ego.IsAlive)
                                    return;

                                Ego.RunAnimation = true;
                                EgoMoveSpeed = 2.5;
                                EgoMoveUpTimer.start();
                            },
                        Up =
                            delegate
                            {
                                EgoMoveUpTimer.stop();
                                Ego.RunAnimation = false;
                            }
                    };

                    var KeyDown = new KeyboardButton(stage)
                    {
                        Groups = new[]
                        {
                            MovementWASD[Keyboard.S],
                            MovementArrows[Keyboard.DOWN],
                        },
                        Filter = EgoIsOnTheField.And(EgoIsAlive),
                        Down =
                            delegate
                            {
                                if (!Ego.IsAlive)
                                    return;

                                Ego.RunAnimation = true;
                                EgoMoveSpeed = -1.5;
                                EgoMoveUpTimer.start();
                            },
                        Up =
                            delegate
                            {
                                EgoMoveSpeed = 1;
                                EgoMoveUpTimer.stop();
                                Ego.RunAnimation = false;
                            }
                    };

                    var KeyWeaponNext = new KeyboardButton(stage)
                    {
                        Groups = new[]
                        {
                            MovementWASD[Keyboard.X],
                            MovementArrows[Keyboard.PAGE_UP],
                        },

                        Up = EgoTakeNextWeapon,
                    };

                    var KeyWeaponPrevious = new KeyboardButton(stage)
                    {
                        Groups = new[]
                        {
                            MovementWASD[Keyboard.Z],
                            MovementArrows[Keyboard.PAGE_DOWN],
                        },
                        Up = EgoTakePreviousWeapon
                    };

                    var KeyControl = new KeyboardButton(stage)
                    {
                        Groups = new[]
                        {
                            MovementWASD[ new KeyboardKeyInfo { Button = Keyboard.CONTROL, Location = KeyLocation.LEFT } ],
                            MovementArrows[ new KeyboardKeyInfo { Button = Keyboard.CONTROL, Location = KeyLocation.RIGHT  } ],
                        },
                        Filter = EgoIsOnTheField.And(EgoIsAlive),
                        Up = EgoDoFireWeapon
                    };


                    var KeyMusic = new KeyboardButton(stage)
                    {
                        Buttons = new[] { Keyboard.M },
                        Up = () => ToggleMusic()
                    };




                    var KeyEnter = new KeyboardButton(stage)
                    {
                        Groups = new[]
                        {
                            MovementWASD[Keyboard.F],
                            MovementArrows[Keyboard.ENTER],
                        },
                        Filter = EgoIsAlive,
                        Up =
                            delegate
                            {
                                if (EgoIsOnTheField())
                                {
                                    if (EgoIsCloseToTurret())
                                    {
                                        if (EgoCanManTurret())
                                        {


                                            Ego.Orphanize();
                                            Ego.RunAnimation = false;
                                            EgoMoveUpTimer.stop();
                                            EgoAimMoveTimer.stop();
                                            PrebuiltTurretBlinkTimer.stop();
                                            PrebuiltTurret.alpha = 1;

                                            Ego.CurrentWeapon = Ego.Weapons.FirstOrDefault(i => i.SelectMode == Weapon.SelectModeEnum.Turret);

                                            ShowMessage("Machinegun manned!");
                                            Mouse.hide();

                                            if (CurrentTarget != null)
                                            {
                                                Aim.x = CurrentTarget.x;
                                                Aim.y = CurrentTarget.y;
                                            }

                                            Sounds.door_open.ToSoundAsset().play();

                                            if (EgoEnteredMachineGun != null)
                                                EgoEnteredMachineGun();
                                        }
                                        else
                                        {
                                            ShowMessage("Cannot man the machinegun!");
                                        }
                                    }
                                    else
                                    {
                                        ShowMessage("The machinegun is too far! Get closer!");
                                    }
                                }
                                else
                                {
                                    Sounds.door_open.ToSoundAsset().play();


                                    ShowMessage("Machinegun unmanned!");

                                    TeleportEgoNearTurret();
                                    PrebuiltTurret.AnimationEnabled = false;

                                    PrebuiltTurret.alpha = 0.5;
                                    Mouse.show();
                                    PrebuiltTurretBlinkTimer.start();



                                    if (EgoExitedMachineGun != null)
                                        EgoExitedMachineGun();
                                }
                            }
                    };



                };

            PrebuiltTurretBlinkTimer = 500.AtInterval(t => PrebuiltTurret.alpha = ((t.currentCount % 2) + 1) / 2);
            PrebuiltTurretBlinkTimer.stop();

            #region readiness
            if (stage == null)
            {
                this.addedToStage +=
                    delegate
                    {
                        StageIsReady();
                    };
            }
            else
            {
                StageIsReady();
            }
            #endregion

            //Mouse.hide();



            ShowMessage("Aim at the enemy unit and hold down the mouse!");
            ShowMessage("Press 'Enter' to exit the machinegun");
            //ShowMessage("Day " + CurrentLevel);

            GameEvent =
                delegate
                {
                    // do not add if the day is over...
                    //if (WaveEndCountdown <= 0)
                    //    return;

                    AddNewActorsToMap(UpdateScoreBoard, GetEntryPointY, AttachRules);

                };




            ReportDays =
                delegate
                {
                    if (WaveEndCountdown < 0)
                    {
                        if (InterlevelMusic == null)
                        {
                            InterlevelMusic = Sounds.snd_birds.ToSoundAsset().play(0, 999);
                            ShowMessage("Day " + CurrentLevel + " is ending...");

                            if (GameInterlevelBegin != null)
                                GameInterlevelBegin();
                        }

                        if (WaveEndsWhenAllBadGuysAreDead)
                        {
                            // wait for all actors get off stage
                            if (BadGuys.Where(i => i.IsAlive).Any())
                                return;
                        }


                        // show "level END"
                        ShowMessage("Day " + CurrentLevel + " Survived!");

                        ReportDaysTimer.stop();



                        InterlevelTimeout.AtDelayDo(
                            delegate
                            {
                                if (GameInterlevelEnd != null)
                                    GameInterlevelEnd();


                                // maybe higher levels will have more enemies?
                                WaveEndCountdown = 15;
                                CurrentLevel++;

                                // show "level START"
                                ShowMessage("Day " + CurrentLevel);
                                ReportDaysTimer.start();

                                var InterlevelMusicStopping = InterlevelMusic;
                                InterlevelMusic = null;
                                2000.AtDelayDoOnRandom(InterlevelMusicStopping.stop);
                            }
                        );


                        UpdateScoreBoard();

                        return;
                    }


                    if (CanAutoSpawnEnemies)
                    {
                        // new actors if we got less 10 
                        if (InterlevelMusic != null)
                            return;

                        if (BadGuys.Where(i => i.IsAlive).Count() < 8)
                        {

                            GameEvent();
                        }
                    }
                };

            ReportDaysTimer = 1500.AtIntervalDo(ReportDays);


            (1000 / 15).AtInterval(
                delegate
                {


                    Aim.rotation += 1;

                    foreach (var s in
                           from ss in BadGuys
                           where ss.IsAlive
                           select ss)
                        s.x += s.speed;
                }
            );

            //#region powered_by_jsc
            //var powered_by_jsc = new TextField
            //{

            //    x = 32,

            //    defaultTextFormat = new TextFormat
            //    {
            //        size = 24
            //    },
            //    autoSize = TextFieldAutoSize.LEFT,

            //    // how to make a link
            //    // http://www.actionscript.com/Article/tabid/54/ArticleID/actionscript-quick-tips-and-gotchas/Default.aspx
            //    htmlText = "<a href='http://jsc.sf.net' target='_blank'>powered by <b>jsc</b></a>",
            //    selectable = false,
            //    filters = new[] { new BlurFilter() },
            //    textColor = ColorBlack
            //}.AttachTo(this);

            //powered_by_jsc.y = DefaultHeight - powered_by_jsc.height - 32;

            //// make it fade/show in time
            //200.AtInterval(t => 
            //    {
            //        var a = (Math.Sin(t.currentCount * 0.05) + 1) * 0.5;

            //        powered_by_jsc.alpha = a;
            //        powered_by_jsc.mouseEnabled = a > 0.8;
            //    }
            //);

            //#endregion

            ScoreBoard.AttachTo(this);

            //BlurWarzoneOnHover(powered_by_jsc, true);

            40000.AtIntervalOnRandom(
                delegate
                {
                    Sounds.snd_bird2.ToSoundAsset().play();
                }
            );


            #region music on off
            var MusicButton = new Sprite
            {
                x = DefaultWidth - 32,
                y = 32,
                filters = new[] { new GlowFilter(ColorBlueLight) },

            };

            var MusicOn = Images.music_on.ToBitmapAsset().MoveToCenter();
            var MusicOff = Images.music_off.ToBitmapAsset().MoveToCenter();

            MusicButton.mouseOver +=
                delegate
                {
                    Mouse.show();
                    Aim.visible = false;
                };

            MusicButton.mouseOut +=
              delegate
              {
                  Mouse.hide();
                  Aim.visible = true;
              };

            ToggleMusic =
                delegate
                {
                    if (MusicOn.parent == MusicButton)
                    {
                        MusicOn.Orphanize();
                        MusicOff.AttachTo(MusicButton);
                        ShowMessage("Music silenced");
                        IngameMusic.soundTransform = new SoundTransform(0);
                    }
                    else
                    {
                        IngameMusic.soundTransform = new SoundTransform(IngameMusicVolume);
                        ShowMessage("Music activated");

                        MusicOff.Orphanize();
                        MusicOn.AttachTo(MusicButton);
                    }
                };

            MusicButton.click +=
                delegate
                {
                    ToggleMusic();
                };

            MusicOn.AttachTo(MusicButton);

            MusicButton.AttachTo(this);
            #endregion

            Action<InteractiveObject, InteractiveObject> OnMouseDownDisableMouseOnTarget =
                (subject, target) =>
                {
                    subject.mouseDown += delegate { target.mouseEnabled = false; };
                    subject.mouseUp += delegate { target.mouseEnabled = true; };
                };

            OnMouseDownDisableMouseOnTarget(GetWarzone(), MusicButton);
            OnMouseDownDisableMouseOnTarget(GetWarzone(), ScoreBoard);
            //OnMouseDownDisableMouseOnTarget(GetWarzone(), powered_by_jsc);
        }
        public MySoundDemo2()
        {
            Text = "Howdy!";
            Color = 0x00ffff00;
            Filter = new DropShadowFilter();


            

            var preview = Assets.Preview;

            preview.x = 100;
            preview.y = 100;
            var front = new TextField
                {
                    text = "powered by jsc",
                    x = 20,
                    y = 40,
                    selectable = false,
                    textColor = 0xffffff,
                };

            front.mouseOver += ev => front.textColor = 0x00ff0000;

            front.mouseOut += ev => front.textColor = 0xffffff;

            var timer = new Timer(10, 0);


            preview.rotation = 45;


            timer.timer +=
                ev =>
                {
                    preview.rotation++;
                };

           // timer.start();

            preview.filters = new[] { new BlurFilter() };
            addChild(preview);




            for (var j = 0.0; j < 1; j += 0.1)
            {
                this.graphics.beginFill(0xff0000, j);
                this.graphics.drawCircle(40, 40, 40 * (1.0 - j));
                this.graphics.endFill();
            }


            DrawHelloWorld(50);



            addChild(
                    new TextField
                    {
                        text = "powered by jsc",
                        x = 20,
                        y = 40,
                        selectable = false,
                        sharpness = -400,
                        textColor = 0xffffff,
                        filters = new[] { new BlurFilter() }
                    }
                );

            addChild(
           front
            );


            var snd = Assets.world;
            var channel = default(SoundChannel);

            stage.activate +=
                delegate
                {
                    channel = snd.play(0, 999);
                    timer.start();
                };

            stage.deactivate +=
                delegate
                {
                    if (channel != null)
                    {
                        channel.stop();
                        channel = null;
                    }

                    timer.stop();
                };
        }