Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

281 Neutral

About Krankles

  • Rank
  1. Hi, I'm reading up on ECS on t-machine and other places, but now I'm trying to implement my own simple ECS. I'm stuck on trying to convert https://github.com/adamgit/Entity-System-RDBMS-Inspired-Java from Java to C++. In the EntityManager, he has a variable called componentStores which is defined as  HashMap<Class, HashMap<Integer, ? extends Component>> componentStores; However, I don't know the equivalent of this in C++.   So far, I've been able to create and generate entity ids, but I don't know how to actually add the component to the entity in a map. In the hashmap above, what types of data is it containing? Also, the second hashmap inside the hashmap, is the "? extends Component" supposed to be a pointer to a given Component? For example, I made a PositionComponent, would the hashmap contain a pointer to the PositionComponent? And, what is the point of the first data type "Class?" Sorry if this doesn't make sense, I don't fully understand what's happening, but the big question is how can you convert the hashmap into C++?   My entity header file looks like this: #ifndef ENTITY_MANAGER_H #define ENTITY_MANAGER_H #include <map> #include <vector> #include <cstdint> #include <iostream> #include <algorithm> class EntityManager { public: EntityManager(); ~EntityManager(); uint32_t create_entity(); void kill_entity(uint32_t id); private: std::vector<uint32_t> entity_list; uint32_t assignable_entity_id; uint32_t generate_entity_id(); }; #endif and this is my EntityManager source file #include "EntityManager.h" EntityManager::EntityManager() : assignable_entity_id(1) { }; EntityManager::~EntityManager() { }; uint32_t EntityManager::create_entity() { uint32_t id = generate_entity_id(); if (id < 1) { // throw error return 0; } else { entity_list.push_back(id); return id; } } uint32_t EntityManager::generate_entity_id() { if (assignable_entity_id < UINT32_MAX) { std::cout << "Generated ID: " << assignable_entity_id << std::endl; return assignable_entity_id++; } else { for (unsigned int i = 1; i < UINT32_MAX; i++) { std::vector<uint32_t>::iterator it = std::find(entity_list.begin(), entity_list.end(), i); if (*it != i) { std::cout << "Generated ID: " << i << std::endl; return i; } } // throw error return 0; } } void EntityManager::kill_entity(uint32_t id) { std::vector<uint32_t>::iterator it = entity_list.begin(); for (; it != entity_list.end(); it++) { if (*it == id) { std::cout << "Killing Entity: " << *it << std::endl; entity_list.erase(it); return; } } }  Any help would be greatly appreciated, thanks.
  2. Thanks for the descriptive answers guys! I think I got it now.
  3.   I see! This makes a lot of sense, thanks. And yeah, I should probably learn more of C++ before I start doing this. However, I have a quick question. What if you wanted separate functionality for a specific entity that operates within the same system? Should you just create a new system entirely? Or possibly check if it's a specific entity and run that code inside the system? For example, I have a JumpSystem and the player could double jump but the enemy can't, should you create a new DoubleJumpSystem? Or should you just check within the JumpSystem for the player entity? Or another example to possibly clear the question up, what if I have an AnimationSystem and the 2 different entities animate differently, should it just check for a specific entity or create a new system?   Thank you.
  4. Sorry for the triple post! But, ignore what I said earlier, I was being stupid. I think I got a good system going. I need to know if this is how a decent ECS should work though, or even if this is a good basis. I took out the Render component and replaced it with Velocity and Position instead, as I find it much easier to start out with. #include "Entity.h" #include "PositionComponent.h" #include "VelocityComponent.h" #include "MovementSystem.h"   int main(int argc, char const* argv[]) {     MovementSystem movementSystem;       Entity player;     player.AddComponent(new PositionComponent(2, 2));     player.AddComponent(new VelocityComponent(5, 5));       for (int i = 0; i < 10; i++) {         movementSystem.ProcessEntity(&player);     }       return 0; } That's basically how everything works, I create a movement system, entity, add components to the entity and then use the system to process my entity. I don't know whether or not this is how ECS works or not, but it seems right to me.   MovementSystem.h #ifndef MOVEMENT_SYSTEM_H #define MOVEMENT_SYSTEM_H   #include "EntitySystem.h" #include <vector>   class VelocityComponent; class PositionComponent;   class MovementSystem : public EntitySystem {     public:         MovementSystem();         ~MovementSystem();           void ProcessEntity(Entity* entity);       private:         VelocityComponent* velocityComponent;         PositionComponent* positionComponent; };   #endif MovementSystem.cpp #include <iostream> #include "Entity.h" #include "MovementSystem.h" #include "PositionComponent.h" #include "VelocityComponent.h"   MovementSystem::MovementSystem() {   }   MovementSystem::~MovementSystem() {   }   void MovementSystem::ProcessEntity(Entity* entity) {     positionComponent = dynamic_cast<PositionComponent *>(entity->GetComponent("position"));     velocityComponent = dynamic_cast<VelocityComponent *>(entity->GetComponent("velocity"));       positionComponent->SetX(positionComponent->GetX() + velocityComponent->GetVelocityX());     positionComponent->SetY(positionComponent->GetY() + velocityComponent->GetVelocityY());     std::cout << "Player X: " <<  positionComponent->GetX() << std::endl; } That's how my movement system works, but I was wondering if there's anything I could improve my system on?
  5. So I've been researching even more, and I am confused a bit now. Should the System know how to do a function? Or should the Component know how to do a function? For example, JumpComponent and JumpSystem, should the System know how to Jump? Or should the Component know how to jump? I'm confused because I've read that the component should just contain the data, etc, and the system should handle the components. However, in some people's implementations, I've seen them having the component having the data and knowing how to do something, and the system should just have a list of components, and make them interact with each other.   Also, I've been thinking, for my RenderComponent and RenderSystem -- to make it work -- should I have the Render function inside my RenderComponent, and then have the RenderSystem loop through all of the RenderComponents and call the respective Render function?   Not only that, but I was also thinking that for my problem earlier, I could possibly fix the problem by using my newly created RenderSystem by passing in the component pointer to the RenderSystem component list and then be able to access the member named "image".   Lastly, I was wondering, why do people in their Entity class don't include the component header? I see them just doing "Class Component;" and that's it. (Sorry for the noob questions, I didn't fully learn C++, I learned the basics, learned some SDL and went on creating basic games. I also can't test this ideas right now because I'm busy with other things currently.)   Thanks.
  6.   My bad, I guess I got too used to it!   Anyways, thanks guys, I started my own attempt at ECS, but I'm having troubles connecting things together. This is what I have so far.   Entity.h #ifndef ENTITY_H #define ENTITY_H   #include <vector> #include <string> #include "Component.h"   class Entity {     public:         Entity();         ~Entity();           void AddComponent(Component *component);         Component* GetComponent(std::string name);         void Update();       private:         std::vector<Component*> components; };   #endif   Entity.cpp #include "Entity.h"   Entity::Entity() {   }   Entity::~Entity() {   }   void Entity::AddComponent(Component *component) {     components.push_back(component); }   Component* Entity::GetComponent(std::string name) {     for (unsigned int i = 0; i < components.size(); i++) {         if (name.compare(components[i]->name) == 0)             return components[i];     } }   void Entity::Update() {     for (unsigned int i = 0; i < components.size(); i++) {         components[i]->Update();     } }   BaseSystem.h #ifndef BASE_SYSTEM_H #define BASE_SYSTEM_H   class BaseSystem {     public:         BaseSystem();         virtual ~BaseSystem(); };   #endif   Component.h #ifndef COMPONENT_H #define COMPONENT_H   #include <string>   class Component {     public:         Component();         virtual ~Component();           std::string name;         virtual void Update(); };   #endif   RenderSystem.h #ifndef RENDER_SYSTEM_H #define RENDER_SYSTEM_H   #include <SDL2/SDL.h>   class RenderSystem : public BaseSystem {     public:         void Render(SDL_Renderer* renderer, SDL_Texture* image); };   #endif   RenderSystem.cpp #include "RenderSystem.h"   void RenderSystem::Render(SDL_Renderer* renderer, SDL_Texture* image) {     SDL_RenderCopy(renderer, image, NULL, NULL); }   RenderComponent.h #ifndef RENDER_COMPONENT_H #define RENDER_COMPONENT_H #include "Component.h" #include <SDL2/SDL.h> class RenderComponent : public Component { public:         RenderComponent();         ~RenderComponent();         SDL_Texture* image; }; #endif   RenderComponent.cpp #include "RenderComponent.h" RenderComponent::RenderComponent(){ name = "render"; }   So that's all I have right now, but I don't know if I'm even doing this right or not. Right now, I don't want to complicate anything, and just want a simple entity (background, player, what-have-you) to draw. Once I have that down, I believe I can implement the rest.   I need some help being guided in the right direction, I know my code might look like utter crap right now, but I'm just learning, so please bear with me. When I try creating an entity in my test program, I tried doing this: Entity background; background.AddComponent(new RenderComponent()); SDL_Surface *tmp_image = NULL; tmp_image = IMG_Load("gfx/background.png"); background.GetComponent("render")->image = SDL_CreateTextureFromSurface(renderer, tmp_image); But it says that "class Component" has no member named "image". Which is obvious, since it's not declared in the class Component, but in RenderComponent. How do I solve this? Or should I NOT be doing this?   Thanks.   EDIT: Basically what I'm asking is, is that how you correctly add a component? If so, then when I get my component, I want to be able to manipulate it, but it doesn't let me due to the class Component having no member named image. The list of components is an array of Components, which means I can't access the image variable. Also, how are systems supposed to work. I've been googling around and it's somewhat confusing. I feel like I'm doing this completely wrong.
  7. Hello, so I've made a couple of basic games in C++ and AS3, through the traditional object oriented way, and then I came across an article about Entity Component Systems on GameDev. Everything made a lot more sense than having a big hierarchy of classes, but as I try to research more about this on google and gamedev, I only find explanations on how it works (and very partial implementations). I can't wrap my head around getting the design to work.   I've seen previous threads that have some code in them, but I still don't quite understand it. Is there any existing tutorials, books, resources, etc, that I could read to further understand how it works? It'd also help immensely if there's code to go along with it, as I don't understand much without some code. Also, if anyone has made a simple game or basic system showing how it works, I'd be very interested in seeing your code, most preferably in C++ as well. Thanks.
  8. Krankles

    C++11 Lesson Two: Variables!

  9. Krankles

    C++11 Lesson One: Hello World!

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!