203 lines
6.1 KiB
C#
203 lines
6.1 KiB
C#
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<Circle> circles, List<Rectangle> rectangles, List<Line> 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<Circle> circles;
|
|
public List<Rectangle> rectangles;
|
|
public List<Line> lines;
|
|
|
|
public SimulationManager()
|
|
{
|
|
circles = new List<Circle>();
|
|
rectangles = new List<Rectangle>();
|
|
lines = new List<Line>();
|
|
}
|
|
|
|
public void Step(float timeStep)
|
|
{
|
|
foreach (var circle in circles)
|
|
{
|
|
circle.Move(timeStep, circles, rectangles, lines);
|
|
}
|
|
}
|
|
}
|
|
|
|
|