public ApplicationSprite()
        {
            // http://www.adobe.com/devnet/flash/articles/avoiding-mistakes-assets.html

            // http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/ui/MouseCursorData.html

            //Returns a Vector containing 8 cursor images
            Func<Vector<BitmapData>> makeCursorImages = () =>
            {
                var cursorData = new Vector<BitmapData>();

                var cursorShape = new Shape();
                cursorShape.graphics.beginFill(0xff5555, .75);
                cursorShape.graphics.lineStyle(1);

                //Graphics path data for an arrow
                var cursorPoints = new double[] { 0, 8, 16, 8, 16, 0, 24, 12, 16, 24, 16, 16, 0, 16, 0, 8 };
                var cursorDrawCommands = new int[] { 1, 2, 2, 2, 2, 2, 2, 2 };



                cursorShape.graphics.drawPath(
                    cursorDrawCommands,
                    cursorPoints
                );

                cursorShape.graphics.endFill();
                var transformer = new Matrix();

                //Rotate and draw the arrow shape to a BitmapData object for each of 8 frames 
                for (var i = 0; i < 8; i++)
                {
                    var cursorFrame = new BitmapData(32, 32, true, 0);
                    cursorFrame.draw(cursorShape, transformer);
                    cursorData.push(cursorFrame);

                    transformer.translate(-15, -15);
                    transformer.rotate(0.785398163);
                    transformer.translate(15, 15);
                }
                return cursorData;
            };


            // wtf? missing api? not defined in air?
            var mouseCursorData = new MouseCursorData();
            mouseCursorData.data = makeCursorImages();
            mouseCursorData.frameRate = 1;

            Mouse.registerCursor("spinningArrow", mouseCursorData);
            Mouse.cursor = "spinningArrow";
        }
		public FixedBorderCanvas(int DefaultWidth, int DefaultHeight)
		{
	
			CanvasOverlay = new Sprite();
			// canvas is not attached

			InfoOverlay = new Sprite().AttachTo(this);
			BorderOverlay = new Shape().AttachTo(this);

			#region mask
			var CanvasMask = new Shape();

			CanvasMask.graphics.beginFill(0x00ffffff);
			CanvasMask.graphics.drawRect(0, 0, DefaultWidth, DefaultHeight);

			CanvasMask.AttachTo(this);

			CanvasOverlay.mask = CanvasMask;
			#endregion


			BorderOverlay.graphics.lineStyle(1, Colors.Green, 1);
			BorderOverlay.graphics.drawRect(0, 0, DefaultWidth - 1, DefaultHeight - 1);
		}
		public void createGradation()
		{
			var tmpShape = new Shape();
			var matrix = new Matrix();
			matrix.createGradientBox(255, 0);
			//var colorList = new[] { 0xa7a7c4u, 0xf3f8ffu, 0xffffffu, 0x418fdfu };
			var colorListA =
				new[]
				{
				new[] { 0xa7a7c4u, 0xf3f8ffu, 0xffffffu, 0x418fdfu },
				 new[] {0x824229u, 0xfb8f1bu, 0xffc768u, 0xa0afacu }
				};
			var colorList = colorListA[ColorListIndex % colorListA.Length];

			//new[] { 0xa7a7FFu, 0xf3f8FFu, 0xffffffu, 0x418fFFu };
			//new[] { 0xFFa7a7u, 0xFFf3f8u, 0xffffffu, 0xFF418fu };
			//new[] { 0x007777u, 0x007378u, 0x0u, 0x00214fu };
			//= new[] {0x824229u, 0xfb8f1bu, 0xffc768u, 0xa0afacu };

			var alphaList = new[] { 1.0, 1.0, 1.0, 1.0 };
			var ratioList = new[] { 0, 80, 100, 200 };
			tmpShape.graphics.beginGradientFill(GradientType.LINEAR, colorList, alphaList, ratioList, matrix);
			tmpShape.graphics.drawRect(0, 0, 255, 1);
			var tmpBitmap = new BitmapData(255, 1, false);
			tmpBitmap.draw(tmpShape);
			for (var i = 0; i < 256; i++)
			{
				_pallet[i] = (tmpBitmap.getPixel(i, 0));
				_nullPallet[i] = (0x000000);
			}
		}
		ManualControl AttachMovementInput(ViewEngineBase view, bool EnableMouse, bool Visualize)
		{
			var mc = new ManualControl();

			var stage = this.stage;

			if (stage == null)
				throw new Exception("stage is null");


			var snapcontainer = new Shape();

			var vectorized = new Shape();
			var delta = new Shape { alpha = 0.5 };

			if (Visualize)
			{
				snapcontainer.AttachTo(this);
				vectorized.AttachTo(this);
				delta.AttachTo(this);
			}


			var mouseDown_args = default(Point);
			var mouseUp_fadeOut = default(Timer);

			uint color = 0;

			var snap_radius = 64;

			mc.down =
				p =>
				{
					if (!MovementEnabled)
						return;

					color = 0;


					// snap to old point
					if (!mc.disable_join)
						if (mouseDown_args != null)
							if (snapcontainer.alpha > 0)
								if ((mouseDown_args - p).length < snap_radius)
								{
									color = 0xff;

									p = mouseDown_args;
								}

					mouseDown_args = p;
					mc.disable_join = false;
				};

			if (EnableMouse)
				stage.mouseDown +=
						e =>
						{
							mc.down(e.ToStagePoint());

							//Write("down ", new { e.localX, e.localY, e.buttonDown });
						};

			Action<Shape, double, double, uint> DrawArrow =
					(s, x, y, c) =>
					{

						if (Visualize)
						{
							s.graphics.lineStyle(2, c, 1);
							s.graphics.moveTo(mouseDown_args.x, mouseDown_args.y);
							s.graphics.lineTo(x, y);
							s.graphics.drawCircle(x, y, 4);
						}
					};

			var mouseMove_args = default(Point);
			var delta_pos = 0.0;

			mc.move =
				p =>
				{
					if (!MovementEnabled)
						return;

					if (mouseDown_args == null)
						return;

					mouseMove_args = p;

					if (mouseUp_fadeOut != null)
						mouseUp_fadeOut.stop();

					vectorized.alpha = 1;
					vectorized.graphics.clear();

					snapcontainer.alpha = 1;
					snapcontainer.graphics.clear();


					snapcontainer.graphics.lineStyle(2, 0xff, 1);
					snapcontainer.graphics.drawCircle(mouseDown_args.x, mouseDown_args.y, snap_radius);

					DrawArrow(vectorized, mouseMove_args.x, mouseMove_args.y, color);
				};

			if (EnableMouse)
				stage.mouseMove +=
					e =>
					{
						if (e.buttonDown)
						{
							mc.move(e.ToStagePoint());
						}
					};

			mc.up +=
				delegate
				{
					if (mouseUp_fadeOut != null)
						mouseUp_fadeOut.stop();

					var _vectorized = vectorized;
					var _snapcontainer = snapcontainer;

					mouseUp_fadeOut = 50.AtInterval(
							t =>
							{
								if (vectorized.alpha < 0)
								{
									t.stop();
									return;
								}

								_vectorized.alpha -= 0.02;
								_snapcontainer.alpha -= 0.04;
							}
					);
				};

			if (EnableMouse)
				stage.mouseUp +=
					delegate
					{
						mc.up();
					};



			(1000 / 24).AtInterval(
				t =>
				{
					if (mouseDown_args == null)
						return;

					if (mouseMove_args == null)
						return;

					delta.graphics.clear();

					if (vectorized.alpha == 1)
					{
						delta_pos += mc.delta_acc;
						mc.delta_acc += mc.delta_acc_acc;
					}
					else
					{
						mc.delta_acc -= mc.delta_acc_acc * 3;
						if (mc.delta_acc < mc.delta_acc_min)
							mc.delta_acc = mc.delta_acc_min;


						delta_pos -= mc.delta_acc;
					}

					delta_pos = delta_pos.Min(1).Max(0);

					var u = (mouseMove_args - mouseDown_args) * delta_pos;
					var z = mouseDown_args + u;

					var Q1 = mouseDown_args.y < DefaultControlHeight * 1 / 6;
					var Q4 = mouseDown_args.y > DefaultControlHeight * 5 / 6;
					var IsPan = Q1 || Q4;


					if (delta_pos > 0)
						if (!IsPan)
						{

							NextViewDirection += u.x * 0.0004;

							NextViewPosition = NextViewPosition.MoveToArc(NextViewDirection, -u.y.Max(-snap_radius * 2).Min(snap_radius * 2) * 0.001);
						}
						else
						{
							NextViewPosition = NextViewPosition.MoveToArc(u.GetRotation() + NextViewDirection + 270.DegreesToRadians(), -(u.length.Min(snap_radius * 2)) * 0.001);
						}

					DrawArrow(delta, z.x, z.y, 0xff00);
				}
			);

			return mc;
		}
        private void Initialize()
        {

            #region CreateView
            Func<FlashTowerDefenseSized> CreateView =
                delegate
                {

                    var v = new FlashTowerDefenseSized(ReallyNarrowWidth, FlashTowerDefense.DefaultHeight);

                    var v_mask = new Shape();
                    v_mask.graphics.beginFill(0xffffff);
                    v_mask.graphics.drawRect(0, 0, ReallyNarrowWidth, FlashTowerDefense.DefaultHeight);
                    v_mask.graphics.endFill();

                    v.mask = v_mask;
                    v_mask.AttachTo(v);

                    return v;
                };
            #endregion


            // now we need a bridge and a server

            var server = new Game
            {
                AtInterval = (a, i) => i.AtIntervalDo(a).stop,
                AtDelay = (a, i) => i.AtDelayDo(a).stop,
            };

            var left_to_server = new global::FlashTowerDefense.Shared.SharedClass1.Bridge();
            var server_to_left = new global::FlashTowerDefense.Shared.SharedClass1.Bridge();

            var right_to_server = new global::FlashTowerDefense.Shared.SharedClass1.Bridge();
            var server_to_right = new global::FlashTowerDefense.Shared.SharedClass1.Bridge();

            var player_left = new Player
            {
                FromPlayer = left_to_server,
                ToPlayer = server_to_left,
                ToOthers = server_to_right,
                UserId = 0,
                Username = "******",
                AddScore = delegate { }
            };


            Action<SharedClass1.IEvents, SharedClass1.RemoteEvents.WithUserArgumentsRouter_Broadcast> AttachRouter =
                (from, _Router) =>
                {
                    from.TeleportTo += _Router.UserTeleportTo;
                    from.WalkTo += _Router.UserWalkTo;
                    from.TakeBox += _Router.UserTakeBox;
                    from.FiredWeapon += _Router.UserFiredWeapon;
                    from.EnterMachineGun += _Router.UserEnterMachineGun;
                    from.ExitMachineGun += _Router.UserExitMachineGun;
                    from.StartMachineGun += _Router.UserStartMachineGun;
                    from.StopMachineGun += _Router.UserStopMachineGun;
                    from.AddDamage += _Router.UserAddDamage;
                    from.AddDamageFromDirection += _Router.UserAddDamageFromDirection;
                    from.ShowBulletsFlying += _Router.UserShowBulletsFlying;
                    from.PlayerResurrect += _Router.UserPlayerResurrect;
                    from.UndeployExplosiveBarrel += _Router.UserUndeployExplosiveBarrel;
                    from.DeployExplosiveBarrel += _Router.UserDeployExplosiveBarrel;
                };

            AttachRouter(
                left_to_server,
                new SharedClass1.RemoteEvents.WithUserArgumentsRouter_Broadcast
                {
                    user = player_left.UserId,
                    Target = player_left.ToOthers
                }
            );

            var player_right = new Player
            {
                FromPlayer = right_to_server,
                ToPlayer = server_to_right,
                ToOthers = server_to_left,
                UserId = 1,
                Username = "******",
                AddScore = delegate { }
            };

            AttachRouter(
                  right_to_server,
                  new SharedClass1.RemoteEvents.WithUserArgumentsRouter_Broadcast
                  {
                      user = player_right.UserId,
                      Target = player_right.ToOthers
                  }
              );

            var left = CreateView();
            left.MovementArrows.Enabled = false;
            //left.ToggleMusic();

            var left_client = new FlashTowerDefenseClient.Implementation
            {
                Map = left,
                NetworkEvents = server_to_left,
                NetworkMessages = left_to_server,


            };

            left_client.InitializeEvents();
            left_client.InitializeMap();

            left.MoveTo(0, 0).AttachTo(this);


            var right = CreateView();
            right.MovementWASD.Enabled = false;
            var right_client = new FlashTowerDefenseClient.Implementation
            {
                Map = right,
                NetworkEvents = server_to_right,
                NetworkMessages = right_to_server,
            };


            right_client.InitializeEvents();
            right_client.InitializeMap();

            right.MoveTo(Padding + ReallyNarrowWidth, 0).AttachTo(this);

            //server_to_left.ServerPlayerHello += e => Console.WriteLine(e.ToString());
            //server_to_right.ServerPlayerHello += e => Console.WriteLine(e.ToString());

            //right_to_server.WalkTo += e => Console.WriteLine("server sees this: " + e.ToString());
            //server_to_left.WalkTo += e => Console.WriteLine("left sees this: " + e.ToString());

            server.GameStarted();

            100.AtDelayDo(
                delegate
                {
                    server.Users.Add(player_left);
                    server.UserJoined(player_left);
                }
            );

            300.AtDelayDo(
                delegate
                {
                    server.Users.Add(player_right);
                    server.UserJoined(player_right);
                }
            );
        }
		private void InitializeWriteLine()
		{
			// show fps
			var fps = new TextField { textColor = 0xff0000, x = DefaultControlWidth / 2 }.AttachTo(this).Do(t => EgoView.FramesPerSecondChanged += () => t.text = "fps: " + EgoView.FramesPerSecond);


			var dumperbg = new Shape().AttachTo(this);

			dumperbg.graphics.beginFill(0, 0.5);
			dumperbg.graphics.drawRect(0, DefaultControlHeight / 4, DefaultControlWidth, DefaultControlHeight / 2);

			var dumper = new TextField
			{
				width = DefaultControlWidth,
				height = DefaultControlHeight / 2,
				textColor = 0xffff00,
				mouseEnabled = false,
				y = DefaultControlHeight / 4,

			}.AttachTo(this);

			WriteLineControl = dumper;
			var dumper_queue = new Queue<string>();

			Action Update =
				delegate
				{
					dumper.text = "";

					foreach (var v in dumper_queue)
					{
						dumper.appendText(v + Environment.NewLine);
					};
				};
			WriteLine =
				text =>
				{
					dumper_queue.Enqueue(text);

					while (dumper_queue.Count > 10)
						dumper_queue.Dequeue();

					if (dumper.visible)
						Update();
				};

			BooleanProperty CheatMode = true;

			CheatMode.ValueChangedTo +=
				value =>
				{
					dumperbg.visible = value;
					dumper.visible = value;
					fps.visible = value;
					Keyboard_Cheats.Enabled = value;
				};

			if (global::ScriptCoreLib.ActionScript.flash.system.Capabilities.isDebugger)
			{
				var ButtonT = new KeyboardButton(stage)
				{
					Groups = new[]
			    {
			        MovementArrows[Keyboard.T],
			    },
					Up = CheatMode.Toggle
				};

				this.EgoView.WriteLine = this.WriteLine;
			}

			CheatMode.Toggle();

		}
        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 void ShowBulletsFlying(Point DamagePointOfOrigin, double DamageDirection, WeaponInfo Weapon)
        {
            if (Weapon == null)
                return;

            if (Weapon.VisibleBulletLines > 0)
                (1 + ((Weapon.VisibleBulletLines - 1).Random())).Times(
                    delegate
                    {
                        var VisibleBullet = new Shape().AttachTo(GetWarzone());

                        var RandomGray = (0x40 + 0x80.Random()).ToInt32();

                        VisibleBullet.graphics.lineStyle(1, RandomGray.ToGrayColor(), 1);


                        var BulletDirection = DamageDirection + (2.0.Random() - 1.0) * (Weapon.ArcRange * 0.75);
                        var BulletDropFromRange = 32 + (Weapon.Range / 2 - 32).Random();
                        var BulletDropFrom = DamagePointOfOrigin.MoveToArc(BulletDirection, BulletDropFromRange);

                        VisibleBullet.graphics.moveTo(BulletDropFrom.x, BulletDropFrom.y);

                        var BulletDropTo = DamagePointOfOrigin.MoveToArc(BulletDirection, BulletDropFromRange + (Weapon.Range.Random() / 2));

                        VisibleBullet.graphics.lineTo(BulletDropTo.x, BulletDropTo.y);

                        50.AtDelayDo(() => VisibleBullet.Orphanize());
                    }
                );
        }
        void AttachMovementInput(ViewEngineBase view)
        {
            var stage = this.stage;

            if (stage == null)
                throw new Exception("stage is null");


            var snapcontainer = new Shape().AttachTo(this);
            var vectorized = new Shape().AttachTo(this);
            var delta = new Shape { alpha = 0.5 }.AttachTo(this);




            var mouseDown_args = default(MouseEvent);
            var mouseUp_fadeOut = default(Timer);

            uint color = 0;

            var snap_radius = 64;

            stage.mouseDown +=
                    e =>
                    {
                        color = 0;

                        // snap to old point
                        if (mouseDown_args != null)
                            if (snapcontainer.alpha > 0)
                                if ((mouseDown_args.ToStagePoint() - e.ToStagePoint()).length < snap_radius)
                                {
                                    color = 0xff;

                                    e = mouseDown_args;
                                }

                        mouseDown_args = e;

                        //Write("down ", new { e.localX, e.localY, e.buttonDown });
                    };

            Action<Shape, double, double, uint> DrawArrow =
                    (s, x, y, c) =>
                    {


                        s.graphics.lineStyle(2, c, 1);
                        s.graphics.moveTo(mouseDown_args.stageX, mouseDown_args.stageY);
                        s.graphics.lineTo(x, y);
                        s.graphics.drawCircle(x, y, 4);
                    };

            var mouseMove_args = default(MouseEvent);
            var delta_pos = 0.0;

            stage.mouseMove +=
                    e =>
                    {
                        if (e.buttonDown)
                        {
                            mouseMove_args = e;

                            if (mouseUp_fadeOut != null)
                                mouseUp_fadeOut.stop();

                            vectorized.alpha = 1;
                            vectorized.graphics.clear();

                            snapcontainer.alpha = 1;
                            snapcontainer.graphics.clear();


                            snapcontainer.graphics.lineStyle(2, 0xff, 1);
                            snapcontainer.graphics.drawCircle(mouseDown_args.stageX, mouseDown_args.stageY, snap_radius);

                            DrawArrow(vectorized, e.stageX, e.stageY, color);
                        }
                    };

            stage.mouseUp +=
                    e =>
                    {
                        if (mouseUp_fadeOut != null)
                            mouseUp_fadeOut.stop();

                        var _vectorized = vectorized;
                        var _snapcontainer = snapcontainer;

                        mouseUp_fadeOut = 50.AtInterval(
                                t =>
                                {
                                    if (vectorized.alpha < 0)
                                    {
                                        t.stop();
                                        return;
                                    }

                                    _vectorized.alpha -= 0.02;
                                    _snapcontainer.alpha -= 0.04;
                                }
                        );
                    };


            var delta_acc_min = 0.02;
            var delta_acc = delta_acc_min;
            var delta_acc_acc = delta_acc_min * 0.01;

            var delta_deacc_min = 0.03;
            var delta_deacc = delta_deacc_min;

            (1000 / 24).AtInterval(
                t =>
                {
                    if (mouseDown_args == null)
                        return;

                    if (mouseMove_args == null)
                        return;

                    delta.graphics.clear();

                    if (vectorized.alpha == 1)
                    {
                        delta_pos += delta_acc;
                        delta_acc += delta_acc_acc;
                    }
                    else
                    {
                        delta_acc -= delta_acc_acc * 3;
                        if (delta_acc < delta_acc_min)
                            delta_acc = delta_acc_min;


                        delta_pos -= delta_acc;
                    }

                    delta_pos = Math.Max(Math.Min((double)1, (double)delta_pos), (double)0);

                    var u = (mouseMove_args.ToStagePoint() - mouseDown_args.ToStagePoint()) * delta_pos;
                    var z = mouseDown_args.ToStagePoint() + u;

                    var Q1 = mouseDown_args.stageY < stage.height * 1 / 6;
                    var Q4 = mouseDown_args.stageY > stage.height * 5 / 6;
                    var IsPan = Q1 || Q4;


                    if (delta_pos > 0)
                        if (!IsPan)
                        {

                            view.ViewDirection += u.x * 0.0004;

                            view.ViewPosition = view.ViewPosition.MoveToArc(view.ViewDirection,
                                Math.Min(
                                Math.Max(-u.y, -snap_radius * 2), (snap_radius * 2) * 0.001
                                )
                                );
                        }
                        else
                        {
                            view.ViewPosition = view.ViewPosition.MoveToArc(u.GetRotation() + view.ViewDirection + 270.DegreesToRadians(), -(u.length.Min(snap_radius * 2)) * 0.001);
                        }

                    DrawArrow(delta, z.x, z.y, 0xff00);
                }
            );
        }
		private void Initialize()
		{
			var stage = this.stage;

			if (stage == null)
				throw new Exception("stage is null");


			this.graphics.beginFill(0xefff80);
			this.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight / 2);

			this.graphics.beginFill(0xef8fff);
			this.graphics.drawRect(0, stage.stageHeight / 2, stage.stageWidth, stage.stageHeight / 2);


			var info = new TextField
			{
				selectable = false,
				multiline = true,
				width = stage.stageWidth,
				height = stage.stageHeight 
			}.AttachTo(this);

			var snapcontainer = this.Attach(new Shape());
			var vectorized = this.Attach(new Shape());
			var delta = new Shape { alpha = 0.5 }.AttachTo(this);

			var ego = new Sprite { mouseEnabled = false, x = stage.stageWidth / 2, y = stage.stageHeight / 2 }.AttachTo(this);
			var ego_img = gtataxi.ToBitmapAsset().AttachTo(ego);

			ego_img.x = -ego_img.width / 2;
			ego_img.y = -ego_img.height / 2;

			Action<string, object> Write = (p, e) =>
					{
						info.appendText(p + e.ToString() + Environment.NewLine);
						info.setSelection(info.text.Length - 1, info.text.Length - 1);
					};





			var mouseDown_args = default(MouseEvent);
			var mouseUp_fadeOut = default(Timer);

			uint color = 0;

			var snap_radius = 64;

			stage.mouseDown +=
					e =>
					{
						color = 0;

						// snap to old point
						if (mouseDown_args != null)
							if (snapcontainer.alpha > 0)
								if ((mouseDown_args.ToStagePoint() - e.ToStagePoint()).length < snap_radius)
								{
									color = 0xff;

									e = mouseDown_args;
								}

						mouseDown_args = e;

						Write("down ", new { e.localX, e.localY, e.buttonDown });
					};

			Action<Shape, double, double, uint> DrawArrow =
					(s, x, y, c) =>
					{


						s.graphics.lineStyle(2, c, 1);
						s.graphics.moveTo(mouseDown_args.stageX, mouseDown_args.stageY);
						s.graphics.lineTo(x, y);
						s.graphics.drawCircle(x, y, 4);
					};

			var mouseMove_args = default(MouseEvent);
			var delta_pos = 0.0;

			stage.mouseMove +=
					e =>
					{
						if (e.buttonDown)
						{
							mouseMove_args = e;

							if (mouseUp_fadeOut != null)
								mouseUp_fadeOut.stop();

							vectorized.alpha = 1;
							vectorized.graphics.clear();

							snapcontainer.alpha = 1;
							snapcontainer.graphics.clear();


							snapcontainer.graphics.lineStyle(2, 0xff, 1);
							snapcontainer.graphics.drawCircle(mouseDown_args.stageX, mouseDown_args.stageY, snap_radius);

							DrawArrow(vectorized, e.stageX, e.stageY, color);
						}
						else
						{
							if (delta_pos == 0)
								Write("move ", new { e.stageY, stage.stageHeight, stageScaleY = stage.scaleY, this.scaleY, stage.height });
							//Write("move ", new { e.stageX, e.stageY, stage.stageWidth, stage.stageHeight, stage.scaleX, stage.scaleY });
						}
					};

			stage.mouseUp +=
					e =>
					{
						Write("up ", new { e.localX, e.localY, e.buttonDown });

						if (mouseUp_fadeOut != null)
							mouseUp_fadeOut.stop();


						mouseUp_fadeOut = 50.AtInterval(
								t =>
								{
									vectorized.alpha -= 0.02;

									snapcontainer.alpha -= 0.04;
								}
						);
					};


			var delta_acc_min = 0.02;
			var delta_acc = delta_acc_min;
			var delta_acc_acc = delta_acc_min * 0.01;

			var delta_deacc_min = 0.03;
			var delta_deacc = delta_deacc_min;

			(1000 / 24).AtInterval(
				t =>
				{
					if (mouseDown_args == null)
						return;

					if (mouseMove_args == null)
						return;

					delta.graphics.clear();

					if (vectorized.alpha == 1)
					{
						delta_pos += delta_acc;
						//delta_deacc = (delta_deacc - delta_deacc_acc).Max(delta_deacc_min);
						delta_acc += delta_acc_acc;
					}
					else
					{
						delta_pos -= delta_deacc;
						delta_acc -= delta_acc_acc;

						if (delta_acc < delta_acc_min)
							delta_acc = delta_acc_min;

						//delta_deacc += delta_deacc_acc;
					}

					delta_pos = delta_pos.Min(1).Max(0);

					var u = (mouseMove_args.ToStagePoint() - mouseDown_args.ToStagePoint()) * delta_pos;
					var z = mouseDown_args.ToStagePoint() + u;

					if (delta_pos > 0)
						if (mouseDown_args.stageY > stage.height / 2)
						{
							// boolean
							Write("rot ", new { delta_pos, u.x, u.y });

							ego.rotation += u.x * 0.2;

							var p = ego.ToPoint().MoveToArc(((int)ego.rotation).DegreesToRadians(), -u.y * 0.2);

							ego.x = p.x;
							ego.y = p.y;
						}
						else
						{
							Write("pan ", new { delta_pos, u.x, u.y });

							var p = ego.ToPoint().MoveToArc(u.GetRotation() + ((int)ego.rotation + 270).DegreesToRadians(), -u.length * 0.2);

							ego.x = p.x;
							ego.y = p.y;
						}

					DrawArrow(delta, z.x, z.y, 0xff00);
				}
			);
		}