public Branch(Path2D path, GameContent gameContent, World world, Branch nearestBranch)
        {
            this.gameContent = gameContent;
            dot = gameContent.dot;
            circle = gameContent.jointCircle;
            square = gameContent.jointSquare;
            cursor = gameContent.cursor;

            BodyDef bd = new BodyDef();
            bd.position = path.Keys[0];
            bd.type = BodyType.Dynamic;
            body = world.CreateBody(bd);

            fixtureCount = path.Keys.Count;
            for (int i = 0; i < path.Keys.Count; i++)
                CreateFixture(path.Keys[i] - path.Keys[0]);

            if (nearestBranch != null)
            {
                RevoluteJointDef revJd = new RevoluteJointDef();
                revJd.bodyA = body;
                revJd.bodyB = nearestBranch.body;

                revJd.localAnchorA = Vector2.Zero;

                AABB aabb; nearestBranch.nearestFixture.GetAABB(out aabb);
                Vector2 p = aabb.GetCenter();
                revJd.localAnchorB = nearestBranch.nearestFixture.GetBody().GetLocalPoint(p);

                revJd.enableMotor = true;
                revJd.referenceAngle = nearestBranch.nearestFixture.GetBody().Rotation;

                revoJoint = (RevoluteJoint)world.CreateJoint(revJd);
                revoJoint.SetUserData((Branch)nearestBranch);

                nearestBranch.nearestFixture.SetUserData((Branch)this);
            }

            newGrow = true;
        }
        private void CreateStem()
        {
            AddBranch = true;

            AABB aabb = new AABB(); body.GetFixtureList().GetAABB(out aabb);
            Vector2 v = aabb.GetCenter() + new Vector2(0, 15);

            Path2D p = new Path2D();
            p.AddPoint(v); p.AddPoint(v + new Vector2(0, -10));

            stem = new Branch(p, gameContent, body.GetWorld(), null);
            RevoluteJointDef revJd = new RevoluteJointDef();
            revJd.bodyA = stem.body;
            revJd.bodyB = ground;

            revJd.collideConnected = true;

            revJd.localAnchorA = Vector2.Zero;
            revJd.localAnchorB = stem.body.Position;
            revJd.enableMotor = true;

            stem.revoJoint = (RevoluteJoint)world.CreateJoint(revJd);

            // A Small rotation sets the body in motion
            stem.body.Rotation = (float)Math.PI / 360;
        }
        public void Grow(Path2D path)
        {
            AABB aabb; body.GetFixtureList().GetAABB(out aabb);
            Vector2 p = aabb.GetCenter();
            float d = Vector2.Distance(p, body.Position);
            float theta = (float)Math.Atan2((double)(p.Y - body.Position.Y),
                    (double)(p.X - body.Position.X));

            theta -= body.Rotation;
            Vector2 localEnd = d * new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta));

            fixtureCount += path.Keys.Count - 1;
            for (int i = 1; i < path.Keys.Count; i++)
            {
                d = Vector2.Distance(path.Keys[i], path.Keys[0]);
                theta = (float)Math.Atan2((double)(path.Keys[i].Y - path.Keys[0].Y),
                    (double)(path.Keys[i].X - path.Keys[0].X));
                theta -= body.Rotation;

                CreateFixture(localEnd + d * new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)));
                //CreateFixture(body.GetLocalPoint(p) + path.Keys[i] - path.Keys[0]);
            }

            newGrow = true;
        }
        public void Update(GameTime gameTime)
        {
            bool groundContact = false;

            for (ContactEdge ce = body.GetContactList(); ce != null; ce = ce.Next)
                if (ce.Contact.IsTouching() && ce.Other.GetType() == BodyType.Static) groundContact = true;

            if (groundContact || body.Position.Y > gameContent.viewport.Height * 2)
                dTime += (float)gameTime.ElapsedGameTime.TotalSeconds;
            else dTime = 0;
            if (dTime > DestroyTime) body.GetWorld().DestroyBody(body);

            IsConnected = true;

            if (revoJoint == null) IsConnected = false;
            else
            {
                object o = revoJoint.GetUserData();
                if (o is Branch)
                {
                    IsConnected = ((Branch)o).IsConnected;
                    if (((Branch)o).body.GetFixtureList() == null) IsConnected = false;
                }

                // If Ground is in contact
                if (groundContact) IsConnected = false;
            }

            DropAndGrowLeaves(gameTime);

            wasConnected = IsConnected;

            path = new Path2D();
            for (Fixture f = body.GetFixtureList(); f != null; f = f.GetNext())
            {
                // Clear if the other joint body is destroyed
                if (f.GetUserData() is Branch && ((Branch)f.GetUserData()).body.GetFixtureList() == null)
                    f.SetUserData(null);

                AABB aabb; f.GetAABB(out aabb);
                path.Keys.Add(aabb.GetCenter());
            }

            if (revoJoint != null && body.GetFixtureList() != null)
            {
                AABB aabb; body.GetFixtureList().GetAABB(out aabb);
                float length = Vector2.Distance(aabb.GetCenter(), body.Position);

                float angleError = revoJoint.GetJointAngle();
                float gain = 0.5f;
                int torqueFactor = 10000;

                if (angleError != 0)
                {
                    revoJoint.SetMotorSpeed(-gain * angleError);
                    revoJoint.SetMaxMotorTorque(torqueFactor * (float)Math.Min(Math.Abs(angleError), Math.PI / 18)
                        * (float)Math.Pow(length, 1.5f));
                }
            }

            UpdateLeavesAndApples(gameTime);

            if (!IsConnected && body.Position.Y > gameContent.viewport.Height * 3)
                body.GetWorld().DestroyBody(body);
        }
        public void HandleInput(InputState input, int playerIndex)
        {
            MouseState prevMouseState = input.LastMouseState[0];
            MouseState mouseState = input.CurrentMouseState[0];
            mousePos = new Vector2(mouseState.X, mouseState.Y);

            if (prevMouseState.LeftButton == ButtonState.Pressed && mouseState.LeftButton == ButtonState.Released
                && path.Keys.Count != 0)
            {
                if (path.Keys.Count > 1)
                {
                    if (nearestBranch != null && nearestBranch.body.GetFixtureList() != null)
                    {
                        if (nearestBranch.body.GetFixtureList() == nearestBranch.nearestFixture)
                            nearestBranch.Grow(path);
                        else
                            branches.Add(new Branch(path, GameContent, world, nearestBranch));
                    }

                    //else branches.Add(new Branch(path, GameContent, world, null));
                }
                path = new Path2D();
            }

            if (prevMouseState.RightButton == ButtonState.Pressed && mouseState.RightButton == ButtonState.Released
                && nearestBranch != null && path.Keys.Count == 0)
            {
                nearestBranch.CutDown(nearestBranch.nearestFixture);
            }

            if (mouseState.LeftButton == ButtonState.Pressed)
            {
                if (GameContent.viewport.TitleSafeArea.Contains(new Point(mouseState.X, mouseState.Y)))
                    path.AddPoint(mousePos);
            }
            else
            {
                nearestBranch = null;
                float nearestDist = 10;
                foreach (Branch b in branches)
                {
                    float d = b.NearestFixtureDistance(mousePos, nearestDist);
                    if (d < nearestDist)
                    {
                        if (nearestBranch != null) nearestBranch.nearestFixture = null;

                        nearestBranch = b;
                        nearestDist = d;
                    }
                }
            }
        }