From e2d12804d20ac1c06050f98822bf226a77fc382a Mon Sep 17 00:00:00 2001 From: Miloslav Ciz Date: Thu, 3 Aug 2023 21:12:23 +0200 Subject: [PATCH] Create block adding functions --- constants.h | 7 ++ debug.h | 23 ++++++ frontend_sdl.c | 1 + main.c | 8 +- map.h | 202 +++++++++++++++++++++++++++++++++++++++++++++---- settings.h | 2 +- 6 files changed, 225 insertions(+), 18 deletions(-) create mode 100644 constants.h create mode 100644 debug.h create mode 100644 frontend_sdl.c diff --git a/constants.h b/constants.h new file mode 100644 index 0000000..aa4a0be --- /dev/null +++ b/constants.h @@ -0,0 +1,7 @@ +#ifndef _LCR_CONSTANTS_H +#define _LCR_CONSTANTS_H + +/** Maximum number of triangles of a block shape. */ +#define LCR_MAP_BLOCK_SHAPE_MAX_TRIANGLES 32 + +#endif diff --git a/debug.h b/debug.h new file mode 100644 index 0000000..8cf705e --- /dev/null +++ b/debug.h @@ -0,0 +1,23 @@ +#ifndef _LCR_DEBUG_H +#define _LCR_DEBUG_H + +#include "map.h" +#include + +void LCR_debugPrintCurrentMap() +{ + puts("current map:"); + + for (int i = 0; i < LCR_currentMap.blockCount; ++i) + { + uint8_t x, y, z; + + LCR_mapBlockGetCoords(LCR_currentMap.blocks + i * 4,&x,&y,&z); + + printf(" block %d: type %d, coord %d (%d %d %d)\n",i, + LCR_currentMap.blocks[i * 4],LCR_mapBlockGetCoordNumber( + LCR_currentMap.blocks + i * 4),x,y,z); + } +} + +#endif diff --git a/frontend_sdl.c b/frontend_sdl.c new file mode 100644 index 0000000..7bb61ba --- /dev/null +++ b/frontend_sdl.c @@ -0,0 +1 @@ +#include "game.h" diff --git a/main.c b/main.c index 247e0ae..77012a4 100644 --- a/main.c +++ b/main.c @@ -1,9 +1,13 @@ #include #include "game.h" +#include "debug.h" int main(void) { - puts("aaa"); - return 1; + LCR_mapLoad(LCR_map0); + + LCR_debugPrintCurrentMap(); + + return 0; } diff --git a/map.h b/map.h index 2cbce76..e4fc7e4 100644 --- a/map.h +++ b/map.h @@ -2,6 +2,8 @@ #define _LCR_MAP #include +#include "constants.h" +#include "settings.h" /** The map (track) module for Licar. @@ -12,7 +14,7 @@ - x goes right, y goes up, z goes forward - coordinate number is a single number obtained as x + 64 * y + 64 * 64 * z - Map format is binary and consists of the following values: + The STORAGE map format is binary and consists of the following values: - 76, 77 (for "LM", magic number) - ASCII map name - 10 (separator) @@ -20,7 +22,7 @@ - 10 (separator) - block values, each one in the format: - 1 byte type: says the type of block. If the highest bit is 0, the block - is normal, otherwise it is a special block (e.g. a "command") + is normal, otherwise it is a special block (will be preprocessed) - 3 bytes: A, B, C, such that: - A, B and lowest 2 bits of C form the block coordinate number (A being the lowest part etc.) @@ -36,6 +38,10 @@ blocks placed on the same coordinate. Internally the map will be preprocessed to RAM when loaded so that thing like the magic number and special blocks are removed and the remaining blocks will be sorted for fast block searching. + + The PREPROCESSED map format is similar, but only consists of block values but + there are only normal blocks (no special blocks) and they are sorted by their + coordinate number. */ #define LCR_BLOCK_TRANSFORM_ROT_MASK 0x60 @@ -48,33 +54,62 @@ #define LCR_BLOCK_XYZ_TO_COORD(x,y,z) -#define LCR_MAP_MAGIC_NUMBER 'L', 'M' +#define LCR_MAP_MAGIC_NUMBER1 'L' +#define LCR_MAP_MAGIC_NUMBER2 'M' +#define LCR_MAP_MAGIC_NUMBER LCR_MAP_MAGIC_NUMBER1, LCR_MAP_MAGIC_NUMBER2 #define LCR_MAP_TERMINATOR 0xff -#define LCR_MAP_BLOCK(t,x,y,z,r) 0 // TODO +#define LCR_MAP_BLOCK(t,x,y,z,m,r) t,(unsigned char) (x | (y << 6)), \ + (unsigned char) ((y >> 2) | (z << 4)), \ + (unsigned char) ((z >> 4) | (m << 2) | \ + (r << 4)) #define LCR_BLOCK_MATERIAL_CONCRETE 0x00 +#define LCR_BLOCK_MATERIAL_DIRT 0x01 #define LCR_MAP_COUNT 1 -#define LCR_BLOCK_FULL 0x00 ///< completely filled block -#define LCR_BLOCK_BOTTOM 0x01 ///< filled bottom half of block -#define LCR_BLOCK_LEFT 0x02 ///< filled left half of block -#define LCR_BLOCK_LEFT_FRONT 0x03 ///< filled left front quarter of block -#define LCR_BLOCK_BOTTOM_LEFT 0x04 ///< filled bottom left quarter of block +// normal blocks: +#define LCR_BLOCK_FULL 0x00 ///< completely filled block +#define LCR_BLOCK_BOTTOM 0x01 ///< filled bottom half of block +#define LCR_BLOCK_LEFT 0x02 ///< filled left half of block +#define LCR_BLOCK_LEFT_FRONT 0x03 ///< filled left front quarter of block +#define LCR_BLOCK_BOTTOM_LEFT 0x04 ///< filled bottom left quarter of block -typedef struct +#define LCR_BLOCK_CHECKPOINT_NOT 0x10 ///< checkpoint, not taken +#define LCR_BLOCK_CHECKPOINT_YES 0x11 ///< checkpoint, taken +#define LCR_BLOCK_FINISH 0x12 ///< finish + +// special blocks: +#define LCR_BLOCK_NONE 0x80 /**< no block, can be used e.g to make + holes */ +#define LCR_BLOCK_CUBOID_FILL 0x81 /**< makes a cuboid from the previously + specified block, the size is given + by block coordinates */ +#define LCR_BLOCK_CUBOID_HOLLOW 0x82 /**< same as the cuboid special block, but + makes a hollow cuboid */ +#define LCR_BLOCK_START 0x83 /**< specifies start block position */ + +struct { - uint8_t type; ///< block type - uint8_t coordMatTrans[3]; ///< coordinate, material and transform -} LCR_MapBlock; + uint16_t blockCount; + uint8_t blocks[LCR_SETTING_MAP_MAX_SIZE * 4]; + uint32_t startPos; + + // TODO: name, desc? possibly as a single '\n' separated string? +} LCR_currentMap; static const uint8_t LCR_map0[] = { LCR_MAP_MAGIC_NUMBER, - 77, 48, 10 // map name: M0 + 77, 48, 10, // map name: M0 10, // map comment: - LCR_MAP_BLOCK( LCR_BLOCK_CUBE, 1, 2, 3, 0), + LCR_MAP_BLOCK( LCR_BLOCK_NONE, 3, 0, 0, LCR_BLOCK_MATERIAL_CONCRETE, 0), + LCR_MAP_BLOCK( LCR_BLOCK_FULL, 3, 0, 0, LCR_BLOCK_MATERIAL_CONCRETE, 0), + LCR_MAP_BLOCK( LCR_BLOCK_FULL, 0, 1, 0, LCR_BLOCK_MATERIAL_CONCRETE, 0), + LCR_MAP_BLOCK( LCR_BLOCK_FULL, 2, 0, 0, LCR_BLOCK_MATERIAL_CONCRETE, 0), + LCR_MAP_BLOCK( LCR_BLOCK_FULL, 0, 1, 0, LCR_BLOCK_MATERIAL_CONCRETE, 0), + LCR_MAP_BLOCK( LCR_BLOCK_FULL, 3, 0, 0, LCR_BLOCK_MATERIAL_CONCRETE, 0), LCR_MAP_TERMINATOR }; @@ -83,4 +118,141 @@ static const uint8_t *LCR_maps[LCR_MAP_COUNT] = LCR_map0 }; +void LCR_mapBlockGetCoords(const uint8_t block[4], uint8_t *x, uint8_t *y, + uint8_t *z) +{ + *x = block[1] & 0x3f; + *y = (block[1] >> 6) | ((block[2] & 0x0f) << 2); + *z = (block[2] >> 4) | ((block[3] & 0x03) << 4); +} + +uint32_t LCR_mapBlockGetCoordNumber(const uint8_t block[4]) +{ + return block[1] | (((uint32_t) block[2]) << 8) | + ((((uint32_t) block[3]) & 0x3) << 16); +} + +/** + Adds given block to current map, including possibly deleting a block by + adding LCR_BLOCK_NONE. The function handles sorting the block to the right + position. Returns 1 on success, else 0. +*/ +uint8_t _LCR_mapAddBlock(const uint8_t block[4]) +{ + if (LCR_currentMap.blockCount >= LCR_SETTING_MAP_MAX_SIZE) + return 0; + + uint32_t coord = LCR_mapBlockGetCoordNumber(block); + uint16_t insertAt = 0; + + while (insertAt < LCR_currentMap.blockCount && + coord > LCR_mapBlockGetCoordNumber(LCR_currentMap.blocks + insertAt * 4)) + insertAt++; + + if (block[0] == LCR_BLOCK_NONE) + { + if (insertAt < LCR_currentMap.blockCount && + coord == LCR_mapBlockGetCoordNumber(LCR_currentMap.blocks + insertAt * 4)) + { + // shift all left (remove the block): + for (uint16_t i = insertAt * 4; i < LCR_currentMap.blockCount * 4 - 1; ++i) + LCR_currentMap.blocks[i] = LCR_currentMap.blocks[i + 1]; + + LCR_currentMap.blockCount--; + } + + return 1; + } + + if (insertAt == LCR_currentMap.blockCount || + coord != LCR_mapBlockGetCoordNumber(LCR_currentMap.blocks + insertAt * 4)) + { + // shift from here to the right, make room for the new block + + LCR_currentMap.blockCount++; + + for (int16_t i = ((int16_t) LCR_currentMap.blockCount) - 1; i > insertAt; i--) + for (uint8_t j = 0; j < 4; ++j) + LCR_currentMap.blocks[i * 4 + j] = LCR_currentMap.blocks[(i - 1) * 4 + j]; + } + + insertAt *= 4; + + for (uint8_t j = 0; j < 4; ++j) + LCR_currentMap.blocks[insertAt + j] = block[j]; + + return 1; +} + +/** + Loads and preprocesses given map. Returns 1 on success, otherwise 0. +*/ +uint8_t LCR_mapLoad(const uint8_t *map) +{ + LCR_currentMap.startPos = 0; + LCR_currentMap.blockCount = 0; + + if (map[0] != LCR_MAP_MAGIC_NUMBER1 || map[1] != LCR_MAP_MAGIC_NUMBER2) + return 1; + + map += 2; + + while (*map != 10) // read map name + { + // TODO + map++; + } + + map++; + + while (*map != 10) // read map description + { + // TODO + map++; + } + + map++; + + while (*map != LCR_MAP_TERMINATOR) + { + if (!_LCR_mapAddBlock(map)) + return 0; + + map += 4; + } + + // process and remove special blocks: + + // TODO + + // sort the blocks (for fast searching): + + // TODO + + return 1; +} + +/** + Gets a pointer to a map block of the currently loaded map at given + coordinates. If there is no block at given coordinates, 0 is returned. +*/ +const uint8_t *LCR_mapGetBlockAt(uint8_t x, uint8_t y, uint8_t z) +{ + return 0; +} + +/** + Gets a shape of given map block type as a 3D model composed of triangles. The + model is returned as an array of 16 bit ints, each of which represents + X with lowest 5 bits, Y with next 5 bits and Z with next 5 bits (the + directions of axes are same as map X, Y, Z directions). Each coordinate can + go from 0 to 16; WATCH OUT, THIS IS 17 VALUES, NOT 16, so as to allow having + a mid coord (8), mid-mid coords (4, 12) and mid-mid-mid coords. +*/ +void LCR_mapGetBlockShape(uint8_t blockType, uint8_t transform, + uint16_t triangles[LCR_MAP_BLOCK_SHAPE_MAX_TRIANGLES * 3], + uint8_t *triangleCount) +{ +} + #endif // guard diff --git a/settings.h b/settings.h index 028ca41..66882c2 100644 --- a/settings.h +++ b/settings.h @@ -4,7 +4,7 @@ #ifndef LCR_SETTING_MAP_MAX_SIZE /** Maximum number of blocks a map can consist of, decreasing will save RAM but also rule out loading bigger maps. */ - #define LCR_SETTING_MAP_MAX_SIZE 256 + #define LCR_SETTING_MAP_MAX_SIZE 4096 #endif #endif // guard