From 80167969fe39de1536af094e6db8e642a8b3718e Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Tue, 22 Dec 2020 17:01:59 +0100 Subject: [PATCH] convert map and implement collisions --- CMakeLists.txt | 4 +- MystNB.g1a | Bin 33556 -> 34840 bytes assets-fx/converters.py | 89 ++++++++++++++++++++++++++++++ assets-fx/lv1.png | Bin 0 -> 580 bytes assets-fx/map/fxconv-metadata.txt | 3 + assets-fx/map/lv1.txt | 10 ++++ src/engine.c | 5 +- src/engine.h | 26 ++++++++- src/main.c | 8 +-- 9 files changed, 135 insertions(+), 10 deletions(-) create mode 100644 assets-fx/converters.py create mode 100644 assets-fx/lv1.png create mode 100644 assets-fx/map/fxconv-metadata.txt create mode 100644 assets-fx/map/lv1.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 88d740c..2e54d50 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,10 +21,11 @@ set(ASSETS ) set(ASSETS_fx assets-fx/levels.png + assets-fx/lv1.png assets-fx/title.png assets-fx/spritesheet.png assets-fx/font_mystere.png - # ... + assets-fx/map/lv1.txt ) set(ASSETS_cg assets-cg/example.png @@ -32,6 +33,7 @@ set(ASSETS_cg ) fxconv_declare_assets(${ASSETS} ${ASSETS_fx} ${ASSETS_cg} WITH_METADATA) +fxconv_declare_converters(assets-fx/converters.py) add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}}) target_compile_options(myaddin PRIVATE -Wall -Wextra -Os) diff --git a/MystNB.g1a b/MystNB.g1a index fd225e9364a4f535bcd82fd60a1b639be21fbf83..f4a7e2a1f8e63dc6c1c7d5d879efcbe442b6e8c4 100644 GIT binary patch delta 2627 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 Bx+VYs diff --git a/assets-fx/converters.py b/assets-fx/converters.py new file mode 100644 index 0000000..b043745 --- /dev/null +++ b/assets-fx/converters.py @@ -0,0 +1,89 @@ +import fxconv +import re +import os.path + +def convert(input, output, params, target): + if params["custom-type"] == "map": + convert_map(input, output, params, target) + return 0 + else: + return 1 + +def convert_map(input, output, params, target): + TILE_AIR = 0 + TILE_WALL = 1 + TILE_START = 2 + TILE_END = 3 + TILE_KEY = 16 + TILE_VDOOR = 24 + TILE_HDOOR = 32 + + # Read input file + + with open(input, "r") as fp: + tiles, cycles = fp.read().split("\n\n") + tiles = tiles.split("\n") + cycle_texts = [c for c in cycles.split("\n") if c] + + w = max(len(t) for t in tiles) + h = len(tiles) + fog = 0 + + filename = os.path.splitext(os.path.basename(input))[0] + + # Generate map contents + + encoded_tiles = bytearray(w * h) + for (y, t) in enumerate(tiles): + for (x, c) in enumerate(t): + if c == " ": + tile = TILE_AIR + elif c == "#": + tile = TILE_WALL + elif c == "~": + tile = TILE_START + elif c == "@": + tile = TILE_END + elif ord("0") <= ord(c) <= ord("9"): + tile = TILE_KEY + int(c) + elif ord("a") <= ord(c) <= ord("z"): + tile = TILE_VDOOR + (ord(c) - ord("a")) + elif ord("A") <= ord(c) <= ord("Z"): + tile = TILE_HDOOR + (ord(c) - ord("A")) + else: + raise fxconv.FxconvError(f"unknown tile character {c}") + + encoded_tiles[y*w + x] = tile + + # Parse door cycles + + RE_CYCLE = re.compile(r'^([a-zA-Z]):\s*([#.]+)$') + cycles = dict() + + for c in cycle_texts: + m = re.match(RE_CYCLE, c) + if not m: + raise fxconv.FxconvError(f"cannot parse door cycle '{c}'") + cycles[m[1]] = m[2].encode("utf-8") + + # Generate door cycle data + + door_cycle = b"" + door_cycle_index = bytearray(16) + + for index, letter in enumerate("abcdefghABCDEFGH"): + door_cycle_index[index] = len(door_cycle) + if letter in cycles: + door_cycle += cycles[letter] + b" " + + door_cycle = door_cycle + bytes(128 - len(door_cycle)) + + # Generate the structure + + o = fxconv.ObjectData() + o += fxconv.u32(w) + fxconv.u32(h) + fxconv.u32(fog) + o += door_cycle + door_cycle_index + o += fxconv.ref(f"img_{filename}") + o += fxconv.ref(encoded_tiles) + + fxconv.elf(o, output, "_" + params["name"], **target) diff --git a/assets-fx/lv1.png b/assets-fx/lv1.png new file mode 100644 index 0000000000000000000000000000000000000000..4bdd166d4a632a9e0e64b8fd64e17790d308ab4b GIT binary patch literal 580 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!3HERU8}DLQk(@Ik;M!QddeWoSh3W;3@FH6 z;_2(k{)9)2%UJKq%HQ!oA;}Wgh!W@g+}zZ>5(ej@)Wnk16ovB4k_-iRPv3y>Mm}){ z2F87!E{-7;x8BYTTy@xhhvn&m-|>;}R|_yLEt{XUeyOC!vcDc8rJKV-W}B6lThF+5 zYg@7WJS$`4-8^2GcOK5NzG7OuVB*KGRp0B<&NLPM`?aF$?%&51;eTF#{@vOmm;OBV zv$lA^+4~!qd**#vx$k%D*%%iycA$Xh$_LA<_Veyr#r)<({O>OkE8>m_-2eaRbs+n# zP}}(iu^P|&?HmdP7?>JPl{|g0$(Hv4L%f*(#N?Fay3X#w_ZZXW*N2zh+VsWviLAn} z(;ct2q`u6En<}HQ>GHIrjBQqpr+RyYZ%p04!7pLzl8+(`91H>s3JeaQuw(?9d4@-y zTfWh>=K0a<%1yI)efDmR(X?B}kOfrXAh=_bM$rG2=H4}@%h}J18LmE_^|95L@uGHo z-A<luEt!)hk&ZoYc`S88Yf-GdNI7+9dTRw(VZ zoO1WzQPu_XcIY^zaV=m2N{KX{*=U+QMTBp`zBYbFodU+EqBa}}jm#SBA38HwG~~Ve zaeTt9kF9U{+KfND%P+9tU|@7eoi)?&WO#W)?A$Gvt&5gFKYRBrzwd|Nx6^0b=LbeN NgQu&X%Q~loCIHyn@Rk4o literal 0 HcmV?d00001 diff --git a/assets-fx/map/fxconv-metadata.txt b/assets-fx/map/fxconv-metadata.txt new file mode 100644 index 0000000..2aa60e2 --- /dev/null +++ b/assets-fx/map/fxconv-metadata.txt @@ -0,0 +1,3 @@ +*.txt: + custom-type: map + name_regex: (.*)\.txt map_\1 diff --git a/assets-fx/map/lv1.txt b/assets-fx/map/lv1.txt new file mode 100644 index 0000000..3de9215 --- /dev/null +++ b/assets-fx/map/lv1.txt @@ -0,0 +1,10 @@ +##### ##### +# ##### # +# a a # +##A### ###A## +# a a # +# ~ ##### @ # +##### ##### + +a: #. +A: #. diff --git a/src/engine.c b/src/engine.c index 0c79ea2..078dde3 100644 --- a/src/engine.c +++ b/src/engine.c @@ -40,6 +40,7 @@ static void engine_draw_player(struct player const *player) void engine_draw(struct game const *game) { dclear(C_WHITE); + dimage(0, 0, game->map->img); for(int p = 0; game->players[p]; p++) { @@ -54,8 +55,8 @@ void engine_draw(struct game const *game) /* Check whether a cell of the map is walkable */ static int map_walkable(struct map const *map, int x, int y) { - /* TODO: Read the map's data array */ - return (x >= 1) && (y >= 1) && (x < map->w - 1) && (y < map->h - 1); + int tile = map->tiles[y * map->w + x]; + return (tile != TILE_WALL); } int engine_move(struct game *game, struct player *player, int dir) diff --git a/src/engine.h b/src/engine.h index 6e0393c..da7d5dd 100644 --- a/src/engine.h +++ b/src/engine.h @@ -37,8 +37,30 @@ struct map int w, h; /* Whether fog is enabled */ int fog; - /* Raw data */ - uint8_t *data; + /* Door cycle string */ + char door_cycle[128]; + /* Mapping of door types to cycle string index */ + uint8_t door_cycle_index[16]; + /* Background image */ + bopti_image_t *img; + /* Array of tiles in row-major order */ + uint8_t *tiles; +}; + +/* enum map_tile: Single cell in the map */ +enum map_tile +{ + TILE_AIR = 0, + TILE_WALL = 1, + TILE_START = 2, + TILE_END = 3, + + /* 8 keys in interval 16..23 */ + TILE_KEY = 16, + /* 8 vertical doors in interval 24..31 */ + TILE_VDOOR = 24, + /* 8 horizontal doors in interval 32..39 */ + TILE_HDOOR = 32, }; /* struct game: A running game with a map and some players */ diff --git a/src/main.c b/src/main.c index 8dfb3d4..6c67035 100644 --- a/src/main.c +++ b/src/main.c @@ -97,12 +97,10 @@ int main(void) }; singleplayer.idle = !anim_player_idle(&singleplayer.anim, 1); - struct map map = { - .w = 13, - .h = 7 - }; + extern struct map map_lv1; + struct game game = { - .map = &map, + .map = &map_lv1, .players = { &singleplayer, NULL }, .time = 0, };