Skip to content

santiago0411/ECS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 

Repository files navigation

ECS (Entity Component System)

A simple implementation of an entity component system for a game engine. API based on entt. Provides classes to create/destroy entities and to add any type of components to them. As well as a 'View' to iterate over all existing entities have all the provided types. The component data of a specific type is packed together in an array so that iterating over it will yield more cpu cache hits. Using C++ powerful template system the View class provides a way to mix and match any type of components and iterate over them.

Usage Example

#include <iostream>
#include <format>

#include "Registry.hpp"

struct UUIDComponent
{
	uint64_t Id;
};

struct TagComponent
{
	std::string Name;
};

struct PointComponent
{
	int X, Y;

	std::string ToString() const
	{
		return std::format("({}, {})", X, Y);
	}
};

int main()
{
	using namespace ECS;

	// Create a new registry
	Registry registry;

	// Create entities
	Entity entity1 = registry.CreateEntity();
	Entity entity2 = registry.CreateEntity();

	// Add components to them with different values
	registry.AddComponent<UUIDComponent>(entity1, 5);
	registry.AddComponent<TagComponent>(entity1, "Pepe");
	registry.AddComponent<PointComponent>(entity1, 1, 2);

	registry.AddComponent<UUIDComponent>(entity2, 10);
	registry.AddComponent<TagComponent>(entity2, "Tom");
	registry.AddComponent<PointComponent>(entity2, 3, 4);

	// Create a view that will match every entity that has components of type
	// UUIDComponent, TagComponent, PointComponent, in this case both entities will match
	// because both have all three types
	View view = registry.View<UUIDComponent, TagComponent, PointComponent>();

	std::cout << "View.Each() with Entity:\n\n";
	// First way to iterate over all the entities in the view using View.Each()
	view.Each([](Entity entity, UUIDComponent& uuid, TagComponent& tc, PointComponent& pc)
	{
		std::cout << "- Entity: " << entity << 
			"\n\tId: " << uuid.Id <<
			"\n\tName: " << tc.Name << 
			"\n\tPoint: " << pc.ToString() << "\n\n";
	});

	std::cout << "\nView.Each() with no Entity:\n\n";
	// Same as above but it can also not have entity as the lambda's first argument
	view.Each([](UUIDComponent& uuid, TagComponent& tc, PointComponent& pc)
	{
		std::cout << "Id: " << uuid.Id <<
			"\nName: " << tc.Name <<
			"\nPoint: " << pc.ToString() << "\n\n";
	});

	std::cout << "\nRanged-based loop on the view:\n\n";
	// Iterate over the view using a range-based loop
	for (const Entity entity : view)
	{
		// Get the tuple with all the components using view.Get(entity)
		// Using C++17 structured bindings there is no need to have
		// std::tuple<UUIDComponent, TagComponent, PointComponent> as the return type
		// The get function also accepts template arguments if you only want some of the components
		// i.e. const auto& [tagComponent] = view.Get<TagComponent>(entity); 
		const auto& [uuid, tc, pc] = view.Get(entity);
		std::cout << "- Entity: " << entity <<
			"\n\tId: " << uuid.Id <<
			"\n\tName: " << tc.Name <<
			"\n\tPoint: " << pc.ToString() << "\n\n";
	}

	// Finally destroy the entities from the registry
	registry.DestroyEntity(entity1);
	registry.DestroyEntity(entity2);

	return 0;
}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages