major update

-added custom Array container with iterator support and a space effecient bool specializaton
-changed tabs from spaces to indents
-renamed src/Classes to src/Entities
This commit is contained in:
Joseph Aquino 2025-07-03 15:41:33 -04:00
parent 1f4826fcc4
commit 2a9e531711
19 changed files with 730 additions and 262 deletions

2
.gitignore vendored
View File

@ -384,3 +384,5 @@ Makefile
*.d *.d
*.ninja* *.ninja*
.idea/

View File

@ -11,6 +11,6 @@ Pos=60,60
Size=536,286 Size=536,286
[Window][sdfkjasbdf] [Window][sdfkjasbdf]
Pos=249,161 Pos=679,86
Size=610,481 Size=610,481

3
include/Containers.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
#include <Containers/Array.h>

451
include/Containers/Array.h Normal file
View File

@ -0,0 +1,451 @@
#pragma once
#include "utility.h"
#include <cstddef>
#include <iterator>
namespace container
{
template<typename T, EntityIndex capacity>
class Array
{
public:
using data_type = T;
using pointer = data_type*;
using reference = data_type&;
using const_pointer = const pointer;
using const_reference = const data_type&;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
public:
class Iterator
{
public:
Iterator(const_pointer input)
: m_ptr(input)
{ }
Iterator& operator++()
{
m_ptr++;
return *this;
}
Iterator operator++(int)
{
auto it = *this;
m_ptr++;
return it;
}
Iterator& operator--()
{
m_ptr--;
return *this;
}
Iterator operator--(int)
{
auto it = *this;
m_ptr++;
return it;
}
reference operator[](const int index) const { return m_ptr[index]; }
pointer operator->() const { return m_ptr; }
reference operator*() const { return *m_ptr; }
bool operator==(const Iterator& other) const { return m_ptr == other.m_ptr; }
bool operator!=(const Iterator& other) const { return m_ptr != other.m_ptr; }
private:
pointer m_ptr;
};
class ConstIterator
{
public:
ConstIterator(const_pointer input)
: m_ptr(input)
{ }
ConstIterator& operator++()
{
m_ptr++;
return *this;
}
ConstIterator operator++(int)
{
auto it = *this;
m_ptr++;
return it;
}
ConstIterator& operator--()
{
m_ptr--;
return *this;
}
ConstIterator operator--(int)
{
auto it = *this;
m_ptr++;
return it;
}
const_reference operator[](const int index) const { return m_ptr[index]; }
const_pointer operator->() const { return m_ptr; }
const_reference operator*() const { return *m_ptr; }
bool operator==(const ConstIterator& other) const { return m_ptr == other.m_ptr; }
bool operator!=(const ConstIterator& other) const { return m_ptr != other.m_ptr; }
private:
pointer m_ptr;
};
public:
Array() { m_data = new T[capacity]; }
~Array() { delete[] m_data; }
Array<T, capacity>(const Array<T, capacity>&) = delete;
Array(Array&& other)
: m_data(other.m_data)
{
other.m_data = nullptr;
}
Array& operator=(Array&& other)
{
if (this != &other)
{
delete[] m_data;
m_data = other.m_data;
other.m_data = nullptr;
}
return *this;
}
pointer data() { return m_data; }
reference operator[](const int index) { return m_data[index]; }
const_reference operator[](const int index) const { return m_data[index]; }
inline constexpr EntityIndex size() { return capacity; }
Iterator begin() { return Iterator(m_data); }
Iterator end() { return Iterator(m_data + capacity); }
ConstIterator cbegin() const { return ConstIterator(m_data); }
ConstIterator cend() const { return ConstIterator(m_data + capacity); }
private:
pointer m_data;
};
template <EntityIndex capacity>
class Array<bool, capacity>
{
public:
class reference;
class const_reference;
using data_type = u8;
using pointer = reference;
using const_pointer = const_reference;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
public:
class reference
{
friend class Array;
reference(data_type* ptr_in, u8 mask_in)
: m_ptr(ptr_in)
, m_mask(mask_in)
{
}
public:
~reference()
{ }
reference(const reference&) = default;
operator bool () const
{
return !!(*m_ptr & m_mask);
}
reference& operator=(bool input)
{
if (input)
{
*m_ptr |= m_mask;
}
else
{
*m_ptr &= m_mask;
}
return *this;
}
reference& operator=(const reference& other)
{
return *this = bool(other);
}
void flip()
{
*m_ptr ^= m_mask;
}
private:
data_type* m_ptr;
u8 m_mask;
};
class const_reference
{
friend class Array;
const_reference(data_type* ptr_in, u8 mask_in)
: m_ptr(ptr_in)
, m_mask(mask_in)
{ }
public:
~const_reference()
{ }
const_reference(const const_reference&) = delete;
operator bool () const { return !!(*m_ptr & m_mask); }
const_reference& operator=(bool) = delete;
const_reference& operator=(const const_reference& other) = delete;
const_reference& operator=(const reference& other) = delete;
void flip() = delete;
private:
const data_type* m_ptr;
u8 m_mask;
};
class Iterator
{
public:
Iterator(data_type* input, u8 index)
: m_ptr(input)
, m_currentClusterIndex(index)
{ }
Iterator& operator++()
{
if (m_currentClusterIndex++ == 7)
{
m_currentClusterIndex = 0;
m_ptr++;
}
return *this;
}
Iterator operator++(int)
{
auto it = *this;
if (m_currentClusterIndex++ == 7)
{
m_ptr++;
m_currentClusterIndex = 0;
}
return it;
}
Iterator& operator--()
{
if (m_currentClusterIndex-- == 0)
{
m_ptr--;
m_currentClusterIndex = 7;
}
return *this;
}
Iterator operator--(int)
{
auto it = *this;
if (m_currentClusterIndex-- == 0)
{
m_ptr--;
m_currentClusterIndex = 7;
}
return it;
}
bool operator[](const int) = delete;
reference operator*() const
{
return reference(m_ptr, 1 << m_currentClusterIndex);
}
bool operator==(const Iterator& other) const
{
return (m_ptr == other.m_ptr) && (m_currentClusterIndex == other.m_currentClusterIndex);
}
bool operator!=(const Iterator& other) const
{
return (m_ptr != other.m_ptr) || (m_currentClusterIndex != other.m_currentClusterIndex);
}
private:
data_type* m_ptr;
u8 m_currentClusterIndex{};
};
class ConstIterator
{
public:
ConstIterator(const data_type* input, u8 index)
: m_ptr(input)
, m_currentClusterIndex(index)
{ }
ConstIterator& operator++()
{
if (m_currentClusterIndex++ == 7)
{
m_currentClusterIndex = 0;
m_ptr++;
}
return *this;
}
ConstIterator operator++(int)
{
auto it = *this;
if (m_currentClusterIndex++ == 7)
{
m_ptr++;
m_currentClusterIndex = 0;
}
return it;
}
ConstIterator& operator--()
{
if (m_currentClusterIndex-- == 0)
{
m_ptr--;
m_currentClusterIndex = 7;
}
return *this;
}
ConstIterator operator--(int)
{
auto it = *this;
if (m_currentClusterIndex-- == 0)
{
m_ptr--;
m_currentClusterIndex = 7;
}
return it;
}
bool operator[](const int) = delete;
const_reference operator*() const
{
return const_reference(m_ptr, 1 << m_currentClusterIndex);
}
bool operator==(const ConstIterator& other) const
{ return (m_ptr == other.m_ptr) && (m_currentClusterIndex == other.m_currentClusterIndex); }
bool operator!=(const ConstIterator& other) const
{ return (m_ptr != other.m_ptr) || (m_currentClusterIndex != other.m_currentClusterIndex); }
private:
const data_type* m_ptr;
u8 m_currentClusterIndex{};
};
public:
Array() { m_data = new data_type[(capacity / 8) + 1]; }
~Array() { delete[] m_data; }
Array<bool, capacity>(const Array<bool, capacity>&) = delete;
Array(Array&& other)
: m_data(other.m_data)
{
other.m_data = nullptr;
}
Array& operator=(Array&& other)
{
if (this != &other)
{
delete[] m_data;
m_data = other.m_data;
other.m_data = nullptr;
}
return *this;
}
data_type* data() { return m_data; }
//use readAt() instead
reference operator[](int index)
{
return reference(m_data + (index / 8), 1 << (index % 8));
}
inline constexpr EntityIndex size() { return capacity; }
bool readAt(const int index) const { return m_data[index / 8] & (1 << (index % 8)); }
void setTrueAt(const int index) { m_data[index / 8] |= (1 << (index % 8)); }
void setFalseAt(const int index) { m_data[index / 8] &= ~(1 << (index % 8)); }
Iterator begin() { return Iterator(m_data, 0); }
Iterator end() { return Iterator(m_data + (capacity / 8), capacity % 8); }
ConstIterator cbegin() const { return ConstIterator(m_data, 0); }
ConstIterator cend() const { return ConstIterator(m_data + (capacity / 8), capacity % 8); }
private:
data_type* m_data;
};
}//namespace

View File

@ -37,5 +37,5 @@ public:
bool isAlive() const; bool isAlive() const;
private: private:
EntityIndex m_id; EntityIndex m_index;
}; };

View File

@ -8,6 +8,8 @@
class EntityManager class EntityManager
{ {
public:
void update();
private: private:
EntityView getEntiites(EntityTag); EntityView getEntiites(EntityTag);

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "utility.h"
#include <cstddef>
#include <tuple> #include <tuple>
#include <vector> #include <vector>
@ -19,6 +21,7 @@ private:
ComponentVectorTuple m_components; ComponentVectorTuple m_components;
std::vector<EntityTag> m_tags; std::vector<EntityTag> m_tags;
std::vector<bool> m_aliveStates; std::vector<bool> m_aliveStates;
std::vector<size_t> m_ids;
private: private:
EntityMemoryPool(); EntityMemoryPool();
@ -41,5 +44,7 @@ public:
bool getAlive(EntityIndex) const; bool getAlive(EntityIndex) const;
size_t getId(EntityIndex) const;
void removeEntity(EntityIndex); void removeEntity(EntityIndex);
}; };

View File

@ -22,13 +22,12 @@ class EntityViewIterator
Entity operator*(); Entity operator*();
Entity operator[](int); Entity operator[](int);
Entity* operator->();
bool operator==(EntityViewIterator); bool operator==(EntityViewIterator);
bool operator!=(EntityViewIterator); bool operator!=(EntityViewIterator);
private: private:
Entity m_currentEntity; EntityIndex m_currentEntity;
}; };
class EntityViewConstIterator class EntityViewConstIterator
@ -49,14 +48,12 @@ class EntityViewConstIterator
const Entity operator[](int index); const Entity operator[](int index);
const Entity* operator->();
bool operator==(EntityViewConstIterator); bool operator==(EntityViewConstIterator);
bool operator!=(EntityViewConstIterator); bool operator!=(EntityViewConstIterator);
private: private:
Entity m_currentEntity; EntityIndex m_currentEntity;
}; };
class EntityView class EntityView
@ -72,8 +69,6 @@ public:
iterator begin() { return iterator(m_start); } iterator begin() { return iterator(m_start); }
iterator end() { return iterator(m_start + m_size); } iterator end() { return iterator(m_start + m_size); }
const_iterator cbegin() const { return const_iterator(m_start); } const_iterator cbegin() const { return const_iterator(m_start); }
const_iterator cend() const { return const_iterator(m_start + m_size); } const_iterator cend() const { return const_iterator(m_start + m_size); }
private: private:

View File

@ -3,7 +3,9 @@
#include <iostream> #include <iostream>
#ifdef LOG_ENABLE #ifdef LOG_ENABLE
#define LOG_CONDITON(x) if (x)
#define LOG(x) std::cout << x << "\n" #define LOG(x) std::cout << x << "\n"
#else #else
#define LOG(x) #define LOG(x)
#define LOG_CONDITON(x)
#endif #endif

View File

@ -29,20 +29,24 @@ namespace util
{ {
using namespace std::string_view_literals; using namespace std::string_view_literals;
inline constexpr EntityIndex MAX_PLAYERS{1u};
inline constexpr EntityIndex MAX_ENTITIES {60'000u};
inline constexpr EntityIndex MAX_TILES {1'000u}; inline constexpr EntityIndex MAX_TILES {1'000u};
inline constexpr EntityIndex MAX_ENEMIES {1'000u}; inline constexpr EntityIndex MAX_ENEMIES {1'000u};
inline constexpr EntityIndex MAX_ENTITIES {MAX_PLAYERS + MAX_TILES + MAX_ENEMIES};
// used for imgui // used for imgui
inline constexpr std::array<const char*, tagCount> tagStringsC = inline constexpr std::array<const char*, tagCount> tagStringsC =
{ {
"player" "player",
"tile",
"enemy"
}; };
inline constexpr std::array<std::string_view, tagCount> tagStrings = inline constexpr std::array<std::string_view, tagCount> tagStrings =
{ {
"player"sv "player"sv,
"tile"sv,
"enemy"sv
}; };
inline constexpr std::array<EntityIndex, tagCount> tagStart = inline constexpr std::array<EntityIndex, tagCount> tagStart =

View File

@ -1,52 +0,0 @@
#include <Entities/Entity.h>
#include <Entities/Components.h>
#include <Entities/EntityMemoryPool.h>
#include <utility.h>
Entity::Entity(EntityIndex id_in)
: m_id(id_in)
{
}
template<typename T>
bool Entity::hasComponent() const
{
return EntityMemoryPool::instance().hasComponent<T>(m_id);
}
template<typename T>
T& Entity::getComponent() const
{
return EntityMemoryPool::instance().getComponent<T>(m_id);
}
template<typename T>
T& Entity::getComponent()
{
return EntityMemoryPool::instance().getComponent<T>(m_id);
}
template<typename T>
void Entity::addComponent(const T&& data)
{
T& component = EntityMemoryPool::instance().getComponent<T>(m_id);
component = data;
component.active = true;
}
EntityIndex Entity::id() const
{
return m_id;
}
EntityTag Entity::tag() const
{
return EntityMemoryPool::instance().getTag(m_id);
}
bool Entity::isAlive() const
{
return EntityMemoryPool::instance().getAlive(m_id);
}

View File

@ -1,52 +0,0 @@
#include <Entities/EntityMemoryPool.h>
#include <Entities/Entity.h>
#include <vector>
#include <utility.h>
EntityMemoryPool::EntityMemoryPool()
{
std::apply([=](auto&&... args) {((args.reserve(util::MAX_ENTITIES)), ...); }, m_components);
m_tags.reserve(util::MAX_ENTITIES);
m_aliveStates.reserve(util::MAX_ENTITIES);
}
EntityMemoryPool& EntityMemoryPool::instance()
{
static EntityMemoryPool pool{};
return pool;
}
template<typename T>
bool EntityMemoryPool::hasComponent(EntityIndex id) const
{
return std::get<std::vector<T>>(m_components)[id].active;
}
template<typename T>
T& EntityMemoryPool::getComponent(EntityIndex id) const
{
return std::get<std::vector<T>>(m_components)[id];
}
template<typename T>
T& EntityMemoryPool::getComponent(EntityIndex id)
{
return std::get<std::vector<T>>(m_components)[id];
}
EntityTag EntityMemoryPool::getTag(EntityIndex id) const
{
return m_tags[id];
}
bool EntityMemoryPool::getAlive(EntityIndex id) const
{
return m_aliveStates[id];
}
void EntityMemoryPool::removeEntity(EntityIndex id)
{
m_aliveStates[id] = false;
return;
}

52
src/Entities/Entity.cpp Normal file
View File

@ -0,0 +1,52 @@
#include <Entities/Entity.h>
#include <Entities/Components.h>
#include <Entities/EntityMemoryPool.h>
#include <utility.h>
Entity::Entity(EntityIndex index_in)
: m_index(index_in)
{
}
template<typename T>
bool Entity::hasComponent() const
{
return EntityMemoryPool::instance().hasComponent<T>(m_index);
}
template<typename T>
T& Entity::getComponent() const
{
return EntityMemoryPool::instance().getComponent<T>(m_index);
}
template<typename T>
T& Entity::getComponent()
{
return EntityMemoryPool::instance().getComponent<T>(m_index);
}
template<typename T>
void Entity::addComponent(const T&& data)
{
T& component = EntityMemoryPool::instance().getComponent<T>(m_index);
component = data;
component.active = true;
}
EntityIndex Entity::id() const
{
return EntityMemoryPool::instance().getId(m_index);
}
EntityTag Entity::tag() const
{
return EntityMemoryPool::instance().getTag(m_index);
}
bool Entity::isAlive() const
{
return EntityMemoryPool::instance().getAlive(m_index);
}

View File

@ -5,6 +5,11 @@
inline constexpr EntityIndex PLAYER_INDEX = 0; inline constexpr EntityIndex PLAYER_INDEX = 0;
void EntityManager::update()
{
}
inline Entity EntityManager::player() inline Entity EntityManager::player()
{ {
return m_player; return m_player;

View File

@ -0,0 +1,58 @@
#include <Entities/EntityMemoryPool.h>
#include <Entities/Entity.h>
#include <cstddef>
#include <vector>
#include <utility.h>
EntityMemoryPool::EntityMemoryPool()
{
std::apply([=](auto&&... args) {((args.reserve(util::MAX_ENTITIES)), ...); }, m_components);
m_tags.reserve(util::MAX_ENTITIES);
m_aliveStates.reserve(util::MAX_ENTITIES);
}
EntityMemoryPool& EntityMemoryPool::instance()
{
static EntityMemoryPool pool{};
return pool;
}
template<typename T>
bool EntityMemoryPool::hasComponent(EntityIndex index) const
{
return std::get<std::vector<T>>(m_components)[index].active;
}
template<typename T>
T& EntityMemoryPool::getComponent(EntityIndex index) const
{
return std::get<std::vector<T>>(m_components)[index];
}
template<typename T>
T& EntityMemoryPool::getComponent(EntityIndex index)
{
return std::get<std::vector<T>>(m_components)[index];
}
EntityTag EntityMemoryPool::getTag(EntityIndex index) const
{
return m_tags[index];
}
bool EntityMemoryPool::getAlive(EntityIndex index) const
{
return m_aliveStates[index];
}
size_t EntityMemoryPool::getId(EntityIndex index) const
{
return m_ids[index];
}
void EntityMemoryPool::removeEntity(EntityIndex index)
{
m_aliveStates[index] = false;
return;
}

View File

@ -19,26 +19,26 @@ EntityViewIterator::EntityViewIterator(EntityIndex index)
EntityViewIterator& EntityViewIterator::operator++() EntityViewIterator& EntityViewIterator::operator++()
{ {
m_currentEntity.m_id++; m_currentEntity++;
return *this; return *this;
} }
EntityViewIterator EntityViewIterator::operator++(int) EntityViewIterator EntityViewIterator::operator++(int)
{ {
m_currentEntity.m_id++; m_currentEntity++;
return m_currentEntity.m_id - 1; return m_currentEntity - 1;
} }
EntityViewIterator& EntityViewIterator::operator--() EntityViewIterator& EntityViewIterator::operator--()
{ {
m_currentEntity.m_id--; m_currentEntity--;
return *this; return *this;
} }
EntityViewIterator EntityViewIterator::operator--(int) EntityViewIterator EntityViewIterator::operator--(int)
{ {
m_currentEntity.m_id--; m_currentEntity--;
return m_currentEntity.m_id + 1; return m_currentEntity + 1;
} }
Entity EntityViewIterator::operator*() Entity EntityViewIterator::operator*()
@ -48,22 +48,17 @@ Entity EntityViewIterator::operator*()
Entity EntityViewIterator::operator[](int index) Entity EntityViewIterator::operator[](int index)
{ {
return m_currentEntity.m_id + index; return m_currentEntity + index;
}
Entity* EntityViewIterator::operator->()
{
return &m_currentEntity;
} }
bool EntityViewIterator::operator==(EntityViewIterator other) bool EntityViewIterator::operator==(EntityViewIterator other)
{ {
return m_currentEntity.m_id == other->m_id; return m_currentEntity == other.m_currentEntity;
} }
bool EntityViewIterator::operator!=(EntityViewIterator other) bool EntityViewIterator::operator!=(EntityViewIterator other)
{ {
return m_currentEntity.m_id != other->m_id; return m_currentEntity != other.m_currentEntity;
} }
//const iterator //const iterator
@ -75,26 +70,26 @@ EntityViewConstIterator::EntityViewConstIterator(EntityIndex index)
EntityViewConstIterator& EntityViewConstIterator::operator++() EntityViewConstIterator& EntityViewConstIterator::operator++()
{ {
m_currentEntity.m_id++; m_currentEntity++;
return *this; return *this;
} }
EntityViewConstIterator EntityViewConstIterator::operator++(int) EntityViewConstIterator EntityViewConstIterator::operator++(int)
{ {
m_currentEntity.m_id++; m_currentEntity++;
return m_currentEntity.m_id - 1; return m_currentEntity - 1;
} }
EntityViewConstIterator& EntityViewConstIterator::operator--() EntityViewConstIterator& EntityViewConstIterator::operator--()
{ {
m_currentEntity.m_id--; m_currentEntity--;
return *this; return *this;
} }
EntityViewConstIterator EntityViewConstIterator::operator--(int) EntityViewConstIterator EntityViewConstIterator::operator--(int)
{ {
m_currentEntity.m_id--; m_currentEntity--;
return m_currentEntity.m_id + 1; return m_currentEntity + 1;
} }
const Entity EntityViewConstIterator::operator*() const Entity EntityViewConstIterator::operator*()
@ -104,20 +99,15 @@ const Entity EntityViewConstIterator::operator*()
const Entity EntityViewConstIterator::operator[](int index) const Entity EntityViewConstIterator::operator[](int index)
{ {
return m_currentEntity.m_id + index; return m_currentEntity + index;
}
const Entity* EntityViewConstIterator::operator->()
{
return &m_currentEntity;
} }
bool EntityViewConstIterator::operator==(EntityViewConstIterator other) bool EntityViewConstIterator::operator==(EntityViewConstIterator other)
{ {
return m_currentEntity.m_id == other->m_id; return m_currentEntity == other.m_currentEntity;
} }
bool EntityViewConstIterator::operator!=(EntityViewConstIterator other) bool EntityViewConstIterator::operator!=(EntityViewConstIterator other)
{ {
return m_currentEntity.m_id != other->m_id; return m_currentEntity != other.m_currentEntity;
} }

View File

@ -1,4 +1,6 @@
#include "Containers/Array.h"
#include "log.h"
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
#include <imgui-SFML.h> #include <imgui-SFML.h>
#include <imgui.h> #include <imgui.h>
@ -10,6 +12,7 @@
int main() int main()
{ {
container::Array<bool, 3> arr;
auto window = sf::RenderWindow(sf::VideoMode({ 1920u, 1080u }), "Fake Mario"); auto window = sf::RenderWindow(sf::VideoMode({ 1920u, 1080u }), "Fake Mario");
window.setFramerateLimit(144); window.setFramerateLimit(144);

View File