Add support for loading stages from a file
This commit is contained in:
parent
19f0ce06f6
commit
40f3e4e3bf
|
@ -0,0 +1,26 @@
|
||||||
|
Example bundle
|
||||||
|
|
||||||
|
Stages are separated by ten dashes, and each stage must be 10 lines of 10
|
||||||
|
characters each. At the top of the file is a free-form comment field.
|
||||||
|
----------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
!
|
||||||
|
gggggggggg
|
||||||
|
----------
|
||||||
|
!
|
||||||
|
D 4
|
||||||
|
C 3 44
|
||||||
|
3 3 4
|
||||||
|
B
|
||||||
|
222 2 2
|
||||||
|
|
||||||
|
A 1 111
|
||||||
|
@g
|
||||||
|
gd
|
110
switcher.c
110
switcher.c
|
@ -17,6 +17,7 @@
|
||||||
enum game_mode { TITLESCREEN, STAGE };
|
enum game_mode { TITLESCREEN, STAGE };
|
||||||
enum game_mode game_mode = TITLESCREEN;
|
enum game_mode game_mode = TITLESCREEN;
|
||||||
bool stages_beat[STAGES];
|
bool stages_beat[STAGES];
|
||||||
|
size_t stages_num;
|
||||||
|
|
||||||
#define PLAYFIELD_SIDE 100
|
#define PLAYFIELD_SIDE 100
|
||||||
#define TILE_SIDE 10
|
#define TILE_SIDE 10
|
||||||
|
@ -93,7 +94,8 @@ static enum palette playfield[PLAYFIELD_SIDE * PLAYFIELD_SIDE];
|
||||||
#include "rebind_rebind1_alt_tile.inc"
|
#include "rebind_rebind1_alt_tile.inc"
|
||||||
|
|
||||||
static char tilemap[TILES * TILES + 1];
|
static char tilemap[TILES * TILES + 1];
|
||||||
static char *stages[] = {
|
static char *stages[STAGES];
|
||||||
|
static char *builtin_stages[] = {
|
||||||
" "
|
" "
|
||||||
" "
|
" "
|
||||||
" "
|
" "
|
||||||
|
@ -446,7 +448,7 @@ static void update_stage(struct timespec now, struct timespec dt_timespec) {
|
||||||
switch(sample_tilemap(midpoint_x, midpoint_y)) {
|
switch(sample_tilemap(midpoint_x, midpoint_y)) {
|
||||||
case '!':
|
case '!':
|
||||||
stages_beat[selection_index] = true;
|
stages_beat[selection_index] = true;
|
||||||
if (selection_index < STAGES - 1)
|
if (selection_index + 1 < stages_num)
|
||||||
selection_index++;
|
selection_index++;
|
||||||
game_mode = TITLESCREEN;
|
game_mode = TITLESCREEN;
|
||||||
initialize();
|
initialize();
|
||||||
|
@ -473,7 +475,7 @@ static void update_titlescreen(struct timespec now, struct timespec dt_timespec)
|
||||||
(void) dt_timespec;
|
(void) dt_timespec;
|
||||||
if (keys_released && left_held && selection_index > 0)
|
if (keys_released && left_held && selection_index > 0)
|
||||||
selection_index--;
|
selection_index--;
|
||||||
if (keys_released && right_held && selection_index < STAGES - 1)
|
if (keys_released && right_held && selection_index + 1 < stages_num)
|
||||||
selection_index++;
|
selection_index++;
|
||||||
if (keys_released && jump_held)
|
if (keys_released && jump_held)
|
||||||
stage_selected = true;
|
stage_selected = true;
|
||||||
|
@ -549,20 +551,20 @@ static void draw_stage(struct timespec now) {
|
||||||
|
|
||||||
static void draw_titlescreen(struct timespec now) {
|
static void draw_titlescreen(struct timespec now) {
|
||||||
(void) now;
|
(void) now;
|
||||||
for (size_t i = 0; i < STAGES; i++) {
|
for (size_t i = 0; i < stages_num; i++) {
|
||||||
size_t x = i * TILE_SIDE + TILE_SIDE;
|
size_t x = i * TILE_SIDE + TILE_SIDE;
|
||||||
size_t y = 0;
|
size_t y = 0;
|
||||||
if (stages_beat[i])
|
if (stages_beat[i])
|
||||||
draw_tile(star_tile, x, y);
|
draw_tile(star_tile, x, y);
|
||||||
}
|
}
|
||||||
draw_tile(stage1_tile, 1 * TILE_SIDE, TILE_SIDE);
|
if (stages_num >= 1) draw_tile(stage1_tile, 1 * TILE_SIDE, TILE_SIDE);
|
||||||
draw_tile(stage2_tile, 2 * TILE_SIDE, TILE_SIDE);
|
if (stages_num >= 2) draw_tile(stage2_tile, 2 * TILE_SIDE, TILE_SIDE);
|
||||||
draw_tile(stage3_tile, 3 * TILE_SIDE, TILE_SIDE);
|
if (stages_num >= 3) draw_tile(stage3_tile, 3 * TILE_SIDE, TILE_SIDE);
|
||||||
draw_tile(stage4_tile, 4 * TILE_SIDE, TILE_SIDE);
|
if (stages_num >= 4) draw_tile(stage4_tile, 4 * TILE_SIDE, TILE_SIDE);
|
||||||
draw_tile(stage5_tile, 5 * TILE_SIDE, TILE_SIDE);
|
if (stages_num >= 5) draw_tile(stage5_tile, 5 * TILE_SIDE, TILE_SIDE);
|
||||||
draw_tile(stage6_tile, 6 * TILE_SIDE, TILE_SIDE);
|
if (stages_num >= 6) draw_tile(stage6_tile, 6 * TILE_SIDE, TILE_SIDE);
|
||||||
draw_tile(stage7_tile, 7 * TILE_SIDE, TILE_SIDE);
|
if (stages_num >= 7) draw_tile(stage7_tile, 7 * TILE_SIDE, TILE_SIDE);
|
||||||
draw_tile(stage8_tile, 8 * TILE_SIDE, TILE_SIDE);
|
if (stages_num >= 8) draw_tile(stage8_tile, 8 * TILE_SIDE, TILE_SIDE);
|
||||||
size_t underline_y = 2 * TILE_SIDE + 1;
|
size_t underline_y = 2 * TILE_SIDE + 1;
|
||||||
size_t underline_x = selection_index * TILE_SIDE + TILE_SIDE + 2;
|
size_t underline_x = selection_index * TILE_SIDE + TILE_SIDE + 2;
|
||||||
for (size_t x = 0; x < TILE_SIDE - 4; x++)
|
for (size_t x = 0; x < TILE_SIDE - 4; x++)
|
||||||
|
@ -605,7 +607,91 @@ static void draw(struct timespec now) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void load_stages(char *path) {
|
||||||
|
FILE *f = fopen(path, "r");
|
||||||
|
if (!f)
|
||||||
|
err(1, "%s", path);
|
||||||
|
|
||||||
|
stages_num = 0;
|
||||||
|
|
||||||
|
bool in_comment = true;
|
||||||
|
size_t linenum = 0;
|
||||||
|
size_t stage_fill = 0;
|
||||||
|
char *stage[10];
|
||||||
|
while (true) {
|
||||||
|
linenum++;
|
||||||
|
char *line = NULL;
|
||||||
|
size_t size = 0;
|
||||||
|
ssize_t length = getline(&line, &size, f);
|
||||||
|
if (length < 0) {
|
||||||
|
break;
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
if (line[length - 1] == '\n') {
|
||||||
|
line[length - 1] = 0;
|
||||||
|
length--;
|
||||||
|
}
|
||||||
|
if (!strcmp(line, "----------")) {
|
||||||
|
if (in_comment) {
|
||||||
|
in_comment = false;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if (stages_num == STAGES)
|
||||||
|
errx(1, "%s: %zu: Too many stages (maximum %zu)", path, linenum, (size_t)STAGES);
|
||||||
|
free(line);
|
||||||
|
if (stage_fill < 10)
|
||||||
|
errx(1, "%s: %zu: Not enough lines for a stage (expected 10, got %zu)", path, linenum, stage_fill);
|
||||||
|
char *stage_str;
|
||||||
|
asprintf(&stage_str, "%s%s%s%s%s%s%s%s%s%s", stage[0], stage[1], stage[2], stage[3], stage[4], stage[5], stage[6], stage[7], stage[8], stage[9]);
|
||||||
|
stages[stages_num++] = stage_str;
|
||||||
|
for (size_t i = 0; i < stage_fill; i++)
|
||||||
|
free(stage[i]);
|
||||||
|
stage_fill = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (stage_fill == 10)
|
||||||
|
errx(1, "%s: %zu: Too many lines for a stage (expected 10)", path, linenum);
|
||||||
|
if (in_comment)
|
||||||
|
free(line);
|
||||||
|
else if (length < 10)
|
||||||
|
errx(1, "%s: %zu: Line too short (expected 10 character, got %zd)", path, linenum, length);
|
||||||
|
else if (length > 10)
|
||||||
|
errx(1, "%s: %zu: Line too long (expected 10 character, got %zd)", path, linenum, length);
|
||||||
|
else
|
||||||
|
stage[stage_fill++] = line;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stage_fill) {
|
||||||
|
if (stages_num == STAGES)
|
||||||
|
errx(1, "%s: %zu: Too many stages (maximum %zu)", path, linenum, (size_t)STAGES);
|
||||||
|
if (stage_fill < 10)
|
||||||
|
errx(1, "%s: %zu: Not enough lines for a stage (expected 10, got %zu)", path, linenum, stage_fill);
|
||||||
|
char *stage_str;
|
||||||
|
asprintf(&stage_str, "%s%s%s%s%s%s%s%s%s%s", stage[0], stage[1], stage[2], stage[3], stage[4], stage[5], stage[6], stage[7], stage[8], stage[9]);
|
||||||
|
stages[stages_num++] = stage_str;
|
||||||
|
for (size_t i = 0; i < stage_fill; i++)
|
||||||
|
free(stage[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stages_num)
|
||||||
|
errx(1, "%s: Bundle did not contain any stages", path);
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc == 1) {
|
||||||
|
stages_num = sizeof(builtin_stages) / sizeof(*builtin_stages);
|
||||||
|
for (size_t i = 0; i < stages_num; i++) {
|
||||||
|
stages[i] = builtin_stages[i];
|
||||||
|
}
|
||||||
|
} else if (argc == 2)
|
||||||
|
load_stages(argv[1]);
|
||||||
|
else {
|
||||||
|
printf("Usage: %s [/path/to/stage-bundle]\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
struct display_connection *connection = display_connect_default();
|
struct display_connection *connection = display_connect_default();
|
||||||
if (!connection && errno == ECONNREFUSED)
|
if (!connection && errno == ECONNREFUSED)
|
||||||
display_spawn(argc, argv);
|
display_spawn(argc, argv);
|
||||||
|
|
Loading…
Reference in New Issue