Petra Engine Source Code
========================

1. About
2. Building
3. Quick Start
4. Documentation

1. About
--------

  This is the source code for the Petra Engine, a 3D game engine for 
retro PC systems (mainly DOS but also Win9x), originally written for the 
2020 MS-DOS Game Jam #2 game "Post Apocalyptic Petra" (hence the name) 
but later ported to other systems.

  This version of the engine has been extracted from the original game's 
source code (specifically, version 0.99o) with -almost- all 
game-specific code removed.  A very simple game template with the 
minimum required assets has replaced the Post Apocalyptic Petra code.  A 
script to create a new project directory alongside the engine directory 
is provided too.


2. Building
-----------

  The engine needs game-specific source units to build and work.  A 
simple example game ("Petra Engine Template Game") is provided that can 
be used as a starting point.  Building the engine is basically about 
building a game that uses the engine.

  To build the game, you need to install Free Pascal.  For most targets 
(DOS, Linux, etc) the latest version will do, but if you want to target 
retro Win9x PCs you need to download Free Pascal 2.2.4 (FPC 2.2.4 and 
whatever is the latest version can be installed alongside each other). 
The fpc binary must also be available at the PATH (e.g. running fpc -h 
from a command-line window should show the Free Pascal help screen). 

  Obviously you also need any cross-compilers for the targets you want 
(if you are not building it for the OS you are running Free Pascal at). 
Note that if you are targeting go32v2 (i.e. DOS) and using Windows then 
you can simply extract the unit files from the DOS distribution of Free 
Pascal since the Windows utilities can also work with the DOS utilities 
(this is not the case for other OSes though).

  To build the editor you also need to install Lazarus (FPC is part of 
Lazarus for the Windows version but it is recommended to also install a 
standalone version).  Since the editor needs to be build against the 
game-specific code (and is the recommended IDE for editing it) you 
should install it anyway.

  Note that under Linux you almost always want to install Lazarus from 
source code (i.e. download the source code, extract it to a directory, 
enter it and type 'make bigide' inside it - then install any missing 
libraries, like the gtk2 development files, etc that the linker 
complains about) since the versions available from repositories tend to 
often not work correctly.  You can install Free Pascal from Linux 
repositories without issues though.

  There are two ways to decide where and how to build the game:

    1. Build the game inside the engine's directory - this is easiest 
       and allows for modifying the engine itself for each game

    2. Use new-game.sh from the Scripts directory to make a new 
       directory with only the game code and data that references the 
       engine's directory - this allows for the engine code to be shared 
       between different games

  Either way you also need to have a GNU Bash shell available running as 
a native application (i.e. no VM and no WSL if you use Windows).  
Unix-based OSes (i've only tried Linux but should work with macOS too) 
already come with GNU Bash preinstalled.  For Windows you can use MSYS2 
or Cygwin.

  To use the new-game.sh script you must run it from the same directory 
that contains the PetraEngine directory - e.g. if you uncompressed the 
engine's ZIP file to ~/Code (or C:\Code) and thus have a 
~/Code/PetraEngine (or C:\Code\PetraEngine) directory, then you must run 
the script from ~/Code (or C:\Code) like this ($ is the Bash prompt):

    $ PetraEngine/Scripts/new-game.sh MyGameName

(replace MyGameName with the name of the directory to put the new game - 
the directory must not exist, otherwise the script will display an 
error)

  For either approach, you will have a script named build.sh in the game 
(or engine's) source directory.  You may want to edit this build.sh file 
to point at the paths where FPC 2.2.4 and Lazarus' lazbuild tools are 
installed for building the Win32 versions and editor respectively.  
Strictly speaking this is not required unless you want to build the 
standalone Windows versions and/or the editor from the command line - 
otherwise you can just ignore the standalone Windows versions (if you 
are only targeting DOS or one of the other non-Win32 platforms) and open 
(and run) the editor project file from inside Lazarus.

  To run build.sh simply do a...

    $ ./build.sh

  ...from inside the game source directory.  This will display the 
available targets, which should include -among others- the dos, sdl and 
gdi targets that should require no additional dependencies than what is 
available out of the box by Free Pascal.  So, to build the DOS version you
need to enter:

    $ ./build.sh dos

The DOS version of the game will be build as pgame.exe inside the Build 
subdirectory (which will be created if it doesn't exist).  Note that the 
"pgame" part is a common name that will be used for each target with 
target-specific prefixes and suffixes (e.g. the SDL software rendering 
target is called sdlpgame and the DirectDraw target is called 
winpgame.exe). You can modify the exe= line in build.sh to use a 
different name.

  Similarly to build the SDL version you type:

    $ ./build.sh sdl

The SDL version should build and run under most OSes and can be used for 
development testing purposes (though running the game from inside the 
editor is also possible).  The template game assumes all data are stored 
under the GameData directory under the current directory, so you need to 
run it like:

    $ Build/sdlpgame

This is also important for the editor: if you build it using the 
./build.sh script (by entering ./build.sh editor) you need to run it like

    $ Build/editor

so that it can find the data.  If you open the editor.lpi file from 
Lazarus you also must set the working directory from Run -> Run 
Parameters to be the game's (or engine's) own directory instead of the 
GameSrc subdirectory (where the game sources are located), otherwise the 
editor will not find the data and throw various exceptions.  If you get 
something like a Range check error or errors about failing to load files 
then you tried to run the editor from some other directory.

Some utilities are also provided for creating PAK files (can contain all
assets in a single file which can help a bit with ZIP compression) and
converting between palette and image files.  To build those use:

    $ ./build.sh utils

The utilities will be under the Build directory like the game and
editor.


3. Quick Start
--------------

  Once you have the game and the editor binaries build you can run the 
editor and open the map1.map file from the GameData directory.  This 
opens some default map with a single grid (the world is made up of grids 
- you do not really *have* to use the grids, you could write your own 
logic for making the scene, but the engine can use the grids to generate 
sectors and portals and provides some very simple checks against the 
grids for collisions), a light and a TPlayer entity that represents the 
player character (again, not necessary, but a common and useful starting 
point).

  Press F9 to enter in Play mode.  The camera will move at the player's
position and... you can't do much from there.  Press F9 to exit Play mode.

  When entering Play mode the engine creates a deep copy of the TGame 
object instance, swaps the new copy with the previous game instance (which
is kept around to be swapped again when exiting Play mode) and enters in
"game mode", allowing the game logic to run.  Exiting Play mode simply
deletes that copy and restores the original instance.

  Maps (levels) are basically serialized TWorld objects, which contain 
serialized TEntity (and subclasses) objects.  To create a new object 
type you subclass TEntity and register it with a call to 
RegisterSerializableClass from the unit's initialization section.  The 
template game already registers a TPlayer class in the EPlayer.pas unit 
that provides some example code that can be used as a starting point.  
The engine also provides some other common entity classes like TLight, 
which provides a light source that is used to calculate static lighting 
for grids, TStaticMeshEntity that can be used to render a static mesh, 
TSoundEmitter that is emitting a sound in 3D space, etc.

  The TPlayer class that is part of the template game is a 
TSceneNodeEntity subclass - that is an entity that is represented in the 
game via a scene node (a TSceneNode subclass, itself providing 
functionality to render things - e.g. by overriding the RenderNode 
method).  The scene node is created in the CreateSceneNode method 
(though in the example it does nothing nor is the scene node itself 
used).  This can be a starting point for when the game uses some 3rd
person perspective - for 1st person games the class can be changed to
TEntity and the CreateSceneNode method be deleted.

  The TPlayer class also implements the TInputHandler interface and when
the entity is added to the world (notified by the AddedToWorld method), it
registers itself with the input driver so that it can handle key and mouse
events.

  Some other methods that the TPlayer overrides (though it only uses 
them as placeholders for games to expand on) are: RemovedFromWorld (the 
opposite of AddedToWorld, which is called when the entity is removed 
from the world), AddSceneNodes/RemoveSceneNodes (added to add any 
previously created scene nodes - strictly speaking you do not need to 
override this for TSceneNodeEntity subclasses since TSceneNodeEntity 
will add the node created via CreateSceneNode to the scene for you), 
Update (called at a fixed rate), Frame (called for every frame) and
PerformCommand (called whenever a script wants to perform a command on
an entity - usually via the "send [target] [command]" command).


4. Documentation
----------------

  There isn't really any guide-like documentation (or even reference for 
that matter) for the engine.  The source code however is thoroughly 
commented and every class and method has a comment above it giving it a 
brief description which the Lazarus IDE will display in a popup when 
hovering the mouse or during auto-completion, which can help as a simple 
API reference.

  Documentation for the editor and scripts are not (yet) available, you 
can try to play around with the editor and perhaps download Post 
Apocalyptic Petra with the editor and play with that too (checking the 
scripts, etc). You can also check a ~3h video of making a map for Post 
Apocalyptic Petra which shows some functionality and using the editor: 
https://www.youtube.com/watch?v=a0nisHz424A


Kostas "Bad Sector" Michalopoulos
badsector@runtimeterror.com

You may find the latest version of the engine at
http://runtimeterror.com/tech/petra

