A small game engine for 2D games based of Raylib
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

157 regels
5.2 KiB

#pragma once
#include <memory>
#include <vector>
#include <chrono>
#include <utility>
#include <ranges>
#include "transform.h"
#include "component.h"
namespace ant::core {
struct entity {
[[nodiscard]] auto transform() const -> ant::core::transform<float> {
return m_transform;
}
auto transform() -> ant::core::transform<float>& {
return m_transform;
}
[[nodiscard]] auto world_transform() const -> ant::core::transform<float> {
ant::core::transform<float> ret{{0,0},0};
if(auto parent = m_parent.lock(); parent) {
ret = parent->world_transform();
}
auto transform_pivot = transform();
if(ret.angle != 0.0f) {
transform_pivot.position.X *= std::cos(ret.angle*std::numbers::pi/180);
transform_pivot.position.Y *= std::sin(ret.angle*std::numbers::pi/180);
}
return ret + transform_pivot;
}
[[nodiscard]] auto parent() const -> std::shared_ptr<entity> {
return m_parent.lock();
}
[[nodiscard]] auto is_visible() const -> bool {
if(auto parent = m_parent.lock(); parent){
if(not parent->is_visible()) {
return false;
}
}
return m_is_visible;
}
[[nodiscard]] auto visibility_flag() const -> bool {
return m_is_visible;
}
[[nodiscard]] auto find_components(std::string name) const -> std::vector<std::shared_ptr<component>> {
decltype(m_components) ret;
auto source = m_components | std::views::filter([&](const auto& elem) {return name == elem->name();});
std::ranges::copy(source, std::back_inserter(ret));
return ret;
}
[[nodiscard]] auto components_list() const -> const std::vector<std::shared_ptr<component>>& {
return m_components;
}
[[nodiscard]] auto components_list() -> std::vector<std::shared_ptr<component>>& {
return m_components;
}
template<std::derived_from<component> ComponentType, typename... ARGS>
auto add_component(ARGS&&... constructor_args) -> std::shared_ptr<entity> {
auto component = std::make_shared<ComponentType>(std::forward<ARGS>(constructor_args)...);
auto self = m_self.lock();
component->m_owner = self;
m_components.push_back(component);
component->initialize();
return self;
}
auto set_visible(bool visible) -> bool {
return std::exchange(m_is_visible, visible);
}
virtual void initialize() {
for (auto& comp : m_components) {
comp->initialize();
}
}
virtual void render() {
if(not visibility_flag()) return;
for(auto& child : m_children | std::views::filter([](const std::shared_ptr<entity>& elem){return elem->visibility_flag();})) {
child->render();
}
for(auto& component : m_components) {
component->render();
}
}
virtual void update(std::chrono::duration<double> delta_time) {
for(auto& child : m_children) {
child->update(delta_time);
}
for(auto& component : m_components) {
component->update(delta_time);
}
}
entity(const std::shared_ptr<entity>& parent)
: m_is_visible(true)
, m_parent(parent)
, m_children()
, m_components()
, m_transform{.position = {0,0}, .angle = 0}
{}
entity()
: m_is_visible(true)
, m_parent(std::shared_ptr<entity>(nullptr))
, m_children()
, m_components()
, m_transform{.position = {0,0}, .angle = 0}
{}
private:
bool m_is_visible;
std::weak_ptr<entity> m_parent;
std::weak_ptr<entity> m_self;
std::vector<std::shared_ptr<entity>> m_children;
std::vector<std::shared_ptr<component>> m_components;
ant::core::transform<float> m_transform;
template<std::derived_from<entity> EntityType>
friend auto make_entity(const std::shared_ptr<entity>& parent, auto&&... ARGS) -> std::shared_ptr<EntityType>;
template<std::derived_from<entity> EntityType>
friend auto make_entity(auto&&... ARGS) -> std::shared_ptr<EntityType>;
friend auto make_entity(const std::shared_ptr<entity>& parent) -> std::shared_ptr<entity>;
};
template<std::derived_from<entity> EntityType>
[[nodiscard]] auto make_entity(const std::shared_ptr<entity>& parent, auto&&... ARGS) -> std::shared_ptr<EntityType> {
auto object = std::make_shared<EntityType>(std::forward<decltype(ARGS)>(ARGS)...);
const std::shared_ptr<entity>& entity_router = object;
entity_router->m_parent = parent;
entity_router->m_self = object;
if(parent) {
parent->m_children.push_back(object);
}
object->initialize();
return object;
}
template<std::derived_from<entity> EntityType>
[[nodiscard]] auto make_entity(auto&&... ARGS) -> std::shared_ptr<EntityType> {
auto object = std::make_shared<EntityType>(std::shared_ptr<entity>(nullptr), std::forward<decltype(ARGS)>(ARGS)...);
const std::shared_ptr<entity>& entity_router = object;
entity_router->m_parent = std::shared_ptr<entity>(nullptr);
entity_router->m_self = object;
object->initialize();
return object;
}
[[nodiscard]] inline auto make_entity(const std::shared_ptr<entity>& parent) -> std::shared_ptr<entity> {
auto object = std::make_shared<entity>(parent);
const std::shared_ptr<entity>& entity_router = object;
entity_router->m_parent = parent;
entity_router->m_self = object;
if(parent) {
parent->m_children.push_back(object);
}
object->initialize();
return object;
}
}