From 2985a3af8190641260c65d594fb642fb55f8ea9a Mon Sep 17 00:00:00 2001 From: bailwillharr Date: Sun, 22 Jan 2023 18:20:10 +0000 Subject: [PATCH] Try add player collision --- include/components/collider.hpp | 13 ++++++- include/systems/render.hpp | 2 +- src/systems/physics.cpp | 66 +++++++++++++++++++++++---------- src/systems/render.cpp | 7 ++-- test/src/camera_controller.cpp | 23 ++++++++---- test/src/camera_controller.hpp | 1 + test/src/game.cpp | 14 +++++-- 7 files changed, 90 insertions(+), 36 deletions(-) diff --git a/include/components/collider.hpp b/include/components/collider.hpp index d96805c..e37de02 100644 --- a/include/components/collider.hpp +++ b/include/components/collider.hpp @@ -4,10 +4,21 @@ namespace engine { class PhysicsSystem; + enum class ColliderType { + SPHERE, + PLANE, + }; + struct ColliderComponent { friend PhysicsSystem; - float r; + ColliderType colliderType; + + union { + struct { + float r; + } sphereCollider; + } colliders; bool getIsColliding() { return m_isColliding; } bool getJustCollided() { return m_justCollided; } diff --git a/include/systems/render.hpp b/include/systems/render.hpp index 5f8f29b..aed217d 100644 --- a/include/systems/render.hpp +++ b/include/systems/render.hpp @@ -22,7 +22,7 @@ namespace engine { struct { // only uses transform component, which is required for all entities anyway uint32_t camEntity = 0; - float horizontalFovDegrees = 70.0f; + float verticalFovDegrees = 70.0f; float clipNear = 0.1f; float clipFar = 1000.0f; } m_camera; diff --git a/src/systems/physics.cpp b/src/systems/physics.cpp index e702b38..988cd7b 100644 --- a/src/systems/physics.cpp +++ b/src/systems/physics.cpp @@ -54,36 +54,64 @@ namespace engine { } for (size_t i = 0; i < entityColliders.size(); i++) { + auto* ec1 = &entityColliders[i]; + for (size_t j = i + 1; j < entityColliders.size(); j++) { - const vec3 v = entityColliders[i].pos - entityColliders[j].pos; - 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 sumOfRadiiSquared = sumOfRadii * sumOfRadii; - if (distanceSquared < sumOfRadiiSquared) { - entityColliders[i].c->m_isColliding = true; - entityColliders[j].c->m_isColliding = true; - } - } + auto* ec2 = &entityColliders[j]; - if (entityColliders[i].wasColliding != entityColliders[i].c->getIsColliding()) { - if (entityColliders[i].c->getIsColliding()) { - entityColliders[i].c->m_justCollided = true; + 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 sumOfRadii = ec1->c->colliders.sphereCollider.r + ec2->c->colliders.sphereCollider.r; + const float sumOfRadiiSquared = sumOfRadii * sumOfRadii; + if (distanceSquared < sumOfRadiiSquared) { + ec1->c->m_isColliding = true; + ec2->c->m_isColliding = true; + } + + } else if ( (ec1->c->colliderType == ColliderType::PLANE && + ec2->c->colliderType == ColliderType::SPHERE) || + (ec1->c->colliderType == ColliderType::SPHERE && + ec2->c->colliderType == ColliderType::PLANE)) { + CollisionInfo *plane, *sphere; + if (ec1->c->colliderType == ColliderType::PLANE) { + plane = ec1; + sphere = ec2; + } else { + 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 { - entityColliders[i].c->m_justUncollided = true; + 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(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(ec1->entity); if (r != nullptr) { r->shown = true; } } - if (entityColliders[i].c->getJustUncollided()) { - TRACE("'{}' has stopped colliding!", entityColliders[i].t->tag); - auto r = m_scene->getComponent(entityColliders[i].entity); + if (ec1->c->getJustUncollided()) { + TRACE("'{}' has stopped colliding!", ec1->t->tag); + auto r = m_scene->getComponent(ec1->entity); if (r != nullptr) { r->shown = false; } diff --git a/src/systems/render.cpp b/src/systems/render.cpp index d5dc1d7..b08c6a7 100644 --- a/src/systems/render.cpp +++ b/src/systems/render.cpp @@ -40,9 +40,10 @@ namespace engine { gfx->getViewportSize(&w, &h); m_viewportAspectRatio = (float)w / (float)h; } - const float horizontalFovRadians = glm::radians(m_camera.horizontalFovDegrees); - const float verticalFov = glm::atan( glm::tan(horizontalFovRadians / 2.0f) / m_viewportAspectRatio ) * 2.0f; - const glm::mat4 projMatrix = glm::perspectiveZO(verticalFov, m_viewportAspectRatio, m_camera.clipNear, m_camera.clipFar); + const float verticalFovRadians = glm::radians(m_camera.verticalFovDegrees); +// const float horizontalFovRadians = glm::radians(m_camera.horizontalFovDegrees); +// 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 */ diff --git a/test/src/camera_controller.cpp b/test/src/camera_controller.cpp index f3e2d39..94a9a12 100644 --- a/test/src/camera_controller.cpp +++ b/test/src/camera_controller.cpp @@ -6,6 +6,7 @@ #include "scene.hpp" #include "components/transform.hpp" +#include "components/collider.hpp" #include #include @@ -23,14 +24,17 @@ void CameraControllerSystem::onUpdate(float ts) { engine::TransformComponent* t = nullptr; + engine::ColliderComponent* col = nullptr; CameraControllerComponent* c = nullptr; for (uint32_t entity : m_entities) { t = m_scene->getComponent(entity); + col = m_scene->getComponent(entity); c = m_scene->getComponent(entity); break; } if (t == nullptr) return; if (c == nullptr) return; + if (col == nullptr) return; // calculate new position @@ -48,23 +52,26 @@ void CameraControllerSystem::onUpdate(float ts) if (m_scene->app()->inputManager()->getButton("jump") && c->isJumping == false) { c->isJumping = true; c->dy = JUMPVEL; - //standingHeight = tcomp->position.y; } if (c->isJumping) { c->dy -= G * dt; - t->position.y += c->dy * dt; - if (t->position.y < c->standingHeight) { + if (col->getIsColliding()) { c->isJumping = false; 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)) { - //standingHeight = tcomp->position.y; c->dy += dt * c->thrust; c->isJumping = true; } @@ -98,9 +105,9 @@ void CameraControllerSystem::onUpdate(float ts) constexpr float MAX_DISTANCE_FROM_ORIGIN = 1000.0f; 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->isJumping = false; + c->isJumping = true; } /* ROTATION STUFF */ diff --git a/test/src/camera_controller.hpp b/test/src/camera_controller.hpp index 23c591c..ed2ed0e 100644 --- a/test/src/camera_controller.hpp +++ b/test/src/camera_controller.hpp @@ -14,6 +14,7 @@ struct CameraControllerComponent { float dy = 0.0f; float standingHeight = 0.0f; const float thrust = 25.0f; + }; class CameraControllerSystem : public engine::System { diff --git a/test/src/game.cpp b/test/src/game.cpp index 5bed49b..72a83d7 100644 --- a/test/src/game.cpp +++ b/test/src/game.cpp @@ -53,8 +53,11 @@ void playGame() myScene->registerSystem(); auto camera = myScene->createEntity("camera"); - myScene->addComponent(camera)->standingHeight = myScene->getComponent(camera)->position.y = 2.0f; - myScene->addComponent(camera)->r = 1.0f; + myScene->getComponent(camera)->position.y = 2.0f; + auto cameraCollider = myScene->addComponent(camera); + cameraCollider->colliderType = engine::ColliderType::SPHERE; + cameraCollider->colliders.sphereCollider.r = 1.8f; + myScene->addComponent(camera); myScene->getSystem()->setCameraEntity(camera); @@ -69,12 +72,14 @@ void playGame() auto enemyRenderable = myScene->addComponent(enemy); enemyRenderable->material = std::make_unique(app.getResource("engine.textured")); 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(enemy); enemyT->position.x += 5.0f; enemyT->position.y += 2.0f; enemyT->position.z += 3.0f; - myScene->addComponent(enemy)->r = 10.0f; + auto enemyCollider = myScene->addComponent(enemy); + enemyCollider->colliderType = engine::ColliderType::SPHERE; + enemyCollider->colliders.sphereCollider.r = 5.0f; uint32_t sphere = myScene->createEntity("sphere"); auto sphereRenderable = myScene->addComponent(sphere); @@ -94,6 +99,7 @@ void playGame() floorRenderable->material = std::make_shared(*sphereRenderable->material); floorRenderable->material->m_texture = grassTexture; floorRenderable->mesh = genCuboidMesh(app.gfx(), 100.0f, 0.1f, 100.0f); + myScene->addComponent(floor)->colliderType = engine::ColliderType::PLANE; app.gameLoop();