However, then that means the render system deals with whole assets and not just graphical primitives, right? But how does that jibe with what the person on that gamedev.net site was saying?
Assets ARE data structures of graphical primitives. They are a set of instructions to the Render System as to how this particular asset is produced out of graphical primitives. The supplementary data provided by the graphics component tells us what transformations are applied to that data before/after it's position is evaluated in real space*.
In other words, the Render System only deals with graphical primitives, but receives instructions in the form of assets and transformations. To be clear, a transformation is typically in the form of the traditional scale, translation, and rotation matrices (but there are others that we produce from a combination of these- like shearing and... stuff >_>).
* This can get a little confusing, because our components are supposed to be shared whenever possible. We don't want to put graphical transformations on a graphics component if that same information is used by logic (such as rotation and location). HOWEVER, sometimes we actually want the logical position and the mesh position to be different-- not often, but sometimes. This just gets into implementation details. The spirit of components remains the same.
And, I suppose, the RenderSystem also stores a copy of a pointer to the AssetLibrary so it can access it, right?
Yep! You CAN store the reference to the asset on the entity instead of the key for the library, but only processes related to Asset Loading should modify that reference. Most any specialized modifications or transformations of assets for a particular special entity are handled in its various graphics components.
Doesn't the input manager then also have to know about all possible places it can send the input? Like it has to know about the pile of entities, so it can send input there. It needs to know about the windows on the display, so it can send input there. But isn't that making too many dependencies?
We don't send input to entities, we just send input to Screens, Frame, Windows, whatever you want to call them. This gets into window management-- but basically each different window may have some specialized keybindings for that window. The input manager simply maps key input to an action for whatever window has focus. In the case of actual gameplay, we aren't necessarily sending input directly to entities, but through the game window, where the action is delegated to the appropriate entity.
Honestly, it's better to learn why this is important by NOT doing it the first couple times around. Window management is a PITA that you should avoid until necessary, as it will keep you from actually working on your game.
So then event systems are fundamentally tied to the "inheritance" method of construction, where you subclass entities to get different kinds of entities?
Yes, event systems are all about letting disjunct classes do all of the work through a messaging system. Component systems aren't that different, except that all messaging is isolated to relevant components in relevant systems- so there is no classical inheritance scheme. For game logic, it's all to accomplish the same thing, components just tend to give us a more transparent awareness and simplicity into specifying the functionality of our game.
Since classes do the logic in event systems, we can easily make design mistakes-- like, say, the application of a stun effect. Where should it go? Well, the instigator should send a message to another entity to be stunned. The recipient of the stun message then determines whether it should be stunned or not (or do something else). This represents a continuum of game logic that really doesn't need to be happening in two different places.
Nonetheless, we aren't tied into stupid hierarchies with event systems, we just have to use its power intelligently
http://en.wikipedia.org/wiki/Composition_over_inheritance.
Was looking at the links you gave -- I notice the method described there has an "update" function on the systems and components, which seems it's designed for a real-time game. How does this change in a turn-based game like a roguelike?
His game engine isn't necessarily real-time, it's tick-based (by default, real-time ticks). All you would do, in the Controller System, where input/AI is mapped to actions, is just throw a 'waitForPlayerAction' in there and your game is now turn-based... well, almost. You need to update each entity per system, instead of update each system per entity.
The biggest mistake with components IMO is to confuse game things with code objects. That leads you to the question like you had before of 'where do I put quit-game()'? Just because you have an entity system where entities are 'game things' does not mean that your source code objects are limited to describing just entities, their managers, and the systems that act on them.
His source code uses an event system for component interactions. It's okay to have both for GAME LOGIC, but you need to be clear about what produces and handles events and what gets handled in systems. A global game message might be simpler to deal with as an event, but a global game message isn't typically going to effect entities that don't have relevant components.
But yea-- you need to make a distinction between Game Logic Events, Application Events, and possibly even System Events. You can structure an entire application as a component system, but the DOP is designed for data-driven logic, like a game.