Dawn/archive/physics_components/2d/CharacterController2D.cpp

92 lines
2.5 KiB
C++

// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "CharacterController2D.hpp"
using namespace Dawn;
CharacterController2D::CharacterController2D(std::weak_ptr<SceneItem> i) :
SceneItemComponent(i)
{
}
void CharacterController2D::onStart() {
useEvent([&](float_t delta){
// if(velocity == glm::vec2(0, 0)) return;
// Common variables
auto item = this->item.lock();
auto myCollider = item->getComponent<Collider2D>();
// Friction
velocity -= velocity * friction * delta;
// Solid Collision Check
glm::vec2 moveAmount;
if(myCollider == nullptr) {
moveAmount = velocity;
} else {
// Perform sweep
auto allColliders = getScene()->findComponents<SolidController2D>();
auto itColliders = allColliders.begin();
struct CharacterController2DCollisionEventInfo info;
bool_t result = false;
// Check for collisions, definitely not working 100% yet
while(itColliders != allColliders.end()) {
auto c = *itColliders;
++itColliders;
auto cItem = c->item.lock();
if(cItem == item || cItem->isChildOf(item)) continue;
result = c->getCollidingResult(
velocity,
myCollider,
info.normal,
info.entryTime,
info.exitTime,
info.entryPoint,
info.exitPoint
) && info.entryTime <= delta;
if(result) {
info.collider = c;
break;
}
}
if(result) {
moveAmount = glm::vec2(0, 0);
velocity = glm::vec2(0, 0);
this->eventCollision.invoke(info);
} else {
moveAmount = velocity;
}
}
if(moveAmount != glm::vec2(0, 0)) {
item->setLocalPosition(
item->getLocalPosition() + (glm::vec3(moveAmount.x, 0, moveAmount.y) * delta)
);
}
// Now perform trigger collision check
auto allTriggers = getScene()->findComponents<TriggerController2D>();
auto itTriggers = allTriggers.begin();
while(itTriggers != allTriggers.end()) {
auto c = *itTriggers;
++itTriggers;
auto cItem = c->item.lock();
if(cItem == item || cItem->isChildOf(item)) continue;
if(c->getCollidingResult(myCollider)) {
c->eventTriggerEnter.invoke(this);
}
}
// Stop velocity near zero.
if(mathAbs<float_t>(velocity.x) <= 0.001f) velocity.x = 0;
if(mathAbs<float_t>(velocity.y) <= 0.001f) velocity.y = 0;
}, getScene()->eventSceneUpdate);
}