-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathColliderComponent.cpp
99 lines (80 loc) · 2.77 KB
/
ColliderComponent.cpp
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
#include "precomp.h"
#include "ColliderComponent.h"
#include "TileMap.h"
#include "Quadtree.h"
#include "TransformComponent.h"
#include "SpriteComponent.h"
#include "Entity.h"
#include "Scene.h"
ColliderComponent::ColliderComponent(Entity* owner, CollisionLayer a_layer) :
Component(owner, ComponentType::collider),
layer(a_layer)
{
TransformComponent* transformComponent = owner->GetComponent<TransformComponent>();
assert(transformComponent != nullptr);
transformComponent->AddObserver(this);
SpriteComponent* sprite = owner->GetComponent<SpriteComponent>();
assert(sprite != nullptr);
relativeBox = { float2{0.0f, 0.0f}, make_float2(sprite->GetSize()) };
worldBox = relativeBox;
UpdateWorldBox();
owner->scene.quadTree->Add(this);
}
ColliderComponent::~ColliderComponent()
{
GetOwner()->scene.quadTree->Remove(this);
}
void ColliderComponent::ObservationMade()
{
Quadtree* colliders = GetOwner()->scene.quadTree.get();
colliders->Remove(this);
UpdateWorldBox();
colliders->Add(this);
}
vector<ColliderComponent*> ColliderComponent::CollisionsWhenAt(float2 worldPos)
{
BoundingBox checkingArea = worldBox;
checkingArea.SetTopLeft(worldPos);
vector<ColliderComponent*> collisions = GetOwner()->scene.quadTree->Query(checkingArea, layer);
collisions.erase(remove(collisions.begin(), collisions.end(), this), collisions.end());
return collisions;
}
vector<ColliderComponent*> ColliderComponent::Collisions()
{
return CollisionsWhenAt(worldBox.GetTopLeft());
}
vector<NearbyCollider> ColliderComponent::CollidersInRange(float range, bool myLayerOnly) const
{
float2 myCentre = worldBox.GetCentre();
float sqrdRange = range * range;
BoundingBox checkingArea(myCentre - float2{ range, range }, float2{ range, range } *2.0f);
vector<ColliderComponent*> nearbyColliders = CollidersInArea(checkingArea, myLayerOnly);
vector<NearbyCollider> ret(nearbyColliders.size(), { nullptr, 0.0f });
size_t retIndex = 0;
for (size_t i = 0; i < nearbyColliders.size(); ++i)
{
ColliderComponent* collider = nearbyColliders[i];
float sqrdDist = SqrdDistance(myCentre, collider->GetBoundingBox().GetCentre());
if (sqrdDist <= sqrdRange)
{
ret[retIndex++] = NearbyCollider{ collider, sqrtf(sqrdDist) };
}
}
ret.resize(retIndex);
return ret;
}
vector<ColliderComponent*> ColliderComponent::CollidersInArea(BoundingBox area, bool myLayerOnly) const
{
CollisionLayer layerToCheck = myLayerOnly ? layer : allLayersMask;
vector<ColliderComponent*> colliders = GetOwner()->scene.quadTree->Query(area, layerToCheck);
auto myself = find(colliders.begin(), colliders.end(), this);
if (myself != colliders.end())
{
colliders.erase(myself);
}
return colliders;
}
void ColliderComponent::UpdateWorldBox()
{
worldBox.SetTopLeft(GetOwner()->GetComponent<TransformComponent>()->GetWorldPos());
}