-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPhysics.cs
More file actions
106 lines (95 loc) · 2.92 KB
/
Physics.cs
File metadata and controls
106 lines (95 loc) · 2.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
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Xna.Framework;
namespace StarPong.Framework
{
/// <summary>
/// Applies collision and overlap detection to objects in the scene tree.
/// Only objects in the scene tree (being updated) are tracked.
/// Uses a very naive O(n^2) collision detection scheme.
/// </summary>
public class Physics
{
public static Physics Instance;
Dictionary<CollisionObject, List<CollisionObject>> ActiveCollisions = new();
public Physics()
{
Instance = this;
}
public void Update(float delta)
{
List<GameObject> objects = SceneTree.GetObjectsInGroup("physics");
// Very inefficient collision scheme that does not take into account the
// local position, nor sorting with a quadtree.
for (int i = 0; i < objects.Count; i++)
{
for (int j = i + 1; j < objects.Count; j++)
{
CollisionObject cobj1 = objects[i] as CollisionObject;
CollisionObject cobj2 = objects[j] as CollisionObject;
if (!cobj1.CollisionEnabled || !cobj2.CollisionEnabled) continue;
bool colliding = cobj1.GetBoundingRect().IsOverlapping(cobj2.GetBoundingRect());
bool previouslyColliding = GetCollidingObjects(cobj1).Contains(cobj2);
if (!previouslyColliding && colliding)
{
// TODO: Implement position and normal.
cobj1.OnCollision(Vector2.Zero, Vector2.Zero, cobj2);
cobj2.OnCollision(Vector2.Zero, Vector2.Zero, cobj1);
AddCollision(cobj1, cobj2);
AddCollision(cobj2, cobj1);
}
else if (previouslyColliding && !colliding)
{
RemoveCollision(cobj1, cobj2);
RemoveCollision(cobj2, cobj1);
}
}
}
}
public List<CollisionObject> GetCollidingObjects(CollisionObject cobj)
{
if (ActiveCollisions.ContainsKey(cobj))
{
return ActiveCollisions[cobj];
}
return new();
}
void AddCollision(CollisionObject cobj1, CollisionObject cobj2)
{
// If this is the first time this object is colliding,
// we must also hook its behavior for when it leaves the tree.
if (!ActiveCollisions.ContainsKey(cobj1))
{
cobj1.TreeExited += () => OnObjectTreeExited(cobj1);
ActiveCollisions[cobj1] = new([cobj2]);
}
else
{
ActiveCollisions[cobj1].Add(cobj2);
}
}
void RemoveCollision(CollisionObject cobj1, CollisionObject cobj2)
{
ActiveCollisions[cobj1].Remove(cobj2);
ActiveCollisions[cobj2].Remove(cobj1);
}
/// <summary>
/// When an object exits the tree, we want it to unregister from any collisions.
/// Any active collisions will be marked as finished.
/// </summary>
/// <param name="cobj"></param>
void OnObjectTreeExited(CollisionObject cobj)
{
if (ActiveCollisions.ContainsKey(cobj))
{
List<CollisionObject> activeColliders = ActiveCollisions[cobj];
foreach (CollisionObject other in activeColliders)
{
ActiveCollisions[other].Remove(cobj);
}
ActiveCollisions.Remove(cobj);
}
}
}
}