/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { kCurrentState = Keyboard.GetState(); mCurrentState = Mouse.GetState(); //controlla l'input solo se la finestra ha il focus per evitare input non desiderati mentre si utilizza un altra applicazione //(ad esempio il client di controllo) if (GetForegroundWindow() == this.Window.Handle) { #region Telecamera //matrice di traslazione per passare dal sistema di riferimento della finestra a quello del mondo, traslato a causa della telecamera matrice = Matrix.CreateTranslation(new Vector3(camera.Pos, 0) - new Vector3(GraphicsDevice.Viewport.Width * 0.5f, GraphicsDevice.Viewport.Height * 0.5f, 0)); //posizione del mouse nelle coordinate traslate tenendo conto della telecamera mousePos = Vector2.Transform(new Vector2(mCurrentState.X, mCurrentState.Y), matrice); //varia lo zoom if (kCurrentState.IsKeyDown(Keys.H)) Const.Zoom = Const.Zoom + 1; if (kCurrentState.IsKeyDown(Keys.L)) { if ((Const.Zoom - 1) > 0) Const.Zoom = Const.Zoom - 1; } //movimento telecamera if (kCurrentState.IsKeyDown(Keys.W)) camera.Muovi(new Vector2(0, -3)); if (kCurrentState.IsKeyDown(Keys.A)) camera.Muovi(new Vector2(-3, 0)); if (kCurrentState.IsKeyDown(Keys.S)) camera.Muovi(new Vector2(0, 3)); if (kCurrentState.IsKeyDown(Keys.D)) camera.Muovi(new Vector2(3, 0)); #endregion //blocca/muove le parti if (kCurrentState.IsKeyDown(Keys.P) && kPreviousState.IsKeyUp(Keys.P)) { moving = !moving; if (moving) foreach (FParte part in partList) part.BodyType = BodyType.Dynamic; else foreach (FParte part in partList) part.BodyType = BodyType.Static; } #region Selezione parte //controlla se si tenta di selezionare una parte if (!drawingPart && (mCurrentState.LeftButton == ButtonState.Pressed) && (mPreviousState.LeftButton == ButtonState.Released)) foreach (FParte parte in partList) { /* Vector2 partRelativeMousePos = Coord.InvTranslateAndRotate(mousePos, Coord.ToGraphics(parte.Position, Const.Zoom), parte.Rotation); if ((Math.Abs(partRelativeMousePos.X) <= Coord.ToGraphics(parte.BodySize).X) && (Math.Abs(partRelativeMousePos.Y) <= Coord.ToGraphics(parte.BodySize).Y)) selectedPart = parte; * */ if (parte.TestPoint(Utils.ToPhysics(mousePos))) selectedPart = parte; } if (selectedPart != null) //se è stata selezionata una parte tenta di calcolare partRelativeMouseProjection { //coordinate del mouse rispetto al sistema di riferimento della parte partRelativeMouseProjection = Utils.InvTranslateAndRotate(mousePos, Utils.ToGraphics(selectedPart.Position, Const.Zoom), selectedPart.Rotation); //passa in coordinate fisiche (per evitare di effettuare molte più conversioni in coordinate grafiche partRelativeMouseProjection = Utils.ToPhysics(partRelativeMouseProjection, Const.Zoom); //verifica se il mouse è in corrispondenza di uno dei lati della parte e, in caso affermativo, aggiorna il vettore //con la proiezione della posizione del mouse sul bordo della creatura (altrimenti non la modifica) if ((partRelativeMouseProjection.X < 0) && (Math.Abs(partRelativeMouseProjection.Y) <= (selectedPart.BodySize.Y / 2))) { partRelativeMouseProjection.X = -selectedPart.BodySize.X / 2; onSide = true; projectionSide = Side.Left; } else if ((partRelativeMouseProjection.X >= 0) && (Math.Abs(partRelativeMouseProjection.Y) <= (selectedPart.BodySize.Y / 2))) { partRelativeMouseProjection.X = selectedPart.BodySize.X / 2; onSide = true; projectionSide = Side.Right; } else if ((partRelativeMouseProjection.Y < 0) && (Math.Abs(partRelativeMouseProjection.X) <= (selectedPart.BodySize.X / 2))) { partRelativeMouseProjection.Y = -selectedPart.BodySize.Y / 2; onSide = true; projectionSide = Side.Top; } else if ((partRelativeMouseProjection.Y >= 0) && (Math.Abs(partRelativeMouseProjection.X) <= (selectedPart.BodySize.X / 2))) { partRelativeMouseProjection.Y = selectedPart.BodySize.Y / 2; onSide = true; projectionSide = Side.Bottom; } else onSide = false; //torna in coordinate grafiche partRelativeMouseProjection = Utils.ToGraphics(partRelativeMouseProjection, Const.Zoom); } //verifica se il mouse si trova o meno all'interno di una parte e aggiorna noCollision noCollision = true; foreach (FParte parte in partList) { Vector2 partRelativeMousePos = Utils.InvTranslateAndRotate(mousePos, Utils.ToGraphics(parte.Position, Const.Zoom), parte.Rotation); if ((Math.Abs(partRelativeMousePos.X) <= (Utils.ToGraphics(parte.BodySize, Const.Zoom).X / 2)) && (Math.Abs(partRelativeMousePos.Y) <= (Utils.ToGraphics(parte.BodySize, Const.Zoom).Y) / 2)) { noCollision = false; break; } } #endregion //switch (list.SelectedIndex) switch (comando) { case 0: //creazione blocchi #region Creazione blocchi if (kCurrentState.IsKeyDown(Keys.Space) && kPreviousState.IsKeyUp(Keys.Space) && (mCurrentState.Y <= (Const.ScreenHeigh - Const.ControlsAreaHeigh))) { //creazione di un blocco inizialmente fermo nella posizione attuale del mouse, premendo spazio Fixture newBlock = FixtureFactory.CreateRectangle(world, rectangleSize.X, rectangleSize.Y, 0.01f, Utils.ToPhysics(mousePos, Const.Zoom)); newBlock.Body.BodyType = BodyType.Dynamic; newBlock.Restitution = 0.4f; newBlock.Friction = 0.3f; blocks.Add(newBlock); } if ((mCurrentState.LeftButton == ButtonState.Pressed) && (mPreviousState.LeftButton == ButtonState.Released) && (mCurrentState.Y <= (Const.ScreenHeigh - Const.ControlsAreaHeigh))) { //punto di rilascio del blocco con velocità iniziale non nulla e punto d'inizio del vettore immaginario che ne definisce il vettore velocità start = Utils.ToPhysics(mousePos, Const.Zoom); started = true; } else if ((mCurrentState.LeftButton == ButtonState.Released) && (mPreviousState.LeftButton == ButtonState.Pressed) && started) { //ho rilasciato il mouse sx -> crea il blocco started = false; end = Utils.ToPhysics(mousePos, Const.Zoom); Fixture newBlock = FixtureFactory.CreateRectangle(world, rectangleSize.X, rectangleSize.Y, Const.PartDensity, new Vector2(start.X, start.Y)); newBlock.Body.BodyType = BodyType.Dynamic; newBlock.Restitution = 0.4f; newBlock.Friction = 0.3f; newBlock.Body.IsBullet = true; newBlock.Body.LinearVelocity = (end - start); blocks.Add(newBlock); } if ((mCurrentState.RightButton == ButtonState.Released) && (mPreviousState.RightButton == ButtonState.Pressed) && (mCurrentState.Y < (Const.ScreenHeigh - Const.ControlsAreaHeigh))) createExplosion(mousePos / Const.Zoom, blocks); #endregion break; case 1: //manipolazione creatura #region Creazione nuova parte if ((mCurrentState.LeftButton == ButtonState.Pressed) && (mCurrentState.Y < (Const.ScreenHeigh - Const.ControlsAreaHeigh))) if ((mPreviousState.LeftButton == ButtonState.Released) && noCollision) { //ho appena premuto il tasto sx del mouse e non sono in area controlli //-> se il mouse non si trova all'interno di una parte inizia a disegnarne una nuova partWhileDrawed = new Rectangle(Convert.ToInt32(mousePos.X), Convert.ToInt32(mousePos.Y), 1, 1); drawingPart = true; } else { //sto tenendo premuto il tasto sx -> aggiorna partWhileDrawed if (mousePos.X > partWhileDrawed.X) partWhileDrawed.Width = Convert.ToInt32(mousePos.X - partWhileDrawed.X); else { int temp = partWhileDrawed.X; partWhileDrawed.X = Convert.ToInt32(mousePos.X); partWhileDrawed.Width = Convert.ToInt32(mousePos.X) - temp; } if (mousePos.Y > partWhileDrawed.Y) partWhileDrawed.Height = Convert.ToInt32(mousePos.Y) - partWhileDrawed.Y; else { int temp = partWhileDrawed.Y; partWhileDrawed.Y = Convert.ToInt32(mousePos.Y); partWhileDrawed.Height = Convert.ToInt32(mousePos.Y) - temp; } } else if (drawingPart) //else di if(mCurrentState.LeftButton == Pressed) ecc. { //ho appena rilasciato il tasto sx e stavo creando una nuova parte -> la crea drawingPart = false; Vector2 partSize = Utils.ToPhysics(new Vector2(partWhileDrawed.Width, partWhileDrawed.Height), Const.Zoom); Vector2 partPosition = Utils.ToPhysics(new Vector2(partWhileDrawed.Center.X, partWhileDrawed.Center.Y), Const.Zoom); if ((partSize.X >= 0.05f) && (partSize.Y >= 0.05f)) //crea la parte solo se è sufficientemente grande, per evitare di causare blocchi del programma { FParte newPart = new FParte(partSize, partPosition, Const.PartDensity, world, Color.Blue, Color.White); if (moving) newPart.BodyType = BodyType.Dynamic; else newPart.BodyType = BodyType.Static; partList.Add(newPart); } } #endregion #region Creazione giunti if (!pendingJoint) //se devo ancora iniziare a creare il giunto { if ((mCurrentState.RightButton == ButtonState.Pressed) && (mCurrentState.Y <= (Const.ScreenHeigh - Const.ControlsAreaHeigh)) && !moving) { if ((mPreviousState.RightButton == ButtonState.Released) && onSide && !creatingJoint) { //ho appena cliccato col tasto dx e sono correttamente aggangiato sul bordo della parte selezionata //-> inizio a creare il giunto creatingJoint = true; part1 = selectedPart; part1JointPos = new Vector2(partRelativeMouseProjection.X, partRelativeMouseProjection.Y); //(in coordinate grafiche e riferito alla posizione di part1) } else if (noCollision && creatingJoint) { //il mouse è ancora premuto, quindi sto trascinando per determinare la dimensione del giunto Vector2 relMousePos = Utils.InvTranslateAndRotate(mousePos, Utils.ToGraphics(part1.Position, Const.Zoom), part1.Rotation); Vector2 relMousePosPhysics = Utils.ToPhysics(relMousePos, Const.Zoom); Vector2 part1JointPosPhysics = Utils.ToPhysics(part1JointPos, Const.Zoom); if ((projectionSide == Side.Right) && (relMousePosPhysics.X > (part1.BodySize.X / 2))) { //bordo destro della parte jointRadius = relMousePos.X - part1JointPos.X; if (jointRadius < 0.05f) //per evitare dimensioni nulle o negative jointRadius = 0.05f; //centro del giunto in coordinate grafiche e assolute jointCenter = Utils.TranslateAndRotate(part1JointPos + new Vector2(jointRadius, 0), Utils.ToGraphics(part1.Position, Const.Zoom), part1.Rotation); } else if ((projectionSide == Side.Left) && (relMousePosPhysics.X < -(part1.BodySize.X / 2))) { //bordo sinistro della parte jointRadius = part1JointPos.X - relMousePos.X; if (jointRadius < 0.05f) jointRadius = 0.05f; jointCenter = Utils.TranslateAndRotate(part1JointPos - new Vector2(jointRadius, 0), Utils.ToGraphics(part1.Position, Const.Zoom), part1.Rotation); } else if ((projectionSide == Side.Bottom) && (relMousePosPhysics.Y > (part1.BodySize.Y / 2))) { //bordo inferiore della parte jointRadius = relMousePos.Y - part1JointPos.Y; if (jointRadius < 0.05f) jointRadius = 0.05f; jointCenter = Utils.TranslateAndRotate(part1JointPos + new Vector2(0, jointRadius), Utils.ToGraphics(part1.Position, Const.Zoom), part1.Rotation); } else if ((projectionSide == Side.Top) && (relMousePosPhysics.Y < -(part1.BodySize.Y / 2))) { //bordo superiore della parte jointRadius = part1JointPos.Y - relMousePos.Y; if (jointRadius < 0.05f) jointRadius = 0.05f; jointCenter = Utils.TranslateAndRotate(part1JointPos - new Vector2(0, jointRadius), Utils.ToGraphics(part1.Position, Const.Zoom), part1.Rotation); } } } else if (creatingJoint) { //ho appena rilasciato il tasto dx -> il giunto ha le dimensioni definitive creatingJoint = false; pendingJoint = true; } } //-> pendingJoint è true -> il giunto è già stato creato, occorre scegliere la seconda parte else if ((mCurrentState.RightButton == ButtonState.Pressed) && (mCurrentState.Y <= (Const.ScreenHeigh - Const.ControlsAreaHeigh)) && !moving && (mPreviousState.RightButton == ButtonState.Released) && onSide && (selectedPart != part1)) { Vector2 part2JointPosPhysics = Utils.ToPhysics(partRelativeMouseProjection, Const.Zoom); Vector2 part1JointPosPhysics = Utils.ToPhysics(part1JointPos, Const.Zoom); selectedPart.Join(part1, part2JointPosPhysics, part1JointPosPhysics, Color.Aqua, jointRadius / Const.Zoom); pendingJoint = false; } #endregion break; } //applica le forze ai muscoli della parte selezionata, se possiede un Actuator (cioè se è una parte figlia) if ((selectedPart != null) && moving && (selectedPart.PartActuator != null)) { if (muscoli) selectedPart.PartMotionSystem = MotionSystem.Actuator; else selectedPart.PartMotionSystem = MotionSystem.Motor; if (kCurrentState.IsKeyDown(Keys.M)) selectedPart.ApplyMotion(1.0f); else if (kCurrentState.IsKeyDown(Keys.N)) selectedPart.ApplyMotion(-1.0f); else selectedPart.ApplyMotion(0.0f); } foreach (FParte part in partList) part.UpdateCollisionPoints(); } world.Step((float)gameTime.ElapsedGameTime.TotalMilliseconds / 1000); kPreviousState = kCurrentState; mPreviousState = mCurrentState; base.Update(gameTime); }
/* 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(FParte 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(FParte parteFiglio, FParte 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(FParte part) { ChildParts.Add(part); }