#ifndef _TILEMAP_H_ #define _TILEMAP_H_ #include "actor.h" #include "staticstring.h" #include #define AKGL_TILEMAP_MAX_WIDTH 512 #define AKGL_TILEMAP_MAX_HEIGHT 512 #define AKGL_TILEMAP_MAX_LAYERS 16 #define AKGL_TILEMAP_MAX_TILESETS 16 #define AKGL_TILEMAP_MAX_TILES_PER_IMAGE 65536 #define AKGL_TILEMAP_MAX_TILESET_NAME_SIZE 512 #define AKGL_TILEMAP_MAX_TILESET_FILENAME_SIZE 512 #define AKGL_TILEMAP_MAX_OBJECT_NAME_SIZE 512 #define AKGL_TILEMAP_MAX_OBJECTS_PER_LAYER 128 #define AKGL_TILEMAP_OBJECT_TYPE_ACTOR 1 #define AKGL_TILEMAP_LAYER_TYPE_TILES 1 #define AKGL_TILEMAP_LAYER_TYPE_OBJECTS 2 #define AKGL_TILEMAP_LAYER_TYPE_IMAGE 3 typedef struct { float x; float y; int gid; int id; int height; int width; int rotation; int type; bool visible; akgl_Actor *actorptr; char name[AKGL_TILEMAP_MAX_OBJECT_NAME_SIZE]; } akgl_TilemapObject; typedef struct { short type; float opacity; bool visible; int height; int width; int x; int y; int id; SDL_Texture *texture; int data[AKGL_TILEMAP_MAX_WIDTH * AKGL_TILEMAP_MAX_HEIGHT]; akgl_TilemapObject objects[AKGL_TILEMAP_MAX_OBJECTS_PER_LAYER]; } akgl_TilemapLayer; typedef struct { int columns; int firstgid; char imagefilename[AKGL_TILEMAP_MAX_TILESET_FILENAME_SIZE]; int imageheight; int imagewidth; char name[AKGL_TILEMAP_MAX_TILESET_NAME_SIZE]; SDL_Texture *texture; // Use this as a lookup table instead of storing tiles // in individual textures to blit them from a single // texture at runtime // FIXME: This is probably not very efficient. For a map // with a single tileset it makes sense. For a map with // multiple tilesets you may have set A start at firstgid 1 // and have 1728 tiles. Set B may start at firstgid 1729 and // have 1728 more tiles. This means Set B has 1728 empty // tile_offsets[] entries before firstgid 1729 because of the // way akgl_tilemap_load_tilesets() works. This is really inefficient // and should be improved in the future, and will eventually // lead to premature exhaustion of AKGL_TILEMAP_MAX_TILES_PER_IMAGE // because set D or E may only have 64 tiles but they may be // at the upper end of the array bound already because of this. int tile_offsets[AKGL_TILEMAP_MAX_TILES_PER_IMAGE][2]; int tilecount; int tileheight; int tilewidth; int spacing; int margin; } akgl_Tileset; typedef struct { int tilewidth; int tileheight; int width; int height; int numlayers; int orientation; // 0 = orthogonal, 1 = isometric int numtilesets; int p_foreground_y; int p_vanishing_y; int p_foreground_h; int p_vanishing_h; float p_scale; float p_rate; akgl_Tileset tilesets[AKGL_TILEMAP_MAX_TILESETS]; akgl_TilemapLayer layers[AKGL_TILEMAP_MAX_LAYERS]; } akgl_Tilemap; akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_load(char *fname, akgl_Tilemap *dest); akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_draw(SDL_Renderer *renderer, akgl_Tilemap *dest, SDL_FRect *viewport, int layeridx); akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_draw_tileset(SDL_Renderer *renderer, akgl_Tilemap *dest, int tilesetidx); /* * These functions are part of the internal API and should not be called by the user. * They are only exposed here for unit testing. */ akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_tilemap_property(json_t *obj, char *key, char *type, json_t **dest); akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_properties_string(json_t *obj, char *key, akgl_String **dest); akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_properties_integer(json_t *obj, char *key, int *dest); akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_compute_tileset_offsets(akgl_Tilemap *dest, int tilesetidx); akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_load_layer_objects(akgl_Tilemap *dest, json_t *root, int layerid); akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_load_layer_tile(akgl_Tilemap *dest, json_t *root, int layerid); akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_load_layers(akgl_Tilemap *dest, json_t *root); akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_load_tilesets_each(json_t *tileset, akgl_Tilemap *dest, int tsidx); akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_load_tilesets(akgl_Tilemap *dest, json_t *root); akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_release(akgl_Tilemap *dest); akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_scale_actor(akgl_Tilemap *map, akgl_Actor *actor); #endif //_TILEMAP_H_