This question was asked a few years back, but I'm actually going through the process of building an Entity Component System (ECS) architecture myself and may have some insight that you and the community may find helpful.
Note: framework is short for ECS framework and both are used in place of game engine. ECS frameworks are just a specific type of game engine. In addition, there is more than one way to crack an egg and the same is true for ECS framework design. There is not one definition on which ECS frameworks are built. There are however some generally accepted characteristics that guide their design. I try to stick to just the characteristics when possible. Some things I present here may be more flexible when talking about a different ECS architecture. Being such an old question, the OP may not be around to clarify so I'm just taking a stab at the kind of ECS architecture the OP is asking about based on the wording of the question.
"For example, let's say I want a rule saying that I want all towers to move, except when it's within a certain range of an enemy. Where would this logic reside?"
Rules related to movement would most likely be implemented as a special case of your tower movement logic. As an example of one way to do it, see below.
public void update()
var enemies = worldManager.findLocalEnemies(positionComponent);
// Move towers...
There are a lot of details missing from the above example, but the important takeaway is the logic for movement goes into a system. The
update() function gets executed by some higher level framework code such as the game loop or a system management utility. That means the
update() function is, most likely, never called by code written by the game developer, despite the system class being written by the game developer.
"If it resides in the Movement system, that would me that I would need to create a new movement system for each game..."
Correct. Movement is different per game. Mario moves very different from a space ship in Asteroids. The game designer is responsible for defining that movement.
"... which is not how game engines are supposed to work right? The whole idea is that you feed it any game and the systems can handle it."
I understand where you are coming from with this question. A variation of this question plagued my mind when I first got into hobby game development. I eventually came to an answer partly through experience using several game engines over the years, but also from evaluating the idea of you are getting at when you say "feed it any game".
What is a game in a technical sense? I'm not trying to get philosophical or anything here, but we need a working definition so we can say for certain what we are feeding the framework. To me, a game is a collection of entities, that change state through interactions with players and other entities, where the interactions are constrained by some set of rules.
Here are some examples to illustrate.
Pong - The Pong Ball
The Pong ball (entity) changes position (state change) based on its velocity. It moves in a strait line (rule constraint) unless bouncing off a wall (rule constraint)(state change) or paddle (rule constraint)(state change).
Mario - 2D Goomba
The Goomba (entity) changes position (state change) based on its velocity. It moves in one direction, left or right (rule constraint), in a strait line (rule constraint). When it bumps into an obstacle (rule constraint) it changes direction (state change) and continues to move. It dies (state change) when stepped on (rule constraint) by Mario.
All of the above maps very nicely into the ECS architecture (One reason why ECS architecture is becoming very popular for game development).
Definition Concept -> ECS Architecture Concept -> Examples
Entities -> Entities -> Pong ball, Mario Goomba
States -> Components -> PositionComponent, VelocityComponent, LifeComponent
Rule Constraint Sets -> Systems -> PongBallMovementSystem, GoombaMovementSystem, MarioMovementSystem
So what we feed to the framework are entities, components, and systems. Systems are not a part of the framework, they are feed or registered to the framework. Systems implement the rule sets specific to each game (or levels) and the framework operates them to drive interactions that will cause state changes for your entities. They are implemented external to the framework. This could be by the game developer (most likely case) or may be implemented by a framework developer and shipped as an helpful addon package for game developers to use.
If the framework developer supplies some pre-made systems, the issue becomes they can only guess what type of games will be made with their software. This restricts them to only supplying generic systems that will not have custom rules like "octupple jump" or "stop when in range of enemies" (unless they provide source code that can be modified and re-built or build in some scripting capabilities which is probably more trouble than its worth).
"Because what I have is a game engine, it needs to be able to handle specific user defined rules which may vary from Game to Game, or even from Level to Level within a Game."
That statement is incorrect. The framework provides the mechanisms for you to define your game, but never knows any specifics about your game such as game rules or level constraints. Those are things that go in the systems we talked about earlier. The framework is like the foundation on which to build your game. The framework addresses concerns like
- Registration/De-registration/Creation/Destruction of
- Execution of systems.
- Inter-framework communication (system-system communication, logging, etc.)
- How the game loop progresses
- Event driven
- Time driven
- Fixed timestep
- Variable timestep
- Entity definition
- Object with data
- Integer ID only
- How to store components
- Store copies in each system keyed with entity IDs
- Store in an entity object
- Store in component manager with entity IDs
- How Systems communicate
- Event messages
- Observer pattern
- No communication allowed
- Many more...
As you can see, the framework does not address concerns for any particular game or game rules. It addresses meta-concerns necessary to build a game using ECS architecture.