Skip to content

Code Structure

Nick McDonald edited this page Jan 20, 2020 · 1 revision

Territory Code Structure

This document will explain how to read the code and why I do certain things in a certain way.

Main Structure

In the source folder, you will find the main file territory.cpp, which only includes the territory.h file.

Inside territory.h you will find all the dependencies, and the structure for linking all of the remaining classes.

There are 3 main classes which do most of the work.:

class World (/source/world/)- World data structure, responsible for storage / loading / saving.
class View  (/source/render/)- Renderer data structure, responsible for all rendering with OpenGL
class Population (/source/taskbot/) - Population data structure, responsible for all updates of the in-game agents.

See which order they are created in the main file and look at what calls are made to understand how the program is launched and how it operates.

Inside their respective folders, they have a number of support classes which they utilize to do their job.

For instance, the world class has access to an octree data structure, a blueprint class, a chunk class, and a block class.

There are two more which are created in the main file:

class Audio (/source/render/audio.h)- Simple data structure that loads audio files and trigger their playing.
class eventHandler (/source/game/event.h) - Simple data structure that uses SDL user inputs to manipulate the other data structures.

The folder game provides a number of other useful data structures which don't strictly belong to the above mentioned systems, but exist anyway. This is an item data structure for use by agents.

Besides these, there is a large folder called helpers which provide a number of namespaces with useful functions that are used for a variety of algorithms, benchmarking, math data structures, error logging, etc.

The folder astar contains an implementation of astar path finding.

The folder imgui contains the DearImgui library.

Forward Declaration System

To avoid cyclical dependency problems, we can structure our object definitions in the following way:

( main.cpp )
  - Include the main header file
  - Main Function
( main.h )
  - Include all general dependencies (e.g. stdlib)
  - Include (unordered) class .cpp files
( x.cpp )
  - Direct inclusion of all dependency class header files (y.h)
  - Direct inclusion of own class header file (x.h)
  - Beneath, contains member functions to its class X
( x.h )
  - Pragma Once, then include all dependency class forward declarations
  - Beneath, full class definition of class X
( x.fwd.h )
  - Single Pragma Once forward declaration of the class x

Example:

main.cpp
  #include main.h
  //... main function
  
main.h
  #include <external_dependency>
  #include x.cpp
  #include z.cpp //Unordered!
  #include y.cpp  
  
x.cpp
  #include <y.h>
  #include <z.h>
  #include <x.h> //Include ourselves last
  //...member functions
  
x.h
  #pragma once
  #include x.fwd.h  //Order irrelevant
  #include y.fwd.h
  #include z.fwd.h
  
  class X{  //Works even though in main.h, x.cpp was included before z.cpp
    Z z;
    Y y;
  };

This is called using forward declarations, and I make use of it in this project.

Clone this wiki locally