mirror of
https://github.com/zoriya/Bomberman.git
synced 2026-06-06 03:12:01 +00:00
Merge branch 'master' into renderer
This commit is contained in:
+8
-3
@@ -1,9 +1,14 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.11)
|
||||
cmake_minimum_required(VERSION 3.11)
|
||||
project(Bomberman)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/lib/wal)
|
||||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/lib/raylib)
|
||||
|
||||
add_executable(bomberman
|
||||
sources/main.cpp
|
||||
sources/main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(bomberman raylib)
|
||||
find_package(raylib REQUIRED)
|
||||
target_link_libraries(bomberman wal raylib)
|
||||
@@ -0,0 +1,20 @@
|
||||
# Usage:
|
||||
# FIND_PACKAGE(raylib REQUIRED)
|
||||
# [...]
|
||||
# TARGET_LINK_LIBRARIES(target_name raylib)
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.11)
|
||||
|
||||
if (NOT raylib_FOUND)
|
||||
INCLUDE(FetchContent)
|
||||
|
||||
FetchContent_Declare(raylib URL https://github.com/raysan5/raylib/archive/master.tar.gz)
|
||||
FetchContent_GetProperties(raylib)
|
||||
if (NOT raylib_POPULATED)
|
||||
SET(FETCHCONTENT_QUIET NO)
|
||||
FetchContent_Populate(raylib)
|
||||
SET(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||
ADD_SUBDIRECTORY(${raylib_SOURCE_DIR} ${raylib_BINARY_DIR})
|
||||
SET(raylib_FOUND TRUE)
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,42 @@
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
project(wal)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
add_library(wal
|
||||
sources/Entity/Entity.hpp
|
||||
sources/Component/Component.hpp
|
||||
sources/System/System.hpp
|
||||
sources/Wal.cpp
|
||||
sources/Wal.hpp
|
||||
sources/Scene/SceneManager.cpp
|
||||
sources/Scene/SceneManager.hpp
|
||||
sources/Scene/Scene.cpp
|
||||
sources/Scene/Scene.hpp
|
||||
sources/Events/EventManager.cpp
|
||||
sources/Events/EventManager.hpp
|
||||
sources/Exception/WalError.cpp
|
||||
sources/Exception/WalError.hpp
|
||||
sources/Entity/Entity.cpp
|
||||
sources/Component/Component.cpp
|
||||
sources/Component/Position/PositionComponent.cpp
|
||||
sources/Component/Position/PositionComponent.hpp
|
||||
sources/Models/Vector3.hpp
|
||||
sources/Component/Movable/MovableComponent.cpp
|
||||
sources/Component/Movable/MovableComponent.hpp
|
||||
sources/System/Movable/MovableSystem.cpp
|
||||
sources/System/Movable/MovableSystem.hpp
|
||||
sources/System/System.cpp
|
||||
)
|
||||
|
||||
target_include_directories(wal PUBLIC sources)
|
||||
|
||||
add_executable(wal_tests EXCLUDE_FROM_ALL
|
||||
tests/EntityTests.cpp
|
||||
tests/MainTest.cpp
|
||||
tests/EngineTests.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(wal_tests PRIVATE wal)
|
||||
find_package(Catch2 REQUIRED)
|
||||
target_link_libraries(wal_tests PRIVATE Catch2::Catch2)
|
||||
@@ -1,64 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Component/Component.hpp"
|
||||
|
||||
//! @brief I'm deeply sorry for this name
|
||||
//! @note I am not, he is a liar
|
||||
namespace WAL
|
||||
{
|
||||
//! @brief An entity of the WAL's ECS.
|
||||
class Entity
|
||||
{
|
||||
private:
|
||||
//! @brief The unique ID of the entity
|
||||
unsigned _uid;
|
||||
//! @brief An entity name (this is useful for debugging)
|
||||
std::string _name;
|
||||
//! @brief Is this entity enabled?
|
||||
bool _disabled;
|
||||
//! @brief The list of the components of this entity
|
||||
std::vector<Component> _components;
|
||||
public:
|
||||
//! @brief Get the ID of the entity.
|
||||
unsigned getUid() const;
|
||||
//! @brief Get the name fo the entity
|
||||
std::string getName() const;
|
||||
|
||||
//! @brief Used if the entity is disabled
|
||||
bool isDisable() const;
|
||||
|
||||
//! @brief Disable this entity.
|
||||
void setDisable(bool disabled);
|
||||
|
||||
//! @brief Get a component of a specific type
|
||||
//! @throw ComponentNotFoundError if the component could not be found
|
||||
template<typename T>
|
||||
T getComponent();
|
||||
|
||||
//! @brief Add a component to this entity. The component is constructed in place.
|
||||
//! @return This entity is returned
|
||||
template<typename T, ...Types>
|
||||
Entity &addComponent(...params);
|
||||
|
||||
//! @brief Copy a component to this entity.
|
||||
//! @return This entity is returned.
|
||||
Entity &addComponent(const Component &component);
|
||||
|
||||
//! @brief Remove a specific component (by type).
|
||||
template<typename T>
|
||||
Entity &removeComponent();
|
||||
|
||||
//! @brief A default constructor
|
||||
Entity(const std::string &name);
|
||||
//! @brief An entity is copyable
|
||||
Entity(const Entity &);
|
||||
//! @brief A default destructor
|
||||
~Entity() = default;
|
||||
//! @brief An entity is assignable
|
||||
Entity &operator=(const Entity &);
|
||||
};
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Entity/Entity.hpp"
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
//! @brief A base system of WAL
|
||||
class System
|
||||
{
|
||||
public:
|
||||
//! @brief A virtual, default, destructor
|
||||
virtual ~System() = default;
|
||||
|
||||
//! @brief Get the name of the component corresponding to this system.
|
||||
virtual std::string getComponentName() const = 0;
|
||||
|
||||
//! @brief Update the corresponding component of the given entity
|
||||
//! @param entity The entity to update.
|
||||
virtual void onUpdate(Entity &entity) = 0;
|
||||
protected:
|
||||
//! @brief A system can't be instantiated, it should be derived.
|
||||
System() = default;
|
||||
//! @brief A system can't be instantiated, it should be derived.
|
||||
System(const System &) = default;
|
||||
//! @brief A system can't be instantiated, it should be derived.
|
||||
System &operator=(const System &) = default;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// Created by Zoe Roux on 2021-05-14.
|
||||
//
|
||||
|
||||
#include "Component/Component.hpp"
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
Component::Component(Entity &entity)
|
||||
: _entity(entity)
|
||||
{ }
|
||||
|
||||
bool Component::isDisabled() const
|
||||
{
|
||||
return this->_disabled;
|
||||
}
|
||||
|
||||
void Component::setDisable(bool disabled)
|
||||
{
|
||||
this->_disabled = disabled;
|
||||
}
|
||||
|
||||
const std::vector<std::type_index> &Component::getDependencies() const
|
||||
{
|
||||
return this->_dependencies;
|
||||
}
|
||||
|
||||
void Component::onStart()
|
||||
{
|
||||
//TODO handle events here
|
||||
}
|
||||
|
||||
void Component::onStop()
|
||||
{
|
||||
//TODO handle events here
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
|
||||
|
||||
//
|
||||
// Created by Zoe Roux on 2021-05-14.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <typeindex>
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
@@ -15,38 +17,40 @@ namespace WAL
|
||||
class Component
|
||||
{
|
||||
private:
|
||||
//! @brief The name of this component
|
||||
std::string _name;
|
||||
//! @brief Is this component disabled?
|
||||
bool _disabled;
|
||||
bool _disabled = false;
|
||||
protected:
|
||||
//! @brief The entity that own this component
|
||||
Entity &_entity;
|
||||
//! @brief The list of dependencies of this component.
|
||||
// TODO check if there is a better type than strings
|
||||
std::vector<std::string> _dependencies;
|
||||
std::vector<std::type_index> _dependencies;
|
||||
|
||||
//! @brief A component can't be instantiated, it should be derived.
|
||||
explicit Component(Entity &entity);
|
||||
//! @brief A component can't be instantiated, it should be derived.
|
||||
Component(const Component &) = default;
|
||||
public:
|
||||
//! @brief Get the name of this component
|
||||
std::string _getName() const;
|
||||
//! @brief A component can't be assigned
|
||||
Component &operator=(const Component &) = delete;
|
||||
//! @brief A virtual destructor
|
||||
virtual ~Component() = default;
|
||||
|
||||
//! @brief Clone a component for another or the same entity.
|
||||
//! @param entity The entity that owns the ne component.
|
||||
virtual Component *clone(Entity &entity) const = 0;
|
||||
|
||||
//! @brief Used if the component is disabled
|
||||
bool isDisable() const;
|
||||
bool isDisabled() const;
|
||||
//! @brief Disable this component.
|
||||
void setDisable(bool disabled);
|
||||
|
||||
//! @brief Get the dependencies of this component.
|
||||
const std::vector<std::type_index> &getDependencies() const;
|
||||
|
||||
//! @brief The entity or this component has just been enabled.
|
||||
//! @param entity The entity that has this component
|
||||
virtual void onStart(Entity &entity);
|
||||
virtual void onStart();
|
||||
|
||||
//! @brief The entity or this component has just been disable.
|
||||
//! @param entity The entity that has this component
|
||||
virtual void onStop(Entity &entity);
|
||||
|
||||
//! @brief A virtual destructor (that also calls onStop)
|
||||
virtual ~Component();
|
||||
protected:
|
||||
//! @brief A component can't be instantiated, it should be derived.
|
||||
Component() = default;
|
||||
//! @brief A component can't be instantiated, it should be derived.
|
||||
Component(const Component &) = default;
|
||||
//! @brief A component can't be instantiated, it should be derived.
|
||||
Component &operator=(const Component &) = default;
|
||||
virtual void onStop();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// Created by Zoe Roux on 5/17/21.
|
||||
//
|
||||
|
||||
#include "MovableComponent.hpp"
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
MovableComponent::MovableComponent(Entity &entity)
|
||||
: Component(entity)
|
||||
{}
|
||||
|
||||
Component *MovableComponent::clone(Entity &entity) const
|
||||
{
|
||||
return new MovableComponent(entity);
|
||||
}
|
||||
|
||||
void MovableComponent::addForce(Vector3f force)
|
||||
{
|
||||
this->_acceleration += force;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Created by Zoe Roux on 5/17/21.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Models/Vector3.hpp"
|
||||
#include "Entity/Entity.hpp"
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
//! @brief A component to place on entities that can move or be moved.
|
||||
class MovableComponent : public Component
|
||||
{
|
||||
private:
|
||||
//! @brief The acceleration of this entity.
|
||||
Vector3f _acceleration;
|
||||
//! @brief The velocity of the entity.
|
||||
Vector3f _velocity;
|
||||
public:
|
||||
//! @brief Add an instant force to this entity.
|
||||
//! @param force The force to add to this entity's acceleration. The force is added instantly and in one go.
|
||||
void addForce(Vector3f force);
|
||||
|
||||
//! @inherit
|
||||
Component *clone(Entity &entity) const override;
|
||||
|
||||
//! @brief Create a new movable component.
|
||||
explicit MovableComponent(Entity &entity);
|
||||
//! @brief A movable component is copy constructable.
|
||||
MovableComponent(const MovableComponent &) = default;
|
||||
//! @brief A default destructor
|
||||
~MovableComponent() override = default;
|
||||
//! @brief A movable component is not assignable.
|
||||
MovableComponent &operator=(const MovableComponent &) = delete;
|
||||
|
||||
friend class MovableSystem;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// Created by Zoe Roux on 5/17/21.
|
||||
//
|
||||
|
||||
#include "PositionComponent.hpp"
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
PositionComponent::PositionComponent(Entity &entity)
|
||||
: Component(entity),
|
||||
position()
|
||||
{}
|
||||
|
||||
PositionComponent::PositionComponent(Entity &entity, Vector3f pos)
|
||||
: Component(entity),
|
||||
position(pos)
|
||||
{}
|
||||
|
||||
PositionComponent::PositionComponent(Entity &entity, float x, float y, float z)
|
||||
: Component(entity),
|
||||
position(x, y, z)
|
||||
{}
|
||||
|
||||
Component *PositionComponent::clone(WAL::Entity &entity) const
|
||||
{
|
||||
return new PositionComponent(entity, this->position);
|
||||
}
|
||||
|
||||
float PositionComponent::getX() const
|
||||
{
|
||||
return this->position.x;
|
||||
}
|
||||
|
||||
float PositionComponent::getY() const
|
||||
{
|
||||
return this->position.y;
|
||||
}
|
||||
|
||||
float PositionComponent::getZ() const
|
||||
{
|
||||
return this->position.z;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// Created by Zoe Roux on 5/17/21.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Models/Vector3.hpp"
|
||||
#include "Component/Component.hpp"
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
//! @brief A basic position component
|
||||
class PositionComponent : public Component
|
||||
{
|
||||
public:
|
||||
//! @brief Get the editable position of this entity
|
||||
Vector3f position;
|
||||
|
||||
//! @brief Get the X position of this entity.
|
||||
float getX() const;
|
||||
//! @brief Get the Y position of this entity.
|
||||
float getY() const;
|
||||
//! @brief Get the Z position of this entity.
|
||||
float getZ() const;
|
||||
|
||||
//! @inherit
|
||||
Component *clone(Entity &entity) const override;
|
||||
|
||||
//! @brief Create a new PositionComponent linked to a specific entity
|
||||
explicit PositionComponent(Entity &entity);
|
||||
//! @brief Create a new PositionComponent at a certain position
|
||||
PositionComponent(Entity &entity, Vector3f pos);
|
||||
//! @brief Create a new PositionComponent at a certain position
|
||||
PositionComponent(Entity &entity, float x, float y, float z);
|
||||
//! @brief A position component is copy constructable
|
||||
PositionComponent(const PositionComponent &) = default;
|
||||
//! @brief A default destructor
|
||||
~PositionComponent() override = default;
|
||||
//! @brief A position component is not assignable
|
||||
PositionComponent &operator=(const PositionComponent &) = delete;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// Created by Zoe Roux on 2021-05-14.
|
||||
//
|
||||
|
||||
#include "Entity/Entity.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
unsigned Entity::nextID = 0;
|
||||
|
||||
Entity::Entity(std::string name)
|
||||
: _uid(Entity::nextID++),
|
||||
_name(std::move(name))
|
||||
{ }
|
||||
|
||||
Entity::Entity(const Entity &other)
|
||||
: _uid(Entity::nextID++),
|
||||
_name(other._name),
|
||||
_disabled(other._disabled)
|
||||
{
|
||||
for (const auto &cmp : other._components)
|
||||
this->addComponent(*cmp);
|
||||
}
|
||||
|
||||
unsigned Entity::getUid() const
|
||||
{
|
||||
return this->_uid;
|
||||
}
|
||||
|
||||
std::string Entity::getName() const
|
||||
{
|
||||
return this->_name;
|
||||
}
|
||||
|
||||
bool Entity::isDisable() const
|
||||
{
|
||||
return this->_disabled;
|
||||
}
|
||||
|
||||
void Entity::setDisable(bool disabled)
|
||||
{
|
||||
this->_disabled = disabled;
|
||||
}
|
||||
|
||||
Entity &Entity::addComponent(const Component &component)
|
||||
{
|
||||
if (this->hasComponent(typeid(component)))
|
||||
throw DuplicateError("A component of the type \"" + std::string(typeid(component).name()) + "\" already exists.");
|
||||
this->_components.emplace_back(component.clone(*this));
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Entity::hasComponent(const std::type_info &type) const
|
||||
{
|
||||
auto existing = std::find_if(this->_components.begin(), this->_components.end(), [&type] (const auto &cmp) {
|
||||
return typeid(*cmp) == type;
|
||||
});
|
||||
return existing != this->_components.end();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// Created by Zoe Roux on 2021-05-14.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <typeinfo>
|
||||
#include <memory>
|
||||
#include "Component/Component.hpp"
|
||||
#include "Exception/WalError.hpp"
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
//! @brief An entity of the WAL's ECS.
|
||||
class Entity
|
||||
{
|
||||
private:
|
||||
//! @brief The unique ID of the entity
|
||||
unsigned _uid;
|
||||
//! @brief An entity name (this is useful for debugging)
|
||||
std::string _name;
|
||||
//! @brief Is this entity enabled?
|
||||
bool _disabled = false;
|
||||
//! @brief The list of the components of this entity
|
||||
std::vector<std::unique_ptr<Component>> _components = {};
|
||||
|
||||
//! @brief This ID will be the one of the next entity created.
|
||||
static unsigned nextID;
|
||||
public:
|
||||
//! @brief Get the ID of the entity.
|
||||
unsigned getUid() const;
|
||||
//! @brief Get the name fo the entity
|
||||
std::string getName() const;
|
||||
|
||||
//! @brief Used if the entity is disabled
|
||||
bool isDisable() const;
|
||||
|
||||
//! @brief Disable this entity.
|
||||
void setDisable(bool disabled);
|
||||
|
||||
//! @brief Get a component of a specific type
|
||||
//! @throw NotFoundError if the component could not be found
|
||||
template<typename T>
|
||||
T &getComponent()
|
||||
{
|
||||
const std::type_info &type = typeid(T);
|
||||
auto existing = std::find_if(this->_components.begin(), this->_components.end(), [&type] (const auto &cmp) {
|
||||
return typeid(*cmp) == type;
|
||||
});
|
||||
if (existing == this->_components.end())
|
||||
throw NotFoundError("No component could be found with the type \"" + std::string(type.name()) + "\".");
|
||||
return *static_cast<T *>(existing->get());
|
||||
}
|
||||
|
||||
//! @brief Check if this entity has a component.
|
||||
//! @tparam T The type of the component
|
||||
template<typename T>
|
||||
bool hasComponent() const
|
||||
{
|
||||
const std::type_info &type = typeid(T);
|
||||
return this->hasComponent(type);
|
||||
}
|
||||
|
||||
//! @brief Check if this entity has a component.
|
||||
//! @param type The type of the component
|
||||
bool hasComponent(const std::type_info &type) const;
|
||||
|
||||
//! @brief Add a component to this entity. The component is constructed in place.
|
||||
//! @throw DuplicateError is thrown if a component with the same type already exist.
|
||||
//! @return This entity is returned
|
||||
template<typename T, typename ...Types>
|
||||
Entity &addComponent(Types ...params)
|
||||
{
|
||||
if (this->hasComponent<T>())
|
||||
throw DuplicateError("A component of the type \"" + std::string(typeid(T).name()) + "\" already exists.");
|
||||
this->_components.push_back(std::make_unique<T>(*this, params...));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! @brief Copy a component to this entity.
|
||||
//! @return This entity is returned.
|
||||
Entity &addComponent(const Component &component);
|
||||
|
||||
//! @brief Remove a specific component (by type).
|
||||
//! @throw NotFoundError is thrown if the component could not be found.
|
||||
//! @return This entity is returned.
|
||||
template<typename T>
|
||||
Entity &removeComponent()
|
||||
{
|
||||
const std::type_info &type = typeid(T);
|
||||
auto existing = std::find_if(this->_components.begin(), this->_components.end(), [&type] (const auto &cmp) {
|
||||
return typeid(*cmp) == type;
|
||||
});
|
||||
if (existing == this->_components.end())
|
||||
throw NotFoundError("No component could be found with the type \"" + std::string(type.name()) + "\".");
|
||||
this->_components.erase(existing);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! @brief A default constructor
|
||||
explicit Entity(std::string name);
|
||||
//! @brief An entity is copyable
|
||||
Entity(const Entity &);
|
||||
//! @brief An entity is movable.
|
||||
Entity(Entity &&) = default;
|
||||
//! @brief A default destructor
|
||||
~Entity() = default;
|
||||
//! @brief An entity is assignable
|
||||
Entity &operator=(const Entity &) = default;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
//
|
||||
// Created by Zoe Roux on 2021-05-14.
|
||||
//
|
||||
|
||||
#include "EventManager.hpp"
|
||||
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// Created by Zoe Roux on 2021-05-14.
|
||||
//
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
//! @brief A class to handle events.
|
||||
class EventManager
|
||||
{
|
||||
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// Created by Zoe Roux on 2021-05-14.
|
||||
//
|
||||
|
||||
#include "WalError.hpp"
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
WalError::WalError(const std::string &what)
|
||||
: std::runtime_error(what)
|
||||
{}
|
||||
|
||||
DuplicateError::DuplicateError(const std::string &what)
|
||||
: WalError(what)
|
||||
{}
|
||||
|
||||
NotFoundError::NotFoundError(const std::string &what)
|
||||
: WalError(what)
|
||||
{}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// Created by Zoe Roux on 2021-05-14.
|
||||
//
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
//! @brief The base class for WAL's exceptions.
|
||||
class WalError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
//! @brief Create a new wal exception
|
||||
explicit WalError(const std::string &what);
|
||||
//! @brief A wal exception is copy constructable
|
||||
WalError(const WalError &) = default;
|
||||
//! @brief A default destructor
|
||||
~WalError() override = default;
|
||||
//! @brief A default assignment operator
|
||||
WalError &operator=(const WalError &) = default;
|
||||
};
|
||||
|
||||
//! @brief An exception informing the user that something already exists.
|
||||
class DuplicateError : public WalError
|
||||
{
|
||||
public:
|
||||
//! @brief Create a new wal exception
|
||||
explicit DuplicateError(const std::string &what);
|
||||
//! @brief A wal exception is copy constructable
|
||||
DuplicateError(const DuplicateError &) = default;
|
||||
//! @brief A default destructor
|
||||
~DuplicateError() override = default;
|
||||
//! @brief A default assignment operator
|
||||
DuplicateError &operator=(const DuplicateError &) = default;
|
||||
};
|
||||
|
||||
//! @brief An exception informing the user that something could not be found
|
||||
class NotFoundError : public WalError
|
||||
{
|
||||
public:
|
||||
//! @brief Create a new wal exception
|
||||
explicit NotFoundError(const std::string &what);
|
||||
//! @brief A wal exception is copy constructable
|
||||
NotFoundError(const NotFoundError &) = default;
|
||||
//! @brief A default destructor
|
||||
~NotFoundError() override = default;
|
||||
//! @brief A default assignment operator
|
||||
NotFoundError &operator=(const NotFoundError &) = default;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
//
|
||||
// Created by Zoe Roux on 5/17/21.
|
||||
//
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
//! @brief A Vector3 data type. (templated to allow any kind of vector3)
|
||||
template<typename T>
|
||||
class Vector3
|
||||
{
|
||||
public:
|
||||
//! @brief The x value of the vector
|
||||
T x;
|
||||
//! @brief The y value of the vector
|
||||
T y;
|
||||
//! @brief The y value of the vector
|
||||
T z;
|
||||
|
||||
//! @brief Create a new nil vector3.
|
||||
Vector3<T>()
|
||||
: x(0), y(0), z(0)
|
||||
{}
|
||||
|
||||
//! @brief Create a new vector3 representing a specific coordinate.
|
||||
Vector3<T>(T x, T y, T z)
|
||||
: x(x), y(y), z(z)
|
||||
{}
|
||||
|
||||
//! @brief A default destructor
|
||||
~Vector3() = default;
|
||||
|
||||
bool operator==(const Vector3<T> &other) const
|
||||
{
|
||||
return this->x == other.x && this->y == other.y && this->z == other.z;
|
||||
}
|
||||
|
||||
bool operator!=(const Vector3<T> &other) const
|
||||
{
|
||||
return !this->operator==(other);
|
||||
}
|
||||
|
||||
template<typename T2>
|
||||
Vector3<T> &operator+=(const Vector3<T2> &vec)
|
||||
{
|
||||
this->x += vec.x;
|
||||
this->y += vec.y;
|
||||
this->z += vec.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T2>
|
||||
Vector3<T> operator+(const Vector3<T2> &vec) const
|
||||
{
|
||||
return Vector3<T>(this->x + vec.x, this->y + vec.y, this->z + vec.z);
|
||||
}
|
||||
|
||||
template<typename T2>
|
||||
Vector3<T> &operator-=(const Vector3<T2> &vec)
|
||||
{
|
||||
this->x -= vec.x;
|
||||
this->y -= vec.y;
|
||||
this->z -= vec.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T2>
|
||||
Vector3<T> &operator*=(T2 d)
|
||||
{
|
||||
this->x *= d;
|
||||
this->y *= d;
|
||||
this->z *= d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T2>
|
||||
Vector3<T> operator*(T2 d) const
|
||||
{
|
||||
return Vector3<T>(this->x * d, this->y * d, this->z * d);
|
||||
}
|
||||
|
||||
template<typename T2>
|
||||
Vector3<T> operator*(Vector3<T2> &b) const
|
||||
{
|
||||
return Vector3<T>(this->x * b.x, this->y * b.y, this->z * b.z);
|
||||
}
|
||||
|
||||
template<typename T2>
|
||||
Vector3<T> operator/=(Vector3<T2> &b)
|
||||
{
|
||||
this->x /= b.x;
|
||||
this->y /= b.y;
|
||||
this->z /= b.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
template<typename T2>
|
||||
Vector3<T> operator/(Vector3<T2> &b) const
|
||||
{
|
||||
return Vector3<T>(this->x / b.x, this->y / b.y, this->z / b.z);
|
||||
}
|
||||
|
||||
template<typename T2>
|
||||
Vector3<T> operator/=(T2 b)
|
||||
{
|
||||
this->x /= b;
|
||||
this->y /= b;
|
||||
this->z /= b;
|
||||
return this;
|
||||
}
|
||||
|
||||
template<typename T2>
|
||||
Vector3<T> operator/(T2 b) const
|
||||
{
|
||||
return Vector3<T>(this->x / b, this->y / b, this->z / b);
|
||||
}
|
||||
|
||||
template<typename T2>
|
||||
double distance(const Vector3<T2> &o) const
|
||||
{
|
||||
return std::sqrt(std::pow(this->x - o.x, 2) + std::pow(this->y - o.y, 2) + std::pow(this->z - o.z, 2));
|
||||
}
|
||||
|
||||
double magnitude() const
|
||||
{
|
||||
return (std::sqrt(std::pow(this->x, 2) + std::pow(this->y, 2), std::pow(this->z, 2)));
|
||||
}
|
||||
|
||||
Vector3<T> normalize()
|
||||
{
|
||||
double mag = this->magnitude();
|
||||
|
||||
this->x /= mag;
|
||||
this->y /= mag;
|
||||
this->z /= mag;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector3<T> normalized() const
|
||||
{
|
||||
T mag = this->magnitude();
|
||||
|
||||
return Vector3<T>(this->x / mag, this->y / mag, this->z / mag);
|
||||
}
|
||||
|
||||
Vector3<T> projection(const Vector3<T> &point) const
|
||||
{
|
||||
return (point * this) / std::pow(this->magnitude(), 2) * this;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Vector3<float> Vector3f;
|
||||
typedef Vector3<unsigned> Vector3u;
|
||||
typedef Vector3<int> Vector3i;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream &operator<<(std::ostream &s, const WAL::Vector3<T> &v)
|
||||
{
|
||||
s << "Vector3<" << typeid(T).name() << ">("<< v.x << ", " << v.y << ", " << v.z << ")";
|
||||
return s;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
//
|
||||
// Created by Zoe Roux on 2021-05-14.
|
||||
//
|
||||
|
||||
#include "Scene.hpp"
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
std::vector<Entity> &Scene::getEntities()
|
||||
{
|
||||
return this->_entities;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// Created by Zoe Roux on 2021-05-14.
|
||||
//
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "Entity/Entity.hpp"
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
//! @brief Represent a single scene that contains entities.
|
||||
class Scene
|
||||
{
|
||||
private:
|
||||
//! @brief The list of registered entities
|
||||
std::vector<Entity> _entities;
|
||||
public:
|
||||
//! @brief Get the list of entities.
|
||||
std::vector<Entity> &getEntities();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Created by Zoe Roux on 2021-05-14.
|
||||
//
|
||||
|
||||
#include "SceneManager.hpp"
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
SceneManager &WAL::SceneManager::addScene(WAL::Scene &&scene)
|
||||
{
|
||||
this->_scenes.push_front(scene);
|
||||
return *this;
|
||||
}
|
||||
|
||||
SceneManager &SceneManager::addBackScene(Scene &&scene)
|
||||
{
|
||||
this->_scenes.insert(++this->_scenes.begin(), scene);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Scene &SceneManager::getCurrent()
|
||||
{
|
||||
if (this->_scenes.empty())
|
||||
throw NotFoundError("No scene exists.");
|
||||
return this->_scenes.front();
|
||||
}
|
||||
|
||||
SceneManager &SceneManager::closeCurrent()
|
||||
{
|
||||
this->_scenes.pop_front();
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// Created by Zoe Roux on 2021-05-14.
|
||||
//
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <queue>
|
||||
#include "Scene/Scene.hpp"
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
//! @brief A class to manage scenes
|
||||
class SceneManager
|
||||
{
|
||||
private:
|
||||
std::deque<Scene> _scenes = {};
|
||||
public:
|
||||
//! @brief Add a scene to the container and move to it.
|
||||
//! @return The manager instance used to call this function is returned. This allow method chaining.
|
||||
SceneManager &addScene(Scene &&scene);
|
||||
|
||||
//! @brief Add a scene before the current scene. This could be useful for lobbies or scene where the next scene can be constructed.
|
||||
//! @return The manager instance used to call this function is returned. This allow method chaining.
|
||||
SceneManager &addBackScene(Scene &&scene);
|
||||
|
||||
//! @breif Get the current scene
|
||||
Scene &getCurrent();
|
||||
|
||||
//! @brief Remove the current scene and switch to the previous scene on the stack.
|
||||
//! @return The manager instance used to call this function is returned. This allow method chaining.
|
||||
SceneManager &closeCurrent();
|
||||
|
||||
//! @brief A default constructor
|
||||
SceneManager() = default;
|
||||
//! @brief A scene manager is copy constructable
|
||||
SceneManager(const SceneManager &) = default;
|
||||
//! @brief A default destructor.
|
||||
~SceneManager() = default;
|
||||
//! @brief A scene manager is assignable
|
||||
SceneManager &operator=(const SceneManager &) = default;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Created by Zoe Roux on 5/17/21.
|
||||
//
|
||||
|
||||
#include "Component/Position/PositionComponent.hpp"
|
||||
#include "System/Movable/MovableSystem.hpp"
|
||||
#include "Component/Movable/MovableComponent.hpp"
|
||||
#include "Wal.hpp"
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
const std::type_info &MovableSystem::getComponent() const
|
||||
{
|
||||
return typeid(MovableComponent);
|
||||
}
|
||||
|
||||
void MovableSystem::onFixedUpdate(Entity &entity)
|
||||
{
|
||||
auto &movable = entity.getComponent<MovableComponent>();
|
||||
auto &position = entity.getComponent<PositionComponent>();
|
||||
|
||||
position.position += movable._velocity * Wal::timestep.count();
|
||||
movable._velocity = movable._acceleration * Wal::timestep.count();
|
||||
movable._acceleration = Vector3f();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
//
|
||||
// Created by Zoe Roux on 5/17/21.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "System/System.hpp"
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
//! @brief A system to handle movable entities. This system update velocity based on accelerations and positions based on velocity.
|
||||
class MovableSystem : public System
|
||||
{
|
||||
public:
|
||||
//! @inherit
|
||||
const std::type_info &getComponent() const override;
|
||||
//! @inherit
|
||||
void onFixedUpdate(Entity &entity) override;
|
||||
|
||||
//! @brief A default constructor
|
||||
MovableSystem() = default;
|
||||
//! @brief A movable system is copy constructable
|
||||
MovableSystem(const MovableSystem &) = default;
|
||||
//! @brief A default destructor
|
||||
~MovableSystem() override = default;
|
||||
//! @brief A movable system is assignable.
|
||||
MovableSystem &operator=(const MovableSystem &) = default;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// Created by Zoe Roux on 5/17/21.
|
||||
//
|
||||
|
||||
#include "System.hpp"
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
|
||||
void System::onUpdate(Entity &entity, std::chrono::nanoseconds dtime)
|
||||
{}
|
||||
|
||||
void System::onFixedUpdate(Entity &entity)
|
||||
{}
|
||||
|
||||
void System::onSelfUpdate()
|
||||
{}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// Created by Zoe Roux on 2021-05-14.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include "Entity/Entity.hpp"
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
//! @brief A base system of WAL
|
||||
class System
|
||||
{
|
||||
public:
|
||||
//! @brief A virtual, default, destructor
|
||||
virtual ~System() = default;
|
||||
//! @brief A system can be moved
|
||||
System(System &&) = default;
|
||||
|
||||
//! @brief Get the name of the component corresponding to this system.
|
||||
virtual const std::type_info &getComponent() const = 0;
|
||||
|
||||
//! @brief Update the corresponding component of the given entity
|
||||
//! @param entity The entity to update.
|
||||
//! @param dtime The delta time.
|
||||
virtual void onUpdate(Entity &entity, std::chrono::nanoseconds dtime);
|
||||
|
||||
//! @brief An alternative of onUpdate that is called every 8ms (120 times per seconds). If the system slow down, it will try to catch up.
|
||||
//! @remark This should be used for Physics, AI and everything that could be imprecise due to float rounding.
|
||||
//! @param entity The entity to update.
|
||||
virtual void onFixedUpdate(Entity &entity);
|
||||
|
||||
//! @brief A method called after all entities that this system manage has been updated.
|
||||
virtual void onSelfUpdate();
|
||||
protected:
|
||||
//! @brief A system can't be instantiated, it should be derived.
|
||||
System() = default;
|
||||
//! @brief A system can't be instantiated, it should be derived.
|
||||
System(const System &) = default;
|
||||
//! @brief A system can't be instantiated, it should be derived.
|
||||
System &operator=(const System &) = default;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// Created by Zoe Roux on 2021-05-14.
|
||||
//
|
||||
|
||||
#include <chrono>
|
||||
#include "Wal.hpp"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
std::chrono::nanoseconds Wal::timestep = 8ms;
|
||||
|
||||
SceneManager &Wal::getSceneManager()
|
||||
{
|
||||
return this->_sceneManager;
|
||||
}
|
||||
|
||||
void Wal::run()
|
||||
{
|
||||
auto lastTick = std::chrono::steady_clock::now();
|
||||
std::chrono::nanoseconds fBehind(0);
|
||||
|
||||
while (!this->_shouldClose) {
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
std::chrono::nanoseconds dtime = now - lastTick;
|
||||
fBehind += dtime;
|
||||
lastTick = now;
|
||||
|
||||
while (fBehind > Wal::timestep) {
|
||||
fBehind -= Wal::timestep;
|
||||
this->_fixedUpdate();
|
||||
}
|
||||
this->_update(dtime);
|
||||
}
|
||||
}
|
||||
|
||||
void Wal::_update(std::chrono::nanoseconds dtime)
|
||||
{
|
||||
auto &entities = this->_sceneManager.getCurrent().getEntities();
|
||||
|
||||
for (auto &system : this->_systems) {
|
||||
for (auto &entity : entities) {
|
||||
const auto &cmp = system->getComponent();
|
||||
if (!entity.hasComponent(cmp))
|
||||
continue;
|
||||
// TODO handle dependencies.
|
||||
system->onUpdate(entity, dtime);
|
||||
}
|
||||
system->onSelfUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void Wal::_fixedUpdate()
|
||||
{
|
||||
auto &entities = this->_sceneManager.getCurrent().getEntities();
|
||||
|
||||
for (auto &system : this->_systems) {
|
||||
for (auto &entity : entities) {
|
||||
auto &cmp = system->getComponent();
|
||||
if (!entity.hasComponent(cmp))
|
||||
continue;
|
||||
// TODO handle dependencies.
|
||||
system->onFixedUpdate(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
//
|
||||
// Created by Zoe Roux on 2021-05-14.
|
||||
//
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <typeinfo>
|
||||
#include <Exception/WalError.hpp>
|
||||
#include "Events/EventManager.hpp"
|
||||
#include "Scene/SceneManager.hpp"
|
||||
#include "Entity/Entity.hpp"
|
||||
#include "System/System.hpp"
|
||||
|
||||
namespace WAL
|
||||
{
|
||||
//! @brief The main WAL class, it is used to setup and run the ECS.
|
||||
class Wal
|
||||
{
|
||||
private:
|
||||
//! @brief The scene manager that allow multiple scene to work together.
|
||||
SceneManager _sceneManager;
|
||||
//! @brief The event manager
|
||||
EventManager _eventManager;
|
||||
//! @brief The list of registered systems
|
||||
std::vector<std::unique_ptr<System>> _systems = {};
|
||||
//! @brief True if the engine should close after the end of the current tick.
|
||||
bool _shouldClose = false;
|
||||
|
||||
//! @brief Call the onUpdate of every system with every component
|
||||
void _update(std::chrono::nanoseconds dtime);
|
||||
|
||||
//! @brief Call the onFixedUpdate of every system with every component
|
||||
void _fixedUpdate();
|
||||
public:
|
||||
//! @brief The time between each fixed update.
|
||||
static std::chrono::nanoseconds timestep;
|
||||
|
||||
//! @brief Create a new system in place.
|
||||
//! @return The wal instance used to call this function is returned. This allow method chaining.
|
||||
template<typename T, class ...Types>
|
||||
Wal &addSystem(Types ...params)
|
||||
{
|
||||
const std::type_info &type = typeid(T);
|
||||
auto existing = std::find_if(this->_systems.begin(), this->_systems.end(), [&type] (auto &sys) {
|
||||
return typeid(*sys) == type;
|
||||
});
|
||||
if (existing != this->_systems.end())
|
||||
throw DuplicateError("A system of the type \"" + std::string(type.name()) + "\" already exists.");
|
||||
this->_systems.push_back(std::make_unique<T>(params...));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! @brief Add a system by copy.
|
||||
//! @return The wal instance used to call this function is returned. This allow method chaining.
|
||||
template<typename T>
|
||||
Wal &addSystem(const T &system)
|
||||
{
|
||||
const std::type_info &type = typeid(T);
|
||||
auto existing = std::find_if(this->_systems.begin(), this->_systems.end(), [&type] (auto &sys) {
|
||||
return typeid(*sys) == type;
|
||||
});
|
||||
if (existing != this->_systems.end())
|
||||
throw DuplicateError("A system of the type \"" + std::string(type.name()) + "\" already exists.");
|
||||
this->_systems.push_back(std::make_unique<T>(system));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! @brief Get a system of a specific type
|
||||
//! @tparam T the type of the system.
|
||||
template<typename T>
|
||||
T &getSystem()
|
||||
{
|
||||
const std::type_info &type = typeid(T);
|
||||
auto existing = std::find_if(this->_systems.begin(), this->_systems.end(), [&type] (auto &sys) {
|
||||
return typeid(*sys) == type;
|
||||
});
|
||||
if (existing == this->_systems.end())
|
||||
throw NotFoundError("A system of the type \"" + std::string(type.name()) + "\" could not be found.");
|
||||
return *static_cast<T *>(existing->get());
|
||||
|
||||
}
|
||||
|
||||
//! @brief Remove a system using it's type.
|
||||
template<typename T>
|
||||
Wal &removeSystem()
|
||||
{
|
||||
const std::type_info &type = typeid(T);
|
||||
auto existing = std::find_if(this->_systems.begin(), this->_systems.end(), [&type] (auto &sys) {
|
||||
return typeid(*sys) == type;
|
||||
});
|
||||
if (existing == this->_systems.end())
|
||||
throw NotFoundError("No system could be found with the type \"" + std::string(type.name()) + "\".");
|
||||
this->_systems.erase(existing);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! @brief Get the scene manager.
|
||||
SceneManager &getSceneManager();
|
||||
|
||||
//! @brief Start the game loop
|
||||
void run();
|
||||
|
||||
//! @brief A default constructor
|
||||
Wal() = default;
|
||||
//! @brief A WAL can't be copy constructed
|
||||
Wal(const Wal &) = delete;
|
||||
//! @brief A default destructor
|
||||
~Wal() = default;
|
||||
//! @brief A WAL can't be assigned.
|
||||
Wal &operator=(const Wal &) = delete;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Created by Zoe Roux on 5/17/21.
|
||||
//
|
||||
|
||||
|
||||
#include "Wal.hpp"
|
||||
#include "System/Movable/MovableSystem.hpp"
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
using namespace WAL;
|
||||
|
||||
TEST_CASE("Create system", "[Engine][System]")
|
||||
{
|
||||
Wal wal;
|
||||
wal.addSystem<MovableSystem>();
|
||||
|
||||
SECTION("Check existence") {
|
||||
REQUIRE_NOTHROW(wal.getSystem<MovableSystem>());
|
||||
}
|
||||
SECTION("Duplicate check") {
|
||||
REQUIRE_THROWS_AS(wal.addSystem<MovableSystem>(), DuplicateError);
|
||||
}
|
||||
SECTION("Remove system") {
|
||||
wal.removeSystem<MovableSystem>();
|
||||
REQUIRE_THROWS_AS(wal.getSystem<MovableSystem>(), NotFoundError);
|
||||
REQUIRE_THROWS_AS(wal.removeSystem<MovableSystem>(), NotFoundError);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Create system by reference", "[Engine][System]")
|
||||
{
|
||||
Wal wal;
|
||||
MovableSystem system;
|
||||
wal.addSystem(system);
|
||||
REQUIRE_THROWS_AS(wal.addSystem<MovableSystem>(), DuplicateError);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// Created by Zoe Roux on 5/17/21.
|
||||
//
|
||||
|
||||
#include "Entity/Entity.hpp"
|
||||
#include "Component/Position/PositionComponent.hpp"
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
using namespace WAL;
|
||||
|
||||
TEST_CASE("Component", "[Entity]")
|
||||
{
|
||||
Entity entity("Bob");
|
||||
entity.addComponent<PositionComponent>(2, 3, 4);
|
||||
|
||||
SECTION("Check value") {
|
||||
auto &pos = entity.getComponent<PositionComponent>();
|
||||
REQUIRE(entity.hasComponent<PositionComponent>());
|
||||
REQUIRE(pos.position == Vector3f(2, 3, 4));
|
||||
}
|
||||
SECTION("Prevent duplicates") {
|
||||
REQUIRE_THROWS_AS(entity.addComponent<PositionComponent>(), DuplicateError);
|
||||
}
|
||||
SECTION("Remove component") {
|
||||
entity.removeComponent<PositionComponent>();
|
||||
REQUIRE_THROWS_AS(entity.getComponent<PositionComponent>(), NotFoundError);
|
||||
REQUIRE_THROWS_AS(entity.removeComponent<PositionComponent>(), NotFoundError);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("ComponentNotFound", "[Entity]")
|
||||
{
|
||||
Entity entity("Bob");
|
||||
REQUIRE_THROWS_AS(entity.getComponent<PositionComponent>(), NotFoundError);
|
||||
}
|
||||
|
||||
TEST_CASE("Add component by reference", "[Entity]")
|
||||
{
|
||||
Entity entity("Bob");
|
||||
PositionComponent component(entity, 4, 5, 6);
|
||||
|
||||
REQUIRE(&entity.addComponent(component) == &entity);
|
||||
REQUIRE(entity.getComponent<PositionComponent>().position == Vector3f(4, 5, 6));
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
//
|
||||
// Created by Zoe Roux on 5/17/21.
|
||||
//
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch2/catch.hpp>
|
||||
+10
-2
@@ -1,7 +1,15 @@
|
||||
#include <iostream>
|
||||
#include <Wal.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << "Hello, World!" << std::endl;
|
||||
return 0;
|
||||
WAL::Wal wal;
|
||||
|
||||
try {
|
||||
wal.run();
|
||||
return 0;
|
||||
} catch (const std::exception &ex) {
|
||||
std::cerr << ex.what() << std::endl;
|
||||
return 84;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user