Skip to content

Engine layer

Nikolai Wuttke edited this page Sep 6, 2019 · 10 revisions

The in-game engine layer provides various functionality, which can be grouped as follows:

  • Entity management
  • Rendering (map, sprites, particles)
  • Collision detection and movement functions
  • Physics

But before we get into more details on these, let's first define some basics.

Units and coordinate systems

Aside from a few exceptions, the canonical unit for positions, sizes etc. in RigelEngine is tiles. A single tile is made of 8 by 8 pixels in Duke Nukem II. The game map (or world) is constructed out of tiles, and all objects in the game are always aligned to the corresponding grid of 8x8 pixel blocks. It's not possible for an object (aside from particles) to be positioned outside of this grid. Therefore, storing all positions and sizes as tiles makes sense.

There are three coordinate systems in RigelEngine: World, local, and screen.

World coordinates are relative to the entire map, with 0,0 being at the top-left of the map. The maximum x and y depend on the size of the map. Depending on the camera position, a world coordinate can be on-screen or off-screen.

Local coordinates are relative to an object. To turn a local coordinate into a world coordinate, the object's world position is added to the local coordinate.

Screen coordinates are relative to the screen, meaning 0,0 is always at the top-left of the screen, and 31,19 is bottom-right (in non-widescreen mode). To convert from world to screen coordinates, the camera position is subtracted from a world position.

The following picture illustrates these different coordinate systems:

TODO

Entity management

Thanks to the EntityX library, entity management is mostly taken care of already by instantiating an entityx::EntityManager. This class allows creating and destroying entities, as well as iterating over all entities that have a certain set of components.

Aside from particles and the world/map, everything in RigelEngine is represented by an entity. The engine layer provides various components which can be added to entities, in order to give basic functionality.

Position and bounding box

The most commonly used components are WorldPosition and BoundingBox. The former locates an entity inside the world (as the name suggests), by giving it a position (x and y) in the world coordinate system. The latter gives the entity a size, by defining a rectangle (in object space). The bounding box also defined how an entity collides with the world and other entities (see below).

Note that the rectangle's bottom-left corner corresponds to the entity's world position by default. The rectangle can also define an offset, to adjust that. The following image illustrates position and bounding box:

Todo

Orientation

Active state and activation policy

Life-time control

Rendering

There are three different types of visual elements making up a RigelEngine scene: Map, sprites, and particles.

Map rendering

The map is drawn by the MapRenderer class. It consists of three layers, with sprites positioned between and above those layers. The layers are:

  • Parallax background (aka backdrop)
  • Background layer
  • Foreground layer

Sprites can appear between background and foreground, or on top of the foreground.

The map is not represented by entities, but by a 2-dimensional array of tile indices. The MapRenderer operates directly on that grid. The appearance of the map depends on the tile set, which is given to the MapRenderer in form of a texture. Tile indices are used to choose a sub-section of that texture when displaying a tile.

Tile debris, i.e. parts of the map exploding, is drawn by the MapRenderer as well.

Sprite rendering

To make an entity appear visually, it needs to have a Sprite component attached, in addition to a world position. A bounding box is not mandatory for rendering.

Orientation adjustment

Virtual and real frames

Collision detection and movement

Physics

Clone this wiki locally