RogueLife/src/map.h

108 lines
2.6 KiB
C

//---
// map: Dynamic level models
//
// This module provides dynamic maps as they are used during games. This
// includes objects being activated and their current state, doors being
// opened, crates being blown up, you name it. But not moving entities.
//---
#pragma once
#include "fixed.h"
#include "map.h"
#include "geometry.h"
#include <gint/display.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
//---
// Tileset
//---
typedef struct
{
/* Rendering plane */
uint8_t plane;
/* Length of animation cycle. This is only defined for the first tile of
each cycle, because the cycle can use the same tile several times. If
anim_length=0 there is no animation; anim_length=1 is useless. */
uint8_t anim_length;
/* Index in the tileset's animation array where this tile's animation cycle
starts; it spans the range [anim_start .. anim_start+anim_length). */
uint8_t anim_start;
/* Hitbox. TODO: Allow any collision rectangle for tiles, for decor */
bool solid;
} tile_info_t;
typedef struct
{
/* ID of the tile visible during this frame */
uint16_t tile_id;
/* Duration before next frame, in ms */
uint16_t duration_ms;
} tile_animation_frame_t;
typedef struct
{
int width, height;
bopti_image_t const *sheet;
/* Tile information */
tile_info_t *tiles;
/* Animations */
tile_animation_frame_t *anim;
} tileset_t;
/* Shape for a tile; this lives in a coordinate system whose (0,0) ends up at
the middle of the tile in the map space (which is a point with half-integer
coordinates) */
rect tile_shape(tileset_t const *tileset, int id);
//---
// Tiles
//---
typedef struct
{
/* Base layer: floor/wall pattern */
uint8_t base;
/* Decoration layer */
uint8_t decor;
} map_cell_t;
//---
// Map grid, tiles location in space, and entities
//---
typedef struct
{
/* Dimensions, columns are 0 to width-1, rows are 0 to height-1 */
uint16_t width, height;
/* Tileset base (first layer), tileset decor (second layer) */
tileset_t *tileset;
/* All cells */
map_cell_t *cells;
} map_t;
/* Get a pointer to the cell at (x,y) in map; NULL if out of bounds. */
map_cell_t *map_cell(map_t const *m, int x, int y);
/* Check whether a map cell is walkable, only accounting for full hitboxes. */
bool map_cell_walkable(map_t const *m, map_cell_t const *cell);
/* Check whether a hitbox collides with the map. */
bool map_collides(map_t const *m, rect hitbox);
/* Returns the new position of an object with a hitbox trying to move from
[old_pos] to [new_pos]. */
vec2 map_move(map_t const *m, vec2 old_pos, vec2 new_pos, rect hitbox);