using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Numerics; // Definición de la clase Circle public class Circle : ObjetoGeometrico { public Vector2 Center { get; set; } public float Diameter { get; set; } public float Mass { get; set; } [JsonIgnore] public Vector2 Velocity { get; set; } public Circle(Vector2 center, float diameter, float mass, Vector2 velocity) { Center = center; Diameter = diameter; Mass = mass; Velocity = velocity; } public Circle() { Center = new Vector2(0,0); Center.X = 0; Diameter = 10; Mass = 1; Velocity = new Vector2(0,0); } // Método para calcular la nueva posición del círculo en función del tiempo public void Move(float timeStep, List circles, List rectangles, List lines) { Vector2 totalForce = new Vector2(0, 0); // Aplicar fuerza de los rectángulos foreach (var rectangle in rectangles) { totalForce += rectangle.ApplyForce(this); } // Aplicar fuerza a otros círculos foreach (var otherCircle in circles) { if (otherCircle != this) { totalForce += ApplyForceToOtherCircle(otherCircle); } } // Aplicar fuerza debido a la inercia (ejemplo simple) Vector2 inertiaForce = -0.1f * Velocity; // coeficiente de inercia totalForce += inertiaForce; // Calcular la aceleración if (Mass <= 0) Mass = 1; Vector2 acceleration = totalForce / Mass; // Actualizar la velocidad y la posición Velocity += acceleration * timeStep / 1000; Center += Velocity * timeStep; // Controlar la colisión con las líneas foreach (var line in lines) { line.HandleCollision(this); } } private Vector2 ApplyForceToOtherCircle(Circle other) { Vector2 direction = other.Center - this.Center; float distance = direction.Length(); float overlap = this.Diameter / 2 + other.Diameter / 2 - distance; if (overlap > 0) { Vector2 forceDirection = Vector2.Normalize(direction); float transferVelocity = 0.5f * this.Velocity.Length(); // Ejemplo de transferencia de parte de la velocidad if (transferVelocity == 0) transferVelocity = 0.01f; other.Velocity += forceDirection * transferVelocity; // Asumiendo una simplificación del impacto return -forceDirection * transferVelocity; // Retorno de fuerza opuesta aplicada a este círculo } return Vector2.Zero; } } // Definición de la clase Rectangle public class Rectangle : ObjetoGeometrico { public Vector2 AnchorPoint { get; set; } public float Left { get; set; } public float Top { get; set; } public float Width { get; set; } public float Height { get; set; } public float Angle { get; set; } public float Speed { get; set; } public Rectangle(Vector2 anchorPoint, float width, float height, float angle) { AnchorPoint = anchorPoint; Width = width; Height = height; Angle = angle; } public Rectangle() { AnchorPoint = new Vector2(0,0); Width = 1; Height = 1; Angle = 0; } public Vector2 ApplyForce(Circle circle) { // Transformar el centro del círculo al sistema de coordenadas del rectángulo Vector2 circlePositionRelative = Vector2.Transform(circle.Center - AnchorPoint, Matrix3x2.CreateRotation(-Angle)); // Verificar si el círculo está dentro del rectángulo float halfWidth = Width / 2; float halfHeight = Height / 2; if (Math.Abs(circlePositionRelative.X) <= halfWidth && Math.Abs(circlePositionRelative.Y) <= halfHeight) { // Calcular fuerza basada en la proximidad al centro del rectángulo float distanceFromCenter = circlePositionRelative.Length(); float forceMagnitude = Math.Max(0, (Width - distanceFromCenter) / Width); // Simplificación de la magnitud de la fuerza Vector2 forceDirection = Vector2.Transform(new Vector2(1, 0), Matrix3x2.CreateRotation(Angle)); // Fuerza en la dirección del rectángulo return forceDirection * forceMagnitude; } return Vector2.Zero; } } // Definición de la clase Line public class Line : ObjetoGeometrico { public Vector2 StartPoint { get; set; } public Vector2 EndPoint { get; set; } public Line(Vector2 startPoint, Vector2 endPoint) { StartPoint = startPoint; EndPoint = endPoint; } public void HandleCollision(Circle circle) { Vector2 closestPoint = ClosestPoint(circle.Center); float radius = circle.Diameter / 2; if (Vector2.Distance(circle.Center, closestPoint) < radius) { Vector2 lineDirection = Vector2.Normalize(EndPoint - StartPoint); Vector2 normal = new Vector2(-lineDirection.Y, lineDirection.X); // Normal perpendicular a la dirección de la línea circle.Velocity = Vector2.Reflect(circle.Velocity, normal); } } private Vector2 ClosestPoint(Vector2 point) { Vector2 AP = point - StartPoint; Vector2 AB = EndPoint - StartPoint; float magnitudeAB = AB.LengthSquared(); float ABAPproduct = Vector2.Dot(AP, AB); float distance = ABAPproduct / magnitudeAB; return StartPoint + AB * Math.Clamp(distance, 0, 1); } } public class ObjetoGeometrico { } // Clase principal que gestiona la simulación public class SimulationManager { public List circles; public List rectangles; public List lines; public SimulationManager() { circles = new List(); rectangles = new List(); lines = new List(); } public void Step(float timeStep) { foreach (var circle in circles) { circle.Move(timeStep, circles, rectangles, lines); } } }