diff --git a/.gitignore b/.gitignore index 74c6a62..aaea3ac 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,7 @@ /*.g3a # Python bytecode - __pycache__/ +__pycache__/ # Common IDE files *.sublime-project diff --git a/CMakeLists.txt b/CMakeLists.txt index 073a4ad..e13f1e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,10 +22,13 @@ set(SOURCES src/render.c ) set(ASSETS - assets-cg/example.png + assets-cg/tileset_base.png + assets-cg/tileset_decor.png + assets-cg/levels/demo.txt ) fxconv_declare_assets(${ASSETS} ${ASSETS} WITH_METADATA) +fxconv_declare_converters(assets-cg/converters.py) add_executable(addin ${SOURCES} ${ASSETS}) target_compile_options(addin PRIVATE -Wall -Wextra -Os) diff --git a/assets-cg/converters.py b/assets-cg/converters.py new file mode 100644 index 0000000..db298ff --- /dev/null +++ b/assets-cg/converters.py @@ -0,0 +1,58 @@ +import fxconv +import re + +def convert(input, output, params, target): + recognized = True + + if params["custom-type"] == "level": + o = convert_level(input, params) + else: + recognized = False + + if recognized: + fxconv.elf(o, output, "_" + params["name"], **target) + return 0 + + return 1 + +def convert_level(input, params): + RE_CATEGORY = re.compile(r'^\[([^\]]+)\]$', re.MULTILINE) + + with open(input, "r") as fp: + ct = [x.strip() for x in RE_CATEGORY.split(fp.read())] + ct = [x for x in ct if x != ""] + assert(len(ct) % 2 == 0) + + ct = { ct[i]: ct[i+1] for i in range(0, len(ct), 2) } + assert(ct.keys() == { "level", "base", "decor" }) + + # Read tileset + def tileset(desc): + desc = [line.strip().split() for line in desc.split("\n")] + assert(len(line) <= 16 for line in desc) + + tiles = dict() + for y, line in enumerate(desc): + for x, chara in enumerate(line): + tiles[chara] = 16 * y + x + + return tiles + + base = tileset(ct["base"]) + decor = tileset(ct["decor"]) + + level = [line.strip().split() for line in ct["level"].split("\n")] + height = len(level) + width = max(len(line) for line in level) + + tiles = bytearray(2 * width * height) + for y, line in enumerate(level): + for x, tile in enumerate(line): + index = 2 * (width * y + x) + tiles[index] = base[tile[0]] + tiles[index+1] = decor[tile[1]] + + o = bytes() + o += fxconv.u16(width) + fxconv.u16(height) + o += bytes(tiles) + return o diff --git a/assets-cg/fxconv-metadata.txt b/assets-cg/fxconv-metadata.txt index d435d5f..9f19cbb 100644 --- a/assets-cg/fxconv-metadata.txt +++ b/assets-cg/fxconv-metadata.txt @@ -1,3 +1,3 @@ -example.png: +*.png: type: bopti-image - name: img_example + name_regex: (.*)\.png img_\1 diff --git a/assets-cg/levels/demo.txt b/assets-cg/levels/demo.txt new file mode 100644 index 0000000..d2cc7df --- /dev/null +++ b/assets-cg/levels/demo.txt @@ -0,0 +1,25 @@ +[level] + +__ __ __ __ __ __ __ __ #_ #b #_ #t #_ #b #_ __ __ __ __ __ __ __ __ __ +__ __ __ #_ #_ #_ #_ #_ G_ G_ G_ G_ G_ G_ G_ #_ #t #_ #_ __ __ __ __ __ +__ __ __ Y_ Y_ Y_ G_ G_ G_ G_ G_ G_ G_ G_ G_ G_ G_ G_ G_ __ __ __ __ __ +__ __ __ R_ __ __ #_ G_ G_ #_ #_ #_ G_ G_ G_ #_ __ __ Y_ __ __ __ __ __ +__ __ #_ R_ __ __ Y_ Y_ Y_ Y_ Y_ Y_ Y_ __ G_ Y_ __ __ Y_ __ __ __ __ __ +__ #b R_ R_ #t #_ Y_ __ Y_ #_ #_ Y_ #t #_ #_ Y_ __ __ Y_ #t #_ #_ __ __ +__ R_ R_ R_ R_ R_ Y_ __ Y_ Y_ Y_ Y_ Y_ Y_ Y_ Y_ __ __ Y_ Y_ Y_ B_ __ __ +__ R_ R_ R_ R_ R_ Y_ __ Y_ Y_ Y_ Y_ Y_ Y_ Y_ Y_ #_ __ B_ __ __ B_ #_ __ +__ __ R_ R_ R_ __ Y_ #_ Y_ Y_ Y_ Y_ Y_ Y_ Y_ Y_ Y_ #_ B_ #_ #b B_ B_ __ +__ __ R_ R_ R_ __ Y_ Y_ Y_ Y_ Y_ Y_ Y_ Y_ Y_ Y_ Y_ B_ B_ B_ B_ B_ B_ __ +__ __ R_ R_ #_ __ __ __ __ Y_ Y_ Y_ Y_ #_ #_ #t #_ B_ B_ B_ B_ B_ B_ __ +__ __ __ R_ R_ #_ #t #_ #_ #_ #_ #t Y_ Y_ Y_ B_ B_ B_ B_ B_ B_ B_ __ __ +__ __ __ __ Y_ Y_ Y_ Y_ Y_ Y_ Y_ Y_ Y_ __ __ __ __ __ B_ B_ B_ B_ __ __ +__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ + +[base] + +_ Y R G B +# + +[decor] + +_ b t r diff --git a/assets-cg/levels/fxconv-metadata.txt b/assets-cg/levels/fxconv-metadata.txt new file mode 100644 index 0000000..9954e07 --- /dev/null +++ b/assets-cg/levels/fxconv-metadata.txt @@ -0,0 +1,3 @@ +*.txt: + custom-type: level + name_regex: (.*)\.txt lv_\1 diff --git a/assets-cg/tileset_base.png b/assets-cg/tileset_base.png new file mode 100644 index 0000000..ddc135f Binary files /dev/null and b/assets-cg/tileset_base.png differ diff --git a/assets-cg/tileset_decor.png b/assets-cg/tileset_decor.png new file mode 100644 index 0000000..77bee51 Binary files /dev/null and b/assets-cg/tileset_decor.png differ diff --git a/src/level.h b/src/level.h index b917765..3d334a5 100644 --- a/src/level.h +++ b/src/level.h @@ -11,8 +11,13 @@ #include -/* TODO: DEMO */ -struct level { - int zero; - uint16_t colors[]; -}; +typedef struct { + /* Dimensions of the level (yeah no surprise right) */ + uint16_t width, height; + /* Tile definitions; each tile is a dual-layer base/decoration */ + struct { + uint8_t base; + uint8_t decor; + } tiles[]; + +} level_t; diff --git a/src/main.c b/src/main.c index fe48660..0299af9 100644 --- a/src/main.c +++ b/src/main.c @@ -29,22 +29,7 @@ static bool getkey_global_shortcuts(key_event_t e) #define B C_BLUE, #define Y C_RGB(16,16,16), -struct level lv_demo = { 0, { - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - _ _ _ _ _ _ _ _ G G G G G G G _ _ _ _ _ _ _ _ _ - _ _ _ Y Y Y G G G G G G G G G G G G G _ _ _ _ _ - _ _ _ R _ _ _ G G _ _ _ G G G _ _ _ Y _ _ _ _ _ - _ _ _ R _ _ Y Y Y Y Y Y Y _ G Y _ _ Y _ _ _ _ _ - _ _ R R _ _ Y _ Y _ _ Y _ _ _ Y _ _ Y _ _ _ _ _ - _ R R R R R Y _ Y Y Y Y Y Y _ Y _ _ Y Y Y B _ _ - _ R R R R R Y _ Y Y Y Y Y Y Y Y _ _ B _ _ B _ _ - _ _ R R R _ Y _ Y Y Y Y Y Y Y Y Y _ B _ _ B B _ - _ _ R R R _ Y Y Y Y Y Y Y Y Y Y Y B B B B B B _ - _ _ R R _ _ _ _ _ Y Y Y Y _ _ _ _ B B B B B B _ - _ _ _ R R _ _ _ _ _ _ _ Y Y Y B B B B B B B _ _ - _ _ _ _ Y Y Y Y Y Y Y Y Y _ _ _ _ _ B B B B _ _ - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ -}}; +extern level_t lv_demo; int main(void) { @@ -60,8 +45,8 @@ int main(void) //--- struct map *m = malloc(sizeof *m); - m->width = 24; - m->height = 14; + m->width = lv_demo.width; + m->height = lv_demo.height; m->entities = NULL; m->entity_count = 0; m->tiles = malloc(m->width * m->height * sizeof *m->tiles); @@ -69,10 +54,9 @@ int main(void) for(int y = 0; y < m->height; y++) for(int x = 0; x < m->width; x++) { struct tile *t = map_tile(m, x, y); - uint16_t color = lv_demo.colors[y * m->width + x]; - - t->solid = (color == C_BLACK); - t->color = color; + t->base = lv_demo.tiles[lv_demo.width * y + x].base; + t->decor = lv_demo.tiles[lv_demo.width * y + x].decor; + t->solid = (t->base == 0) || (t->base >= 16); } struct camera camera; diff --git a/src/map.h b/src/map.h index c17c02f..ebf755f 100644 --- a/src/map.h +++ b/src/map.h @@ -25,7 +25,10 @@ struct tile { /* TODO: Layers of objects, stuff, dynamic elements, etc? */ /* TODO: Allow any collision shape for the tile! */ bool solid; - uint16_t color; + /* Base layer: floor/wall pattern */ + uint8_t base; + /* Decoration layer */ + uint8_t decor; }; /* Shape for a tile; this lives in a coordinate system whose (0,0) ends up at diff --git a/src/render.c b/src/render.c index ebb1099..4b3fae3 100644 --- a/src/render.c +++ b/src/render.c @@ -105,22 +105,11 @@ fixed_t camera_ppu(struct camera *c) // Rendering //--- -static uint16_t darker2(uint16_t color) -{ - return (color & 0xf7de) >> 1; -} - -static uint16_t darker1(uint16_t color) -{ - int r = (color >> 11); - int g = (color >> 6) & 0x1f; - int b = color & 0x1f; - - return C_RGB(2*r/3, 2*g/3, 2*b/3); -} - void render_map(struct map *m, struct camera *c) { + extern bopti_image_t img_tileset_base; + extern bopti_image_t img_tileset_decor; + /* Render floor and walls */ for(int row = 0; row < m->height; row++) for(int col = 0; col < m->width; col++) { @@ -130,20 +119,14 @@ void render_map(struct map *m, struct camera *c) fpoint_t tile_pos = { fix(col), fix(row) }; ipoint_t p = camera_map2screen(c, tile_pos); - /* TODO: render_map: use images */ - uint16_t color_floor = darker1(t->color); - uint16_t color_wall = darker2(darker2(t->color)); - - int tile_w = c->zoom * TILE_WIDTH; - int tile_h = c->zoom * TILE_HEIGHT; - int wall_h = c->zoom * WALL_HEIGHT; - - drect(p.x, p.y, p.x+tile_w-1, p.y+tile_h-1, color_floor); - - struct tile *above = map_tile(m, col, row-1); - if(above && !t->solid && above->solid) { - drect(p.x, p.y-wall_h, p.x+tile_w-1, p.y-1, color_wall); - } + /* Floor/wall layer */ + dsubimage(p.x, p.y, &img_tileset_base, TILE_WIDTH * (t->base % 16), + TILE_HEIGHT * (t->base / 16), TILE_WIDTH, TILE_HEIGHT, + DIMAGE_NONE); + /* Decoration layer */ + dsubimage(p.x, p.y, &img_tileset_decor, TILE_WIDTH * (t->decor % 16), + TILE_HEIGHT * (t->decor / 16), TILE_WIDTH, TILE_HEIGHT, + DIMAGE_NONE); } /* Render entities */