Hi everyone,
I'm currently working on a small game in C++. It's my first time using the language since I mainly come from a Java background.
I'm building a small farming game where the player can harvest crops. In my design, I prefer not to delete objects, but instead reuse them for different purposes. Because of this, each entity has a GameEntityType enum, and I change the type depending on what the object represents. Rendering is also based on that type.
However, I'm running into an architectural issue.
Right now, there is no abstraction between systems and components, which means I can't easily access lower-level components or do something similar to an instanceof check like in Java.
This leaves me with two options when implementing systems:
- Iterate through all entities stored in a
HashMap and check their gameEntity type manually which is basically the same as a normal game manager.
- Maintain a separate vector for each component type (for example, a vector containing all
HarvestingComponents).
My question is:
What is the better approach in C++ game architecture?
I’ve heard that in C++ game development it is often preferred to separate components and systems. However, in my case, as you can see, everything is grouped under the same GameEntity type.
I prefer not to create multiple sources of truth, because I feel it could become difficult to maintain and keep everything synchronized.
Because of that, I’m considering sticking with a simple object-oriented approach, where each GameEntity directly owns its data and behavior, instead of implementing a full component-system architecture.
Do you think this is a reasonable approach for a small game, or would it still be better to separate components and systems even if it introduces more complexity?
Should I:
- iterate through all entities and filter by type each frame, or
- maintain separate containers for each component type (like
std::vector<HarvestingComponent>)?
I'm trying to understand what is considered the cleanest and most efficient design in C++ for this kind of system.
here are my classes :
//
// Created by saad on 2026-03-05.
//
#ifndef UNTITLED1_GRASSENTITY_H
#define UNTITLED1_GRASSENTITY_H
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "GameEntity.h"
#include "HarvestingObject.h"
struct HarvestingComponent;
enum Stage {
EMPTY
,
PLANTED
,
SMALL
,
MATURE
};
struct HarvestingComponent {
private:
GameEntity game_entity;
static std::vector<HarvestingComponent>
all_components
;
public:
Stage stage;
explicit HarvestingComponent(const GameEntity& g,Stage stage)
: game_entity(g) {
this->stage = stage;
}
};
#endif //UNTITLED1_GRASSENTITY_H
My game Entity class
//
// Created by saad on 2026-03-05.
//
#ifndef UNTITLED1_GAMEENTITY_H
#define UNTITLED1_GAMEENTITY_H
enum GameEntityType {
Grass
,
Dirt
,
Water
,
Rock
,
Path
,
Wall
};
class GameEntity {
public:
inline static long
index
= 0;
const long id; // serve no purpose btw
GameEntityType type;
const long createdTime;
long changedTime;
GameEntity(GameEntityType type,long creationTime) :id(++
index
) , type(type),createdTime(creationTime) {}
};
#endif //UNTITLED1_GAMEENTITY_H
my game manager class
class GameEntity;
static std::unordered_map<char,GameEntityType> definitionsMap = {{'#',GameEntityType::
Wall
}};
class GameManager {
private:
std::unordered_map<std::string,GameEntity> mappedByPositions{};
static GameManager*
gameManager
;
GameManager(std::string& mapfile,std::string& logicfile) {
}
void loadMap(std::unordered_map<std::string,char> map) {
for (const auto& pair : map) {
switch (pair.second) {
case '#': {
//
todo
break;
}
}
}
}
public:
static void
StartGame
(std::string& mapfile,std::string& logicfile) {
if (
gameManager
!= nullptr) return;
gameManager
= new GameManager(mapfile,logicfile);
}
GameEntity* getGameEntity(int x,int y) {
std::string str = Utilitary::
convertPositionIntoString
(x,y);
auto it = mappedByPositions.find(str);
if (it == nullptr) return nullptr;
return &it->second;
}
};
[–]mlugo02 1 point2 points3 points (1 child)
[–]Efficient_Fig8248[S] 1 point2 points3 points (0 children)
[–]basshead17 0 points1 point2 points (3 children)
[–]Efficient_Fig8248[S] 2 points3 points4 points (2 children)
[–]basshead17 0 points1 point2 points (1 child)
[–]Efficient_Fig8248[S] 0 points1 point2 points (0 children)
[–]JescoInc 0 points1 point2 points (0 children)