public PhysicalBarrel(StarlingGameSpriteWithBunkerTextures textures, StarlingGameSpriteWithPhysics Context)
        {
            this.CurrentInput = new KeySample();

            // hide in a barrel?
            //this.driverseat = new DriverSeat();

            this.textures = textures;
            this.Context = Context;


            //for (int i = 0; i < 7; i++)
            //{
            //    this.KarmaInput0.Enqueue(
            //        new KeySample()
            //    );
            //}

            visualshadow = new Image(
               textures.barrel1_shadow()
           ).AttachTo(Context.Content_layer2_shadows);


            visual = new Image(
               textures.barrel1()
           ).AttachTo(Context.Content_layer3_buildings);


            {
                //initialize body
                var bdef = new b2BodyDef();
                bdef.type = Box2D.Dynamics.b2Body.b2_dynamicBody;
                bdef.linearDamping = 8.0;
                bdef.angularDamping = 8;

                bdef.angle = 0;
                this.body = Context.ground_b2world.CreateBody(bdef);

                //initialize shape
                var fixdef = new b2FixtureDef();
                fixdef.density = 1;
                fixdef.friction = 0.01;
                //fixdef.restitution = 0.4; //positively bouncy!

                var shape = new b2PolygonShape();
                fixdef.shape = shape;

                shape.SetAsBox(1.6, 1);




                var fix = this.body.CreateFixture(fixdef);


                var fix_data = new Action<double>(
                    jeep_forceA =>
                    {
                        if (jeep_forceA < 1)
                            return;

                        if (oncollision != null)
                            oncollision(this, jeep_forceA);
                    }
                );
                fix.SetUserData(fix_data);
            }

            {
                //initialize body
                var bdef = new b2BodyDef();
                bdef.type = Box2D.Dynamics.b2Body.b2_dynamicBody;
                bdef.linearDamping = 8.0;
                bdef.angularDamping = 8;

                bdef.angle = 0;
                this.karmabody = Context.groundkarma_b2world.CreateBody(bdef);

                //initialize shape
                var fixdef = new b2FixtureDef();
                fixdef.density = 1;
                fixdef.friction = 0.01;
                //fixdef.restitution = 0.4; //positively bouncy!

                var shape = new b2PolygonShape();
                fixdef.shape = shape;


                shape.SetAsBox(1.6, 1);



                this.karmabody.CreateFixture(fixdef);
            }
            Context.internalunits.Add(this);
        }
        public PhysicalHindWeaponized(
            StarlingGameSpriteWithHindTextures textures_hind,
            StarlingGameSpriteWithRocketTextures textures_rocket,
            StarlingGameSpriteWithPhysics __Context,


            Image Explosion1 = null
            )
            : base(textures_hind, __Context)
        {
            var RocketsMax = 12;
            var Rockets = new Queue<PhysicalRocket>();

            var Context = __Context;
            var rocket0 = new PhysicalRocket(textures_rocket, Context, Explosion1: Explosion1);
            rocket0.body.SetActive(false);
            rocket0.SetPositionAndAngle(-0.5, 2);


            var rocket1 = new PhysicalRocket(textures_rocket, Context, Explosion1: Explosion1);
            rocket1.body.SetActive(false);
            rocket1.SetPositionAndAngle(-0.5, -2);

            #region z fixup
            rocket0.visual.parent.setChildIndex(
                rocket0.visual,

                this.visual.visualnowings.parent.getChildIndex(
                    this.visual.visualnowings
                )
            );
            #endregion

            #region z fixup
            rocket1.visual.parent.setChildIndex(
                rocket1.visual,

                this.visual.visualnowings.parent.getChildIndex(
                    this.visual.visualnowings
                )
            );
            #endregion

            var hind0 = this;

            #region ShowPositionAndAngleForSlaves
            hind0.ShowPositionAndAngleForSlaves = delegate
            {
                // we are faking 3d here!
                var sc = 1 + hind0.visual.airzoom * hind0.visual.Altitude;


                if (rocket0 != null)
                {
                    rocket0.body.SetActive(false);
                    rocket0.Altitude = hind0.visual.Altitude;
                    rocket0.SetPositionAndAngle(


                            hind0.body.GetPosition().x + Math.Cos(hind0.body.GetAngle() - Math.PI * 0.5 - hind0.CameraRotation) * 2.2 * sc,
                            hind0.body.GetPosition().y + Math.Sin(hind0.body.GetAngle() - Math.PI * 0.5 - hind0.CameraRotation) * 2.2 * sc,

                        hind0.body.GetAngle() - hind0.CameraRotation
                    );
                    rocket0.ShowPositionAndAngle();
                }

                if (rocket1 != null)
                {
                    rocket1.body.SetActive(false);
                    rocket1.Altitude = hind0.visual.Altitude;
                    rocket1.SetPositionAndAngle(


                            hind0.body.GetPosition().x + Math.Cos(hind0.body.GetAngle() + Math.PI * 0.5 - hind0.CameraRotation) * 2.2 * sc,
                            hind0.body.GetPosition().y + Math.Sin(hind0.body.GetAngle() + Math.PI * 0.5 - hind0.CameraRotation) * 2.2 * sc,

                        hind0.body.GetAngle() - hind0.CameraRotation
                    );
                    rocket1.ShowPositionAndAngle();
                }
            };
            #endregion

            #region FireRocket
            FireRocket = delegate
            {



                if (rocket0 != null)
                {
                    var sc = 1 + hind0.visual.airzoom * hind0.visual.Altitude;

                    rocket0.SetPositionAndAngle(


                              hind0.body.GetPosition().x + Math.Cos(hind0.body.GetAngle() - Math.PI * 0.5 - hind0.CameraRotation) * 3.5 * sc,
                              hind0.body.GetPosition().y + Math.Sin(hind0.body.GetAngle() - Math.PI * 0.5 - hind0.CameraRotation) * 3.5 * sc,

                          hind0.body.GetAngle() - hind0.CameraRotation
                      );
                    rocket0.ShowPositionAndAngle();
                    rocket0.body.SetActive(true);

                    rocket0.CreateSmoke();
                    {
                        var up = new KeySample();
                        up[Keys.Up] = true;
                        rocket0.speed = 60 + this.body.GetLinearVelocity().Length();
                        rocket0.SetVelocityFromInput(up);
                    }
                    Rockets.Enqueue(rocket0);
                    rocket0 = null;


                    if (rocket1 == null)
                    {
                        if (Rockets.Count > RocketsMax)
                        {
                            rocket1 = Rockets.Dequeue();
                            rocket1.SetVelocityFromInput(new KeySample());
                            rocket1.visual.visible = true;
                        }
                        else
                        {
                            rocket1 = new PhysicalRocket(textures_rocket, Context, Explosion1: Explosion1);
                            rocket1.body.SetActive(false);

                            #region z fixup
                            rocket1.visual.parent.setChildIndex(
                                rocket1.visual,

                                this.visual.visualnowings.parent.getChildIndex(
                                    this.visual.visualnowings
                                )
                            );
                            #endregion
                        }
                    }
                }
                else if (rocket1 != null)
                {
                    var sc = 1 + hind0.visual.airzoom * hind0.visual.Altitude;

                    rocket1.SetPositionAndAngle(


                              hind0.body.GetPosition().x + Math.Cos(hind0.body.GetAngle() + Math.PI * 0.5 - hind0.CameraRotation) * 3.5 * sc,
                              hind0.body.GetPosition().y + Math.Sin(hind0.body.GetAngle() + Math.PI * 0.5 - hind0.CameraRotation) * 3.5 * sc,

                          hind0.body.GetAngle() - hind0.CameraRotation
                      );
                    rocket1.ShowPositionAndAngle();
                    rocket1.body.SetActive(true);

                    rocket1.CreateSmoke();
                    {
                        var up = new KeySample();
                        up[Keys.Up] = true;
                        rocket1.speed = 60 + this.body.GetLinearVelocity().Length();
                        rocket1.SetVelocityFromInput(up);
                    }
                    Rockets.Enqueue(rocket1);
                    rocket1 = null;

                    if (rocket0 == null)
                    {
                        if (Rockets.Count > RocketsMax)
                        {
                            rocket0 = Rockets.Dequeue();
                            rocket0.SetVelocityFromInput(new KeySample());
                            rocket0.visual.visible = true;
                        }
                        else
                        {
                            rocket0 = new PhysicalRocket(textures_rocket, Context, Explosion1: Explosion1);
                            rocket0.body.SetActive(false);

                            #region z fixup
                            rocket0.visual.parent.setChildIndex(
                                rocket0.visual,

                                this.visual.visualnowings.parent.getChildIndex(
                                    this.visual.visualnowings
                                )
                            );
                            #endregion



                        }

                    }
                }
            };
            #endregion

        }
        public PhysicalRocket(
            StarlingGameSpriteWithRocketTextures textures_rocket,
            StarlingGameSpriteWithPhysics Context,
            bool issmoke = false,
            Image Explosion1 = null
            )
        {
            this.issmoke = issmoke;

            this.Context = Context;
            this.textures_rocket = textures_rocket;

            this.CurrentInput = new KeySample();

            visual = new Image(textures_rocket.rocket1());
            visual.AttachTo(Context.Content);


            //this.CameraRotation = Math.PI / 2;

            #region smoke_b2world




            {
                var bodyDef = new b2BodyDef();

                bodyDef.type = Box2D.Dynamics.b2Body.b2_dynamicBody;

                // stop moving if legs stop walking!
                bodyDef.linearDamping = 0;
                bodyDef.angularDamping = 6;
                //bodyDef.angle = 1.57079633;
                //bodyDef.fixedRotation = true;

                if (issmoke)
                {
                    body = Context.smoke_b2world.CreateBody(bodyDef);
                }
                else
                {
                    body = Context.damage_b2world.CreateBody(bodyDef);
                }


                var fixDef = new Box2D.Dynamics.b2FixtureDef();
                fixDef.density = 0.1;
                fixDef.friction = 0.0;
                fixDef.restitution = 0;


                fixDef.shape = new Box2D.Collision.Shapes.b2CircleShape(0.5);

                // 
                var fix = body.CreateFixture(fixDef);

                var fix_data = new Action<double>(
                    jeep_forceA =>
                    {
                        this.body.SetActive(false);
                        this.visual.visible = false;

                        // explode?
                        this.speed = 0;
                        this.CurrentInput = new KeySample();

                        Context.CreateExplosion(
                             this.body.GetPosition().x,
                              this.body.GetPosition().y
                        );


                    }
                );

                // this does NOT work!
                fix.SetUserData(fix_data);
            }


            #endregion





            Context.internalunits.Add(this);
        }
        public PhysicalCannon(StarlingGameSpriteWithCannonTextures textures, StarlingGameSpriteWithPhysics Context)
        {
            this.CurrentInput = new KeySample();
            this.driverseat = new DriverSeat();
            this.Context = Context;

            visual = new VisualCannon(textures, Context);

            for (int i = 0; i < 7; i++)
            {
                this.KarmaInput0.Enqueue(
                    new KeySample()
                );
            }

            {
                //initialize body
                var bdef = new b2BodyDef();
                bdef.angle = 0;
                bdef.fixedRotation = true;
                this.body = Context.ground_b2world.CreateBody(bdef);

                //initialize shape
                var fixdef = new b2FixtureDef();

                var shape = new b2PolygonShape();
                fixdef.shape = shape;

                shape.SetAsBox(2, 2);

                fixdef.restitution = 0.4; //positively bouncy!



                var fix = this.body.CreateFixture(fixdef);


                var fix_data = new Action<double>(
                    jeep_forceA =>
                    {
                        if (jeep_forceA < 1)
                            return;

                        Context.oncollision(this, jeep_forceA);
                    }
                );
                fix.SetUserData(fix_data);
            }

            {
                //initialize body
                var bdef = new b2BodyDef();
                bdef.angle = 0;
                bdef.fixedRotation = true;
                this.karmabody = Context.groundkarma_b2world.CreateBody(bdef);

                //initialize shape
                var fixdef = new b2FixtureDef();

                var shape = new b2PolygonShape();
                fixdef.shape = shape;

                shape.SetAsBox(2, 2);

                fixdef.restitution = 0.4; //positively bouncy!



                this.karmabody.CreateFixture(fixdef);
            }

            Context.internalunits.Add(this);
        }
        public PhysicalWatertower(StarlingGameSpriteWithBunkerTextures textures, StarlingGameSpriteWithPhysics Context)
        {
            this.CurrentInput = new KeySample();
            this.driverseat = new DriverSeat();

            this.textures = textures;
            this.Context = Context;


            for (int i = 0; i < 7; i++)
            {
                this.KarmaInput0.Enqueue(
                    new KeySample()
                );
            }

            visualshadow = new Image(
               textures.watertower0_shadow()
           ).AttachTo(Context.Content_layer2_shadows);


            visual = new Image(
               textures.watertower0()
           ).AttachTo(Context.Content_layer3_buildings);


            {
                //initialize body
                var bdef = new b2BodyDef();
                bdef.angle = 0;
                bdef.fixedRotation = true;
                this.body = Context.ground_b2world.CreateBody(bdef);

                //initialize shape
                var fixdef = new b2FixtureDef();

                var shape = new b2CircleShape(1.2);
                fixdef.shape = shape;


                fixdef.restitution = 0.4; //positively bouncy!



                var fix = this.body.CreateFixture(fixdef);

                var fix_data = new Action<double>(
                   force =>
                   {
                       if (force < 1)
                           return;

                       Context.oncollision(this, force);
                   }
              );

                fix.SetUserData(fix_data);
            }

            {
                //initialize body
                var bdef = new b2BodyDef();
                bdef.angle = 0;
                bdef.fixedRotation = true;
                this.karmabody = Context.groundkarma_b2world.CreateBody(bdef);

                //initialize shape
                var fixdef = new b2FixtureDef();

                var shape = new b2CircleShape(1.2);
                fixdef.shape = shape;


                fixdef.restitution = 0.4; //positively bouncy!



                this.karmabody.CreateFixture(fixdef);
            }
            Context.internalunits.Add(this);
        }
        public PhysicalPed(StarlingGameSpriteWithPedTextures textures, StarlingGameSpriteWithPhysics Context)
        {
            this.CurrentInput = new KeySample();
            this.textures = textures;
            this.Context = Context;

            for (int i = 0; i < 7; i++)
            {
                this.KarmaInput0.Enqueue(
                    new KeySample()
                );
            }


            visual = new VisualPed(textures, Context,
                AnimateSeed:
                    Context.random.Next() % 3000
            );


            #region b2world




            {
                var bodyDef = new b2BodyDef();

                bodyDef.type = Box2D.Dynamics.b2Body.b2_dynamicBody;

                // stop moving if legs stop walking!
                bodyDef.linearDamping = 0;
                bodyDef.angularDamping = 6;
                //bodyDef.angle = 1.57079633;
                //bodyDef.fixedRotation = true;

                body = Context.ground_b2world.CreateBody(bodyDef);


                var fixDef = new Box2D.Dynamics.b2FixtureDef();
                fixDef.density = 0.1;
                fixDef.friction = 0.0;
                fixDef.restitution = 0;


                fixDef.shape = new Box2D.Collision.Shapes.b2CircleShape(1.0);


                var fix = body.CreateFixture(fixDef);

                var fix_data = new Action<double>(
                    zombie_forceA =>
                    {
                        if (zombie_forceA < 1)
                            return;

                        // zombie runs against a building
                        if (zombie_forceA > 3.6)
                            if (visual.WalkLikeZombie)
                            {
                                Console.WriteLine(new { zombie_forceA });

                                this.body.SetActive(false);
                                this.damagebody.SetActive(false);
                                this.visual.LayOnTheGround = true;
                                this.SetVelocityFromInput(new KeySample());
                            }

                        if (oncollision != null)
                            oncollision(this, zombie_forceA);
                    }
                );
                fix.SetUserData(fix_data);
            }


            #endregion

            #region groundkarma_b2world
            {
                var bodyDef = new b2BodyDef();

                bodyDef.type = Box2D.Dynamics.b2Body.b2_dynamicBody;

                // stop moving if legs stop walking!
                bodyDef.linearDamping = 0;
                bodyDef.angularDamping = 6;
                //bodyDef.angle = 1.57079633;
                //bodyDef.fixedRotation = true;

                karmabody = Context.groundkarma_b2world.CreateBody(bodyDef);


                var fixDef = new Box2D.Dynamics.b2FixtureDef();
                fixDef.density = 0.1;
                fixDef.friction = 0.0;
                fixDef.restitution = 0;


                fixDef.shape = new Box2D.Collision.Shapes.b2CircleShape(1.0);


                var fix = karmabody.CreateFixture(fixDef);
            }
            #endregion

            #region damage_b2world




            {
                var bodyDef = new b2BodyDef();

                bodyDef.type = Box2D.Dynamics.b2Body.b2_dynamicBody;

                // stop moving if legs stop walking!
                bodyDef.linearDamping = 0;
                bodyDef.angularDamping = 6;
                //bodyDef.angle = 1.57079633;
                //bodyDef.fixedRotation = true;

                damagebody = Context.damage_b2world.CreateBody(bodyDef);


                var fixDef = new Box2D.Dynamics.b2FixtureDef();
                fixDef.density = 0.1;
                fixDef.friction = 0.0;
                fixDef.restitution = 0;


                fixDef.shape = new Box2D.Collision.Shapes.b2CircleShape(1.0);


                var fix = damagebody.CreateFixture(fixDef);

                var fix_data = new Action<double>(
                    jeep_forceA =>
                    {
                        if (jeep_forceA < 0.5)
                            return;

                        if (visual.WalkLikeZombie)
                        {
                            this.body.SetActive(false);
                            this.damagebody.SetActive(false);
                            this.visual.LayOnTheGround = true;
                            this.SetVelocityFromInput(new KeySample());
                        }
                        //if (jeep_forceA < 1)
                        //    return;

                        //if (oncollision != null)
                        //    oncollision(this, jeep_forceA);
                    }
                );
                fix.SetUserData(fix_data);
            }


            #endregion


            Context.internalunits.Add(this);

        }
        public PhysicalBunker(StarlingGameSpriteWithBunkerTextures textures, StarlingGameSpriteWithPhysics Context, bool IsShop = false)
        {
            var textures_bunker = textures;

            this.CurrentInput = new KeySample();

            this.driverseat = new DriverSeat();

            this.textures = textures;
            this.Context = Context;


            for (int i = 0; i < 7; i++)
            {
                this.KarmaInput0.Enqueue(
                    new KeySample()
                );
            }

            visualshadow = new Image(
               textures.bunker2_shadow()
           ).AttachTo(Context.Content_layer2_shadows);

            visual = new Sprite().AttachTo(Context.Content_layer3_buildings);


            visual_body = new Image(
               textures.bunker2()
           ).AttachTo(visual);

            visual_shopoverlay = new Image(
                 textures.bunker2_shopoverlay()
             ).AttachTo(visual);

            visual_shopoverlay_arrow = new Image(
                 textures.bunker2_shopoverlay_arrow()
             ).AttachTo(visual);


            if (IsShop)
            {

                #region hud_arrow
                var hud_arrow = new Image(
                      textures_bunker.bunker2_shopoverlay_arrow()
                  ).AttachTo(Context);


                StarlingGameSpriteWithPhysics.onframe +=
                    (ScriptCoreLib.ActionScript.flash.display.Stage stage, Starling starling) =>
                    {
                        var gap = new __vec2(
                             (float)(this.body.GetPosition().x - Context.current.body.GetPosition().x),
                             (float)(this.body.GetPosition().y - Context.current.body.GetPosition().y)
                         );

                        var distance = gap.GetLength();

                        if (distance < 40)
                        {
                            visual_shopoverlay_arrow.visible = true;
                            hud_arrow.visible = false;
                            return;
                        }


                        //if (distance < 50)
                        //{
                        //    visual_shopoverlay_arrow.visible = false;
                        //    hud_arrow.visible = false;
                        //    return;
                        //}

                        visual_shopoverlay_arrow.visible = false;
                        hud_arrow.visible = true;

                        var cm = new Matrix();

                        // 
                        var yy = 8 * Math.Sin(this.Context.gametime.ElapsedMilliseconds * 0.002);



                        cm.translate(-128, -128 - 64 + yy);


                        cm.scale(Context.stagescale, Context.stagescale);


                        cm.rotate(gap.GetRotation() - Context.current.body.GetAngle() + Context.current.CameraRotation);

                        cm.translate(
                            (stage.stageWidth * 0.5),
                            (stage.stageHeight * Context.internal_center_y)
                        );


                        hud_arrow.transformationMatrix = cm;
                    };
                #endregion

            }

            this.IsShop = IsShop;

            #region damage_b2world
            {
                //initialize body
                var bdef = new b2BodyDef();
                bdef.angle = 0;
                bdef.fixedRotation = true;
                this.damagebody = Context.damage_b2world.CreateBody(bdef);

                //initialize shape
                var fixdef = new b2FixtureDef();

                var shape = new b2PolygonShape();
                fixdef.shape = shape;

                shape.SetAsBox(4.5, 4.5);

                fixdef.restitution = 0.4; //positively bouncy!



                var fix = this.damagebody.CreateFixture(fixdef);

                var fix_data = new Action<double>(
                     force =>
                     {
                         if (force < 1)
                             return;

                         Context.oncollision(this, force);
                     }
                );

                fix.SetUserData(fix_data);
            }
            #endregion


            #region ground_b2world
            {
                //initialize body
                var bdef = new b2BodyDef();
                bdef.angle = 0;
                bdef.fixedRotation = true;
                this.body = Context.ground_b2world.CreateBody(bdef);

                //initialize shape
                var fixdef = new b2FixtureDef();

                var shape = new b2PolygonShape();
                fixdef.shape = shape;

                shape.SetAsBox(4.5, 4.5);

                fixdef.restitution = 0.4; //positively bouncy!



                var fix = this.body.CreateFixture(fixdef);

                var fix_data = new Action<double>(
                     force =>
                     {
                         if (force < 1)
                             return;

                         Context.oncollision(this, force);
                     }
                );

                fix.SetUserData(fix_data);
            }
            #endregion

            {
                //initialize body
                var bdef = new b2BodyDef();
                bdef.angle = 0;
                bdef.fixedRotation = true;
                this.karmabody = Context.groundkarma_b2world.CreateBody(bdef);

                //initialize shape
                var fixdef = new b2FixtureDef();

                var shape = new b2PolygonShape();
                fixdef.shape = shape;


                shape.SetAsBox(4.5, 4.5);
                fixdef.restitution = 0.4; //positively bouncy!



                this.karmabody.CreateFixture(fixdef);
            }
            Context.internalunits.Add(this);
        }
        public PhysicalHind(StarlingGameSpriteWithHindTextures textures, StarlingGameSpriteWithPhysics Context)
        {
            this.CurrentInput = new KeySample();
            this.driverseat = new DriverSeat();

            this.Context = Context;

            visual = new VisualHind(textures, Context.Content, Context.airzoom);

            for (int i = 0; i < 7; i++)
            {
                this.KarmaInput0.Enqueue(
                    new KeySample()
                );
            }




            #region ground_b2world ground_current


            {
                var ground_bodyDef = new b2BodyDef();

                ground_bodyDef.type = Box2D.Dynamics.b2Body.b2_dynamicBody;

                // stop moving if legs stop walking!
                ground_bodyDef.linearDamping = 10.0;
                ground_bodyDef.angularDamping = 4;
                //bodyDef.angle = 1.57079633;
                //ground_bodyDef.fixedRotation = true;

                ground_body = Context.ground_b2world.CreateBody(ground_bodyDef);


                var ground_fixDef = new Box2D.Dynamics.b2FixtureDef();
                ground_fixDef.density = 0.1;
                ground_fixDef.friction = 0.01;
                ground_fixDef.restitution = 0;

                var ground_fixdef_shape = new b2PolygonShape();

                ground_fixDef.shape = ground_fixdef_shape;

                // physics unit is looking to right
                ground_fixdef_shape.SetAsBox(2, 0.5);



                var ground_fix = ground_body.CreateFixture(ground_fixDef);
            }



            #endregion


            #region groundkarma_body


            {
                var ground_bodyDef = new b2BodyDef();

                ground_bodyDef.type = Box2D.Dynamics.b2Body.b2_dynamicBody;

                // stop moving if legs stop walking!
                ground_bodyDef.linearDamping = 10.0;
                ground_bodyDef.angularDamping = 4;
                //bodyDef.angle = 1.57079633;
                //ground_bodyDef.fixedRotation = true;

                groundkarma_body = Context.groundkarma_b2world.CreateBody(ground_bodyDef);


                var ground_fixDef = new Box2D.Dynamics.b2FixtureDef();
                ground_fixDef.density = 0.1;
                ground_fixDef.friction = 0.01;
                ground_fixDef.restitution = 0;

                var ground_fixdef_shape = new b2PolygonShape();

                ground_fixDef.shape = ground_fixdef_shape;

                // physics unit is looking to right
                ground_fixdef_shape.SetAsBox(2, 0.5);



                var ground_fix = groundkarma_body.CreateFixture(ground_fixDef);
            }



            #endregion


            #region air_b2world air_current




            {
                var air_bodyDef = new b2BodyDef();

                air_bodyDef.type = Box2D.Dynamics.b2Body.b2_dynamicBody;

                // stop moving if legs stop walking!
                air_bodyDef.linearDamping = 10.0;
                air_bodyDef.angularDamping = 4;
                //bodyDef.angle = 1.57079633;
                //air_bodyDef.fixedRotation = true;
                air_bodyDef.active = false;

                air_body = Context.air_b2world.CreateBody(air_bodyDef);


                var air_fixDef = new Box2D.Dynamics.b2FixtureDef();
                air_fixDef.density = 0.1;
                air_fixDef.friction = 0.01;
                air_fixDef.restitution = 0;

                var air_fixdef_shape = new b2PolygonShape();

                air_fixDef.shape = air_fixdef_shape;

                // physics unit is looking to right
                air_fixdef_shape.SetAsBox(2, 0.5);



                var air_fix = air_body.CreateFixture(air_fixDef);
            }


            #endregion

            #region smoke_b2world




            {
                var bodyDef = new b2BodyDef();

                bodyDef.type = Box2D.Dynamics.b2Body.b2_dynamicBody;

                // stop moving if legs stop walking!
                bodyDef.linearDamping = 0;
                bodyDef.angularDamping = 6;
                //bodyDef.angle = 1.57079633;
                //bodyDef.fixedRotation = true;

                damage_body = Context.damage_b2world.CreateBody(bodyDef);
                //body = Context.ground_b2world.CreateBody(bodyDef);


                var fixDef = new Box2D.Dynamics.b2FixtureDef();
                fixDef.density = 0.1;
                fixDef.friction = 0.0;
                fixDef.restitution = 0;


                fixDef.shape = new Box2D.Collision.Shapes.b2CircleShape(2);

                // 
                var fix = damage_body.CreateFixture(fixDef);

                //var fix_data = new Action<double>(
                //    jeep_forceA =>
                //    {
                //        if (jeep_forceA < 1)
                //            return;

                //        if (Context.oncollision != null)
                //            Context.oncollision(this, jeep_forceA);
                //    }
                //);
                //fix.SetUserData(fix_data);
            }


            #endregion



            ApplyVelocityElapsed = Context.gametime.ElapsedMilliseconds;


            Context.internalunits.Add(this);
        }
        public PhysicalTank(StarlingGameSpriteWithTankTextures textures, StarlingGameSpriteWithPhysics Context)
        {
            this.CurrentInput = new KeySample();

            this.textures = textures;
            this.Context = Context;
            this.driverseat = new DriverSeat();
            this.visual = new VisualTank(textures, Context);

            for (int i = 0; i < 7; i++)
            {
                this.KarmaInput0.Enqueue(
                    new KeySample()
                );
            }


            #region b2world



            {
                var bodyDef = new b2BodyDef();

                bodyDef.type = Box2D.Dynamics.b2Body.b2_dynamicBody;

                // stop moving if legs stop walking!
                bodyDef.linearDamping = 1.0;
                bodyDef.angularDamping = 8;
                //bodyDef.angle = 1.57079633;
                //bodyDef.fixedRotation = true;

                body = Context.ground_b2world.CreateBody(bodyDef);
                //current = body;


                var fixDef = new Box2D.Dynamics.b2FixtureDef();
                fixDef.density = 0.1;
                fixDef.friction = 0.01;
                fixDef.restitution = 0;

                var fixdef_shape = new b2PolygonShape();

                fixDef.shape = fixdef_shape;

                // physics unit is looking to right
                fixdef_shape.SetAsBox(3, 2);



                var fix = body.CreateFixture(fixDef);

                var fix_data = new Action<double>(
                    jeep_forceA =>
                    {
                        if (jeep_forceA < 1)
                            return;

                        Context.oncollision(this, jeep_forceA);
                    }
                );
                fix.SetUserData(fix_data);
            }


            {
                var bodyDef = new b2BodyDef();

                bodyDef.type = Box2D.Dynamics.b2Body.b2_dynamicBody;

                // stop moving if legs stop walking!
                bodyDef.linearDamping = 1.0;
                bodyDef.angularDamping = 8;
                //bodyDef.angle = 1.57079633;
                //bodyDef.fixedRotation = true;

                karmabody = Context.groundkarma_b2world.CreateBody(bodyDef);
                //current = body;


                var fixDef = new Box2D.Dynamics.b2FixtureDef();
                fixDef.density = 0.1;
                fixDef.friction = 0.01;
                fixDef.restitution = 0;

                var fixdef_shape = new b2PolygonShape();

                fixDef.shape = fixdef_shape;

                // physics unit is looking to right
                fixdef_shape.SetAsBox(3, 2);



                var fix = karmabody.CreateFixture(fixDef);
            }


            #endregion

            #region b2world



            {
                var bodyDef = new b2BodyDef();

                bodyDef.type = Box2D.Dynamics.b2Body.b2_dynamicBody;

                // stop moving if legs stop walking!
                bodyDef.linearDamping = 1.0;
                bodyDef.angularDamping = 8;
                //bodyDef.angle = 1.57079633;
                //bodyDef.fixedRotation = true;

                damagebody = Context.damage_b2world.CreateBody(bodyDef);
                //current = body;


                var fixDef = new Box2D.Dynamics.b2FixtureDef();
                fixDef.density = 0.1;
                fixDef.friction = 0.01;
                fixDef.restitution = 0;

                var fixdef_shape = new b2PolygonShape();

                fixDef.shape = fixdef_shape;

                // physics unit is looking to right
                fixdef_shape.SetAsBox(3, 2);



                var fix = damagebody.CreateFixture(fixDef);

                var fix_data = new Action<double>(
                    jeep_forceA =>
                    {
                        if (jeep_forceA < 1)
                            return;

                        Context.oncollision(this, jeep_forceA);
                    }
                );
                fix.SetUserData(fix_data);
            }



            #endregion


            Context.internalunits.Add(this);


        }
        public PhysicalJeep(StarlingGameSpriteWithJeepTextures textures, StarlingGameSpriteWithPhysics Context)
        {
            this.CurrentInput = new KeySample();
            this.CameraRotation = Math.PI / 2;

            this.textures = textures;
            this.driverseat = new DriverSeat();
            this.Context = Context;

            visual0 = new VisualJeep(textures, Context);

            for (int i = 0; i < 7; i++)
            {
                this.KarmaInput0.Enqueue(
                    new KeySample()
                );
            }

            Func<double, double, double[]> ff = (a, b) => { return new double[] { a, b }; };


            {
                xwheels = new[] { 
                        //top left
                        new Wheel { b2world = Context.groundkarma_b2world, x = -1.1, y = -1.2, width = 0.4, length = 0.8, revolving = true, powered = true },

                        //top right
                        new Wheel{b2world= Context.groundkarma_b2world, x =1.1,  y =-1.2,  width =0.4,  length =0.8,  revolving =true,  powered =true},


                        //back left
                        new Wheel{b2world= Context.groundkarma_b2world, x =-1.1,  y =1.2,  width =0.4,  length =0.8,  revolving =false,  powered =false},

                        //back right
                        new Wheel{b2world= Context.groundkarma_b2world, x =1.1,  y =1.2,  width =0.4,  length =0.8,  revolving =false,  powered =false},
                    };



                karmaunit4_physics = new Car(
                   b2world: Context.groundkarma_b2world,
                   width: 2,
                   length: 4,
                   position: ff(0, 0),
                   angle: 180,

                   // how fast can the jeep go?
                   power: 120,
                   max_speed: 120,

                   max_steer_angle: 33,
                    //max_steer_angle: 40,

                   wheels: xwheels
               );

            }

            {


                xwheels = new[] { 
                        //top left
                        new Wheel { b2world = Context.ground_b2world, x = -1.1, y = -1.2, width = 0.4, length = 0.8, revolving = true, powered = true },

                        //top right
                        new Wheel{b2world= Context.ground_b2world, x =1.1,  y =-1.2,  width =0.4,  length =0.8,  revolving =true,  powered =true},


                        //back left
                        new Wheel{b2world= Context.ground_b2world, x =-1.1,  y =1.2,  width =0.4,  length =0.8,  revolving =false,  powered =false},

                        //back right
                        new Wheel{b2world= Context.ground_b2world, x =1.1,  y =1.2,  width =0.4,  length =0.8,  revolving =false,  powered =false},
                    };



                unit4_physics = new Car(
                    b2world: Context.ground_b2world,
                    width: 2,
                    length: 4,
                    position: ff(0, 0),
                    angle: 180,

                    // how fast can the jeep go?
                    power: 120,
                    max_speed: 120,

                    max_steer_angle: 33,
                    //max_steer_angle: 40,

                    wheels: xwheels
                );

                var fix = unit4_physics.fix;
                var fix_data = new Action<double>(
                    jeep_forceA =>
                    {
                        if (jeep_forceA < 1)
                            return;

                        if (oncollision != null)
                            oncollision(this, jeep_forceA);
                    }
                );
                fix.SetUserData(fix_data);


                xwheels[0].setAngle += a =>
                {
                    var cm = new Matrix();
                    cm.translate(-2, -2);
                    cm.scale(2, 4);
                    cm.rotate(a.DegreesToRadians());

                    cm.translate(-18, -20);

                    visual0.tire0.transformationMatrix = cm;
                };

                xwheels[1].setAngle += a =>
                {

                    var cm = new Matrix();
                    cm.translate(-2, -2);
                    cm.scale(2, 4);
                    cm.rotate(a.DegreesToRadians());

                    cm.translate(18, -20);

                    visual0.tire1.transformationMatrix = cm;
                };
            }

            {
                //initialize body
                var def = new b2BodyDef();
                def.type = b2Body.b2_dynamicBody;
                def.linearDamping = 0.55;  //gradually reduces velocity, makes the car reduce speed slowly if neither accelerator nor brake is pressed
                def.bullet = true; //dedicates more time to collision detection - car travelling at high speeds at low framerates otherwise might teleport through obstacles.
                def.angularDamping = 0.3;

                this.damagebody = Context.damage_b2world.CreateBody(def);

                //initialize shape
                var fixdef = new b2FixtureDef();
                fixdef.density = 1.0;
                fixdef.friction = 0.3; //friction when rubbing agaisnt other shapes
                fixdef.restitution = 0.4;  //amount of force feedback when hitting something. >0 makes the car bounce off, it's fun!

                var fixdef_shape = new b2PolygonShape();

                fixdef.shape = fixdef_shape;
                fixdef_shape.SetAsBox(2 / 2, 4 / 2);
                var fix = damagebody.CreateFixture(fixdef);

            }

            Context.internalunits.Add(this);

        }