Well, I know that this post is quite old , but I could not resist.
I recently built a game engine. It uses 3d party libraries to rendering and physics, but I wrote the core part, that defines and processes the entities and game logic.
The engine surely follows a traditional approach. There is a main update loop that calls update function for all entities. Collisions are directly reported by callback on the entities. Communications between entities are made using smart pointers exchanged between entities.
There is a primitive message system, That processes only a small group of entity to engine messages. Those messages are preferable to be processed at the end of a game interaction ( example is a entity creation or destruction ) because they can mess with the update list. So , at the end of each game loop, a small list of messages are consumed.
Despite the primitive message system , I would say that the system is largely "update loop based".
Well. After using this system, I think that it is very simple, fast and well organized. The game logic is visible and self contained inside entities, not dynamic like a message quewe. I really would not to make it event driven because in my opinion event systems introduce unnecessary complexity to the game logic , and make the game code very difficult to understand and debug.
But, I also think that a pure "update loop based" system like mine have some problems too.
For example, In some moments, one entity may be at a " do nothing state " , may be waiting the player approaching or something else. In most of those cases , the entity burns processor time for nothing and its is better to turn the entity off, and turn it on when a certain event happens.
So, in my next game engine , I am going to adopt a different approach. Entities will register themselves for engine operations, like update, drawing, collision detection and so one. Each of these events will have separated lists of entity interfaces for the actual entities.