diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index 05fabc7..affba3d 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -90,16 +90,16 @@ namespace CtrEditor double topPixels = centerY - (userControl.ActualHeight / 2); // Establece la posición del UserControl - NuevoOS.LeftPixels = (float)leftPixels; - NuevoOS.TopPixels = (float)topPixels; + NuevoOS.Left = PixelToMeter.Instance.calc.PixelsToMeters((float)leftPixels); + NuevoOS.Top = PixelToMeter.Instance.calc.PixelsToMeters((float)topPixels); NuevoOS.Inicializado = true; } else { // Fuerza a Establecer la posición del UserControl - NuevoOS.LeftPixels = NuevoOS.LeftPixels; - NuevoOS.TopPixels = NuevoOS.TopPixels; + NuevoOS.Left = NuevoOS.Left; + NuevoOS.Top = NuevoOS.Top; } // Suscribirse a eventos de mouse para marcar el Control diff --git a/ObjetosSim/UserControlFactory.cs b/ObjetosSim/UserControlFactory.cs index 073dbcc..173e0ed 100644 --- a/ObjetosSim/UserControlFactory.cs +++ b/ObjetosSim/UserControlFactory.cs @@ -16,6 +16,8 @@ namespace CtrEditor.ObjetosSim return new ucBotella(); if (tipoObjeto == typeof(osTransporteTTop)) return new ucTransporteTTop(); + if (tipoObjeto == typeof(osGuia)) + return new ucGuia(); // Puedes añadir más condiciones para otros tipos @@ -28,6 +30,8 @@ namespace CtrEditor.ObjetosSim return new osBotella(); if (tipoObjeto == typeof(osTransporteTTop)) return new osTransporteTTop(); + if (tipoObjeto == typeof(osGuia)) + return new osGuia(); // Puedes añadir más condiciones para otros tipos diff --git a/ObjetosSim/osBase.cs b/ObjetosSim/osBase.cs index fb761af..61921d5 100644 --- a/ObjetosSim/osBase.cs +++ b/ObjetosSim/osBase.cs @@ -1,4 +1,5 @@ -using System; +using Newtonsoft.Json.Linq; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; @@ -13,6 +14,8 @@ using static System.Runtime.InteropServices.JavaScript.JSType; namespace CtrEditor.ObjetosSim { + + public interface IosBase { string Nombre { get; } @@ -33,8 +36,6 @@ namespace CtrEditor.ObjetosSim public abstract class osBase : INotifyPropertyChanged, IosBase { - public abstract float LeftPixels { get; set; } - public abstract float TopPixels { get; set; } public abstract float Left { get; set; } public abstract float Top { get; set; } @@ -54,6 +55,18 @@ namespace CtrEditor.ObjetosSim set => _visualRepresentation = value; } + public void CanvasSetLeftinMeter(float left) + { + if (_visualRepresentation != null) + Canvas.SetLeft(_visualRepresentation, PixelToMeter.Instance.calc.MetersToPixels(left)); + } + public void CanvasSetTopinMeter(float top) + { + if (_visualRepresentation != null) + Canvas.SetTop(_visualRepresentation, PixelToMeter.Instance.calc.MetersToPixels(top)); + } + + public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) @@ -97,6 +110,22 @@ namespace CtrEditor.ObjetosSim } } + public class MeterToPixelConverterDbl : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + double meters = (double)value; + return (double)PixelToMeter.Instance.calc.MetersToPixels((float)meters); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + double pixels = (double)value; + return PixelToMeter.Instance.calc.PixelsToMeters((float)pixels); + } + } + + public class UnitConverter { // La escala representa cuántos metros hay en un píxel diff --git a/ObjetosSim/ucBotella.xaml b/ObjetosSim/ucBotella.xaml index 8894b38..eab4021 100644 --- a/ObjetosSim/ucBotella.xaml +++ b/ObjetosSim/ucBotella.xaml @@ -1,6 +1,12 @@  - + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:local="clr-namespace:CtrEditor.ObjetosSim"> + + + + \ No newline at end of file diff --git a/ObjetosSim/ucBotella.xaml.cs b/ObjetosSim/ucBotella.xaml.cs index f5ecb65..f44d859 100644 --- a/ObjetosSim/ucBotella.xaml.cs +++ b/ObjetosSim/ucBotella.xaml.cs @@ -23,97 +23,57 @@ namespace CtrEditor.ObjetosSim public class osBotella : osBase { - private Circle Data = new Circle(); + private Circle Geometria = new Circle(); // Otros datos y métodos relevantes para la simulación private string _nombre = "Botella"; public float Diametro { - get => Data.Diameter; + get => Geometria.Diameter; set { - Data.Diameter = value; + Geometria.Diameter = value; OnPropertyChanged(nameof(Diametro)); - OnPropertyChanged(nameof(DiametroPixels)); - } - } - public float DiametroPixels - { - get => PixelToMeter.Instance.calc.MetersToPixels(Data.Diameter); - set - { - Data.Diameter = PixelToMeter.Instance.calc.PixelsToMeters(value); - OnPropertyChanged(nameof(Diametro)); - OnPropertyChanged(nameof(DiametroPixels)); } } public float Mass { - get => Data.Mass; + get => Geometria.Mass; set { - Data.Mass = value; + Geometria.Mass = value; OnPropertyChanged(nameof(Mass)); } } public float Overlap { - get => Data.Overlap; + get => Geometria.Overlap; set { - Data.Overlap = value; + Geometria.Overlap = value; OnPropertyChanged(nameof(Overlap)); } } - - public override float LeftPixels - { - get => PixelToMeter.Instance.calc.MetersToPixels(Data.Left); - set - { - Data.Left = PixelToMeter.Instance.calc.PixelsToMeters(value); - if (_visualRepresentation != null) - Canvas.SetLeft(_visualRepresentation, value); - OnPropertyChanged(nameof(LeftPixels)); - OnPropertyChanged(nameof(Left)); - } - } - public override float TopPixels - { - get => PixelToMeter.Instance.calc.MetersToPixels(Data.Top); - set - { - Data.Top = PixelToMeter.Instance.calc.PixelsToMeters(value); - if (_visualRepresentation != null) - Canvas.SetTop(_visualRepresentation,value); - OnPropertyChanged(nameof(TopPixels)); - OnPropertyChanged(nameof(Top)); - } - } public override float Left { - get => Data.Left; + get => Geometria.Left; set { - Data.Left = value; - if (_visualRepresentation != null) - Canvas.SetLeft(_visualRepresentation, PixelToMeter.Instance.calc.MetersToPixels(value)); - OnPropertyChanged(nameof(LeftPixels)); + Geometria.Left = value; + CanvasSetLeftinMeter(value); OnPropertyChanged(nameof(Left)); } } public override float Top { - get => Data.Top; + get => Geometria.Top; set { - Data.Top = value; - if (_visualRepresentation != null) - Canvas.SetTop(_visualRepresentation, PixelToMeter.Instance.calc.MetersToPixels(value)); - OnPropertyChanged(nameof(TopPixels)); + Geometria.Top = value; + CanvasSetTopinMeter(value); OnPropertyChanged(nameof(Top)); } } @@ -133,19 +93,19 @@ namespace CtrEditor.ObjetosSim public osBotella() { - DiametroPixels = 10; + Diametro = 0.10f; } public override void ConnectSimManager(SimulationManager simulationManager) { - simulationManager.circles.Add(Data); + simulationManager.circles.Add(Geometria); } public override void UpdateControl() { - Top = Data.Top; - Left = Data.Left; - Overlap = Data.Overlap; + Top = Geometria.Top; + Left = Geometria.Left; + Overlap = Geometria.Overlap; } } @@ -162,8 +122,8 @@ namespace CtrEditor.ObjetosSim { if (Datos != null) { - Datos.LeftPixels = LeftPixels; - Datos.TopPixels = TopPixels; + Datos.Left = PixelToMeter.Instance.calc.PixelsToMeters(LeftPixels); + Datos.Top = PixelToMeter.Instance.calc.PixelsToMeters(TopPixels); } } public void Rotate(float Angle) { } diff --git a/ObjetosSim/ucGuia.xaml b/ObjetosSim/ucGuia.xaml new file mode 100644 index 0000000..65e2867 --- /dev/null +++ b/ObjetosSim/ucGuia.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + diff --git a/ObjetosSim/ucGuia.xaml.cs b/ObjetosSim/ucGuia.xaml.cs new file mode 100644 index 0000000..e67fa35 --- /dev/null +++ b/ObjetosSim/ucGuia.xaml.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace CtrEditor.ObjetosSim +{ + /// + /// Interaction logic for ucGuia.xaml + /// + public class osGuia : osBase + { + private string _nombre = "Guia"; + + private Line Geometria = new Line(); + + public override float Left + { + get => Geometria.Left; + set + { + Geometria.Left = value; + CanvasSetLeftinMeter(value); + OnPropertyChanged(nameof(Left)); + } + } + public override float Top + { + get => Geometria.Top; + set + { + Geometria.Top = value; + CanvasSetTopinMeter(value); + OnPropertyChanged(nameof(Top)); + } + } + + public float Ancho + { + get => Geometria.Length; + set + { + Geometria.Length = value; + OnPropertyChanged(nameof(Ancho)); + } + } + public float Alto + { + get => Geometria.Width; + set + { + Geometria.Width = value; + OnPropertyChanged(nameof(Alto)); + } + } + + public float Angulo + { + get => Geometria.Angle; + set + { + Geometria.Angle = value; + OnPropertyChanged(nameof(Angulo)); + } + } + + public override string Nombre + { + get => _nombre; + set + { + if (_nombre != value) + { + _nombre = value; + OnPropertyChanged(nameof(Nombre)); + } + } + } + + public osGuia() + { + Ancho = 1; + Alto = 0.10f; + } + + public override void ConnectSimManager(SimulationManager simulationManager) + { + simulationManager.lines.Add(Geometria); + } + public override void UpdateControl() + { + } + + } + + public partial class ucGuia : UserControl, IDataContainer + { + public osBase? Datos { get; set; } + + public ucGuia() + { + InitializeComponent(); + } + public void Resize(float width, float height) + { + if (Datos is osGuia datos) + datos.Ancho = PixelToMeter.Instance.calc.PixelsToMeters(width); + } + public void Move(float LeftPixels, float TopPixels) + { + if (Datos != null) + { + Datos.Left = PixelToMeter.Instance.calc.PixelsToMeters(LeftPixels); + Datos.Top = PixelToMeter.Instance.calc.PixelsToMeters(TopPixels); + } + } + public void Rotate(float Angle) + { + if (Datos != null) + if (Datos is osGuia datos) + datos.Angulo = Angle; + } + public void Highlight(bool State) { } + public int ZIndex() + { + return 1; + } + + } +} diff --git a/ObjetosSim/ucTransporteGuias.xaml b/ObjetosSim/ucTransporteGuias.xaml new file mode 100644 index 0000000..4385360 --- /dev/null +++ b/ObjetosSim/ucTransporteGuias.xaml @@ -0,0 +1,13 @@ + + + + + + diff --git a/ObjetosSim/ucTransporteGuias.xaml.cs b/ObjetosSim/ucTransporteGuias.xaml.cs new file mode 100644 index 0000000..7f86251 --- /dev/null +++ b/ObjetosSim/ucTransporteGuias.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace CtrEditor.ObjetosSim +{ + /// + /// Interaction logic for ucTransporteGuias.xaml + /// + public partial class ucTransporteGuias : UserControl + { + public ucTransporteGuias() + { + InitializeComponent(); + } + } +} diff --git a/ObjetosSim/ucTransporteTTop.xaml b/ObjetosSim/ucTransporteTTop.xaml index 5bb63eb..94af971 100644 --- a/ObjetosSim/ucTransporteTTop.xaml +++ b/ObjetosSim/ucTransporteTTop.xaml @@ -3,10 +3,15 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:local="clr-namespace:CtrEditor" - mc:Ignorable="d"> + mc:Ignorable="d" + xmlns:local="clr-namespace:CtrEditor.ObjetosSim"> + + + + + - + diff --git a/ObjetosSim/ucTransporteTTop.xaml.cs b/ObjetosSim/ucTransporteTTop.xaml.cs index 946e5b3..4946856 100644 --- a/ObjetosSim/ucTransporteTTop.xaml.cs +++ b/ObjetosSim/ucTransporteTTop.xaml.cs @@ -32,111 +32,60 @@ namespace CtrEditor.ObjetosSim private float tiempoRampa; private bool esMarcha; - private Rectangle Data = new Rectangle(); + private Rectangle Geometria = new Rectangle(); - public override float LeftPixels - { - get => PixelToMeter.Instance.calc.MetersToPixels(Data.Left); - set - { - Data.Left = PixelToMeter.Instance.calc.PixelsToMeters(value); - if (_visualRepresentation != null ) - Canvas.SetLeft(_visualRepresentation,value); - OnPropertyChanged(nameof(LeftPixels)); - OnPropertyChanged(nameof(Left)); - } - } - public override float TopPixels - { - get => PixelToMeter.Instance.calc.MetersToPixels(Data.Top); - set - { - Data.Top = PixelToMeter.Instance.calc.PixelsToMeters(value); - if (_visualRepresentation != null) - Canvas.SetTop(_visualRepresentation, value); - OnPropertyChanged(nameof(TopPixels)); - OnPropertyChanged(nameof(Top)); - } - } public override float Left { - get => Data.Left; + get => Geometria.Left; set { - Data.Left = value; - if (_visualRepresentation != null) - Canvas.SetLeft(_visualRepresentation, PixelToMeter.Instance.calc.MetersToPixels(value)); - OnPropertyChanged(nameof(LeftPixels)); + Geometria.Left = value; + CanvasSetLeftinMeter(value); OnPropertyChanged(nameof(Left)); } } public override float Top { - get => Data.Top; + get => Geometria.Top; set { - Data.Top = value; - if (_visualRepresentation != null) - Canvas.SetTop(_visualRepresentation, PixelToMeter.Instance.calc.MetersToPixels(value)); - OnPropertyChanged(nameof(TopPixels)); + Geometria.Top = value; + CanvasSetTopinMeter(value); OnPropertyChanged(nameof(Top)); } } - public float Ancho { - get => Data.Length; + get => Geometria.Length; set { - Data.Length = value; - OnPropertyChanged(nameof(AnchoPixels)); + Geometria.Length = value; OnPropertyChanged(nameof(Ancho)); } } public float Alto { - get => Data.Width; + get => Geometria.Width; set { - Data.Width = value; - OnPropertyChanged(nameof(AltoPixels)); + Geometria.Width = value; OnPropertyChanged(nameof(Alto)); } } - public float AnchoPixels - { - get => (float)PixelToMeter.Instance.calc.MetersToPixels(Data.Length); - set - { - Data.Length = (float)PixelToMeter.Instance.calc.PixelsToMeters(value); - OnPropertyChanged(nameof(AnchoPixels)); - OnPropertyChanged(nameof(Ancho)); - } - } - public float AltoPixels - { - get => (float)PixelToMeter.Instance.calc.MetersToPixels(Data.Width); - set - { - Data.Width = (float)PixelToMeter.Instance.calc.PixelsToMeters(value); - OnPropertyChanged(nameof(AltoPixels)); - OnPropertyChanged(nameof(Alto)); - } - } public float Angulo { - get => Data.Angle; + get => Geometria.Angle; set { - Data.Angle = value; + Geometria.Angle = value; OnPropertyChanged(nameof(Angulo)); } } public float VelocidadActual { - get => Data.Speed; + get => Geometria.Speed; set { - Data.Speed = value; + Geometria.Speed = value; OnPropertyChanged(nameof(VelocidadActual)); } } @@ -161,13 +110,13 @@ namespace CtrEditor.ObjetosSim public osTransporteTTop() { - AnchoPixels = 100; - AltoPixels = 10; + Ancho = 1; + Alto = 0.10f; } public override void ConnectSimManager(SimulationManager simulationManager) { - simulationManager.rectangles.Add(Data); + simulationManager.rectangles.Add(Geometria); } public override void UpdateControl() { @@ -186,14 +135,14 @@ namespace CtrEditor.ObjetosSim public void Resize(float width, float height) { if (Datos is osTransporteTTop datos) - datos.AnchoPixels = width; + datos.Ancho = PixelToMeter.Instance.calc.PixelsToMeters(width); } public void Move(float LeftPixels, float TopPixels) { if (Datos != null) { - Datos.LeftPixels = LeftPixels; - Datos.TopPixels = TopPixels; + Datos.Left = PixelToMeter.Instance.calc.PixelsToMeters(LeftPixels); + Datos.Top = PixelToMeter.Instance.calc.PixelsToMeters(TopPixels); } } public void Rotate(float Angle) { diff --git a/Simulacion/GeometrySimulator.cs b/Simulacion/GeometrySimulator.cs index 533411d..58a79a1 100644 --- a/Simulacion/GeometrySimulator.cs +++ b/Simulacion/GeometrySimulator.cs @@ -76,53 +76,99 @@ public class Circle if (Speed < 0) Speed = 0; // Evitar que la velocidad sea negativa } - //// Interacción por impacto con otros círculos - //foreach (var other in circles) - //{ - // if (this != other && IsColliding(this, other)) - // { - // Vector2 impactDirection = other.position - this.position; - // Angle = (float)Math.Atan2(impactDirection.Y, impactDirection.X) * (180 / (float)Math.PI); - // Speed = other.Speed; // Asumimos que el círculo receptor adopta la velocidad del impacto - // } - //} - - // Ajustar por superposición con otros círculos - foreach (var other in circles) - { - if (this != other && IsColliding(this, other)) - { - AdjustForOverlap(other); - } - } - - // Cambiar dirección al contacto con líneas - foreach (var line in lines) - { - if (IsCollidingWithLine(this, line)) - { - float impactAngle = CalculateImpactAngle(this, line); - if (impactAngle < 85) - { - AngleofMovement = line.Angle; - } - else if (impactAngle > 95) - { - AngleofMovement = line.Angle + 180; // Movimiento contrario - } - else - { - Speed = 0; // Cancelación de movimiento - } - } - } - // Calcular nueva posición Vector2 direction = new Vector2((float)Math.Cos(AngleofMovement * Math.PI / 180), (float)Math.Sin(AngleofMovement * Math.PI / 180)); Vector2 velocity = direction * Speed * timeStepInSeconds; position += velocity; + + // Ajustar por colisiones con líneas + foreach (var line in lines) + { + Vector2 movementVector = Vector2FromPolar(Speed, AngleofMovement); + Vector2 circleCenter = GetCircleCenter(this); + + // Calcular la nueva posición tentativa del centro del círculo + Vector2 newPosition = circleCenter + movementVector * timeStepInSeconds; + + if (LineCircleCollision(newPosition, Diameter / 2, line, out Vector2 collisionPoint)) + { + // Ajustar la posición del centro del círculo y el vector de movimiento + AdjustCircleAfterCollision(ref newPosition, ref movementVector, line, collisionPoint, Diameter / 2); + } + + // Actualizar la posición del círculo basada en el nuevo centro + Left = newPosition.X - Diameter / 2; + Top = newPosition.Y - Diameter / 2; + Speed = movementVector.Length(); + AngleofMovement = PolarAngleFromVector(movementVector); + } } + Vector2 GetCircleCenter(Circle circle) + { + return new Vector2(circle.Left + circle.Diameter / 2, circle.Top + circle.Diameter / 2); + } + + + private bool LineCircleCollision(Vector2 circleCenter, float radius, Line line, out Vector2 collisionPoint) + { + // Transformar la línea a un vector con el ángulo rotado + float angleRadians = line.Angle * (float)Math.PI / 180; + Vector2 lineDirection = new Vector2( + (float)Math.Cos(angleRadians), + (float)Math.Sin(angleRadians) + ); + + // Calcular los puntos de inicio y fin de la línea + Vector2 lineStart = new Vector2(line.Left, line.Top); + Vector2 lineEnd = lineStart + lineDirection * line.Length; + + // Encontrar el punto más cercano del centro del círculo a la línea + Vector2 lineToCircle = circleCenter - lineStart; + float projection = Vector2.Dot(lineToCircle, lineDirection); + projection = Math.Clamp(projection, 0, line.Length); + Vector2 closestPointOnLine = lineStart + projection * lineDirection; + + // Calcular la distancia entre el círculo y el punto más cercano + float distance = Vector2.Distance(circleCenter, closestPointOnLine); + collisionPoint = closestPointOnLine; + + // Verificar si hay colisión + return distance <= radius; + } + + private void AdjustCircleAfterCollision(ref Vector2 circlePosition, ref Vector2 movementVector, Line line, Vector2 collisionPoint, float radius) + { + // Calcular el vector normal de la línea para reflejar la dirección de movimiento del círculo + float angleRadians = line.Angle * (float)Math.PI / 180; + Vector2 lineNormal = new Vector2(-(float)Math.Sin(angleRadians), (float)Math.Cos(angleRadians)); + + // Asegurar que la normal está correctamente orientada hacia fuera de la línea + if (Vector2.Dot(lineNormal, circlePosition - collisionPoint) < 0) + lineNormal = -lineNormal; + + // Calcular el desplazamiento necesario para separar el círculo de la línea + Vector2 displacement = lineNormal * (radius - Vector2.Distance(circlePosition, collisionPoint)); + circlePosition += displacement; + + // Opcionalmente, ajustar la velocidad si el círculo debe "rebotar" de la línea + movementVector = Vector2.Reflect(movementVector, lineNormal); + } + + + private Vector2 Vector2FromPolar(float speed, float angleDegrees) + { + float angleRadians = angleDegrees * (float)Math.PI / 180; + return new Vector2( + speed * (float)Math.Cos(angleRadians), + speed * (float)Math.Sin(angleRadians) + ); + } + + private float PolarAngleFromVector(Vector2 vector) + { + return (float)Math.Atan2(vector.Y, vector.X) * 180 / (float)Math.PI; + } private void AdjustForOverlap(Circle other) @@ -165,38 +211,7 @@ public class Circle return distance <= radiusSum; } - private bool IsCollidingWithLine(Circle circle, Line line) - { - Vector2 nearestPoint = NearestPointOnLine(circle.position, line.start, line.end); - float distanceToLine = Vector2.Distance(circle.position, nearestPoint); - return distanceToLine <= (circle.Diameter / 2); - } - - private Vector2 NearestPointOnLine(Vector2 point, Vector2 lineStart, Vector2 lineEnd) - { - Vector2 lineVector = lineEnd - lineStart; - Vector2 pointVector = point - lineStart; - float lineLength = lineVector.Length(); - float projectedLength = Vector2.Dot(pointVector, lineVector) / lineLength; - projectedLength = Math.Max(0, Math.Min(lineLength, projectedLength)); // Clamping to the line segment - return lineStart + lineVector * (projectedLength / lineLength); - } - - private float CalculateImpactAngle(Circle circle, Line line) - { - Vector2 movementDirection = new Vector2((float)Math.Cos(circle.AngleofMovement * Math.PI / 180), (float)Math.Sin(circle.AngleofMovement * Math.PI / 180)); - Vector2 lineDirection = line.end - line.start; - Vector2 lineNormal = new Vector2(-lineDirection.Y, lineDirection.X); // Rotar 90 grados para obtener normal - lineNormal = Vector2.Normalize(lineNormal); - - // Calcular ángulo entre el movimiento y la normal de la línea - float dotProduct = Vector2.Dot(movementDirection, lineNormal); - float angle = (float)Math.Acos(dotProduct) * (180 / (float)Math.PI); // Convertir de radianes a grados - - // Ajustar para obtener el ángulo relativo correcto - return angle < 90 ? 90 - angle : angle - 90; - } - + // Circulos sobre Rectangulos public static float CalculateOverlapPercentage(Circle circle, Rectangle rectangle) { // Convertir el círculo en un cuadrado aproximado. @@ -284,37 +299,28 @@ public class Rectangle public class Line { - public Vector2 start; - public Vector2 end; - + private Vector2 position; public float Left { - get { return start.X; } - set { start = new Vector2(value, start.Y); UpdateEnd(); } + get { return position.X; } + set { position = new Vector2(value, position.Y); } } public float Top { - get { return start.Y; } - set { start = new Vector2(start.X, value); UpdateEnd(); } + get { return position.Y; } + set { position = new Vector2(position.X, value); } } public float Length { get; set; } public float Width { get; set; } public float Angle { get; set; } // En grados + public float Grip { get; set; } // Friccion por contacto - public Line(float left, float top, float length, float width, float angle) + public Line(float left = 0, float top = 0, float length = 10, float angle = 0, float grip = 0) { - start = new Vector2(left, top); + position = new Vector2(left, top); Length = length; - Width = width; Angle = angle; - UpdateEnd(); - } - - private void UpdateEnd() - { - // Asumiendo que la línea se extiende en el ángulo desde el punto de inicio - end = new Vector2(start.X + Length * (float)Math.Cos(Angle * Math.PI / 180), - start.Y + Length * (float)Math.Sin(Angle * Math.PI / 180)); + Grip = grip; } }