/* 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; }
/// <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); }