The views that are expressed in this reply are those of the author, and are not necessarily correct. Use your mind to judge what's right and what's wrong, and when you find something wrong, notify me

do you have to have a gaming engine to make a game?
--------------------------------------------------------------------------------
No, but it will make your life a WHOLE lot easier if you make an engine. It will make finding bugs easier, since everything will be set in it's own section and can be debugged in smaller chunks. It will make it possible to reuse large parts of your code base for future games you make. It will make it easier to modify/maintain. The list goes on.
Actually, you have to have a game engine to make a game. A game engine is the code that's compiled and linked to create your game. Whether this code is modular or not, it's the engine.

The GDNet dictionary defines the game engine as "A program code that runs all aspects of the game."

Theoretically, you can write a 3D game in a single function - in your main() function. Practically however, this is somewhat impossible ( It's not actually impossible, it's just so hard that it's nearly impossible )

Modularity, however, is what offers you the abilitiy to extend and upate your engine, keep track of bugs & fix them, ...etc

* The relation between the engine and the API
The engine, is the code that handles all the aspects of the game. It defines the behavior of the game.

This engine has what can be called sub-engines, like a 3D graphics engine, a 3D sound engine, an AI engine, ....etc

Each sub-engine is actually a module that's designed to handle something :
The graphics engine - Handles the visual part of the game. How the game world is displayed
The sound engine - Handles how the game sounds
.
.
.

You essentially define how your game should work, and design the modules accordingly. Some modules are not limited by APIs, the AI module for example - if being written from scracth, without building on 3rd party libraries - doesn't restrict you with anything more than the language & hardware limitations. Thus to design an AI engine, you can just use any design that works on modern computers.

When designing a graphics engine, on the other hand, you have to keep an eye on the limitations and restrictions caused by the graphics API - whether GL or D3D.
In 3D graphics engine, it's often needed that you follow a set of rules or API standards to achieve optimal performance. If you don't, your game would simply suffer from slowness and may not be playable.

In Direct3D for example :
Worlds are always represented by vertices ( You can think of it as a point in space, in case you don't know 3D graphics ). Vertices define your polygons, polygons define your walls, your characters, ... your game world.

When designing a graphics engine that uses Direct3D, you have to design so that you store your vertices in a special Direct3D object called a "Vertex Buffer". If you don't do so, you'll pay a performance penalty.

Also, when rendering your polygons ( drawing things like walls and models on the screen ), there's an optimal number of triangles to be rendered in a single call. Render more triangles than that, and you're not running optimally. Render less, and you're still not running optimally.

These restrictions don't exist - as far as I know - when using GL. Thus when you're using an API, you have to :
1 - Define what your game needs from the API
2 - Check the limitations presented by the API, on the things you decided would be useful to your game
3 - Design your sub-engine ( the one that uses this API ) around the limitations presented, so that you get optimal performance.

* Writing games & game engines
As far as I've seen, it's better to split your game engine into separate modules, and even separate these modules into sub-models.

For example, for a strategy game you need AI. So there's an AI module, this AI module is expected to do a lot of things :
1 - Resource management
2 - Pathfinding
3 - Battle tactics
.
.
.
Each of these points can be a sub-module. Each sub-module should be implemented alone in its own project, and tested thouroughly to make sure it works as expected. Sub-modules can even be divided into smaller sub-modules - that are tested individually - if needed.

That way, you end up by a number of working modules. Then you start joining them with each other to produce a fully working game. Be careful, though, joining modules together isn't that easy. And if you join too many modules together in one time, you might get a load of bugs, bugs that you don't know where they exactly come from ( Virtually, any 2 modules can be conflicting or not working well with each other )

So, it seems to me that the following is the best solution :
When dividing modules, they somewhat form a tree of parent modules and child modules

For example : The AI module is a parent, the pathfinding is a child of the AI module, the terrain recognition is a child of the pathfinding, ...etc

Join the childs modules together to form the parent, and so on.
Basically, you keep joining the modules that are on the same level to create a higher level module, until you get your final modules.

One final note about joining the modules, make sure you design them in a way so that you can expect how the parent module is going to look like.
I use top-down design, where I :
1- Imagine how I want the AI module to work, and then how I'd like the Resource management to work,...etc
2 - Design all the modules from top to bottom ( starting with the high level AI module )
3 - Implement the modules in top-down direction, using empty functions & classes to reflect unfinished things. ( Sometimes I do use bottom-up implementation, when it seems to be better )