One thing we really don't want is for collision to resolve late - for example, a frame finishing with two solid objects lodged inside each other, and then fixing itself on the next frame. Even if it's only for a frame, it's enough for players to detect some awkwardness. It really does look bad.
Think about it... if you were an animator, and you sent an animation test to a director where two objects were overlapping each other for a frame, they would send it back. Games are largely an animation-based medium. So we should take this stuff seriously.
We also need objects to behave differently based on _what_ they collide with. For example, a ball colliding with the top boundary is going to react differently than if it collides with a goal boundary.
One possibility would be to give entities components that tell us what they are. For example, an entity that has BallComponent would react when it collides with an entity that has GoalComponent. I don't like this approach. The power of ECS is that it lets us attain high flexibility and reusability by defining entities by their _behavior_. If we are building our simulation based on object types, we might as well just do object-oriented programming. So we really should be asking what entities _do_, not what they _are_. A ball entity increases the score of one player and is destroyed when it collides with a goal.
I think a good way to achieve this goal is to break collision down into three overarching elements.
**Actors** do things to objects. For example, a **CanDamageComponent** would be an Actor that is capable of causing damage to other objects.
**Responses** do something when a **Receiver** is hit by an **Actor**. For example, a **DieWhenDamagedComponent** would cause a **CanBeDamagedComponent** Receiver object to die when hit by a **CanDamageComponent** Actor.
We already have MotionMessages. Let's keep those, but redirect them slightly. We can't read MotionMessages and then Emit them again later down the line: that would cause a cycle. So let's have a new UpdatePositionMessage.
Let's have the MotionEngine consolidate all the MotionMessages per-component, and send out an UpdatePositionMessage with that final delta after a sweep check.
Finally, a CollisionDispatchEngine figures out what two kinds of objects collided and emits a Message in response. We can then implement various collision resolution Engines that read each of those kinds of Messages. For example, a ScoreEngine would track **CanScore** Actors and **CanBeUsedToScore** Receivers, and perform behavior based on attached **Responses**, like an **IncreaseScoreResponseComponent**.
The thing is: this kind of thing is the backbone of many game designs. So of course it's a bit complex! The point is that there's no point obscuring the complexity of such a system or putting off thinking about it until later. If we build our project on a shoddy foundation we will surely have problems later. Let's get a robust system in there so we don't have to fundamentally reorganize our program at a later time, when it will be more frustrating and have more potential to break things.