6 Module ISOMETRIC_ENGINE
gullradriel edited this page 2026-10-29 20:54:40 +01:00

GRAPHICS: isometric engine, maps, tiles, ...

Structures

Name
struct N_ISO_OBJECT
Drawable object for depth-sorted isometric rendering.
struct N_ISO_CAMERA
2D isometric camera for viewport management.
struct ISO_VISIBLE_EDGES
Per-tile edge visibility flags for height border rendering.
struct ISO_TILE_SEGMENTS
Per-tile height segments.
struct ISO_TILE_SEGMENT
Single vertical segment of a tile: solid matter from bottom to top.
struct ISO_PROJECTION
Axonometric projection parameters.
struct ISO_MAP
Height-aware isometric map with terrain and height layers, per-cell height values, configurable projection, and terrain transition support.
struct ISO_DRAW_ENTRY
Draw order entry for segment-sorted rendering.

Types

Name
typedef void(*)(float screen_x, float screen_y, float zoom, float alpha, void *user_data) N_ISO_OBJECT_DRAW_FN
Object draw callback.
typedef ALLEGRO_COLOR(*)(ALLEGRO_COLOR c) IsoPrimitiveColorFilter
Optional design-RGB to display-RGB filter applied to every primitive color (filled polygons, lines) emitted by [iso_map_draw](Module-ISOMETRIC_ENGINE#user-content-function-iso_map_draw).
typedef void(*)(float *out_dx, float *out_dy) IsoLineJitterCompensationFn

Functions

Name
void n_iso_camera_zoom(N_ISO_CAMERA * cam, float dz, float mouse_x, float mouse_y)
Zoom the camera toward a screen-space point (e.g.
void n_iso_camera_world_to_screen(const N_ISO_CAMERA * cam, float wx, float wy, float * sx, float * sy)
Convert world coordinates to screen pixel coordinates.
void n_iso_camera_scroll(N_ISO_CAMERA * cam, float dx, float dy)
Scroll the camera by (dx, dy) world units.
void n_iso_camera_screen_to_world(const N_ISO_CAMERA * cam, float sx, float sy, float * wx, float * wy)
Convert screen pixel coordinates to world coordinates.
N_ISO_CAMERA * n_iso_camera_new(float zoom_min, float zoom_max)
Create a new camera with the given zoom limits.
void n_iso_camera_free(N_ISO_CAMERA ** cam)
Free a camera and set the pointer to NULL.
void n_iso_camera_follow(N_ISO_CAMERA * cam, float target_x, float target_y, int screen_w, int screen_h, float smoothing, float dt)
Smoothly follow a world-space target (camera lerp).
void n_iso_camera_center_on(N_ISO_CAMERA * cam, float world_x, float world_y, int screen_w, int screen_h)
Center the camera so that a world point is at screen center.
void iso_set_primitive_color_filter(IsoPrimitiveColorFilter fn)
void iso_set_line_jitter_compensation(IsoLineJitterCompensationFn fn)
void iso_screen_to_map_height_f(const ISO_MAP * map, float screen_x, float screen_y, int tile_w, int tile_h, int * mx, int * my, float * out_fx, float * out_fy)
height-aware screen-to-map conversion returning fractional tile coordinates.
void iso_screen_to_map_height(const ISO_MAP * map, float screen_x, float screen_y, int tile_w, int tile_h, int * mx, int * my)
height-aware screen-to-map conversion with diamond hit testing.
void iso_screen_to_map(const ISO_MAP * map, float screen_x, float screen_y, int * mx, int * my)
convert screen pixel coordinates to map tile coordinates (flat, no height)
const char * iso_projection_name(int preset)
get the display name for a projection preset
void iso_mask_tile_to_diamond(ALLEGRO_BITMAP * bmp, int tile_w, int tile_h)
Mask a tile bitmap to the isometric diamond shape.
void iso_map_to_screen_f(const ISO_MAP * map, float fmx, float fmy, float h, float * screen_x, float * screen_y)
convert map tile coordinates to screen pixel coordinates (float version)
void iso_map_to_screen(const ISO_MAP * map, int mx, int my, int h, float * screen_x, float * screen_y)
convert map tile coordinates to screen pixel coordinates
void iso_map_smooth_corner_heights(const ISO_MAP * map, int mx, int my, float * h_n, float * h_e, float * h_s, float * h_w)
compute smooth corner heights with slope clamping (for rendering)
int iso_map_should_transition_smooth(const ISO_MAP * map, int mx1, int my1, int mx2, int my2)
check if terrain transition should render between two cells (height-aware)
int iso_map_should_transition(const ISO_MAP * map, int mx1, int my1, int mx2, int my2)
check if terrain blending should occur between two adjacent cells
void iso_map_set_terrain(ISO_MAP * map, int mx, int my, int terrain)
set terrain type for a cell (bounds-checked)
int iso_map_set_segments(ISO_MAP * map, int mx, int my, const ISO_TILE_SEGMENT * segs, int count)
set per-tile segments on an ISO_MAP.
void iso_map_set_projection_target(ISO_MAP * map, int preset)
set target projection preset for smooth interpolation via iso_map_lerp_projection
void iso_map_set_projection_custom(ISO_MAP * map, float half_w, float half_h, float tile_lift)
set custom projection parameters directly
void iso_map_set_projection(ISO_MAP * map, int preset, float tile_width)
set projection preset and snap to it immediately
void iso_map_set_height(ISO_MAP * map, int mx, int my, int h)
set height for a cell (bounds-checked, clamped)
void iso_map_set_ability(ISO_MAP * map, int mx, int my, int ab)
set ability for a cell (bounds-checked)
int iso_map_save(const ISO_MAP * map, const char * filename)
save ISO_MAP to binary file (chunk-based format)
void iso_map_randomize(ISO_MAP * map)
randomize terrain and height for testing/demo purposes
ISO_MAP * iso_map_new(int width, int height, int num_terrains, int max_height)
create a new height-aware ISO_MAP with given dimensions
ISO_MAP * iso_map_load(const char * filename)
load ISO_MAP from binary file
void iso_map_lerp_projection(ISO_MAP * map, float dt)
smoothly interpolate current projection angle toward target (call every frame)
float iso_map_interpolate_height(const ISO_MAP * map, float fx, float fy)
bilinear height interpolation at fractional map coordinates
ISO_VISIBLE_EDGES iso_map_get_visible_edges_segment(const ISO_MAP * map, int mx, int my, int seg_idx)
Compute per-segment edge visibility for height border rendering.
ISO_VISIBLE_EDGES iso_map_get_visible_edges(const ISO_MAP * map, int mx, int my)
Compute which diamond edges of tile (mx, my) need a height border.
int iso_map_get_terrain(const ISO_MAP * map, int mx, int my)
get terrain type for a cell (bounds-checked)
const ISO_TILE_SEGMENTS * iso_map_get_segments(const ISO_MAP * map, int mx, int my)
get per-tile segments.
int iso_map_get_height(const ISO_MAP * map, int mx, int my)
get height for a cell (bounds-checked, clamped)
int iso_map_get_ability(const ISO_MAP * map, int mx, int my)
get ability for a cell (bounds-checked)
void iso_map_free(ISO_MAP ** map)
free an ISO_MAP and set the pointer to NULL
void iso_map_draw(const ISO_MAP * map, ALLEGRO_BITMAP ** tile_bitmaps, ALLEGRO_BITMAP *** transition_tiles, int num_masks, ALLEGRO_BITMAP ** overlay_bitmaps, int num_overlay_tiles, float cam_px, float cam_py, float zoom, int screen_w, int screen_h, int player_mode, N_ISO_OBJECT * objects, int num_objects)
Draw the full ISO_MAP with height, transitions, overlays, cliff walls, hover, and grid.
void iso_map_corner_heights(const ISO_MAP * map, int mx, int my, float * h_n, float * h_e, float * h_s, float * h_w)
compute average corner heights for smooth rendering (Article 2026)
void iso_map_calc_transitions_full(const ISO_MAP * map, int mx, int my, int * edge_bits, int * corner_bits)
compute per-terrain transition bitmasks with height filtering (Article 934).
void iso_map_calc_transitions(const ISO_MAP * map, int mx, int my, int * edge_bits, int * corner_bits)
compute terrain transition bitmasks for a cell (Article 934)
int iso_map_build_draw_order(const ISO_MAP * map, ISO_DRAW_ENTRY * out, int max_entries)
Build the draw order for segment-sorted rendering.
int iso_is_in_diamond(int px, int py, int tile_w, int tile_h)
test if pixel (px,py) is inside the isometric diamond of size tile_w x tile_h
void iso_generate_transition_tiles(ALLEGRO_BITMAP *** tiles, ALLEGRO_BITMAP ** masks, ALLEGRO_BITMAP ** tile_bitmaps, int num_terrains, int tile_w, int tile_h)
Pre-composite transition tiles (terrain texture * alpha mask).
void iso_generate_transition_masks(ALLEGRO_BITMAP ** masks, int tile_w, int tile_h)
Generate the 32 procedural transition alpha masks (16 edge + 16 corner).
float iso_diamond_dist(int px, int py, int tile_w, int tile_h)
distance from pixel to diamond edge (0 at edge, 1 at center)
void iso_corner_to_screen(const ISO_MAP * map, int cx, int cy, float fh, float cam_x, float cam_y, float zoom, float * sx, float * sy)
Project a tile corner to screen coordinates (canonical formula).
ALLEGRO_COLOR iso_apply_primitive_color_filter(ALLEGRO_COLOR c)
void iso_apply_line_jitter_compensation(float * out_dx, float * out_dy)

Attributes

Name
double n_iso_setup_us
double n_iso_pass3_us
double n_iso_pass2_us
double n_iso_pass1_us
Per-pass timing accumulators populated by iso_map_draw.

Defines

Name
WALK
FLAG of a walkable tile.
SWIM
FLAG of a swimmable tile.
ISO_PROJ_WIDE
Legacy alias: ISO_PROJ_WIDE maps to ISO_PROJ_STAGGERED.
ISO_PROJ_STEEP
Legacy alias: ISO_PROJ_STEEP maps to ISO_PROJ_ISOMETRIC.
ISO_PROJ_STAGGERED
Projection ID: flatter dimetric (~18.43 degree angle).
ISO_PROJ_MILITARY
Projection ID: military/planometric (45 degree angle).
ISO_PROJ_ISOMETRIC
Projection ID: true isometric (30 degree angle).
ISO_PROJ_CLASSIC
Projection ID: classic 2:1 isometric (~26.565 degree angle).
ISO_NUM_PROJECTIONS
Number of built-in projection presets.
ISO_NUM_MASKS
Total number of transition masks (edge + corner).
ISO_NUM_EDGE_MASKS
Number of possible edge mask combinations (2^4 = 16).
ISO_NUM_CORNER_MASKS
Number of possible corner mask combinations (2^4 = 16).
ISO_MAX_SEGMENTS_PER_TILE
Max height segments per tile (ground + one elevated structure).
ISO_EDGE_W
Edge bitmask: west neighbor has higher terrain.
ISO_EDGE_S
Edge bitmask: south neighbor has higher terrain.
ISO_EDGE_N
Edge bitmask: north neighbor has higher terrain.
ISO_EDGE_E
Edge bitmask: east neighbor has higher terrain.
ISO_CORNER_SW
Corner bitmask: southwest diagonal has higher terrain.
ISO_CORNER_SE
Corner bitmask: southeast diagonal has higher terrain.
ISO_CORNER_NW
Corner bitmask: northwest diagonal has higher terrain.
ISO_CORNER_NE
Corner bitmask: northeast diagonal has higher terrain.
BLCK
FLAG of a stopping tile.

Types Documentation

typedef N_ISO_OBJECT_DRAW_FN

typedef void(* N_ISO_OBJECT_DRAW_FN) (float screen_x, float screen_y, float zoom, float alpha, void *user_data);

Object draw callback.

Parameters:

  • screen_x screen pixel X position (camera-transformed)
  • screen_y screen pixel Y position (camera-transformed)
  • zoom current camera zoom factor
  • alpha opacity multiplier (1.0 = normal draw, <1.0 = occluded overlay)
  • user_data user pointer from N_ISO_OBJECT

typedef IsoPrimitiveColorFilter

typedef ALLEGRO_COLOR(* IsoPrimitiveColorFilter) (ALLEGRO_COLOR c);

Optional design-RGB to display-RGB filter applied to every primitive color (filled polygons, lines) emitted by [iso_map_draw](Module-ISOMETRIC_ENGINE#user-content-function-iso_map_draw).

Used by the client to opt into sRGB-correct rendering: when an sRGB FBO is bound and GL_FRAMEBUFFER_SRGB is enabled, RGB literals authored in sRGB space must be hand-converted to linear before being written, otherwise the GPU's linear-to-sRGB encode at FBO store time would double-encode them. Default NULL = identity passthrough; non-sRGB consumers (editor, headless tests) pay nothing. Set via [iso_set_primitive_color_filter](Module-ISOMETRIC_ENGINE#user-content-function-iso_set_primitive_color_filter).

typedef IsoLineJitterCompensationFn

typedef void(* IsoLineJitterCompensationFn) (float *out_dx, float *out_dy);

Functions Documentation

function n_iso_camera_zoom

void n_iso_camera_zoom(
    N_ISO_CAMERA * cam,
    float dz,
    float mouse_x,
    float mouse_y
)

Zoom the camera toward a screen-space point (e.g.

Parameters:

  • cam the camera
  • dz zoom delta (positive = zoom in)
  • mouse_x screen X of zoom pivot
  • mouse_y screen Y of zoom pivot

Zoom the camera toward a screen-space point.

mouse cursor). Zoom the camera toward a screen-space point (e.g.

Adjusts the camera position so the world point under the mouse stays fixed on screen after zooming.

function n_iso_camera_world_to_screen

void n_iso_camera_world_to_screen(
    const N_ISO_CAMERA * cam,
    float wx,
    float wy,
    float * sx,
    float * sy
)

Convert world coordinates to screen pixel coordinates.

Parameters:

  • cam the camera
  • wx world X
  • wy world Y
  • sx output screen X
  • sy output screen Y

function n_iso_camera_scroll

void n_iso_camera_scroll(
    N_ISO_CAMERA * cam,
    float dx,
    float dy
)

Scroll the camera by (dx, dy) world units.

function n_iso_camera_screen_to_world

void n_iso_camera_screen_to_world(
    const N_ISO_CAMERA * cam,
    float sx,
    float sy,
    float * wx,
    float * wy
)

Convert screen pixel coordinates to world coordinates.

Parameters:

  • cam the camera
  • sx screen X
  • sy screen Y
  • wx output world X
  • wy output world Y

function n_iso_camera_new

N_ISO_CAMERA * n_iso_camera_new(
    float zoom_min,
    float zoom_max
)

Create a new camera with the given zoom limits.

Parameters:

  • zoom_min minimum zoom factor (e.g. 0.5)
  • zoom_max maximum zoom factor (e.g. 6.0)

Return: new camera, or NULL on failure

Create a new 2D isometric camera.

Create a new camera with the given zoom limits.

function n_iso_camera_free

void n_iso_camera_free(
    N_ISO_CAMERA ** cam
)

Free a camera and set the pointer to NULL.

function n_iso_camera_follow

void n_iso_camera_follow(
    N_ISO_CAMERA * cam,
    float target_x,
    float target_y,
    int screen_w,
    int screen_h,
    float smoothing,
    float dt
)

Smoothly follow a world-space target (camera lerp).

Parameters:

  • cam the camera
  • target_x target world X
  • target_y target world Y
  • screen_w viewport width
  • screen_h viewport height
  • smoothing lerp speed factor (higher = snappier, e.g. 8.0)
  • dt time step in seconds

Smoothly follow a world-space target.

Smoothly follow a world-space target (camera lerp).

function n_iso_camera_center_on

void n_iso_camera_center_on(
    N_ISO_CAMERA * cam,
    float world_x,
    float world_y,
    int screen_w,
    int screen_h
)

Center the camera so that a world point is at screen center.

Parameters:

  • cam the camera
  • world_x world X to center on
  • world_y world Y to center on
  • screen_w viewport width in pixels
  • screen_h viewport height in pixels

function iso_set_primitive_color_filter

void iso_set_primitive_color_filter(
    IsoPrimitiveColorFilter fn
)

function iso_set_line_jitter_compensation

void iso_set_line_jitter_compensation(
    IsoLineJitterCompensationFn fn
)

function iso_screen_to_map_height_f

void iso_screen_to_map_height_f(
    const ISO_MAP * map,
    float screen_x,
    float screen_y,
    int tile_w,
    int tile_h,
    int * mx,
    int * my,
    float * out_fx,
    float * out_fy
)

height-aware screen-to-map conversion returning fractional tile coordinates.

Parameters:

  • map the iso map
  • screen_x world-space X
  • screen_y world-space Y
  • tile_w tile bitmap width in pixels (for diamond hit test)
  • tile_h tile bitmap height in pixels
  • mx receives integer tile X
  • my receives integer tile Y
  • out_fx receives fractional tile X (NULL-safe)
  • out_fy receives fractional tile Y (NULL-safe)

Height-aware screen-to-map conversion returning fractional tile coordinates.

Like iso_screen_to_map_height but outputs the exact position within the tile via out_fx/out_fy (range: tile.x .. tile.x+1).

height-aware screen-to-map conversion returning fractional tile coordinates.

Works like iso_screen_to_map_height but additionally outputs the exact fractional tile position via out_fx/out_fy.

function iso_screen_to_map_height

void iso_screen_to_map_height(
    const ISO_MAP * map,
    float screen_x,
    float screen_y,
    int tile_w,
    int tile_h,
    int * mx,
    int * my
)

height-aware screen-to-map conversion with diamond hit testing.

Parameters:

  • map the map
  • screen_x world X coordinate (from camera screen-to-world)
  • screen_y world Y coordinate
  • tile_w tile width in pixels (for diamond test)
  • tile_h tile height in pixels (for diamond test)
  • mx output tile X
  • my output tile Y

Height-aware screen-to-map conversion with diamond hit testing.

Tests all heights from max_height down to 0, returns the topmost tile at the given screen position.

height-aware screen-to-map conversion with diamond hit testing.

Iterates from max_height down to 0, testing each height layer for a tile that matches the screen coordinates. Uses iso_is_in_diamond for precise pixel-level hit detection within the diamond boundary.

function iso_screen_to_map

void iso_screen_to_map(
    const ISO_MAP * map,
    float screen_x,
    float screen_y,
    int * mx,
    int * my
)

convert screen pixel coordinates to map tile coordinates (flat, no height)

Parameters:

  • map the map (uses map->proj)
  • screen_x X in pixels
  • screen_y Y in pixels
  • mx output tile X
  • my output tile Y

Convert screen pixel coordinates to map tile coordinates.

convert screen pixel coordinates to map tile coordinates (flat, no height)

Inverse of iso_map_to_screen (without height, assumes h=0). Uses the diamond center to find which tile a screen pixel belongs to.

function iso_projection_name

const char * iso_projection_name(
    int preset
)

get the display name for a projection preset

Parameters:

  • preset projection ID

Return: static string with the projection name

Get the display name for a projection preset.

get the display name for a projection preset

function iso_mask_tile_to_diamond

void iso_mask_tile_to_diamond(
    ALLEGRO_BITMAP * bmp,
    int tile_w,
    int tile_h
)

Mask a tile bitmap to the isometric diamond shape.

Parameters:

  • bmp the tile bitmap to mask
  • tile_w tile width in pixels
  • tile_h tile height in pixels

Pixels outside the diamond are set to fully transparent (0,0,0,0).

function iso_map_to_screen_f

void iso_map_to_screen_f(
    const ISO_MAP * map,
    float fmx,
    float fmy,
    float h,
    float * screen_x,
    float * screen_y
)

convert map tile coordinates to screen pixel coordinates (float version)

Parameters:

  • map the map (uses map->proj)
  • fmx fractional tile X
  • fmy fractional tile Y
  • h height value (float for smooth interpolation)
  • screen_x output X in pixels
  • screen_y output Y in pixels

Convert map coordinates to screen coordinates (float version).

convert map tile coordinates to screen pixel coordinates (float version)

Maps fractional tile positions to world screen coordinates. Unlike iso_map_to_screen (which returns the bounding box top-left), this returns the actual diamond position: (mx, my) maps to the N vertex and (mx+0.5, my+0.5) maps to the diamond center.

function iso_map_to_screen

void iso_map_to_screen(
    const ISO_MAP * map,
    int mx,
    int my,
    int h,
    float * screen_x,
    float * screen_y
)

convert map tile coordinates to screen pixel coordinates

Parameters:

  • map the map (uses map->proj)
  • mx tile X
  • my tile Y
  • h height value at this tile
  • screen_x output X in pixels
  • screen_y output Y in pixels

Convert map tile coordinates to screen pixel coordinates.

convert map tile coordinates to screen pixel coordinates

Uses the standard diamond isometric formula: sx = (mx - my) * half_w + half_w sy = (mx + my) * half_h - h * tile_lift

function iso_map_smooth_corner_heights

void iso_map_smooth_corner_heights(
    const ISO_MAP * map,
    int mx,
    int my,
    float * h_n,
    float * h_e,
    float * h_s,
    float * h_w
)

compute smooth corner heights with slope clamping (for rendering)

Parameters:

  • map the map (uses map->smooth_slope_max)
  • mx tile X
  • my tile Y
  • h_n output north corner
  • h_e output east corner
  • h_s output south corner
  • h_w output west corner

Compute smooth corner heights with slope clamping.

compute smooth corner heights with slope clamping (for rendering)

Like iso_map_corner_heights but clamps neighbors that exceed smooth_slope_max to prevent slopes across cliffs.

function iso_map_should_transition_smooth

int iso_map_should_transition_smooth(
    const ISO_MAP * map,
    int mx1,
    int my1,
    int mx2,
    int my2
)

check if terrain transition should render between two cells (height-aware)

Return: 1 if transition should render, 0 otherwise

Check if terrain transition should render between two cells (height-aware).

check if terrain transition should render between two cells (height-aware)

In cut mode: only same-height tiles get transitions. In smooth mode: tiles within smooth_slope_max get transitions.

function iso_map_should_transition

int iso_map_should_transition(
    const ISO_MAP * map,
    int mx1,
    int my1,
    int mx2,
    int my2
)

check if terrain blending should occur between two adjacent cells

Parameters:

  • map the map
  • mx1 first tile X
  • my1 first tile Y
  • mx2 second tile X
  • my2 second tile Y

Return: 1 if terrains differ (blending needed), 0 if same

Check if terrain blending should occur between two adjacent cells.

check if terrain blending should occur between two adjacent cells

function iso_map_set_terrain

void iso_map_set_terrain(
    ISO_MAP * map,
    int mx,
    int my,
    int terrain
)

set terrain type for a cell (bounds-checked)

Parameters:

  • map the map
  • mx tile X
  • my tile Y
  • terrain terrain type index

Set the terrain type at a cell.

set terrain type for a cell (bounds-checked)

function iso_map_set_segments

int iso_map_set_segments(
    ISO_MAP * map,
    int mx,
    int my,
    const ISO_TILE_SEGMENT * segs,
    int count
)

set per-tile segments on an ISO_MAP.

Parameters:

  • map the ISO_MAP
  • mx tile X coordinate
  • my tile Y coordinate
  • segs array of segments (may be NULL if count==0)
  • count number of segments (0..ISO_MAX_SEGMENTS_PER_TILE)

Return: 1 on success, 0 if invariants violated or out of range

Copies data into map->segments (allocated on first call). Also updates heightmap for the tile.

function iso_map_set_projection_target

void iso_map_set_projection_target(
    ISO_MAP * map,
    int preset
)

set target projection preset for smooth interpolation via iso_map_lerp_projection

Parameters:

  • map the map
  • preset one of ISO_PROJ_CLASSIC, ISO_PROJ_ISOMETRIC, ISO_PROJ_STAGGERED, ISO_PROJ_MILITARY

Set the target projection for smooth interpolation.

set target projection preset for smooth interpolation via iso_map_lerp_projection

Call iso_map_lerp_projection() each frame to animate toward it.

function iso_map_set_projection_custom

void iso_map_set_projection_custom(
    ISO_MAP * map,
    float half_w,
    float half_h,
    float tile_lift
)

set custom projection parameters directly

Parameters:

  • map the map
  • half_w half-width of tile diamond
  • half_h half-height of tile diamond
  • tile_lift vertical pixel offset per height unit

Set custom projection parameters directly.

set custom projection parameters directly

function iso_map_set_projection

void iso_map_set_projection(
    ISO_MAP * map,
    int preset,
    float tile_width
)

set projection preset and snap to it immediately

Parameters:

  • map the map
  • preset one of ISO_PROJ_CLASSIC, ISO_PROJ_ISOMETRIC, ISO_PROJ_STAGGERED, ISO_PROJ_MILITARY
  • tile_width full tile width in pixels (half_w = tile_width / 2)

Set projection parameters from a preset and tile width.

set projection preset and snap to it immediately

function iso_map_set_height

void iso_map_set_height(
    ISO_MAP * map,
    int mx,
    int my,
    int h
)

set height for a cell (bounds-checked, clamped)

Parameters:

  • map the map
  • mx tile X
  • my tile Y
  • h height value

Set the height at a cell (clamped to [0, max_height]).

set height for a cell (bounds-checked, clamped)

function iso_map_set_ability

void iso_map_set_ability(
    ISO_MAP * map,
    int mx,
    int my,
    int ab
)

set ability for a cell (bounds-checked)

Parameters:

  • map the map
  • mx tile X
  • my tile Y
  • ab ability value (WALK/SWIM/BLCK)

Set the ability at a cell.

set ability for a cell (bounds-checked)

function iso_map_save

int iso_map_save(
    const ISO_MAP * map,
    const char * filename
)

save ISO_MAP to binary file (chunk-based format)

Parameters:

  • map the map
  • filename output file path

Return: TRUE on success, FALSE on failure

Save ISO_MAP to a binary file.

save ISO_MAP to binary file (chunk-based format)

Format: 4-byte magic "ISOM", then int32 fields: width, height, num_terrains, max_height, followed by terrain[], heightmap[], ability[].

function iso_map_randomize

void iso_map_randomize(
    ISO_MAP * map
)

randomize terrain and height for testing/demo purposes

Parameters:

  • map the map

Randomize terrain and height for testing/demo purposes.

randomize terrain and height for testing/demo purposes

function iso_map_new

ISO_MAP * iso_map_new(
    int width,
    int height,
    int num_terrains,
    int max_height
)

create a new height-aware ISO_MAP with given dimensions

Parameters:

  • width map width in tiles
  • height map height in tiles
  • num_terrains number of terrain types
  • max_height maximum height value per cell

Return: new ISO_MAP or NULL on failure

Create a new height-aware isometric map.

create a new height-aware ISO_MAP with given dimensions

function iso_map_load

ISO_MAP * iso_map_load(
    const char * filename
)

load ISO_MAP from binary file

Parameters:

  • filename input file path

Return: loaded ISO_MAP, or NULL on failure

Load ISO_MAP from a binary file.

load ISO_MAP from binary file

function iso_map_lerp_projection

void iso_map_lerp_projection(
    ISO_MAP * map,
    float dt
)

smoothly interpolate current projection angle toward target (call every frame)

Parameters:

  • map the map
  • dt time step in seconds (e.g. 1.0/60.0)

Smoothly interpolate the projection angle toward the target.

smoothly interpolate current projection angle toward target (call every frame)

Updates half_h from the new angle; half_w and tile_lift are unchanged.

function iso_map_interpolate_height

float iso_map_interpolate_height(
    const ISO_MAP * map,
    float fx,
    float fy
)

bilinear height interpolation at fractional map coordinates

Parameters:

  • map the map
  • fx fractional tile X (e.g. 3.5 = halfway between tile 3 and 4)
  • fy fractional tile Y

Return: interpolated height value

Bilinear height interpolation at fractional map coordinates.

bilinear height interpolation at fractional map coordinates

Samples the 4 surrounding tile corners and interpolates for smooth terrain.

function iso_map_get_visible_edges_segment

ISO_VISIBLE_EDGES iso_map_get_visible_edges_segment(
    const ISO_MAP * map,
    int mx,
    int my,
    int seg_idx
)

Compute per-segment edge visibility for height border rendering.

Parameters:

  • map the ISO_MAP
  • mx tile X coordinate
  • my tile Y coordinate
  • seg_idx segment index within tile (0..count-1)

Return: ISO_VISIBLE_EDGES with flags set (including draw_underside)

Per-segment edge visibility with adjacency + occlusion.

Uses height-range overlap to determine adjacency: two segments are "touching" only if max(b1,b2) < min(t1,t2). A segment with no overlapping neighbour on a given side draws that edge. Floating segments (bottom > 0) also compute underside border visibility. Compute per-segment edge visibility for height border rendering.

ADJACENCY (per edge direction): For ALL segments (ground and floating): draw edge if no neighbour segment has the same top height. Same top = connected surface = no border. Different top = visible height step = border drawn. Range overlap is NOT used, overlapping ranges with different tops (e.g. {10,12} vs {10,11}) still have a visible step at the top.

OCCLUSION (painter-order): NW and NE edges face away from the camera. A tile drawn later (further south in isometric order) can visually cover these edges.

  • NW edge occluded if SW neighbour (mx, my+1) covers seg.top
  • NE edge occluded if SE neighbour (mx+1, my) covers seg.top SE and SW edges face the camera, never explicitly occluded (painter order handles them automatically).

UNDERSIDE (floating segments only): draw_underside = 1 if bottom > 0 AND any side has the gap below exposed (no neighbour segment reaches up to seg.bottom).

topVertex is never set, the struct has no field for it.

function iso_map_get_visible_edges

ISO_VISIBLE_EDGES iso_map_get_visible_edges(
    const ISO_MAP * map,
    int mx,
    int my
)

Compute which diamond edges of tile (mx, my) need a height border.

Parameters:

  • map the ISO_MAP
  • mx tile X coordinate
  • my tile Y coordinate

Return: ISO_VISIBLE_EDGES with flags set

Compute which diamond edges of tile (mx,my) need a height border.

An edge is marked for drawing when the neighbor in that direction has a height difference > 1 or is out of bounds. Edge-to-neighbor mapping (diamond iso layout): NW -> (mx-1, my), NE -> (mx, my-1), SE -> (mx+1, my), SW -> (mx, my+1) Compute which diamond edges of tile (mx, my) need a height border.

An edge is marked for drawing when the neighbor in that direction has a height difference > 1 or is out of bounds (map boundary).

Edge-to-neighbor mapping (diamond isometric layout): NW (N->W, top-left) -> neighbor (mx-1, my) NE (N->E, top-right) -> neighbor (mx, my-1) SE (E->S, bottom-right) -> neighbor (mx+1, my) SW (S->W, bottom-left) -> neighbor (mx, my+1)

function iso_map_get_terrain

int iso_map_get_terrain(
    const ISO_MAP * map,
    int mx,
    int my
)

get terrain type for a cell (bounds-checked)

Parameters:

  • map the map
  • mx tile X
  • my tile Y

Return: terrain type, or 0 if out of bounds

Get the terrain type at a cell.

get terrain type for a cell (bounds-checked)

function iso_map_get_segments

const ISO_TILE_SEGMENTS * iso_map_get_segments(
    const ISO_MAP * map,
    int mx,
    int my
)

get per-tile segments.

Returns NULL if no segment data is set.

function iso_map_get_height

int iso_map_get_height(
    const ISO_MAP * map,
    int mx,
    int my
)

get height for a cell (bounds-checked, clamped)

Parameters:

  • map the map
  • mx tile X
  • my tile Y

Return: height value, or 0 if out of bounds

Get the height at a cell.

get height for a cell (bounds-checked, clamped)

function iso_map_get_ability

int iso_map_get_ability(
    const ISO_MAP * map,
    int mx,
    int my
)

get ability for a cell (bounds-checked)

Parameters:

  • map the map
  • mx tile X
  • my tile Y

Return: ability value (WALK/SWIM/BLCK), or 0 if out of bounds

Get the ability at a cell.

get ability for a cell (bounds-checked)

function iso_map_free

void iso_map_free(
    ISO_MAP ** map
)

free an ISO_MAP and set the pointer to NULL

Parameters:

  • map_ptr pointer to the ISO_MAP pointer

Free an ISO_MAP and set the pointer to NULL.

free an ISO_MAP and set the pointer to NULL

function iso_map_draw

void iso_map_draw(
    const ISO_MAP * map,
    ALLEGRO_BITMAP ** tile_bitmaps,
    ALLEGRO_BITMAP *** transition_tiles,
    int num_masks,
    ALLEGRO_BITMAP ** overlay_bitmaps,
    int num_overlay_tiles,
    float cam_px,
    float cam_py,
    float zoom,
    int screen_w,
    int screen_h,
    int player_mode,
    N_ISO_OBJECT * objects,
    int num_objects
)

Draw the full ISO_MAP with height, transitions, overlays, cliff walls, hover, and grid.

Parameters:

  • map the ISO_MAP
  • tile_bitmaps array of ALLEGRO_BITMAP* per terrain type
  • transition_tiles 2D array [num_terrains][num_masks] of pre-composited transitions
  • num_masks total number of masks (edge + corner, typically 32)
  • overlay_bitmaps array of ALLEGRO_BITMAP* per overlay tile (may be NULL)
  • num_overlay_tiles number of overlay bitmaps (0 if none)
  • cam_px camera X offset in pixels (pre-snapped)
  • cam_py camera Y offset in pixels (pre-snapped)
  • zoom display zoom factor
  • screen_w current screen width in pixels
  • screen_h current screen height in pixels
  • player_mode 1 if in player mode (hover is green), 0 for editor (hover is yellow)
  • objects array of N_ISO_OBJECT to depth-sort with tiles (may be NULL)
  • num_objects number of objects in the array (0 if none)

Draw the full ISO_MAP with segment-sorted rendering.

Objects (if provided) are depth-sorted and interleaved with tiles using the painter's algorithm. Occluded objects are optionally redrawn as a transparent overlay based on their occluded_alpha setting. Draw the full ISO_MAP with height, transitions, overlays, cliff walls, hover, and grid.

When segment data is available, tiles are decomposed into individual segments and sorted by (segment.bottom, my, mx). This allows multi-segment tiles (bridges, overhangs) to interleave correctly with ground-level tiles in the painter's algorithm.

Per-segment rendering order: Step 0: Underside face (floating segments only, 65% tint) Step 1: Cliff walls (between bottom and top) Step 2: Tile top surface (flat or warped for ground segments) Step 3: Terrain transitions (ground segments only) Step 3.5: Height borders (ground segments only) Step 4: Objects (depth-sorted, interleaved by segment sort key) Step 5: Hover highlight Step 6: Grid overlay Step 7 (post-loop): Occluded object overlays

function iso_map_corner_heights

void iso_map_corner_heights(
    const ISO_MAP * map,
    int mx,
    int my,
    float * h_n,
    float * h_e,
    float * h_s,
    float * h_w
)

compute average corner heights for smooth rendering (Article 2026)

Parameters:

  • map the map
  • mx tile X
  • my tile Y
  • h_n output: north (top) corner height
  • h_e output: east (right) corner height
  • h_s output: south (bottom) corner height
  • h_w output: west (left) corner height

Compute average corner heights for smooth tile rendering (Article 2026).

compute average corner heights for smooth rendering (Article 2026)

Each diamond corner is shared by 4 tiles. This averages the heights of the sharing tiles to produce smooth corners. North corner = average of (mx,my), (mx-1,my), (mx,my-1), (mx-1,my-1).

function iso_map_calc_transitions_full

void iso_map_calc_transitions_full(
    const ISO_MAP * map,
    int mx,
    int my,
    int * edge_bits,
    int * corner_bits
)

compute per-terrain transition bitmasks with height filtering (Article 934).

Parameters:

  • map the map
  • mx tile X
  • my tile Y
  • edge_bits output array [num_terrains] of 4-bit edge masks
  • corner_bits output array [num_terrains] of 4-bit corner masks

Compute per-terrain transition bitmasks with height filtering.

edge_bits and corner_bits must be arrays of size num_terrains.

compute per-terrain transition bitmasks with height filtering (Article 934).

Iterates terrains above the base terrain and sets edge/corner bits for each terrain that has higher visual priority than the cell. edge_bits and corner_bits must be arrays of at least map->num_terrains.

function iso_map_calc_transitions

void iso_map_calc_transitions(
    const ISO_MAP * map,
    int mx,
    int my,
    int * edge_bits,
    int * corner_bits
)

compute terrain transition bitmasks for a cell (Article 934)

Parameters:

  • map the map
  • mx tile X
  • my tile Y
  • edge_bits output: 4-bit edge mask (W, N, E, S)
  • corner_bits output: 4-bit corner mask (NW, NE, SE, SW)

Compute terrain transition bitmasks for a cell (Article 934).

compute terrain transition bitmasks for a cell (Article 934)

For a given terrain at (mx, my), checks all 8 neighbors. If a neighbor has a higher-priority (lower index) terrain, the corresponding edge or corner bit is set. Corner bits are only set when the adjacent edges do NOT have the foreign terrain (to avoid redundant overlaps).

function iso_map_build_draw_order

int iso_map_build_draw_order(
    const ISO_MAP * map,
    ISO_DRAW_ENTRY * out,
    int max_entries
)

Build the draw order for segment-sorted rendering.

Parameters:

  • map the ISO_MAP
  • out output array, must have room for widthheightISO_MAX_SEGMENTS_PER_TILE entries
  • max_entries capacity of out[]

Return: number of entries written

Populates out[] with one entry per segment (or one per tile if no segment data is available), sorted by (bottom, my, mx).

function iso_is_in_diamond

int iso_is_in_diamond(
    int px,
    int py,
    int tile_w,
    int tile_h
)

test if pixel (px,py) is inside the isometric diamond of size tile_w x tile_h

Parameters:

  • px pixel X (0..tile_w-1)
  • py pixel Y (0..tile_h-1)
  • tile_w tile width in pixels
  • tile_h tile height in pixels

Return: 1 if inside, 0 if outside

Test if pixel (px,py) is inside the isometric diamond.

test if pixel (px,py) is inside the isometric diamond of size tile_w x tile_h

The diamond is centered in a tile_w x tile_h rectangle.

function iso_generate_transition_tiles

void iso_generate_transition_tiles(
    ALLEGRO_BITMAP *** tiles,
    ALLEGRO_BITMAP ** masks,
    ALLEGRO_BITMAP ** tile_bitmaps,
    int num_terrains,
    int tile_w,
    int tile_h
)

Pre-composite transition tiles (terrain texture * alpha mask).

Parameters:

  • tiles output 2D array of ALLEGRO_BITMAP* (caller must free)
  • masks array of ISO_NUM_MASKS transition alpha masks
  • tile_bitmaps array of num_terrains terrain tile bitmaps
  • num_terrains number of terrain types
  • tile_w tile width in pixels
  • tile_h tile height in pixels

tiles[t][m] = terrain t composited with mask m. tiles must be a [num_terrains][ISO_NUM_MASKS] array of ALLEGRO_BITMAP*. tiles[t][m] = terrain t composited with mask m.

function iso_generate_transition_masks

void iso_generate_transition_masks(
    ALLEGRO_BITMAP ** masks,
    int tile_w,
    int tile_h
)

Generate the 32 procedural transition alpha masks (16 edge + 16 corner).

Parameters:

  • masks output array of ALLEGRO_BITMAP* (caller must free)
  • tile_w tile width in pixels
  • tile_h tile height in pixels

The masks array must have room for ISO_NUM_MASKS entries. For EDGE masks (0-15): each bit corresponds to one side of the diamond being "covered". The alpha fades from the edge inward using a gradient that follows the diamond edge normals.

For CORNER masks (16-31): each bit corresponds to one corner of the diamond being "covered". The alpha fades radially from the diamond tip inward.

function iso_diamond_dist

float iso_diamond_dist(
    int px,
    int py,
    int tile_w,
    int tile_h
)

distance from pixel to diamond edge (0 at edge, 1 at center)

Parameters:

  • px pixel X
  • py pixel Y
  • tile_w tile width in pixels
  • tile_h tile height in pixels

Return: distance in [0, 1]

Distance from pixel to the diamond edge.

distance from pixel to diamond edge (0 at edge, 1 at center)

Returns 0 at the edge, 1 at the center. Pixels outside the diamond return 0.

function iso_corner_to_screen

void iso_corner_to_screen(
    const ISO_MAP * map,
    int cx,
    int cy,
    float fh,
    float cam_x,
    float cam_y,
    float zoom,
    float * sx,
    float * sy
)

Project a tile corner to screen coordinates (canonical formula).

Parameters:

  • map the map (uses map->proj)
  • cx corner X in tile grid (e.g. mx+1 for the East corner)
  • cy corner Y in tile grid
  • fh height (float, supports smooth-height interpolation)
  • cam_px integer-snapped camera pixel X: floor(cam_x * zoom)
  • cam_py integer-snapped camera pixel Y: floor(cam_y * zoom)
  • zoom zoom factor
  • sx output screen X
  • sy output screen Y

Produces bit-identical results for the same (cx,cy,fh) regardless of which tile's draw call computes the vertex. Used by the renderer to eliminate shared-edge seams between adjacent wall faces.

Public version of the canonical vertex projection used by the renderer. cam_px and cam_py may be integer-snapped (floor(cam_x * zoom)) for stable per-pixel rendering with NEAREST sampling, or sub-pixel (cam_x * zoom) for smooth camera motion paired with MIN_LINEAR bilinear sampling. The renderer uses the sub-pixel path; see docs/rendering.md for details.

function iso_apply_primitive_color_filter

ALLEGRO_COLOR iso_apply_primitive_color_filter(
    ALLEGRO_COLOR c
)

function iso_apply_line_jitter_compensation

void iso_apply_line_jitter_compensation(
    float * out_dx,
    float * out_dy
)

Attributes Documentation

variable n_iso_setup_us

double n_iso_setup_us;

variable n_iso_pass3_us

double n_iso_pass3_us;

variable n_iso_pass2_us

double n_iso_pass2_us;

variable n_iso_pass1_us

double n_iso_pass1_us;

Per-pass timing accumulators populated by iso_map_draw.

Each iso_map_draw() call adds its per-pass elapsed time (microseconds) to these globals. The host application is responsible for resetting them to 0.0 at the start of every measurement window (typically frame start), then reading them after the world render block to see how the cost split across the three internal passes:

  • n_iso_pass1_us: Pass 1: ground tiles (object-free loop)
  • n_iso_pass2_us: Pass 2: elevated segments + interleaved object callbacks (includes time spent inside N_ISO_OBJECT.draw callbacks; subtract any host-side callback timing to isolate the library's segment work)
  • n_iso_pass3_us: Pass 3: occlusion ghost overlay

Always populated. The overhead is six al_get_time() calls per iso_map_draw invocation: empirically < 1 us total, negligible vs the milliseconds-scale work the function does. No runtime flag needed.

Macros Documentation

define WALK

#define WALK 1

FLAG of a walkable tile.

define SWIM

#define SWIM 2

FLAG of a swimmable tile.

define ISO_PROJ_WIDE

#define ISO_PROJ_WIDE ISO_PROJ_STAGGERED

Legacy alias: ISO_PROJ_WIDE maps to ISO_PROJ_STAGGERED.

define ISO_PROJ_STEEP

#define ISO_PROJ_STEEP ISO_PROJ_ISOMETRIC

Legacy alias: ISO_PROJ_STEEP maps to ISO_PROJ_ISOMETRIC.

define ISO_PROJ_STAGGERED

#define ISO_PROJ_STAGGERED 3

Projection ID: flatter dimetric (~18.43 degree angle).

define ISO_PROJ_MILITARY

#define ISO_PROJ_MILITARY 2

Projection ID: military/planometric (45 degree angle).

define ISO_PROJ_ISOMETRIC

#define ISO_PROJ_ISOMETRIC 1

Projection ID: true isometric (30 degree angle).

define ISO_PROJ_CLASSIC

#define ISO_PROJ_CLASSIC 0

Projection ID: classic 2:1 isometric (~26.565 degree angle).

define ISO_NUM_PROJECTIONS

#define ISO_NUM_PROJECTIONS 4

Number of built-in projection presets.

define ISO_NUM_MASKS

#define ISO_NUM_MASKS (ISO_NUM_EDGE_MASKS + ISO_NUM_CORNER_MASKS)

Total number of transition masks (edge + corner).

define ISO_NUM_EDGE_MASKS

#define ISO_NUM_EDGE_MASKS 16

Number of possible edge mask combinations (2^4 = 16).

define ISO_NUM_CORNER_MASKS

#define ISO_NUM_CORNER_MASKS 16

Number of possible corner mask combinations (2^4 = 16).

define ISO_MAX_SEGMENTS_PER_TILE

#define ISO_MAX_SEGMENTS_PER_TILE 2

Max height segments per tile (ground + one elevated structure).

define ISO_EDGE_W

#define ISO_EDGE_W (1 << 0)

Edge bitmask: west neighbor has higher terrain.

define ISO_EDGE_S

#define ISO_EDGE_S (1 << 3)

Edge bitmask: south neighbor has higher terrain.

define ISO_EDGE_N

#define ISO_EDGE_N (1 << 1)

Edge bitmask: north neighbor has higher terrain.

define ISO_EDGE_E

#define ISO_EDGE_E (1 << 2)

Edge bitmask: east neighbor has higher terrain.

define ISO_CORNER_SW

#define ISO_CORNER_SW (1 << 3)

Corner bitmask: southwest diagonal has higher terrain.

define ISO_CORNER_SE

#define ISO_CORNER_SE (1 << 2)

Corner bitmask: southeast diagonal has higher terrain.

define ISO_CORNER_NW

#define ISO_CORNER_NW (1 << 0)

Corner bitmask: northwest diagonal has higher terrain.

define ISO_CORNER_NE

#define ISO_CORNER_NE (1 << 1)

Corner bitmask: northeast diagonal has higher terrain.

define BLCK

#define BLCK 3

FLAG of a stopping tile.