add basic map and tileset definitions

This commit is contained in:
Lephenixnoir 2021-06-02 09:38:59 +02:00
parent dd73f9164e
commit c45fd083bd
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
12 changed files with 124 additions and 60 deletions

2
.gitignore vendored
View File

@ -5,7 +5,7 @@
/*.g3a
# Python bytecode
__pycache__/
__pycache__/
# Common IDE files
*.sublime-project

View File

@ -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)

58
assets-cg/converters.py Normal file
View File

@ -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

View File

@ -1,3 +1,3 @@
example.png:
*.png:
type: bopti-image
name: img_example
name_regex: (.*)\.png img_\1

25
assets-cg/levels/demo.txt Normal file
View File

@ -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

View File

@ -0,0 +1,3 @@
*.txt:
custom-type: level
name_regex: (.*)\.txt lv_\1

BIN
assets-cg/tileset_base.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

BIN
assets-cg/tileset_decor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

View File

@ -11,8 +11,13 @@
#include <stdint.h>
/* 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;

View File

@ -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;

View File

@ -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

View File

@ -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 */