diff --git a/MystNB.g1a b/MystNB.g1a index 369e357..ef54aee 100644 Binary files a/MystNB.g1a and b/MystNB.g1a differ diff --git a/assets-fx/img/lv1.png b/assets-fx/img/lv1.png new file mode 100644 index 0000000..4bdd166 Binary files /dev/null and b/assets-fx/img/lv1.png differ 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/converters.py b/converters.py new file mode 100644 index 0000000..b22244f --- /dev/null +++ b/converters.py @@ -0,0 +1,89 @@ +import fxconv +import re +import os.path + +def convert(input, output, params, target): + if params["type"] == "map": + convert_map(input, output, params, target) + else: + raise fxconv.FxconvError(f"unknown conversion {params['type']}") + sys.exit(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/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 c214b3c..2372d0b 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, };