jancity/src/terrain/src/render.c

134 lines
3.1 KiB
C

#include <terrain.h>
#include <terrain_tiles.h>
#include <camera.h>
#include <gfx.h>
#include <util.h>
#include <ctype.h>
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct sprite terrain_sprites[MAX_TERRAIN_SPRITES];
struct tile
{
const struct sprite *s;
int start, end;
};
static int render_tile(const unsigned char id, const short x,
const short y, const struct tile *const tiles, const size_t n)
{
for (size_t i = 0; i < n; i++)
{
const struct tile *const rt = &tiles[i];
if (id >= rt->start && id <= rt->end)
{
sprite_get_or_ret(s, -1);
if (sprite_clone(rt->s, s))
{
fprintf(stderr, "%s: sprite_clone failed\n", __func__);
return -1;
}
const unsigned char pos = id - rt->start;
const short tx = pos % (s->w / TERRAIN_SZ),
ty = (pos * TERRAIN_SZ) / s->w;
s->x = x;
s->y = y;
s->w = TERRAIN_SZ;
s->h = TERRAIN_SZ;
s->u = tx * TERRAIN_SZ;
s->v = ty * TERRAIN_SZ;
const int ret = sprite_sort(s);
if (ret)
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
return ret;
}
}
fprintf(stderr, "%s: unknown tile %#hhx\n", __func__, id);
return -1;
}
static int render_ground(const struct terrain_tile *const t, const short x,
const short y)
{
static const struct tile tiles[] =
{
#define TILE(t) {.s = &terrain_sprites[t], .start = t##_START, .end = t##_END}
TILE(SIDEWALK),
TILE(ROOF1),
TILE(ROOF2),
TILE(PAVEMENT),
TILE(BUILDING1),
TILE(BUILDING2)
#undef TILE
};
return render_tile(t->t, x, y, tiles, sizeof tiles / sizeof *tiles);
}
static int render_object(const struct terrain_tile *const t, const short x,
const short y)
{
if (t->obj == OBJECT_NONE)
return 0;
static const struct tile tiles[] =
{
#define TILE(t) {.s = &terrain_sprites[t], .start = t##_START, .end = t##_END}
TILE(GRASS),
#undef TILE
};
return render_tile(t->obj, x, y, tiles, sizeof tiles / sizeof *tiles);
}
int terrain_render(const struct terrain_map *const map,
const struct camera *const cam)
{
const int start_x = abs(cam->x / TERRAIN_SZ),
start_y = abs(cam->y / TERRAIN_SZ);
const int remx = cam->x % TERRAIN_SZ,
remy = cam->y % TERRAIN_SZ;
int nx = map->nx, ny = map->ny;
if (abs(remx))
nx++;
if (abs(remy))
ny++;
struct m
{
size_t i;
long p;
};
for (struct m x = {.i = start_x, .p = remx};
x.i < nx + start_x; x.i++, x.p += TERRAIN_SZ)
for (struct m y = {.i = start_y, .p = remy};
y.i < ny + start_y; y.i++, y.p += TERRAIN_SZ)
{
const struct terrain_tile *const t = &map->m[y.i][x.i];
if (render_ground(t, x.p, y.p)
|| render_object(t, x.p, y.p))
return -1;
}
return 0;
}