Gaming and Fantasy, Technology Temerity

Flattening Arrays

Introduction

This guide is written primarily for OpenBOR module builders, but the underlying principle applies anywhere you need to store a fixed or bounded number of records, each with a predictable set of fields.

Flattening refers to a technique where an indexed array’s keys are mathematically calculated to create a table-shaped data structure within a single array. Imagine six shadow trail entries, and each entry stores five values:

  • X position
  • Y position
  • Z position
  • sprite
  • expiration time

Once populated, the data looks like a table:

Trail IndexXYZSpriteTime
0125.12368450.574863200.681584#58438713216
1128.78568150.574863200.681584#58438713218
2130.25636550.574863200.681584#75825284220

If we know how many rows we will store, careful offset math lets us flatten the whole table into one indexed array:

[cursor][x0][y0][z0][sprite0][time0][x1][y1][z1][sprite1][time1]...

To access a given entry, calculate its starting position, including any offset. Start offsets are not strictly necessary, but they allow you to reserve early slots for other important data, such as the ring buffer index in the shadow trail example.

The leading [cursor] is not part of any trail entry. It is reserved metadata. In this example, it stores the ring buffer’s current write position. Reserved slots like this are useful when the array needs to hold both record data and control data:

#define DATA_START 1 // Offset where table-shaped data starts.

#define ENTRY_X 0
#define ENTRY_Y 1
#define ENTRY_Z 2
#define ENTRY_SPRITE 3
#define ENTRY_TIME 4

#define ENTRY_STRIDE 5 // Number of array slots used by one record.

entry_index = DATA_START + (entry_number * ENTRY_STRIDE);

Then access each field as an offset from that position:

x = get(data, entry_index + ENTRY_X);
y = get(data, entry_index + ENTRY_Y);
z = get(data, entry_index + ENTRY_Z);
sprite = get(data, entry_index + ENTRY_SPRITE);
time = get(data, entry_index + ENTRY_TIME);

This is the same technique used in the shadow trail example above.

The main advantage to flattening is speed and simplicity. OpenBOR supports multidimensional-style structures by storing one array pointer inside another. That works, but each nested access requires fetching a child array handle before accessing the field. A flattened array removes that extra step. The data lives in one continuous indexed block, and cleanup is simple because there is only one array to free.

The tradeoff is readability. Flattened arrays require careful index math and clearly named constants. If your constants are wrong, the structure becomes difficult to debug. Use comments and named offsets generously.

Flattened arrays are best for compact, fixed-size records in hot paths: animation state, trails, timers, hit records, cached coordinates, and other data touched every update cycle.

Author: Damon Caskey

Hello all, Damon Caskey here - the esteemed owner of this little slice of cyberspace. Welcome!

Leave a Reply