-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSpaceObject.cs
More file actions
109 lines (87 loc) · 3.92 KB
/
SpaceObject.cs
File metadata and controls
109 lines (87 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
namespace Gravity_Simulation
{
public class SpaceObject(string? name, Vector pos, Vector inertia, double mass, double radius)
{
public string? Name { get; set; } = name;
public Vector Pos { get; set; } = pos;
public Vector Inertia { get; set; } = inertia;
public double Mass { get; } = mass;
public double Radius { get; } = radius;
#region const
public const double G = 6.67408e-11;
#endregion
#region formulas
public double GravitationalForce(double m1, double m2, double r)
{
if (r == 0) throw new ArgumentException("Invalid args");
return G * (m1 * m2) / (r * r);
}
public static double CalculateAcceleration(double mass, double force)
{
if (mass == 0) throw new ArgumentException("Invalid args");
return force / mass; // a = F / m
}
#endregion
public void Draw(Graphics g, float scale, Vector cameraPosition)
{
var screenSize = Screen.PrimaryScreen?.Bounds.Size ?? new Size(800, 600);
float x = (float)((Pos.X - cameraPosition.X) * scale) + (screenSize.Width / 2);
float y = (float)((Pos.Y - cameraPosition.Y) * scale) + (screenSize.Height / 2);
float diameter = (float)(Radius * scale);
if (diameter > 0)
{
g.FillEllipse(Brushes.Blue, x - diameter / 2, y - diameter / 2, diameter, diameter);
DrawName(g, scale, x, y);
}
DrawInertionArrow(g, scale, x, y);
}
public void ApplyGravity(SpaceObject obj, double deltaTime)
{
Vector difference = obj.Pos - Pos;
double distance = difference.Length();
double forceMagnitude = GravitationalForce(Mass, obj.Mass, distance);
if (forceMagnitude > 0 && distance > 0)
{
Vector direction = new(obj.Pos.X - Pos.X, obj.Pos.Y - Pos.Y);
direction.Normalize();
double acceleration = CalculateAcceleration(Mass, forceMagnitude);
Inertia.X += direction.X * acceleration * deltaTime;
Inertia.Y += direction.Y * acceleration * deltaTime;
}
}
public void DrawName(Graphics g, float scale, float x, float y)
{
float fontSize = 12f * scale;
if (fontSize < 6f) fontSize = 6f;
using Font font = new("Arial", fontSize);
using Brush brush = new SolidBrush(Color.White);
g.DrawString(Name, font, brush, x, y - (float)(Radius * scale) / 2 - fontSize);
}
private void DrawInertionArrow(Graphics g, float scale, float x, float y)
{
if(Inertia.X == 0 && Inertia.Y == 0) return;
float arrowLength = 50f;
float endX = x + (float)Inertia.X * arrowLength * scale;
float endY = y + (float)Inertia.Y * arrowLength * scale;
g.DrawLine(Pens.Red, x, y, endX, endY);
DrawArrowHead(g, x, y, endX, endY);
}
private static void DrawArrowHead(Graphics g, float xStart, float yStart, float xEnd, float yEnd)
{
var arrowAngle = Math.Atan2(yEnd - yStart, xEnd - xStart);
var arrowSize = 10;
float leftX = (float)(xEnd - arrowSize * Math.Cos(arrowAngle - Math.PI / 6));
float leftY = (float)(yEnd - arrowSize * Math.Sin(arrowAngle - Math.PI / 6));
float rightX = (float)(xEnd - arrowSize * Math.Cos(arrowAngle + Math.PI / 6));
float rightY = (float)(yEnd - arrowSize * Math.Sin(arrowAngle + Math.PI / 6));
g.DrawLine(Pens.Red, xEnd, yEnd, leftX, leftY);
g.DrawLine(Pens.Red, xEnd, yEnd, rightX, rightY);
}
public void UpdatePosition(double deltaTime)
{
Pos.X += Inertia.X * deltaTime;
Pos.Y += Inertia.Y * deltaTime;
}
}
}