Compare commits

...

7 Commits

41 changed files with 517 additions and 315 deletions

View File

@ -84,9 +84,14 @@ function(level)
cmake_parse_arguments(LEVEL "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN})
file(COPY ${LEVEL_NAME}.txt DESTINATION ${cdroot})
add_custom_command(OUTPUT ${cdroot}/${LEVEL_NAME}.txt
COMMAND cp ${LEVEL_NAME}.txt ${cdroot}/${LEVEL_NAME}.txt
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${LEVEL_NAME}.txt
VERBATIM)
add_custom_target(${LEVEL_NAME}_lvl
DEPENDS ${cdroot}/${LEVEL_NAME})
DEPENDS ${cdroot}/${LEVEL_NAME}.txt)
add_dependencies(${PROJECT_NAME} ${LEVEL_NAME}_lvl)
endfunction()
function(container)

View File

@ -31,7 +31,6 @@ struct building_cfg
void building_create(const struct building_cfg *cfg, struct building *b);
void building_set_alive_cb(void (*f)(const struct util_rect *dim, bool alive, void *p), void *p);
int building_render(const struct building *b, const struct camera *cam, bool sel);
instance_hp building_maxhp(const struct building *b);
const char *building_str(const struct building *b);
extern struct sprite building_sprites[MAX_BUILDING_TYPES];

View File

@ -3,8 +3,6 @@
enum building_type
{
BUILDING_TYPE_BARRACKS,
MAX_BUILDING_TYPES
};

View File

@ -6,16 +6,6 @@
struct sprite building_sprites[MAX_BUILDING_TYPES];
instance_hp building_maxhp(const struct building *const b)
{
static const instance_hp hp[] =
{
[BUILDING_TYPE_BARRACKS] = 100
};
return hp[b->type];
}
int building_render(const struct building *const b,
const struct camera *const cam, const bool sel)
{
@ -33,8 +23,7 @@ int building_render(const struct building *const b,
.prim_type = INSTANCE_RENDER_CFG_SPRITE,
.prim = {.s = s},
.cam = cam,
.sel = sel,
.max_hp = building_maxhp(b)
.sel = sel
};
return instance_render(&cfg);
@ -46,10 +35,7 @@ static void get_dimensions(const enum building_type type, short *const w,
static const struct dim
{
short w, h;
} dim[] =
{
[BUILDING_TYPE_BARRACKS] = {.w = 68, .h = 66}
};
} dim[1];
const struct dim *const d = &dim[type];
*w = d->w;
@ -69,7 +55,6 @@ void building_create(const struct building_cfg *const cfg,
i->r.x = cfg->x;
i->r.y = cfg->y;
i->alive = true;
i->hp = building_maxhp(b);
if (cb)
cb(&i->r, i->alive, op);
@ -84,10 +69,7 @@ void building_set_alive_cb(void (*const f)(const struct util_rect *, bool, void
const char *building_str(const struct building *const b)
{
static const char *const str[] =
{
[BUILDING_TYPE_BARRACKS] = "Barracks"
};
static const char *const str[1];
return str[b->type];
}

View File

@ -19,12 +19,12 @@ struct camera
} dim;
int x, y, x_speed, y_speed;
unsigned int xt, yt;
unsigned xt, yt;
bool pan;
struct cursor
{
unsigned int x, y, x_init, y_init;
unsigned x, y, x_init, y_init;
enum
{
CURSOR_STATE_IDLE,

View File

@ -13,8 +13,8 @@ extern "C"
enum
{
CAMERA_CURSOR_WIDTH = 20,
CAMERA_CURSOR_HEIGHT = 20
CAMERA_CURSOR_WIDTH = 16,
CAMERA_CURSOR_HEIGHT = 16
};
void camera_update_pos(struct camera *cam);

View File

@ -57,13 +57,17 @@ int cursor_render(const struct cursor *const c)
break;
}
sprite_sort(s);
return 0;
const int ret = sprite_sort(s);
if (ret)
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
return ret;
}
void cursor_init(struct cursor *const c)
{
const unsigned int x = (screen_w / 2) - CAMERA_CURSOR_WIDTH,
const unsigned x = (screen_w / 2) - CAMERA_CURSOR_WIDTH,
y = (screen_h / 2) - CAMERA_CURSOR_HEIGHT;
*c = (const struct cursor)

View File

@ -26,11 +26,6 @@ struct container
struct sprite *sprite;
struct sound *sound;
} data;
struct container_rt
{
struct container *c;
} *rt;
};
int container_load_ex(const char *path, const struct container *list, size_t n);

View File

@ -86,7 +86,12 @@ static int renderstr(const enum font f, const short x, short y,
s->v += v;
s->x = rx;
s->y = y;
sprite_sort(s);
if (sprite_sort(s))
{
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
return -1;
}
}
rx += cfg->fs;

View File

@ -30,6 +30,7 @@ struct game_cfg
size_t n;
union peripheral *p;
const char *map;
};
int game_resinit(void);

View File

@ -14,8 +14,11 @@ int game(const struct game_cfg *const cfg)
struct human_player human;
struct terrain_map map;
terrain_init(&map);
building_set_alive_cb(terrain_block_update, &map);
if (terrain_init(cfg->map, &map))
{
fprintf(stderr, "%s: terrain_init failed\n", __func__);
return -1;
}
const struct human_player_cfg hcfg =
{

View File

@ -12,7 +12,45 @@
#include <unit.h>
#include <stdbool.h>
static const struct container c[1];
static const struct container c[] =
{
{
.path = "sidewalk",
.type = CONTAINER_TYPE_SPRITE,
.data.sprite = &terrain_sprites[SIDEWALK]
},
{
.path = "roof1",
.type = CONTAINER_TYPE_SPRITE,
.data.sprite = &terrain_sprites[ROOF1]
},
{
.path = "roof2",
.type = CONTAINER_TYPE_SPRITE,
.data.sprite = &terrain_sprites[ROOF2]
},
{
.path = "cursor",
.type = CONTAINER_TYPE_SPRITE,
.data.sprite = &cursor_sprite
},
{
.path = "btn_left",
.type = CONTAINER_TYPE_SPRITE,
.data.sprite = &gui_button_sprites[GUI_BUTTON_LEFT]
},
{
.path = "btn_mid",
.type = CONTAINER_TYPE_SPRITE,
.data.sprite = &gui_button_sprites[GUI_BUTTON_MID]
},
{
.path = "btn_right",
.type = CONTAINER_TYPE_SPRITE,
.data.sprite = &gui_button_sprites[GUI_BUTTON_RIGHT]
},
};
static bool init;
void game_free(void)

View File

@ -17,14 +17,14 @@ int gfx_set_fullscreen(short w, short h);
bool gfx_fullscreen_available(void);
bool gfx_fullscreen(void);
int gfx_display_size(short *w, short *h);
void sprite_sort(struct sprite *s);
int sprite_sort(struct sprite *s);
int sprite_clone(const struct sprite *src, struct sprite *dst);
void rect_init(struct rect *r);
void semitrans_rect_init(struct rect *r);
void stp_4line_init(struct stp_4line *l);
void quad_sort(struct quad *q);
void rect_sort(struct rect *r);
void stp_4line_sort(struct stp_4line *l);
int quad_sort(struct quad *q);
int rect_sort(struct rect *r);
int stp_4line_sort(struct stp_4line *l);
int sprite_from_fp(struct sprite *s, FILE *f);
int quad_from_sprite(const struct sprite *s, struct quad *q);
bool gfx_inside_drawenv(short x, short y, short w, short h);

View File

@ -2,7 +2,7 @@
#include <gfx_private.h>
#include <stddef.h>
static unsigned int sel;
static unsigned sel;
static size_t heap_i;
void gfx_swapheap(void)

View File

@ -19,24 +19,28 @@ static void add_to_list(union gfx_sznext *const p)
last = p;
}
void sprite_sort(struct sprite *const s)
int sprite_sort(struct sprite *const s)
{
add_to_list(&s->sznext);
return 0;
}
void quad_sort(struct quad *const q)
int quad_sort(struct quad *const q)
{
add_to_list(&q->sznext);
return 0;
}
void rect_sort(struct rect *const r)
int rect_sort(struct rect *const r)
{
add_to_list(&r->sznext);
return 0;
}
void stp_4line_sort(struct stp_4line *const l)
int stp_4line_sort(struct stp_4line *const l)
{
add_to_list(&l->sznext);
return 0;
}
static void gfx_sync(void)
@ -61,7 +65,7 @@ int gfx_draw(void)
add_to_list(&term);
void gpu_ctrl(unsigned int command, unsigned int param);
void gpu_ctrl(unsigned command, unsigned param);
gfx_sync();
gfx_swapbuffers();

View File

@ -98,7 +98,10 @@ static int resize_screen(int w, int h, const bool full_screen)
for (size_t i = 0; i < list_len; i++)
if (sprite_screen_resize_ev(list[i]))
{
fprintf(stderr, "%s: sprite_screen_resize_ev failed\n", __func__);
return -1;
}
screen_w = w;
screen_h = h;
@ -152,14 +155,16 @@ static int get_resize_events(void)
const SDL_ResizeEvent *const res = &ev.resize;
if (resize_screen(res->w, res->h, false))
{
fprintf(stderr, "%s: resize_screen failed\n", __func__);
return -1;
}
}
}
if (n < 0)
{
fprintf(stderr, "%s: SDL_PeepEvents: %s\n",
__func__, SDL_GetError());
fprintf(stderr, "%s: SDL_PeepEvents: %s\n", __func__, SDL_GetError());
return -1;
}
@ -208,6 +213,5 @@ int gfx_draw(void)
return -1;
}
get_resize_events();
return 0;
return get_resize_events();
}

View File

@ -11,6 +11,7 @@ void semitrans_stp_4line_init(struct stp_4line *r)
{
}
void stp_4line_sort(struct stp_4line *const r)
int stp_4line_sort(struct stp_4line *const r)
{
return 0;
}

View File

@ -17,7 +17,7 @@ int quad_from_sprite(const struct sprite *const s, struct quad *const q)
return 0;
}
void quad_sort(struct quad *const q)
int quad_sort(struct quad *const q)
{
const bool xflip = q->x0 > q->x1;
@ -40,5 +40,10 @@ void quad_sort(struct quad *const q)
SDL_Surface *const s = xflip ? q->s_x : q->s;
if (SDL_BlitSurface(s, &clip, gfx_screen(), &r))
{
fprintf(stderr, "SDL_BlitSurface: %s\n", SDL_GetError());
return -1;
}
return 0;
}

View File

@ -3,7 +3,7 @@
#include <sdl-1.2/gfx_private.h>
#include <SDL.h>
void rect_sort(struct rect *const r)
int rect_sort(struct rect *const r)
{
SDL_Rect rct =
{
@ -19,8 +19,10 @@ void rect_sort(struct rect *const r)
if (SDL_FillRect(screen, &rct, map))
{
fprintf(stderr, "SDL_FillRect: %s\n", SDL_GetError());
return;
return -1;
}
return 0;
}
void rect_init(struct rect *const r)

View File

@ -126,7 +126,7 @@ int sprite_from_fp(struct sprite *const s, FILE *const f)
return 0;
}
void sprite_sort(struct sprite *const s)
int sprite_sort(struct sprite *const s)
{
SDL_Rect r =
{
@ -143,5 +143,10 @@ void sprite_sort(struct sprite *const s)
};
if (SDL_BlitSurface(s->s, &clip, gfx_screen(), &r))
{
fprintf(stderr, "SDL_BlitSurface: %s\n", SDL_GetError());
return -1;
}
return 0;
}

View File

@ -15,8 +15,13 @@ static int render_topleft(const struct gui_bar *const b, const short x,
s->x = x;
s->y = y;
sprite_sort(s);
return 0;
const int ret = sprite_sort(s);
if (ret)
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
return ret;
}
static int render_topright(const struct gui_bar *const b, const short x,
@ -29,7 +34,12 @@ static int render_topright(const struct gui_bar *const b, const short x,
s->x = x + b->w - s->w;
s->y = y;
sprite_sort(s);
const int ret = sprite_sort(s);
if (ret)
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
return 0;
}
@ -66,7 +76,11 @@ static int render_topmid(const struct gui_bar *const b, const short x,
else
m->w = mid_w;
sprite_sort(m);
if (sprite_sort(m))
{
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
return -1;
}
}
return 0;

View File

@ -13,8 +13,13 @@ int gui_button_render_sprite(const struct gui_button *const b)
return -1;
gui_coords(&b->common, &s->x, &s->y);
sprite_sort(s);
return 0;
const int ret = sprite_sort(s);
if (ret)
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
return ret;
}
void gui_button_get_dim_sprite(const struct gui_button *const b,

View File

@ -19,7 +19,13 @@ static int render_left(const struct gui_button *const b,
s->x = *x;
s->y = y;
sprite_sort(s);
if (sprite_sort(s))
{
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
return -1;
}
*x = s->x + s->w;
return 0;
}

View File

@ -26,7 +26,13 @@ static int render_left(const struct gui_line_edit *const l,
s->x = *x;
s->y = y;
sprite_sort(s);
if (sprite_sort(s))
{
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
return -1;
}
*x = s->x + s->w;
return 0;
}
@ -66,7 +72,12 @@ static int render_mid(const struct gui_line_edit *const l,
else
m->w = mid_w;
sprite_sort(m);
if (sprite_sort(m))
{
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
return -1;
}
*x += m->w;
}
}
@ -85,8 +96,13 @@ static int render_right(const short x, const short y)
s->x = x;
s->y = y;
sprite_sort(s);
return 0;
const int ret = sprite_sort(s);
if (ret)
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
return ret;
}
static int render(const struct gui_common *const g)

View File

@ -19,7 +19,12 @@ static int render_top(const struct gui_rounded_rect *const r,
left->x = x;
left->y = y;
sprite_sort(left);
if (sprite_sort(left))
{
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
return -1;
}
}
{
@ -33,7 +38,12 @@ static int render_top(const struct gui_rounded_rect *const r,
right->x = x + r->w - ref->w;
right->y = y;
sprite_sort(right);
if (sprite_sort(right))
{
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
return -1;
}
}
return 0;

View File

@ -12,17 +12,12 @@ extern "C"
{
#endif
typedef unsigned int instance_hp;
struct instance
{
bool alive, dying;
unsigned int hp;
bool alive;
struct util_rect r;
};
typedef bool (*instance_attacked_cb)(struct instance *i, unsigned int ap);
typedef bool (*instance_sheltered_cb)(struct instance *self, struct instance *other);
typedef void (*instance_done_cb)(struct instance *i, void *op);
struct instance_render_cfg
@ -48,15 +43,12 @@ struct instance_render_cfg
} prim;
bool sel;
instance_hp max_hp;
const struct instance_render_off
{
short x, y;
} *off;
};
bool instance_attacked(struct instance *self, unsigned int ap);
void instance_clear_pools(void);
int instance_render(const struct instance_render_cfg *cfg);
int instance_render_target(const struct instance *const i, const struct camera *cam);
void instance_cyclic(void);

View File

@ -8,19 +8,6 @@
static unsigned char line_g;
static bool line_g_flip;
bool instance_attacked(struct instance *const self, const instance_hp ap)
{
if (self->hp > ap)
self->hp -= ap;
else
{
self->hp = 0;
self->alive = false;
}
return !self->alive;
}
void instance_cyclic(void)
{
if (!line_g_flip)

View File

@ -74,7 +74,8 @@ int menu(void)
const struct game_cfg gcfg =
{
.p = &c.p
.p = &c.p,
.map = "city1.txt"
};
return game(&gcfg);

View File

@ -40,7 +40,7 @@ union peripheral
struct mouse mouse;
struct keyboard keyboard;
bool long_press;
unsigned int lp_t;
unsigned lp_t;
} kbm;
};

View File

@ -14,7 +14,7 @@ extern "C"
{
#endif
typedef unsigned int player_team;
typedef unsigned player_team;
enum
{

View File

@ -278,8 +278,8 @@ static void update_selected(struct human_player *const h)
{
struct sel_instance *const si = &h->sel[i];
if (si->d.i && (!si->d.i->alive || si->d.i->dying
|| si->type == INSTANCE_TYPE_UNIT))
if (si->d.i
&& (!si->d.i->alive || si->type == INSTANCE_TYPE_UNIT))
{
si->d.i = NULL;
h->n_sel--;

View File

@ -61,43 +61,6 @@ int player_create_building(const struct building_cfg *const cfg, struct player *
int player_init(const struct player_cfg *const cfg, struct player *const pl)
{
const unsigned long x = cfg->x, y = cfg->y;
const struct building_cfg bcfg =
{
.type = BUILDING_TYPE_BARRACKS,
.x = x,
.y = y
};
const struct unit_cfg cfgs[] =
{
{
.type = UNIT_TYPE_PEASANT,
.x = x + 80,
.y = y
},
{
.type = UNIT_TYPE_PEASANT,
.x = x + 80,
.y = y + 40
},
{
.type = UNIT_TYPE_PEASANT,
.x = x + 100,
.y = y + 20
}
};
if (player_create_building(&bcfg, pl))
return -1;
for (size_t i = 0; i < sizeof cfgs / sizeof *cfgs; i++)
if (player_create_unit(&cfgs[i], pl))
return -1;
pl->alive = true;
pl->color = cfg->color;
pl->team = cfg->team;

View File

@ -1,3 +1,7 @@
add_library(terrain "src/terrain.c")
add_library(terrain
"src/init.c"
"src/render.c"
"src/update.c"
)
target_include_directories(terrain PUBLIC "inc")
target_link_libraries(terrain PUBLIC container camera gfx util)

View File

@ -21,26 +21,64 @@ enum
enum terrain_type
{
TERRAIN_TYPE_GRASS
ROOF1_1_NW,
ROOF1_1_N,
ROOF1_1_NE,
ROOF1_2_NW,
ROOF1_2_NE,
ROOF1_3_NW,
ROOF1_3_N,
ROOF1_3_NE,
ROOF1_4_N,
ROOF1_1_W,
ROOF1_1_C,
ROOF1_1_E,
ROOF1_2_SW,
ROOF1_2_SE,
ROOF1_3_SW,
ROOF1_3_S,
ROOF1_3_SE,
ROOF1_4_C,
ROOF1_1_SW,
ROOF1_1_S,
ROOF1_1_SE,
ROOF1_5_W,
ROOF1_5_C,
ROOF1_5_E,
ROOF1_6,
ROOF1_4_S,
ROOF1_START = ROOF1_1_NW,
ROOF1_END = ROOF1_4_S
};
struct terrain_map
{
struct terrain_tile
{
enum terrain_type t;
unsigned char bl;
unsigned char t, obj;
} m[MAP_TILES][MAP_TILES];
int nx, ny, last_w, last_h;
};
void terrain_init(struct terrain_map *map);
int terrain_init(const char *path, struct terrain_map *map);
void terrain_update(struct terrain_map *map);
int terrain_render(const struct terrain_map *map, const struct camera *cam);
void terrain_block_update(const struct util_rect *dim, bool alive, void *p);
extern struct sprite grass_sprite;
enum
{
SIDEWALK,
ROOF1,
ROOF2,
BUILDING1,
MAX_TERRAIN_SPRITES
};
extern struct sprite terrain_sprites[MAX_TERRAIN_SPRITES];
#ifdef __cplusplus
}

154
src/terrain/src/init.c Normal file
View File

@ -0,0 +1,154 @@
#include <terrain.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int read_token(FILE *const f, char *const s, const size_t n)
{
uint8_t c;
size_t i = 0;
while (fread(&c, sizeof c, 1, f))
{
if (isspace(c))
{
if (i)
break;
else
continue;
}
else if (!isalnum(c))
{
fprintf(stderr, "%s: invalid character %" PRIx8 " at offset %ld\n",
__func__, c, ftell(f));
return -1;
}
else if (i + 1 >= n)
{
fprintf(stderr, "%s: exceeded maximum token size %zu\n",
__func__, n);
return -1;
}
s[i++] = c;
}
if (!i)
{
fprintf(stderr, "%s: feof=%d, ferror=%d\n", __func__, feof(f),
ferror(f));
return -1;
}
s[i] = '\0';
return 0;
}
static int read_num(FILE *const f, char *const s, const size_t n,
unsigned *const out, const int base, const int limit)
{
if (read_token(f, s, n))
return -1;
errno = 0;
char *end;
const unsigned long value = strtoul(s, &end, 10);
if (errno)
{
fprintf(stderr, "%s: strtoul(3): %s\n", __func__, strerror(errno));
return -1;
}
else if (*end)
{
fprintf(stderr, "%s: invalid number %s\n", __func__, s);
return -1;
}
else if (value > limit)
{
fprintf(stderr, "%s: %lu exceeds maximum range %d\n", __func__, value,
limit);
return -1;
}
*out = value;
return 0;
}
static int read_dec(FILE *const f, unsigned *const out)
{
char s[sizeof "65535"];
return read_num(f, s, sizeof s, out, 10, UINT16_MAX);
}
static int read_hex(FILE *const f, unsigned *const out)
{
char s[sizeof "0000"];
return read_num(f, s, sizeof s, out, 16, UINT16_MAX);
}
static int read_dimensions(FILE *const f, unsigned *const w, unsigned *const h)
{
if (read_dec(f, w) || read_dec(f, h))
return -1;
else if (*w > MAP_TILES || *h > MAP_TILES)
{
fprintf(stderr, "%s: map size (%ux%u) exceeded, max %dx%d\n",
__func__, *w, *h, MAP_TILES, MAP_TILES);
return -1;
}
return 0;
}
static int read_map(FILE *const f, const unsigned w, const unsigned h,
struct terrain_map *const map)
{
for (unsigned j = 0; j < h; j++)
for (unsigned i = 0; i < w; i++)
{
unsigned tile;
if (read_hex(f, &tile))
return -1;
map->m[j][i].t = tile;
map->m[j][i].obj = tile >> 8;
}
return 0;
}
int terrain_init(const char *const path, struct terrain_map *const map)
{
int ret = -1;
FILE *const f = fopen(path, "rb");
unsigned w, h;
if (!f)
{
fprintf(stderr, "%s: fopen(3): %s\n", __func__, strerror(errno));
goto end;
}
else if (read_dimensions(f, &w, &h) || read_map(f, w, h, map))
goto end;
ret = 0;
end:
if (f && fclose(f))
{
fprintf(stderr, "%s: fclose(3): %s\n", __func__, strerror(errno));
ret = -1;
}
return ret;
}

103
src/terrain/src/render.c Normal file
View File

@ -0,0 +1,103 @@
#include <terrain.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];
static int render_tile(const struct terrain_tile *const t, const short x,
const short y)
{
static const struct tile
{
const struct sprite *s;
int start, end;
} tiles[] =
{
{
.s = &terrain_sprites[ROOF1],
.start = ROOF1_START,
.end = ROOF1_END
}
};
for (size_t i = 0; i < sizeof tiles / sizeof *tiles; i++)
{
const struct tile *const rt = &tiles[i];
if (t->t >= rt->start && t->t <= 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 = t->t - rt->start;
const short tx = pos % TERRAIN_SZ, ty = pos / TERRAIN_SZ;
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__, t->t);
return -1;
}
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_tile(t, x.p, y.p))
return -1;
}
return 0;
}

View File

@ -1,132 +0,0 @@
#include <terrain.h>
#include <camera.h>
#include <gfx.h>
#include <util.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
struct sprite grass_sprite;
void terrain_update(struct terrain_map *const map)
{
if (map->last_w != screen_w)
{
const int extra = !!(screen_w % TERRAIN_SZ);
map->nx = screen_w / TERRAIN_SZ + extra;
map->last_w = screen_w;
}
if (map->last_h != screen_h)
{
const int extra = !!(screen_h % TERRAIN_SZ);
map->ny = screen_h / TERRAIN_SZ + extra;
map->last_h = screen_h;
}
}
struct block
{
size_t x0, x1, y0, y1;
};
void terrain_block_update(const struct util_rect *const dim, const bool alive,
void *const p)
{
const struct block b =
{
.x0 = dim->x / TERRAIN_SZ,
.x1 = (dim->x + dim->w) / TERRAIN_SZ,
.y0 = dim->y / TERRAIN_SZ,
.y1 = (dim->y + dim->h) / TERRAIN_SZ
};
for (size_t x = b.x0; x <= b.x1; x++)
for (size_t y = b.y0; y <= b.y1; y++)
for (size_t i = 0; i < 2; i++)
for (size_t j = 0; j < 2; j++)
{
const struct util_rect sub =
{
.x = x * TERRAIN_SZ + i * (TERRAIN_SZ / 2),
.y = y * TERRAIN_SZ + j * (TERRAIN_SZ / 2),
.w = TERRAIN_SZ / 2,
.h = TERRAIN_SZ / 2
};
if (util_collision(dim, &sub))
{
const enum
{
NO_SUB = 0,
UPPER_LEFT = 1 << 0,
UPPER_RIGHT = 1 << 1,
LOWER_LEFT = 1 << 2,
LOWER_RIGHT = 1 << 3,
ALL_BLOCKS = UPPER_LEFT | UPPER_RIGHT
| LOWER_LEFT | LOWER_RIGHT
} sub = 1 << (i + j * 2);
struct terrain_map *const map = p;
unsigned char *const bl = &map->m[y][x].bl;
*bl = alive ? *bl | sub : *bl & ~sub;
}
}
}
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];
sprite_get_or_ret(s, -1);
switch (t->t)
{
case TERRAIN_TYPE_GRASS:
if (sprite_clone(&grass_sprite, s))
return -1;
break;
}
s->x = x.p;
s->y = y.p;
sprite_sort(s);
}
return 0;
}
void terrain_init(struct terrain_map *const map)
{
*map = (const struct terrain_map){0};
}

20
src/terrain/src/update.c Normal file
View File

@ -0,0 +1,20 @@
#include <terrain.h>
void terrain_update(struct terrain_map *const map)
{
if (map->last_w != screen_w)
{
const int extra = !!(screen_w % TERRAIN_SZ);
map->nx = screen_w / TERRAIN_SZ + extra;
map->last_w = screen_w;
}
if (map->last_h != screen_h)
{
const int extra = !!(screen_h % TERRAIN_SZ);
map->ny = screen_h / TERRAIN_SZ + extra;
map->last_h = screen_h;
}
}

View File

@ -25,8 +25,6 @@ struct unit_target
{
struct instance *ins;
enum unit_state state;
instance_sheltered_cb shelter;
instance_attacked_cb attack;
instance_done_cb done;
void *op;
};
@ -73,9 +71,7 @@ bool unit_can_harvest(const struct unit *u);
bool unit_target_valid(const struct unit *u, const struct unit_target *t);
void unit_set_target(struct unit *u, const struct unit_target *t);
void unit_move_to(struct unit *u, unsigned long x, unsigned long y);
bool unit_attacked(struct instance *, instance_hp ap);
void unit_update(struct unit *u);
instance_hp unit_maxhp(const struct unit *u);
const char *unit_str(const struct unit *u);
enum

View File

@ -3,8 +3,6 @@
enum unit_type
{
UNIT_TYPE_PEASANT,
MAX_UNIT_TYPES
};

View File

@ -64,14 +64,7 @@ static void get_speed(const struct unit *const u, fix16_t *const x,
static const struct speed
{
fix16_t x, y;
} speed[] =
{
[UNIT_TYPE_PEASANT] =
{
.x = FIX16_C_FROM_INT(1),
.y = FIX16_C_FROM_INT(1)
}
};
} speed[1];
const struct speed *const s = &speed[u->type];
const int dx = abs(u->rx - u->tx);
@ -216,16 +209,6 @@ void unit_move_to(struct unit *const u, const unsigned long x, const unsigned lo
u->ty = y > y_off ? fix16_from_int(y - y_off) : 0;
}
instance_hp unit_maxhp(const struct unit *const u)
{
static const instance_hp hp[] =
{
[UNIT_TYPE_PEASANT] = 25
};
return hp[u->type];
}
static int get_ux(const struct unit *const u)
{
switch (u->dir)
@ -268,6 +251,7 @@ typedef const struct
static anim_dim *peasant_anim(const struct unit *const u)
{
#if 0
static anim_dim t[] =
{
{
@ -322,6 +306,9 @@ static anim_dim *peasant_anim(const struct unit *const u)
return NULL;
return &t[ux];
#else
return NULL;
#endif
}
struct render_cfg
@ -377,10 +364,7 @@ static int unit_quad(const struct unit *const u, struct render_cfg *const rcfg)
{
struct instance_render_quad *const qcfg = &rcfg->qcfg;
static anim_dim *(*const f[])(const struct unit *) =
{
[UNIT_TYPE_PEASANT] = peasant_quad
};
static anim_dim *(*const f[1])(const struct unit *);
anim_dim *const dim = f[u->type](u);
@ -416,7 +400,6 @@ int unit_render(const struct unit *const u, const struct camera *const cam,
.prim = {.quad = &rcfg.qcfg},
.cam = cam,
.sel = sel,
.max_hp = unit_maxhp(u),
.off = &rcfg.off
};
@ -429,10 +412,7 @@ static void get_dimensions(const enum unit_type type, short *const w,
static const struct dim
{
short w, h;
} dim[] =
{
[UNIT_TYPE_PEASANT] = {.w = 36, .h = 36}
};
} dim[1];
const struct dim *const d = &dim[type];
*w = d->w;
@ -448,7 +428,6 @@ void unit_create(const struct unit_cfg *const cfg, struct unit *const u)
.instance =
{
.alive = true,
.hp = unit_maxhp(u)
},
.type = cfg->type,
@ -463,10 +442,7 @@ void unit_create(const struct unit_cfg *const cfg, struct unit *const u)
const char *unit_str(const struct unit *const u)
{
static const char *const str[] =
{
[UNIT_TYPE_PEASANT] = "Peasant"
};
static const char *const str[1];
return str[u->type];
}