开发者

Structuring a state based game engine, and Makefile structure help?

开发者 https://www.devze.com 2023-03-14 21:54 出处:网络
I\'m working on a state based game engine and have something I\'m happy with as a start. There\'s an abstract class GameState.hpp with virtual methods I use (init, run, pause, etc...).

I'm working on a state based game engine and have something I'm happy with as a start.

There's an abstract class GameState.hpp with virtual methods I use (init, run, pause, etc...).

There's GameEngine.cpp/hpp which is a class that contains a stack of GameState objects and sets up the game loop by running the current state's relevant methods.

My test game TestGame.cpp creates a GameEngine object and pushes a TestState instance and runs, etc... All works as I expect.

I want to structure my source tree rather than compiling everything from the same directory, and was thinking of the following, as there will be multiple states per game:

src/
  +Engine/
    +GameEngine.cpp
    +GameEngine.hpp
    +GameState.hpp
  +TestGame/
    +States/
      +TestState.cpp
      +TestState.hpp
    +TestGame.cpp

When building, I'm not sure if I understand what needs to be compiled with what, and where the compiled objects should go.

So far, my initial thoughts are:

  1. Compile GameEngine.cpp/hpp with GameState.hpp, gives GameEngine.o

  2. Compile each game state, eg. TestState.cpp/hpp with GameState.hpp, gives TestState.o

  3. Compile TestGame.cpp/hpp with GameEngine.o/hpp, GameState.hpp, TestState.o/hpp (and any other states), gives TestGame.bin

Am I on the right track? Should GameEngine build a lib, or is a regular .o ok? I'm still a bit hazy on whether I need to include the headers in each compilation. Also, do the ouput files for each compilation go in the same directory as the source, or should they be in a structured bin/ directory?

I'll have a play around and post some Makefile attempts and output. Let me know if I should post code, there's probably 200 lines total. No actual graphics implementation, etc... Just a framework at the moment.

Thanks guys, any help is super appreciated!

EDIT: Thanks for the quick responses people. I've read the comments below and wanted to give an update and clear a few things up.

Firstly, I'm looking into autotools but this is largely a learning project, and part of that is grokking makefiles. Also I come from a Java background, so I really want to understand exactly what I'm building and how my project fits together. As above, I don't even know whether something should be a library or ju开发者_StackOverflow社区st pointed to at compile time.

An overview of my goal: I see the engine almost as a sub-project. Even though its simple (<10 files), it will load what I think of as 'states' and loop the [handle events, update, display] methods that state defines. I've got an algorithm that aims for a constant number of updates per second, while varying the framerate as needed.

The states display method for example will make use of the engine's SDL-backed display functions (maybe a tile engine, the state can say 'load these resources, display these tiles', or a widget library, whatever...) to render a representation of the game world model. The handle events method could use an abstracted keyboard interface. I want to be able to add functionality like this in the engine. Update will manage a model that represents the game world. It will keep track of the objects in the world (scene, player and np), apply movement based on physics and collision detection, etc...

I think I want to be able to build this and just include the object (and headers?) in with a game I'm working on. Whether its a matter of 'copy the engine source dir to the root of the game project and add this to the main Makefile, build it all together', or 'run make on the engine whenever it changes, build the game project with a copy of the latest engine object (,shared object,something else?) and headers', what will be easiest for me to work with multiple small game projects using the one engine? I kind of want to set myself up so I can hit the ground running with random game ideas as I have them, like 2 week coding comps, etc...

The states represent any different view and set of interactions. The engine has a LIFO stack of states, so a simple game could have the following states on the stack: DrivingMode - PauseMenu - Settings The actual game has an instance of GameEngine, and would have added DrivingMode to start the game. The user pauses, which pauses the DrivingMode state and pushes a PauseMenu state (running its init, run, etc... at push). Here the user selects settings which pauses the PauseMenu state and loads the Settings... As they exit back, states are popped (cleanup, etc... run first), and the top state resumed.

Wow, that's heaps for now. I'll add more or make new questions as I progress. A huge thanks again for all your help.


First of all, do you really need the states to be modular? If you are planning to write an engine for a specific purpose, your states are likely to not change much and thus should probably be compiled as part of the engine itself.

Having the states separated from the engine will add an additional layer of complexity and make the implementation trickier.

The next issue is whether you want your engine to be a library which games link in order to use, or if the engine's source is dropped in a subfolder of the game, and compiled along with it.

Your choices are:

  • Compile the engine and the states as one library (perhaps a static one that you link your game against)
  • Compile the engine as a static library and then compile states as shared objects that can be dynamically linked (That would fit the modular state option, but it would add a lot of complexity)
  • Compile the whole Engine + Game into one big executable which eliminates the need for any library linking (But also makes the engine and the game more coupled)

In my opinion option 1 looks like the best.

With either options, I would keep the engine in its own sub-directory from the game. Your file structure so far looks pretty solid and you should stick to it.

If you still choose to allow the game to define its own states, then you will want to go with option two and implement a few core states in your engine (perhaps something like INIT, MAIN_MENU, SHUT_DOWN) as well as something like a "plugin manager", which in this case will be responsible for registering the game's states with the game engine.

Each state can then be compiled individually as a shared object (.so) and loaded dynamically when the game is loaded.

As for Makefiles, it really depends on what you plan to use (CMake, GNU autotools, etc.)

GNU Makefiles have a pretty simple syntax, but learning to use them well might be a bit tricky.

They consist of targets which are defined like so:

default:
    gcc [...]

all:
    gcc [...]
    gcc [...]
    <...>

The first target is the default target when make is called with no arguments I will not describe in depth how to use makefiles (for GNU Make: this link)

You should know that makefiles quickly become incredibly tedious to maintain and a solution like autotools is usually preferred.

Note that autotools is a very big system consisting of many programs and can be quite time consuming to learn. If what you want to focus on is developing your game engine, I would strongly suggest using a project IDE like Code::blocks to do the code compiling and linking for you.

EDIT

In response to your edit, I would add the following:

You seem to be very aware of where you are headed, which is the most important part. From what you said, you would be much better as having the game engine be it's own static library that your many games link against.

Your engine would then provide an interface to register states which the games will use to say "Here's my state called title" and would later tell the engine "switch to the state called title" whenever it needs to.

One thing you might want to consider is having a few basic states that all games must register (imposed by the engine itself).

The engine would then be a project of its own, and game projects would simply have a copy of the engine library in /lib for example. You would then statically link the engine to your game at compile time.

If you want more details on how you could go about structuring the state objects, let me know.



Many of the things you ask do not have a definitive answer it is often personal preference.

I have the impression from your question that you also compile your headers, you shouldn't compile headers, they should only be included in .cpp files and other headers. Then they are compiled as part of the cpp. Files should only include the headers they really need.

As long as your project is small keeping everyting in one directory is often best but if you know it is going to grow then setting up a good directory structure is a good idea. Seperating the potentially reusable GameEngine from the actual Game like you do is a good.

Creating a library is usefull when that part is going to be reused in other projects or when your project get's so big that the number of .o files becomes very high. So if that applies to the GameEngine make it a lib. For reusable projects like a game engine it is often also useful to keep the headers in a seperate directory. Because projects depending on it will only need the headers and the lib, they do not need the rest of the sources.

When projects get bigger using seperate directories for source, intermeddiate (.o) and final executables helps keeping your files manageable as storing .o with your sources would typically increase the number of files in your src dir by 50%.

If you want to set it up really well you might want to have a look at autoconf and automake. They have a steep learning curve but they will take a lot of Makefile writing out of your hands. These are the tools that create the configure script found in the source distributions of many opensource packages.

0

精彩评论

暂无评论...
验证码 换一张
取 消