/* VERSIONE OBSOLETA DA AGGIORNARE
        /// <summary>
        /// Posiziona la parte vicino a quella a cui deve unirsi e crea il giunto.
        /// </summary>
        /// <param name="otherPart">Altra parte a cui unire questa</param>
        /// <param name="thisPartPosition">Posizione del centro del giunto rispetto al baricentro di questa parte</param>
        /// <param name="otherPartPosition">Posizione del centro del giunto rispetto al baricentro dell'altra parte</param>
        /// <param name="jointColor">Colore del giunto</param>
        /// <returns>false se thisPartPosizion è all'interno della parte, true altrimenti</returns>
        public bool Join(FParte otherPart, Vector2 thisPartPosition, Vector2 otherPartPosition, Color jointColor)
        {
            Body.Position = Utils.TranslateAndRotate((otherPartPosition - thisPartPosition), otherPart.Body.Position, otherPart.Body.Rotation);
            Body.Rotation = otherPart.Body.Rotation;
            Joint = JointFactory.CreateRevoluteJoint(World, otherPart.Body, this.Body, thisPartPosition);
            JointOffset = new Vector2(thisPartPosition.X, thisPartPosition.Y);
            Joint.MotorEnabled = true;
            Joint.MaxMotorTorque = Const.MaxMotorTorquePerAreaUnit * this.BodySize.X * this.BodySize.Y;

            //determina la dimensione del giunto in base alla posizione rispetto al centro del corpo e alla dimensione del corpo stesso
            if ((thisPartPosition.X > BodySize.X / 2) && (Math.Abs(thisPartPosition.Y) <= BodySize.Y / 2))
            {
                JointRadius = thisPartPosition.X - BodySize.X / 2;
                ConnectionSide = Side.Right;
            }
            else if ((thisPartPosition.X < -BodySize.X / 2) && (Math.Abs(thisPartPosition.Y) <= BodySize.Y / 2))
            {
                JointRadius = -thisPartPosition.X - BodySize.X / 2;
                ConnectionSide = Side.Left;
            }
            else if ((thisPartPosition.Y > BodySize.Y / 2) && (Math.Abs(thisPartPosition.X) <= BodySize.X / 2))
            {
                JointRadius = thisPartPosition.Y - BodySize.Y / 2;
                ConnectionSide = Side.Bottom;
            }
            else if ((thisPartPosition.Y < -BodySize.Y / 2) && (Math.Abs(thisPartPosition.X) <= BodySize.X / 2))
            {
                JointRadius = -thisPartPosition.Y - BodySize.Y / 2;
                ConnectionSide = Side.Top;
            }
            else
                return false;

            JointFixture = FixtureFactory.CreateCircle(JointRadius, Density, Body, JointOffset);
            if(JointColor != null)
                JointColor = jointColor;
            Joint.CollideConnected = true;      //abilita la collisione dei due body connessi dal giunto
            PartActuator = new Actuator(this, otherPart, Const.MaxForcePerAreaUnit * BodyArea);
            return true;
        }
        */
        /// <summary>
        /// Posiziona la parte vicino a quella a cui deve unirsi e crea il giunto.
        /// </summary>
        /// <param name="otherPart">Altra parte a cui unire questa</param>
        /// <param name="thisPartSidePosition">Posizione del punto di contatto del giunto con il bordo di questa parte rispetto al centro di questa parte</param>
        /// <param name="otherPartSidePosition">Posizione del punto di contatto del giunto con il bordo dell'altra parte rispetto al centro dell'altra parte</param>
        /// <param name="jointColor">Colore del giunto</param>
        /// <param name="jointRadius">Raggio del giunto</param>
        /// <returns>false se thisPartSidePosition non è sul bordo della parte, true altrimenti</returns>
        public bool Join(FenotipoCell otherPart, Vector2 thisPartSidePosition, Vector2 otherPartSidePosition, Color jointColor, float jointRadius)
        {
            Vector2 jointOffset;
            if (thisPartSidePosition.X == -(BodySize.X / 2))
            {
                jointOffset = new Vector2(-jointRadius * 2, 0);
                ConnectionSide = Side.Left;
            }
            else if (thisPartSidePosition.X == (BodySize.X / 2))
            {
                jointOffset = new Vector2(jointRadius * 2, 0);
                ConnectionSide = Side.Right;
            }
            else if (thisPartSidePosition.Y == -(BodySize.Y / 2))
            {
                jointOffset = new Vector2(0, -jointRadius * 2);
                ConnectionSide = Side.Top;
            }
            else if (thisPartSidePosition.Y == (BodySize.Y / 2))
            {
                jointOffset = new Vector2(0, jointRadius * 2);
                ConnectionSide = Side.Bottom;
            }
            else
                return false;

            Body.Position = Utils.TranslateAndRotate(otherPartSidePosition - thisPartSidePosition - jointOffset, otherPart.Body.Position, otherPart.Body.Rotation);
            Body.Rotation = otherPart.Body.Rotation;
            if (Joint != null)
                World.RemoveJoint(Joint);
            Joint = JointFactory.CreateRevoluteJoint(World, otherPart.Body, this.Body, thisPartSidePosition + jointOffset/2);
            Joint.MotorEnabled = true;
            Joint.MaxMotorTorque = Const.MaxMotorTorquePerAreaUnit * this.BodySize.X * this.BodySize.Y;

            JointRadius = jointRadius;
            JointFixture = FixtureFactory.CreateCircle(JointRadius, Density, Body, thisPartSidePosition + jointOffset/2);
            if (JointColor != null)
                JointColor = jointColor;
            JointOffset = thisPartSidePosition + jointOffset / 2;
            Joint.CollideConnected = true;
            PartActuator = new Actuator(this, otherPart, Const.MaxForcePerAreaUnit * BodyArea);
            otherPart.AddChild(this);
            return true;
        }
Esempio n. 2
0
        /// <summary>
        /// Costruttore che calcola automaticamente la posizione dei punti di contatto
        /// </summary>
        /// <param name="parteFiglio">Parte figlia (parte che possiede questo Actuator)</param>
        /// <param name="partePadre">Parte padre (parte a cui è attaccata la parte figlia attraverso questo Actuator)</param>
        /// <param name="maxForce">Forza massima da applicare a ciascun muscolo</param>
        public Actuator(FenotipoCell parteFiglio, FenotipoCell partePadre, float maxForce)
        {
            MaxForce = maxForce;
            PartePadre = partePadre;
            ParteFiglia = parteFiglio;
            Vector2 jointSideOffset = parteFiglio.JointSideOffset;
            LocalFigliaDir = new Vector2();
            LocalFigliaInv = new Vector2();
            LocalPadreDir = new Vector2();
            LocalPadreInv = new Vector2();
            /*
             * noto il lato attraverso cui le due parti sono collegate e dove quindi dovranno essere posizionati i muscoli, questi
             * saranno collocati in corrispondenza dell'estremo più interno tra quelli delle due parti. Occorre quindi calcolare le
             * posizioni degli angoli delle due parti rispetto ad un unico sistema di riferimento locale (in questo caso quello della
             * parte figlia), in modo da poter determinare subito quale dei due sia il più interno.
             */
            switch (ParteFiglia.ConnectionSide)
            {
                case Side.Right:
                    Vector2 figlioRelativePadreUpperCorner = Utils.InvTranslateAndRotate(Utils.TranslateAndRotate(new Vector2(-PartePadre.BodySize.X / 2, PartePadre.BodySize.Y / 2), PartePadre.Position, PartePadre.Rotation), ParteFiglia.Position, ParteFiglia.Rotation);
                    Vector2 figlioRelativePadreLowerCorner = Utils.InvTranslateAndRotate(Utils.TranslateAndRotate(new Vector2(-PartePadre.BodySize.X / 2, -PartePadre.BodySize.Y / 2), PartePadre.Position, PartePadre.Rotation), ParteFiglia.Position, ParteFiglia.Rotation);
                    LocalFigliaDir.X = ParteFiglia.BodySize.X / 2;
                    LocalFigliaInv.X = ParteFiglia.BodySize.X / 2;
                    Vector2 padreRelativeFiglioUpperCorner = Utils.InvTranslateAndRotate(Utils.TranslateAndRotate(new Vector2(ParteFiglia.BodySize.X / 2, ParteFiglia.BodySize.Y / 2), ParteFiglia.Position, ParteFiglia.Rotation), PartePadre.Position, PartePadre.Rotation);
                    Vector2 padreRelativeFiglioLowerCorner = Utils.InvTranslateAndRotate(Utils.TranslateAndRotate(new Vector2(ParteFiglia.BodySize.X / 2, -ParteFiglia.BodySize.Y / 2), ParteFiglia.Position, ParteFiglia.Rotation), PartePadre.Position, PartePadre.Rotation);
                    LocalPadreDir.X = -PartePadre.BodySize.X / 2;
                    LocalPadreInv.X = -PartePadre.BodySize.X / 2;
                    if (figlioRelativePadreUpperCorner.Y < (ParteFiglia.BodySize.Y / 2)) //l'angolo superiore più interno è quello della parte padre (ha la coordinata Y minore)
                    {
                        LocalFigliaDir.Y = figlioRelativePadreUpperCorner.Y;
                        LocalPadreDir.Y = PartePadre.BodySize.Y / 2;
                    }
                    else  //l'angolo superiore più interno è quello della parte figlia
                    {
                        LocalFigliaDir.Y = ParteFiglia.BodySize.Y / 2;
                        LocalPadreDir.Y = padreRelativeFiglioUpperCorner.Y;
                    }

                    if (figlioRelativePadreLowerCorner.Y > (-ParteFiglia.BodySize.Y / 2)) //stessa cosa per gli angoli inferiori (ora però il più interno ha la coordinata Y maggiore)
                    {
                        LocalFigliaInv.Y = figlioRelativePadreLowerCorner.Y;
                        LocalPadreInv.Y = -PartePadre.BodySize.Y / 2;
                    }
                    else
                    {
                        LocalFigliaInv.Y = -ParteFiglia.BodySize.Y / 2;
                        LocalPadreInv.Y = padreRelativeFiglioLowerCorner.Y;
                    }
                    break;
                case Side.Left:
                    //simmetrico al caso precedente, con PartePadre e ParteFiglia invertiti
                    figlioRelativePadreUpperCorner = Utils.InvTranslateAndRotate(Utils.TranslateAndRotate(new Vector2(PartePadre.BodySize.X / 2, PartePadre.BodySize.Y / 2), PartePadre.Position, PartePadre.Rotation), ParteFiglia.Position, ParteFiglia.Rotation);
                    figlioRelativePadreLowerCorner = Utils.InvTranslateAndRotate(Utils.TranslateAndRotate(new Vector2(PartePadre.BodySize.X / 2, -PartePadre.BodySize.Y / 2), PartePadre.Position, PartePadre.Rotation), ParteFiglia.Position, ParteFiglia.Rotation);
                    LocalFigliaDir.X = -ParteFiglia.BodySize.X / 2;
                    LocalFigliaInv.X = -ParteFiglia.BodySize.X / 2;
                    padreRelativeFiglioUpperCorner = Utils.InvTranslateAndRotate(Utils.TranslateAndRotate(new Vector2(-ParteFiglia.BodySize.X / 2, ParteFiglia.BodySize.Y / 2), ParteFiglia.Position, ParteFiglia.Rotation), PartePadre.Position, PartePadre.Rotation);
                    padreRelativeFiglioLowerCorner = Utils.InvTranslateAndRotate(Utils.TranslateAndRotate(new Vector2(-ParteFiglia.BodySize.X / 2, -ParteFiglia.BodySize.Y / 2), ParteFiglia.Position, ParteFiglia.Rotation), PartePadre.Position, PartePadre.Rotation);
                    LocalPadreDir.X = PartePadre.BodySize.X / 2;
                    LocalPadreInv.X = PartePadre.BodySize.X / 2;
                    if (figlioRelativePadreUpperCorner.Y < (ParteFiglia.BodySize.Y / 2))
                    {
                        LocalFigliaDir.Y = figlioRelativePadreUpperCorner.Y;
                        LocalPadreDir.Y = PartePadre.BodySize.Y / 2;
                    }
                    else
                    {
                        LocalFigliaDir.Y = ParteFiglia.BodySize.Y / 2;
                        LocalPadreDir.Y = padreRelativeFiglioUpperCorner.Y;
                    }

                    if (figlioRelativePadreLowerCorner.Y > (-ParteFiglia.BodySize.Y / 2))
                    {
                        LocalFigliaInv.Y = figlioRelativePadreLowerCorner.Y;
                        LocalPadreInv.Y = -PartePadre.BodySize.Y / 2;
                    }
                    else
                    {
                        LocalFigliaInv.Y = -ParteFiglia.BodySize.Y / 2;
                        LocalPadreInv.Y = padreRelativeFiglioLowerCorner.Y;
                    }
                    break;
                case Side.Top:
                    //simmetrico rispetto al case Side.Right, con X <-> Y, Right <-> Upper, Left <-> Lower
                    Vector2 figlioRelativePadreRightCorner = Utils.InvTranslateAndRotate(Utils.TranslateAndRotate(new Vector2(PartePadre.BodySize.X / 2, PartePadre.BodySize.Y / 2), PartePadre.Position, PartePadre.Rotation), ParteFiglia.Position, ParteFiglia.Rotation);
                    Vector2 figlioRelativePadreLeftCorner = Utils.InvTranslateAndRotate(Utils.TranslateAndRotate(new Vector2(-PartePadre.BodySize.X / 2, PartePadre.BodySize.Y / 2), PartePadre.Position, PartePadre.Rotation), ParteFiglia.Position, ParteFiglia.Rotation);
                    LocalFigliaDir.Y = -ParteFiglia.BodySize.Y / 2;
                    LocalFigliaInv.Y = -ParteFiglia.BodySize.Y / 2;
                    Vector2 padreRelativeFiglioRightCorner = Utils.InvTranslateAndRotate(Utils.TranslateAndRotate(new Vector2(ParteFiglia.BodySize.X / 2, -ParteFiglia.BodySize.Y / 2), ParteFiglia.Position, ParteFiglia.Rotation), PartePadre.Position, PartePadre.Rotation);
                    Vector2 padreRelativeFiglioLeftCorner = Utils.InvTranslateAndRotate(Utils.TranslateAndRotate(new Vector2(-ParteFiglia.BodySize.X / 2, -ParteFiglia.BodySize.Y / 2), ParteFiglia.Position, ParteFiglia.Rotation), PartePadre.Position, PartePadre.Rotation);
                    LocalPadreDir.Y = PartePadre.BodySize.Y / 2;
                    LocalPadreInv.Y = PartePadre.BodySize.Y / 2;
                    if (figlioRelativePadreRightCorner.X < (ParteFiglia.BodySize.X / 2))
                    {
                        LocalFigliaDir.X = figlioRelativePadreRightCorner.X;
                        LocalPadreDir.X = PartePadre.BodySize.X / 2;
                    }
                    else
                    {
                        LocalFigliaDir.X = ParteFiglia.BodySize.X / 2;
                        LocalPadreDir.X = padreRelativeFiglioRightCorner.X;
                    }

                    if (figlioRelativePadreLeftCorner.X > (-ParteFiglia.BodySize.X / 2))
                    {
                        LocalFigliaInv.X = figlioRelativePadreLeftCorner.X;
                        LocalPadreInv.X = -PartePadre.BodySize.X / 2;
                    }
                    else
                    {
                        LocalFigliaInv.X = -ParteFiglia.BodySize.X / 2;
                        LocalPadreInv.X = padreRelativeFiglioLeftCorner.X;
                    }
                    break;
                case Side.Bottom:
                    //simmetrico rispetto al caso Top, con PartePadre <-> ParteFiglia
                    figlioRelativePadreRightCorner = Utils.InvTranslateAndRotate(Utils.TranslateAndRotate(new Vector2(PartePadre.BodySize.X / 2, -PartePadre.BodySize.Y / 2), PartePadre.Position, PartePadre.Rotation), ParteFiglia.Position, ParteFiglia.Rotation);
                    figlioRelativePadreLeftCorner = Utils.InvTranslateAndRotate(Utils.TranslateAndRotate(new Vector2(-PartePadre.BodySize.X / 2, -PartePadre.BodySize.Y / 2), PartePadre.Position, PartePadre.Rotation), ParteFiglia.Position, ParteFiglia.Rotation);
                    LocalFigliaDir.Y = ParteFiglia.BodySize.Y / 2;
                    LocalFigliaInv.Y = ParteFiglia.BodySize.Y / 2;
                    padreRelativeFiglioRightCorner = Utils.InvTranslateAndRotate(Utils.TranslateAndRotate(new Vector2(ParteFiglia.BodySize.X / 2, ParteFiglia.BodySize.Y / 2), ParteFiglia.Position, ParteFiglia.Rotation), PartePadre.Position, PartePadre.Rotation);
                    padreRelativeFiglioLeftCorner = Utils.InvTranslateAndRotate(Utils.TranslateAndRotate(new Vector2(-ParteFiglia.BodySize.X / 2, ParteFiglia.BodySize.Y / 2), ParteFiglia.Position, ParteFiglia.Rotation), PartePadre.Position, PartePadre.Rotation);
                    LocalPadreDir.Y = -PartePadre.BodySize.Y / 2;
                    LocalPadreInv.Y = -PartePadre.BodySize.Y / 2;
                    if (figlioRelativePadreRightCorner.X < (ParteFiglia.BodySize.X / 2))
                    {
                        LocalFigliaDir.X = figlioRelativePadreRightCorner.X;
                        LocalPadreDir.X = PartePadre.BodySize.X / 2;
                    }
                    else
                    {
                        LocalFigliaDir.X = ParteFiglia.BodySize.X / 2;
                        LocalPadreDir.X = padreRelativeFiglioRightCorner.X;
                    }

                    if (figlioRelativePadreLeftCorner.X > (-ParteFiglia.BodySize.X / 2))
                    {
                        LocalFigliaInv.X = figlioRelativePadreLeftCorner.X;
                        LocalPadreInv.X = -PartePadre.BodySize.X / 2;
                    }
                    else
                    {
                        LocalFigliaInv.X = -ParteFiglia.BodySize.X / 2;
                        LocalPadreInv.X = padreRelativeFiglioLeftCorner.X;
                    }
                    break;
            }
        }
 public void AddChild(FenotipoCell part)
 {
     ChildParts.Add(part);
 }