e.g an "isOpen" member might make sense for a "door" entity, but it hardly makes sense for a "bullet" entity.
My understanding is that Quake2 "solves" this issue by making a big structure from the union of all specialized members (see: https://github.com/id-Software/Quake-2/blob/master/game/g_lo... ).
Although Quake2 certainly is industry-proven, it doesn't feel right for every specialized entity behaviour function to depend on members needed by other specialized entity behaviour functions.
But this is all that is really necessary. Once you start getting into components, you add a lot of complexity (even if the pitch is that it's "simple").
I'm not fully convinced by components either, I don't like the idea of the bullet behaviour code having to check if "this entity has 'propeller' and 'rigid_body' components", as if the bullet behaviour code had to re-discover what a bullet was made of (BTW, this feels like a re-implementation of coarse-grained dynamic duck-typing for static languages).
This problem is less visible when the game logic is written in Lua, where dynamic duck-typing is the rule.
I do write my game logic in C++/D, though, and the problem is perfectly visible.
The way you describe how you would do it raises a few questions ; because now it seems you can't process entities in a systematic/opaque way.
This implies that, say, the renderer has to loop over bullets, then to loop over doors, and so on. Each time a new entity type is added, this part of the code has to be modified, even though most entities might share the drawing code (e.g mesh).
This sequence of loops appears in many places, like collision checking, game logic update, save/load, etc. and all of them have to be updated when a new entity type is added.
Something in my understanding must be wrong, because the way you do it obviously works ; maybe the issues I just described isn't so problematic in practise?
Bullets probably would be simple structs in a shooty game, not full blown entities.
The next step beyond that simple approach is to store the components outside the entity. E.g. using SoA that Jon's new language has support for.
In my game (http://moonman.io) i use an approach similar to that in the bitsquid engine, with static polymorphism and crtp and other nonsense. It works but i admit is probably overkill.
You still need to render bullets, to load/save them to disk, to synchronize them over a network ; some of them move by themselves, they physically interact with the rest of the world, play sounds, and have animations. And actually, many other entities also inflict damage on collision (spikes, forcefields ...).
So from the point of view of your game low-level internals, there's nothing very specific about bullets.
BTW, the same applies with powerups, doors, monsters, spikes, moving platforms, ...
But some bullets might have a locked target, some powerups might disappear after a while, some doors might need a key to be open ... these behaviours are typically not shared between game object types ; I might be wrong, but having a new component/array for each of them also seems overkill.
> The next step beyond that simple approach is to store the components outside the entity. E.g. using SoA that Jon's new language has support for.
For one second I thought you were talking about "service-oriented architecture" :-)