mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-21 04:51:18 +00:00
Get event system working; add collision events
This commit is contained in:
parent
a0b000d3df
commit
062b2d6c8f
@ -23,8 +23,12 @@ set(SRC_FILES
|
||||
"src/resources/mesh.cpp"
|
||||
"src/resources/texture.cpp"
|
||||
|
||||
"src/event_system.cpp"
|
||||
|
||||
"src/scene.cpp"
|
||||
|
||||
"src/gfx_device_vulkan.cpp"
|
||||
"src/gfx_device_null.cpp"
|
||||
|
||||
"src/util/files.cpp"
|
||||
"src/util/model_loader.cpp"
|
||||
@ -51,6 +55,8 @@ set(INCLUDE_FILES
|
||||
"include/resources/mesh.hpp"
|
||||
"include/resources/texture.hpp"
|
||||
|
||||
"include/event_system.hpp"
|
||||
|
||||
"include/engine_api.h"
|
||||
|
||||
"include/util/files.hpp"
|
||||
|
2
TODO
2
TODO
@ -1,5 +1,7 @@
|
||||
----- TO DO LIST -----
|
||||
|
||||
TODO now: the collision system doesn't use the "isTrigger" bool properly.
|
||||
|
||||
Add support for shadows and other complex lighting. Also add post-processing.
|
||||
|
||||
The engine needs an event/message system, this will be helpful for collision
|
||||
|
2
debug.sh
2
debug.sh
@ -3,4 +3,4 @@ set -e
|
||||
cd Debug
|
||||
cmake --build .
|
||||
cd test
|
||||
./enginetest
|
||||
./enginetest $@
|
||||
|
@ -20,13 +20,14 @@ namespace engine {
|
||||
|
||||
}
|
||||
|
||||
bool isStatic;
|
||||
AABB aabb;
|
||||
bool isStatic = true;
|
||||
bool isTrigger = false; // entity receives an event on collision enter and exit
|
||||
AABB aabb{};
|
||||
|
||||
glm::vec3 getLastCollisionNormal() { return {0.0f, 1.0f, 0.0f}; }
|
||||
glm::vec3 getLastCollisionPoint() { return {}; }
|
||||
bool getIsColliding() { return true; }
|
||||
bool getJustUncollided() { return false; }
|
||||
bool getIsColliding() { return isColliding; }
|
||||
|
||||
private:
|
||||
bool isColliding = false;
|
||||
|
||||
};
|
||||
|
||||
|
119
include/event_system.hpp
Normal file
119
include/event_system.hpp
Normal file
@ -0,0 +1,119 @@
|
||||
#pragma once
|
||||
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace engine {
|
||||
|
||||
enum class EventSubscriberKind {
|
||||
ENTITY,
|
||||
};
|
||||
|
||||
// Event handler base-class
|
||||
template <typename T>
|
||||
class EventHandler {
|
||||
public:
|
||||
virtual void onEvent(T data) = 0;
|
||||
};
|
||||
|
||||
// Event queue interface to allow for different type queues to be in the map
|
||||
class IEventQueue {
|
||||
public:
|
||||
virtual void dispatchEvents() = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class EventQueue : public IEventQueue {
|
||||
// holds events of type T and subscribers to those events
|
||||
|
||||
public:
|
||||
void subscribe(EventSubscriberKind kind, uint32_t id, EventHandler<T>* handler)
|
||||
{
|
||||
// For the time being, ignore kind (TODO)
|
||||
(void)kind;
|
||||
assert(m_subscribers.contains(id) == false && "subscribing to an event with ID that's already in use!");
|
||||
m_subscribers.emplace(id, handler);
|
||||
}
|
||||
|
||||
void queueEvent(EventSubscriberKind kind, uint32_t id, T event)
|
||||
{
|
||||
// For the time being, ignore kind (TODO)
|
||||
(void)kind;
|
||||
assert(m_subscribers.contains(id) && "Attempt to submit event to non-existing subscriber!");
|
||||
EventHandler<T>* handler = m_subscribers.at(id);
|
||||
m_eventQueue.emplace(handler, event);
|
||||
}
|
||||
|
||||
void dispatchEvents() override
|
||||
{
|
||||
while (m_eventQueue.empty() == false) {
|
||||
auto [handler, event] = m_eventQueue.front();
|
||||
handler->onEvent(event);
|
||||
m_eventQueue.pop();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<uint32_t, EventHandler<T>*> m_subscribers;
|
||||
|
||||
struct QueuedEvent {
|
||||
EventHandler<T>* handler;
|
||||
T event;
|
||||
};
|
||||
std::queue<QueuedEvent> m_eventQueue{};
|
||||
|
||||
};
|
||||
|
||||
class EventSystem {
|
||||
|
||||
public:
|
||||
EventSystem();
|
||||
EventSystem(const EventSystem&) = delete;
|
||||
EventSystem& operator=(const EventSystem&) = delete;
|
||||
~EventSystem();
|
||||
|
||||
template <typename T>
|
||||
void registerEventType()
|
||||
{
|
||||
size_t hash = typeid(T).hash_code();
|
||||
assert(m_eventQueues.contains(hash) == false && "Registering an event queue more than once!");
|
||||
m_eventQueues.emplace(hash, std::make_unique<EventQueue<T>>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void subscribeToEventType(EventSubscriberKind kind, uint32_t id, EventHandler<T>* handler)
|
||||
{
|
||||
size_t hash = typeid(T).hash_code();
|
||||
assert(m_eventQueues.contains(hash) && "Subscribing to event type that isn't registered!");
|
||||
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(m_eventQueues.at(hash).get());
|
||||
assert(queue != nullptr && "This cast should work?!! wot");
|
||||
queue->subscribe(kind, id, handler);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void queueEvent(EventSubscriberKind kind, uint32_t subscriberID, T event)
|
||||
{
|
||||
size_t hash = typeid(T).hash_code();
|
||||
assert(m_eventQueues.contains(hash) && "Subscribing to event type that isn't registered!");
|
||||
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(m_eventQueues.at(hash).get());
|
||||
assert(queue != nullptr && "This cast should work?!! wot");
|
||||
queue->queueEvent(kind, subscriberID, event);
|
||||
}
|
||||
|
||||
void dispatchEvents()
|
||||
{
|
||||
for (auto& [hash, queue] : m_eventQueues) {
|
||||
queue->dispatchEvents();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<size_t, std::unique_ptr<IEventQueue>> m_eventQueues{};
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
#include "log.hpp"
|
||||
|
||||
#include "ecs_system.hpp"
|
||||
#include "event_system.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <cstdint>
|
||||
@ -25,6 +26,8 @@ namespace engine {
|
||||
|
||||
Application* app() { return m_app; }
|
||||
|
||||
EventSystem* events() { return m_eventSystem.get(); }
|
||||
|
||||
/* ecs stuff */
|
||||
|
||||
uint32_t createEntity(const std::string& tag, uint32_t parent = 0);
|
||||
@ -130,6 +133,8 @@ namespace engine {
|
||||
return castedPtr;
|
||||
}
|
||||
|
||||
std::unique_ptr<EventSystem> m_eventSystem{};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -17,18 +17,30 @@ namespace engine {
|
||||
|
||||
void onComponentInsert(uint32_t entity) override;
|
||||
|
||||
struct CollisionEvent {
|
||||
bool isCollisionEnter; // false == collision exit
|
||||
uint32_t collidedEntity; // the entity that this entity collided with
|
||||
glm::vec3 normal; // the normal of the surface this entity collided with; ignored on collision exit
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// dyanmic arrays to avoid realloc on every frame
|
||||
struct CollisionInfo {
|
||||
uint32_t entity;
|
||||
AABB aabb;
|
||||
// output
|
||||
bool isMaybeColliding; // broad phase
|
||||
bool isColliding; // narrow phase
|
||||
// dynamic arrays to avoid realloc on every frame
|
||||
|
||||
// entity, aabb, isTrigger
|
||||
std::vector<std::tuple<uint32_t, AABB, bool>> m_staticAABBs{};
|
||||
std::vector<std::tuple<uint32_t, AABB, bool>> m_dynamicAABBs{};
|
||||
|
||||
struct PossibleCollision {
|
||||
uint32_t staticEntity;
|
||||
AABB staticAABB;
|
||||
bool staticTrigger;
|
||||
uint32_t dynamicEntity;
|
||||
AABB dynamicAABB;
|
||||
bool dynamicTrigger;
|
||||
};
|
||||
std::vector<CollisionInfo> m_staticInfos{};
|
||||
std::vector<CollisionInfo> m_dynamicInfos{};
|
||||
std::vector<PossibleCollision> m_possibleCollisions{};
|
||||
std::vector<std::pair<uint32_t, CollisionEvent>> m_collisionInfos{}; // target entity, event info
|
||||
|
||||
};
|
||||
|
||||
|
@ -3,4 +3,4 @@ set -e
|
||||
cd Release
|
||||
cmake --build .
|
||||
cd test
|
||||
./enginetest
|
||||
./enginetest $@
|
||||
|
15
src/event_system.cpp
Normal file
15
src/event_system.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include "event_system.hpp"
|
||||
|
||||
namespace engine {
|
||||
|
||||
EventSystem::EventSystem()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
EventSystem::~EventSystem()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
127
src/gfx_device_null.cpp
Normal file
127
src/gfx_device_null.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
// The implementation of the graphics layer using Vulkan 1.3.
|
||||
|
||||
#ifdef ENGINE_BUILD_NULL
|
||||
|
||||
#include "gfx_device.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <unordered_set>
|
||||
#include <array>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
namespace engine {
|
||||
|
||||
struct GFXDevice::Impl {
|
||||
int FRAMECOUNT = 0;
|
||||
};
|
||||
|
||||
GFXDevice::GFXDevice(const char* appName, const char* appVersion, SDL_Window* window, bool vsync)
|
||||
{
|
||||
(void)appName;
|
||||
(void)appVersion;
|
||||
(void)window;
|
||||
(void)vsync;
|
||||
|
||||
pimpl = std::make_unique<Impl>();
|
||||
|
||||
}
|
||||
|
||||
GFXDevice::~GFXDevice()
|
||||
{
|
||||
}
|
||||
|
||||
void GFXDevice::getViewportSize(uint32_t *w, uint32_t *h)
|
||||
{
|
||||
*w = 1024;
|
||||
*h = 768;
|
||||
}
|
||||
|
||||
void GFXDevice::draw(const gfx::Pipeline* pipeline, const gfx::Buffer* vertexBuffer, const gfx::Buffer* indexBuffer, uint32_t count, const void* pushConstantData, size_t pushConstantSize, const gfx::Texture* texture)
|
||||
{
|
||||
(void)pipeline;
|
||||
(void)vertexBuffer;
|
||||
(void)indexBuffer;
|
||||
(void)count;
|
||||
(void)pushConstantData;
|
||||
(void)pushConstantSize;
|
||||
(void)texture;
|
||||
}
|
||||
|
||||
void GFXDevice::renderFrame()
|
||||
{
|
||||
pimpl->FRAMECOUNT++;
|
||||
}
|
||||
|
||||
gfx::Pipeline* GFXDevice::createPipeline(const char* vertShaderPath, const char* fragShaderPath, const gfx::VertexFormat& vertexFormat, uint64_t uniformBufferSize, bool alphaBlending, bool backfaceCulling)
|
||||
{
|
||||
(void)vertShaderPath;
|
||||
(void)fragShaderPath;
|
||||
(void)vertexFormat;
|
||||
(void)uniformBufferSize;
|
||||
(void)alphaBlending;
|
||||
(void)backfaceCulling;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GFXDevice::destroyPipeline(const gfx::Pipeline* pipeline)
|
||||
{
|
||||
(void)pipeline;
|
||||
}
|
||||
|
||||
void GFXDevice::updateUniformBuffer(const gfx::Pipeline* pipeline, const void* data, size_t size, uint32_t offset)
|
||||
{
|
||||
(void)pipeline;
|
||||
(void)data;
|
||||
(void)size;
|
||||
(void)offset;
|
||||
}
|
||||
|
||||
gfx::Buffer* GFXDevice::createBuffer(gfx::BufferType type, uint64_t size, const void* data)
|
||||
{
|
||||
(void)type;
|
||||
(void)size;
|
||||
(void)data;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GFXDevice::destroyBuffer(const gfx::Buffer* buffer)
|
||||
{
|
||||
(void)buffer;
|
||||
}
|
||||
|
||||
gfx::Texture* GFXDevice::createTexture(
|
||||
const void* imageData,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
gfx::TextureFilter minFilter,
|
||||
gfx::TextureFilter magFilter,
|
||||
gfx::MipmapSetting mipmapSetting,
|
||||
bool useAnisotropy)
|
||||
{
|
||||
(void)imageData;
|
||||
(void)width;
|
||||
(void)height;
|
||||
(void)minFilter;
|
||||
(void)magFilter;
|
||||
(void)mipmapSetting;
|
||||
(void)useAnisotropy;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GFXDevice::destroyTexture(const gfx::Texture* texture)
|
||||
{
|
||||
(void)texture;
|
||||
}
|
||||
|
||||
void GFXDevice::waitIdle()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -492,7 +492,7 @@ namespace engine {
|
||||
vkGetPhysicalDeviceProperties(physicalDevice, &physicalDeviceProperties);
|
||||
|
||||
VkSampleCountFlags counts = physicalDeviceProperties.limits.framebufferColorSampleCounts & physicalDeviceProperties.limits.framebufferDepthSampleCounts;
|
||||
counts %= VK_SAMPLE_COUNT_8_BIT; // restricts it to 8
|
||||
counts %= VK_SAMPLE_COUNT_4_BIT; // restricts it to 2 or 1 (0b11)
|
||||
if (counts & VK_SAMPLE_COUNT_64_BIT) { return VK_SAMPLE_COUNT_64_BIT; }
|
||||
if (counts & VK_SAMPLE_COUNT_32_BIT) { return VK_SAMPLE_COUNT_32_BIT; }
|
||||
if (counts & VK_SAMPLE_COUNT_16_BIT) { return VK_SAMPLE_COUNT_16_BIT; }
|
||||
@ -657,6 +657,14 @@ namespace engine {
|
||||
|
||||
// create the render pass
|
||||
if (swapchain->renderpass == VK_NULL_HANDLE) {
|
||||
|
||||
/*
|
||||
* render pass layout:
|
||||
* 0: color attachment with msaa samples,
|
||||
* 1: depth attachment with msaa samples, used for fragment shading
|
||||
* 2: present src (resolve) attachment with 1 sample, used for swapchain present
|
||||
*/
|
||||
|
||||
VkAttachmentDescription colorAttachment{};
|
||||
colorAttachment.format = swapchain->surfaceFormat.format;
|
||||
colorAttachment.samples = swapchain->msaaSamples;
|
||||
@ -1579,7 +1587,7 @@ namespace engine {
|
||||
renderPassInfo.renderArea.extent = pimpl->swapchain.extent;
|
||||
|
||||
std::array<VkClearValue, 2> clearValues{};
|
||||
clearValues[0].color = { {0.1f, 0.1f, 0.1f, 1.0f} };
|
||||
clearValues[0].color = { {1.0f, 1.0f, 1.0f, 1.0f} };
|
||||
clearValues[1].depthStencil = { 1.0f, 0 };
|
||||
renderPassInfo.clearValueCount = (uint32_t)clearValues.size();
|
||||
renderPassInfo.pClearValues = clearValues.data();
|
||||
|
@ -12,6 +12,11 @@ namespace engine {
|
||||
Scene::Scene(Application* app)
|
||||
: m_app(app)
|
||||
{
|
||||
// event system
|
||||
m_eventSystem = std::make_unique<EventSystem>();
|
||||
|
||||
// ecs configuration:
|
||||
|
||||
registerComponent<TransformComponent>();
|
||||
registerComponent<RenderableComponent>();
|
||||
registerComponent<ColliderComponent>();
|
||||
@ -64,6 +69,7 @@ namespace engine {
|
||||
system->onUpdate(ts);
|
||||
}
|
||||
|
||||
m_eventSystem->dispatchEvents(); // clears event queue
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -35,13 +35,17 @@ namespace engine {
|
||||
PhysicsSystem::PhysicsSystem(Scene* scene)
|
||||
: System(scene, { typeid(TransformComponent).hash_code(), typeid(ColliderComponent).hash_code() })
|
||||
{
|
||||
m_scene->events()->registerEventType<CollisionEvent>();
|
||||
}
|
||||
|
||||
void PhysicsSystem::onComponentInsert(uint32_t entity)
|
||||
{
|
||||
(void)entity;
|
||||
m_staticInfos.reserve(m_entities.size());
|
||||
m_dynamicInfos.reserve(m_entities.size());
|
||||
const size_t size = m_entities.size();
|
||||
m_staticAABBs.reserve(size);
|
||||
m_dynamicAABBs.reserve(size);
|
||||
m_possibleCollisions.reserve(size);
|
||||
m_collisionInfos.reserve(size);
|
||||
TRACE("added entity {} to collider system", entity);
|
||||
}
|
||||
|
||||
@ -49,12 +53,12 @@ namespace engine {
|
||||
{
|
||||
(void)ts;
|
||||
|
||||
m_staticInfos.clear();
|
||||
m_dynamicInfos.clear();
|
||||
m_staticAABBs.clear();
|
||||
m_dynamicAABBs.clear();
|
||||
m_possibleCollisions.clear();
|
||||
m_collisionInfos.clear();
|
||||
|
||||
TRACE("Getting collider entities:");
|
||||
for (uint32_t entity : m_entities) {
|
||||
TRACE(" has entity: {}", entity);
|
||||
const auto t = m_scene->getComponent<TransformComponent>(entity);
|
||||
const auto c = m_scene->getComponent<ColliderComponent>(entity);
|
||||
|
||||
@ -63,43 +67,51 @@ namespace engine {
|
||||
AABB globalBoundingBox;
|
||||
globalBoundingBox.pos1 = globalPosition + localBoundingBox.pos1;
|
||||
globalBoundingBox.pos2 = globalPosition + localBoundingBox.pos2;
|
||||
TRACE(" global bounding box:");
|
||||
TRACE(" pos1: {} {} {}", globalBoundingBox.pos1.x, globalBoundingBox.pos1.y, globalBoundingBox.pos1.z);
|
||||
TRACE(" pos2: {} {} {}", globalBoundingBox.pos2.x, globalBoundingBox.pos2.y, globalBoundingBox.pos2.z);
|
||||
|
||||
CollisionInfo info{
|
||||
.entity = entity,
|
||||
.aabb = globalBoundingBox,
|
||||
.isMaybeColliding = false,
|
||||
.isColliding = false
|
||||
};
|
||||
if (c->isStatic) {
|
||||
m_staticInfos.push_back(info);
|
||||
m_staticAABBs.emplace_back(std::make_tuple(entity, globalBoundingBox, c->isTrigger));
|
||||
} else {
|
||||
m_dynamicInfos.push_back(info);
|
||||
m_dynamicAABBs.emplace_back(std::make_tuple(entity, globalBoundingBox, c->isTrigger));
|
||||
}
|
||||
}
|
||||
|
||||
/* BROAD PHASE */
|
||||
|
||||
TRACE("Starting broad phase collision test");
|
||||
|
||||
struct PossibleCollision {
|
||||
|
||||
};
|
||||
|
||||
// Check every static collider against every dynamic collider, and every dynamic collider against every other one
|
||||
// This technique is inefficient for many entities.
|
||||
for (size_t i = 0; i < m_staticInfos.size(); i++) {
|
||||
for (size_t j = 0; j < m_dynamicInfos.size(); j++) {
|
||||
if (checkCollisionFast(m_staticInfos[i].aabb, m_dynamicInfos[j].aabb)) {
|
||||
m_staticInfos[i].isMaybeColliding = true;
|
||||
m_dynamicInfos[i].isMaybeColliding = true;
|
||||
TRACE("Collision detected between {} and {}", m_staticInfos[i].entity, m_dynamicInfos[j].entity);
|
||||
for (auto [staticEntity, staticAABB, staticTrigger] : m_staticAABBs) {
|
||||
for (auto [dynamicEntity, dynamicAABB, dynamicTrigger] : m_dynamicAABBs) {
|
||||
if (checkCollisionFast(staticAABB, dynamicAABB)) {
|
||||
if (staticTrigger || dynamicTrigger) { // only check collisions involved with triggers
|
||||
m_possibleCollisions.emplace_back(
|
||||
staticEntity, staticAABB, staticTrigger,
|
||||
dynamicEntity, dynamicAABB, dynamicTrigger
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get collision details and submit events
|
||||
for (auto possibleCollision : m_possibleCollisions) {
|
||||
if (possibleCollision.staticTrigger) {
|
||||
CollisionEvent info{};
|
||||
info.isCollisionEnter = true;
|
||||
info.collidedEntity = possibleCollision.dynamicEntity;
|
||||
m_collisionInfos.emplace_back(possibleCollision.staticEntity, info);
|
||||
}
|
||||
if (possibleCollision.dynamicTrigger) {
|
||||
CollisionEvent info{};
|
||||
info.isCollisionEnter = true;
|
||||
info.collidedEntity = possibleCollision.staticEntity;
|
||||
m_collisionInfos.emplace_back(possibleCollision.dynamicEntity, info);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto [entity, info] : m_collisionInfos) {
|
||||
m_scene->events()->queueEvent(EventSubscriberKind::ENTITY, entity, info);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -173,3 +173,9 @@ void CameraControllerSystem::onUpdate(float ts)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CameraControllerSystem::onEvent(engine::PhysicsSystem::CollisionEvent info)
|
||||
{
|
||||
(void)info;
|
||||
INFO("COLLISION EVENT!");
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "ecs_system.hpp"
|
||||
#include "event_system.hpp"
|
||||
|
||||
#include "systems/collisions.hpp"
|
||||
|
||||
struct CameraControllerComponent {
|
||||
float m_cameraSensitivity = 0.007f;
|
||||
@ -17,10 +20,14 @@ struct CameraControllerComponent {
|
||||
|
||||
};
|
||||
|
||||
class CameraControllerSystem : public engine::System {
|
||||
class CameraControllerSystem : public engine::System, public engine::EventHandler<engine::PhysicsSystem::CollisionEvent> {
|
||||
|
||||
public:
|
||||
CameraControllerSystem(engine::Scene* scene);
|
||||
|
||||
// engine::System overrides
|
||||
void onUpdate(float ts) override;
|
||||
|
||||
// engine::EventHandler overrides
|
||||
void onEvent(engine::PhysicsSystem::CollisionEvent info) override;
|
||||
};
|
||||
|
@ -38,11 +38,11 @@ static void configureInputs(engine::InputManager* inputManager)
|
||||
inputManager->addInputAxis("looky", engine::inputs::MouseAxis::Y);
|
||||
}
|
||||
|
||||
void playGame()
|
||||
void playGame(bool enableFrameLimiter)
|
||||
{
|
||||
engine::Application app(PROJECT_NAME, PROJECT_VERSION);
|
||||
|
||||
app.setFrameLimiter(false);
|
||||
app.setFrameLimiter(enableFrameLimiter);
|
||||
|
||||
// configure window
|
||||
app.window()->setRelativeMouseMode(true);
|
||||
@ -60,8 +60,12 @@ void playGame()
|
||||
myScene->getComponent<engine::TransformComponent>(camera)->position.y = 8.0f;
|
||||
auto cameraCollider = myScene->addComponent<engine::ColliderComponent>(camera);
|
||||
cameraCollider->isStatic = false;
|
||||
cameraCollider->isTrigger = true;
|
||||
cameraCollider->aabb = { { -0.2f, -1.5f, -0.2f }, { 0.2f, 0.2f, 0.2f} }; // Origin is at eye level
|
||||
myScene->addComponent<CameraControllerComponent>(camera);
|
||||
myScene->events()->subscribeToEventType<engine::PhysicsSystem::CollisionEvent>(
|
||||
engine::EventSubscriberKind::ENTITY, camera, myScene->getSystem<CameraControllerSystem>()
|
||||
);
|
||||
|
||||
myScene->getSystem<engine::RenderSystem>()->setCameraEntity(camera);
|
||||
}
|
||||
@ -83,7 +87,7 @@ void playGame()
|
||||
);
|
||||
|
||||
/* skybox */
|
||||
{
|
||||
if (0) {
|
||||
uint32_t skybox = myScene->createEntity("skybox");
|
||||
auto skyboxRenderable = myScene->addComponent<engine::RenderableComponent>(skybox);
|
||||
skyboxRenderable->material = std::make_unique<engine::resources::Material>(app.getResource<engine::resources::Shader>("engine.skybox"));
|
||||
|
@ -1,3 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void playGame();
|
||||
void playGame(bool enableFrameLimiter);
|
||||
|
@ -7,15 +7,22 @@
|
||||
|
||||
#include <exception>
|
||||
|
||||
int main(int, char *[])
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
bool enableFrameLimiter = true;
|
||||
|
||||
if (argc == 2) {
|
||||
const std::string arg { argv[1] };
|
||||
if (arg == "nofpslimit") enableFrameLimiter = false;
|
||||
}
|
||||
|
||||
engine::setupLog(PROJECT_NAME);
|
||||
|
||||
INFO("{} v{}", PROJECT_NAME, PROJECT_VERSION);
|
||||
|
||||
try {
|
||||
playGame();
|
||||
playGame(enableFrameLimiter);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user