Try add player collision

This commit is contained in:
Bailey Harrison 2023-01-22 18:20:10 +00:00
parent adb47d810c
commit 2985a3af81
7 changed files with 90 additions and 36 deletions

View File

@ -4,10 +4,21 @@ namespace engine {
class PhysicsSystem; class PhysicsSystem;
enum class ColliderType {
SPHERE,
PLANE,
};
struct ColliderComponent { struct ColliderComponent {
friend PhysicsSystem; friend PhysicsSystem;
ColliderType colliderType;
union {
struct {
float r; float r;
} sphereCollider;
} colliders;
bool getIsColliding() { return m_isColliding; } bool getIsColliding() { return m_isColliding; }
bool getJustCollided() { return m_justCollided; } bool getJustCollided() { return m_justCollided; }

View File

@ -22,7 +22,7 @@ namespace engine {
struct { struct {
// only uses transform component, which is required for all entities anyway // only uses transform component, which is required for all entities anyway
uint32_t camEntity = 0; uint32_t camEntity = 0;
float horizontalFovDegrees = 70.0f; float verticalFovDegrees = 70.0f;
float clipNear = 0.1f; float clipNear = 0.1f;
float clipFar = 1000.0f; float clipFar = 1000.0f;
} m_camera; } m_camera;

View File

@ -54,36 +54,64 @@ namespace engine {
} }
for (size_t i = 0; i < entityColliders.size(); i++) { for (size_t i = 0; i < entityColliders.size(); i++) {
auto* ec1 = &entityColliders[i];
for (size_t j = i + 1; j < entityColliders.size(); j++) { for (size_t j = i + 1; j < entityColliders.size(); j++) {
const vec3 v = entityColliders[i].pos - entityColliders[j].pos;
auto* ec2 = &entityColliders[j];
if ( ec1->c->colliderType == ColliderType::SPHERE &&
ec2->c->colliderType == ColliderType::SPHERE ) {
const vec3 v = ec1->pos - ec2->pos;
const float distanceSquared = v.x * v.x + v.y * v.y + v.z * v.z; const float distanceSquared = v.x * v.x + v.y * v.y + v.z * v.z;
const float sumOfRadii = entityColliders[i].c->r + entityColliders[j].c->r; const float sumOfRadii = ec1->c->colliders.sphereCollider.r + ec2->c->colliders.sphereCollider.r;
const float sumOfRadiiSquared = sumOfRadii * sumOfRadii; const float sumOfRadiiSquared = sumOfRadii * sumOfRadii;
if (distanceSquared < sumOfRadiiSquared) { if (distanceSquared < sumOfRadiiSquared) {
entityColliders[i].c->m_isColliding = true; ec1->c->m_isColliding = true;
entityColliders[j].c->m_isColliding = true; ec2->c->m_isColliding = true;
}
} }
if (entityColliders[i].wasColliding != entityColliders[i].c->getIsColliding()) { } else if ( (ec1->c->colliderType == ColliderType::PLANE &&
if (entityColliders[i].c->getIsColliding()) { ec2->c->colliderType == ColliderType::SPHERE) ||
entityColliders[i].c->m_justCollided = true; (ec1->c->colliderType == ColliderType::SPHERE &&
ec2->c->colliderType == ColliderType::PLANE)) {
CollisionInfo *plane, *sphere;
if (ec1->c->colliderType == ColliderType::PLANE) {
plane = ec1;
sphere = ec2;
} else { } else {
entityColliders[i].c->m_justUncollided = true; sphere = ec1;
plane = ec2;
} }
float distance = plane->pos.y - sphere->pos.y;
if (distance < 0.0f) distance = -distance; // make positive
if (distance < sphere->c->colliders.sphereCollider.r) {
plane->c->m_isColliding = true;
sphere->c->m_isColliding = true;
}
} else {
throw std::runtime_error("Collision combination not supported!");
} }
if (entityColliders[i].c->getJustCollided()) { }
TRACE("'{}' has collided!", entityColliders[i].t->tag);
auto r = m_scene->getComponent<RenderableComponent>(entityColliders[i].entity); if (ec1->wasColliding != ec1->c->getIsColliding()) {
if (ec1->c->getIsColliding()) {
ec1->c->m_justCollided = true;
} else {
ec1->c->m_justUncollided = true;
}
}
if (ec1->c->getJustCollided()) {
TRACE("'{}' has collided!", ec1->t->tag);
auto r = m_scene->getComponent<RenderableComponent>(ec1->entity);
if (r != nullptr) { if (r != nullptr) {
r->shown = true; r->shown = true;
} }
} }
if (entityColliders[i].c->getJustUncollided()) { if (ec1->c->getJustUncollided()) {
TRACE("'{}' has stopped colliding!", entityColliders[i].t->tag); TRACE("'{}' has stopped colliding!", ec1->t->tag);
auto r = m_scene->getComponent<RenderableComponent>(entityColliders[i].entity); auto r = m_scene->getComponent<RenderableComponent>(ec1->entity);
if (r != nullptr) { if (r != nullptr) {
r->shown = false; r->shown = false;
} }

View File

@ -40,9 +40,10 @@ namespace engine {
gfx->getViewportSize(&w, &h); gfx->getViewportSize(&w, &h);
m_viewportAspectRatio = (float)w / (float)h; m_viewportAspectRatio = (float)w / (float)h;
} }
const float horizontalFovRadians = glm::radians(m_camera.horizontalFovDegrees); const float verticalFovRadians = glm::radians(m_camera.verticalFovDegrees);
const float verticalFov = glm::atan( glm::tan(horizontalFovRadians / 2.0f) / m_viewportAspectRatio ) * 2.0f; // const float horizontalFovRadians = glm::radians(m_camera.horizontalFovDegrees);
const glm::mat4 projMatrix = glm::perspectiveZO(verticalFov, m_viewportAspectRatio, m_camera.clipNear, m_camera.clipFar); // const float verticalFov = glm::atan( glm::tan(horizontalFovRadians / 2.0f) / m_viewportAspectRatio ) * 2.0f;
const glm::mat4 projMatrix = glm::perspectiveZO(verticalFovRadians, m_viewportAspectRatio, m_camera.clipNear, m_camera.clipFar);
/* render all renderable entities */ /* render all renderable entities */

View File

@ -6,6 +6,7 @@
#include "scene.hpp" #include "scene.hpp"
#include "components/transform.hpp" #include "components/transform.hpp"
#include "components/collider.hpp"
#include <glm/trigonometric.hpp> #include <glm/trigonometric.hpp>
#include <glm/gtc/constants.hpp> #include <glm/gtc/constants.hpp>
@ -23,14 +24,17 @@ void CameraControllerSystem::onUpdate(float ts)
{ {
engine::TransformComponent* t = nullptr; engine::TransformComponent* t = nullptr;
engine::ColliderComponent* col = nullptr;
CameraControllerComponent* c = nullptr; CameraControllerComponent* c = nullptr;
for (uint32_t entity : m_entities) { for (uint32_t entity : m_entities) {
t = m_scene->getComponent<engine::TransformComponent>(entity); t = m_scene->getComponent<engine::TransformComponent>(entity);
col = m_scene->getComponent<engine::ColliderComponent>(entity);
c = m_scene->getComponent<CameraControllerComponent>(entity); c = m_scene->getComponent<CameraControllerComponent>(entity);
break; break;
} }
if (t == nullptr) return; if (t == nullptr) return;
if (c == nullptr) return; if (c == nullptr) return;
if (col == nullptr) return;
// calculate new position // calculate new position
@ -48,23 +52,26 @@ void CameraControllerSystem::onUpdate(float ts)
if (m_scene->app()->inputManager()->getButton("jump") && c->isJumping == false) { if (m_scene->app()->inputManager()->getButton("jump") && c->isJumping == false) {
c->isJumping = true; c->isJumping = true;
c->dy = JUMPVEL; c->dy = JUMPVEL;
//standingHeight = tcomp->position.y;
} }
if (c->isJumping) { if (c->isJumping) {
c->dy -= G * dt; c->dy -= G * dt;
t->position.y += c->dy * dt; if (col->getIsColliding()) {
if (t->position.y < c->standingHeight) {
c->isJumping = false; c->isJumping = false;
c->dy = 0.0f; c->dy = 0.0f;
t->position.y = c->standingHeight; }
} else {
if (col->getIsColliding()) {
c->dy = -c->dy;
} }
} }
if (col->getJustUncollided()) {
c->isJumping = true;
}
// c->dy -= c->dy * dt; // damp velocity
if (m_scene->app()->window()->getButton(engine::inputs::MouseButton::M_LEFT)) { if (m_scene->app()->window()->getButton(engine::inputs::MouseButton::M_LEFT)) {
//standingHeight = tcomp->position.y;
c->dy += dt * c->thrust; c->dy += dt * c->thrust;
c->isJumping = true; c->isJumping = true;
} }
@ -98,9 +105,9 @@ void CameraControllerSystem::onUpdate(float ts)
constexpr float MAX_DISTANCE_FROM_ORIGIN = 1000.0f; constexpr float MAX_DISTANCE_FROM_ORIGIN = 1000.0f;
if (glm::length(t->position) > MAX_DISTANCE_FROM_ORIGIN) { if (glm::length(t->position) > MAX_DISTANCE_FROM_ORIGIN) {
t->position = { 0.0f, c->standingHeight, 0.0f }; t->position = { 0.0f, 5.0f, 0.0f };
c->dy = 0.0f; c->dy = 0.0f;
c->isJumping = false; c->isJumping = true;
} }
/* ROTATION STUFF */ /* ROTATION STUFF */

View File

@ -14,6 +14,7 @@ struct CameraControllerComponent {
float dy = 0.0f; float dy = 0.0f;
float standingHeight = 0.0f; float standingHeight = 0.0f;
const float thrust = 25.0f; const float thrust = 25.0f;
}; };
class CameraControllerSystem : public engine::System { class CameraControllerSystem : public engine::System {

View File

@ -53,8 +53,11 @@ void playGame()
myScene->registerSystem<CameraControllerSystem>(); myScene->registerSystem<CameraControllerSystem>();
auto camera = myScene->createEntity("camera"); auto camera = myScene->createEntity("camera");
myScene->addComponent<CameraControllerComponent>(camera)->standingHeight = myScene->getComponent<engine::TransformComponent>(camera)->position.y = 2.0f; myScene->getComponent<engine::TransformComponent>(camera)->position.y = 2.0f;
myScene->addComponent<engine::ColliderComponent>(camera)->r = 1.0f; auto cameraCollider = myScene->addComponent<engine::ColliderComponent>(camera);
cameraCollider->colliderType = engine::ColliderType::SPHERE;
cameraCollider->colliders.sphereCollider.r = 1.8f;
myScene->addComponent<CameraControllerComponent>(camera);
myScene->getSystem<engine::RenderSystem>()->setCameraEntity(camera); myScene->getSystem<engine::RenderSystem>()->setCameraEntity(camera);
@ -69,12 +72,14 @@ void playGame()
auto enemyRenderable = myScene->addComponent<engine::RenderableComponent>(enemy); auto enemyRenderable = myScene->addComponent<engine::RenderableComponent>(enemy);
enemyRenderable->material = std::make_unique<engine::resources::Material>(app.getResource<engine::resources::Shader>("engine.textured")); enemyRenderable->material = std::make_unique<engine::resources::Material>(app.getResource<engine::resources::Shader>("engine.textured"));
enemyRenderable->material->m_texture = grassTexture; enemyRenderable->material->m_texture = grassTexture;
enemyRenderable->mesh = genSphereMesh(app.gfx(), 2.0f, 30, false); enemyRenderable->mesh = genSphereMesh(app.gfx(), 5.0f, 50, false);
auto enemyT = myScene->getComponent<engine::TransformComponent>(enemy); auto enemyT = myScene->getComponent<engine::TransformComponent>(enemy);
enemyT->position.x += 5.0f; enemyT->position.x += 5.0f;
enemyT->position.y += 2.0f; enemyT->position.y += 2.0f;
enemyT->position.z += 3.0f; enemyT->position.z += 3.0f;
myScene->addComponent<engine::ColliderComponent>(enemy)->r = 10.0f; auto enemyCollider = myScene->addComponent<engine::ColliderComponent>(enemy);
enemyCollider->colliderType = engine::ColliderType::SPHERE;
enemyCollider->colliders.sphereCollider.r = 5.0f;
uint32_t sphere = myScene->createEntity("sphere"); uint32_t sphere = myScene->createEntity("sphere");
auto sphereRenderable = myScene->addComponent<engine::RenderableComponent>(sphere); auto sphereRenderable = myScene->addComponent<engine::RenderableComponent>(sphere);
@ -94,6 +99,7 @@ void playGame()
floorRenderable->material = std::make_shared<engine::resources::Material>(*sphereRenderable->material); floorRenderable->material = std::make_shared<engine::resources::Material>(*sphereRenderable->material);
floorRenderable->material->m_texture = grassTexture; floorRenderable->material->m_texture = grassTexture;
floorRenderable->mesh = genCuboidMesh(app.gfx(), 100.0f, 0.1f, 100.0f); floorRenderable->mesh = genCuboidMesh(app.gfx(), 100.0f, 0.1f, 100.0f);
myScene->addComponent<engine::ColliderComponent>(floor)->colliderType = engine::ColliderType::PLANE;
app.gameLoop(); app.gameLoop();