1
1
Fork 0
Browse Source

save and load level times

emscriptem
user 3 years ago
parent
commit
4e78067f0a
  1. 70
      src/draw.c
  2. 123
      src/game.c
  3. 16
      src/game.h
  4. 82
      src/main.c

70
src/draw.c

@ -535,22 +535,71 @@ int draw_end_screen(SDL_Renderer *ren) { @@ -535,22 +535,71 @@ int draw_end_screen(SDL_Renderer *ren) {
int margin = height / 10;
// Vect position = {.x = width - width / 10, .y = height - margin};
long fastest = get_best_time();
int minutes = level_time / 60000;
float seconds = level_time * 0.001;
char time_string[250];
snprintf(time_string, 250, "TIME: %d:%.4f", minutes, seconds);
char * end_str = "Level over.";
char * ct_str = "Press any key to continue.";
char qual_str[250];
snprintf(qual_str, 250, "Physics quality: %d", quality);
char * end_str = "level over.";
Vect position = {.x = width/3, .y = height / 4};
draw_text(ren, position, colour, end_str);
position.y += 40;
draw_text(ren, position, colour, time_string);
char level_string[250];
snprintf(level_string, 250,"course: %d", level);
draw_text(ren, position, colour, level_string);
position.y += 40;
char qual_str[250];
snprintf(qual_str, 250, "physics quality: %d", quality);
draw_text(ren, position, colour, qual_str);
position.y += 40;
char fastest_time[250];
minutes = fastest / 60000;
seconds = fastest * 0.001;
if (fastest > 0) {
position.y += 40;
snprintf(fastest_time, 250, "old best time: %d:%.4f", minutes, seconds);
draw_text(ren, position, colour, fastest_time);
}
minutes = level_time / 60000;
seconds = level_time * 0.001;
if (level_time > fastest) {
// base time not set yet.
snprintf(time_string, 250, "TIME: %d:%.4f", minutes, seconds);
} else {
snprintf(time_string, 250, "NEW BEST TIME: %d:%.4f", minutes, seconds);
}
Vect position2 = {.x = 3 * width/5, .y = 40 + height / 4};
if (fastest > 0) {
//position.y += 40;
long diff = level_time - fastest;
char diff_str[250];
minutes = diff / 60000;
seconds = diff * 0.001;
if (minutes > 0) {
snprintf(diff_str, 250, "DIFF: %d:%.4f", minutes, fabs(seconds));
} else {
snprintf(diff_str, 250, "DIFF: %.4f s", seconds);
}
draw_text(ren, position2, colour, diff_str);
position2.y += 40;
}
draw_text(ren, position2, colour, time_string);
position.y += 200;
char * ct_str = "press any key to continue";
draw_text(ren, position, colour, ct_str);
SDL_RenderPresent(ren);
@ -561,15 +610,20 @@ int draw_end_screen(SDL_Renderer *ren) { @@ -561,15 +610,20 @@ int draw_end_screen(SDL_Renderer *ren) {
void draw_level_time(SDL_Renderer *ren, struct environment * e) {
int margin = height / 10;
Vect position = {.x = width - width / 10, .y = height - margin};
struct colour colour = e->colours.fg1;
int minutes = level_time / 60000;
float seconds = level_time * 0.001;
char time_string[250];
snprintf(time_string, 250, "%d:%.4f", minutes, seconds);
snprintf(time_string, 250, "time: %d:%.4f", minutes, seconds);
char level_string[250];
snprintf(level_string, 250,"course: %d", level);
Vect position = {.x = margin, .y = height - margin};
draw_text(ren, position, colour, level_string);
position.y += 40;
draw_text(ren, position, colour, time_string);
}

123
src/game.c

@ -23,6 +23,8 @@ long level_time; @@ -23,6 +23,8 @@ long level_time;
int get_floor_ceiling();
struct sg_times_list save_times_lst;
/* array of all the things in the world and their kinds */
//world_thing *world;
@ -69,6 +71,116 @@ void level_timer_update(bool reset) { @@ -69,6 +71,116 @@ void level_timer_update(bool reset) {
}
}
int long_comparator(const void *a, const void *b, void *non) {
long A = *(long *)a;
long B = *(long *)b;
return A - B;
}
void sort_times(void) {
qsort_r(save_times_lst.times, save_times_lst.size, sizeof(long), long_comparator, NULL);
}
long get_best_time(void) {
save_times_lst.sort();
if (save_times_lst.size > 0)
return save_times_lst.times[0];
return -1;
}
int load_score_times(char *filename) {
char *fn;
char lvl_str[250];
snprintf(lvl_str, 250, "%d", level);
int fnlen = strlen(filename) + strlen(lvl_str) + 3;
fn = malloc(fnlen);
snprintf(fn, fnlen, "%s-%s", filename, lvl_str);
printf("%d, lvl_str %s fn %s\n", level, lvl_str, fn);
FILE *f = fopen(fn, "r");
// unload existing score times
if (save_times_lst.times) {
write_times();
free(save_times_lst.times);
free(save_times_lst.filename);
}
if (f) {
// get file size
fseek(f, 0L, SEEK_END);
long sz = ftell(f);
fseek(f, 0L, SEEK_SET);
char *text = malloc((sz + 1) * (sizeof(char)));
// read file
fread(text,sizeof(char),sz, f);
fclose(f);
int count = 1;
for (int i = 0; i < strlen(text); i++) {
if (text[i] == '\n') {
count++;
}
}
long *times = malloc(count * sizeof(long));
char *saveptr;
// extract times
char * token = strtok_r(text, "\n", &saveptr);
int i = 0;
while (token != NULL) {
if (strlen(token) > 2) {
times[i] = atol(token);
i++;
}
token = strtok_r(NULL, "\n", &saveptr);
}
save_times_lst = (struct sg_times_list){.size=i, .capacity = count, .times=times, .sort=sort_times};
save_times_lst.sort();
free(text);
} else {
perror("loading times");
save_times_lst = (struct sg_times_list){.size=0, .capacity = 5, .times=calloc(5, sizeof(long)), .sort=sort_times};
}
save_times_lst.filename = fn;
return 0;
}
int add_time(long time) {
if (save_times_lst.capacity == save_times_lst.size + 5) {
long newcap = save_times_lst.capacity * 2;
save_times_lst.times = realloc(save_times_lst.times, newcap);
save_times_lst.capacity = newcap;
}
save_times_lst.times[save_times_lst.size] = time;
save_times_lst.size++;
return 0;
}
int write_times(void) {
FILE *f = fopen(save_times_lst.filename, "w");
if (!f) {
perror("Saving game");
return 1;
}
for (int i = 0; i < save_times_lst.size; i++) {
fprintf(f, "%ld\n", save_times_lst.times[i]);
}
fclose(f);
return 0;
}
// collision poly size must be 2x shape_size + 1
void cast_update_collision_poly(Body *body) {
for (int i=0; i < body->collision_shape_size; i++) {
@ -587,9 +699,10 @@ void next_level() { @@ -587,9 +699,10 @@ void next_level() {
level *= 7;;
get_floor_ceiling();
load_score_times("saves/times");
v = world.uniques_index[ROOM_W]->room->ceil.items[2]->collision_poly[0];
v.y -= 30;
v.y -= 15;
player.physics->position = v;
player.physics->next_position = v;
@ -1452,6 +1565,9 @@ void startgame(SDL_Renderer * ren) { @@ -1452,6 +1565,9 @@ void startgame(SDL_Renderer * ren) {
level = 31;
save_times_lst = (struct sg_times_list){};
load_score_times("saves/times");
world = create_world();
SDL_GetRendererOutputSize(ren, &width, &height);
@ -1460,7 +1576,7 @@ void startgame(SDL_Renderer * ren) { @@ -1460,7 +1576,7 @@ void startgame(SDL_Renderer * ren) {
get_floor_ceiling();
Vect stpos = *world.uniques_index[ROOM_W]->room->ceil.items[2]->collision_poly;
player = get_player(stpos.x + 20, stpos.y - 60);
player = get_player(stpos.x, stpos.y - 15);
world_thing player_world;
player_world.kind = PLAYER_W;
@ -1574,8 +1690,7 @@ int step(void) { @@ -1574,8 +1690,7 @@ int step(void) {
if (player.physics->position.x > world.uniques_index[ROOM_W]->room
->floor.items[3]->position.x) {
level_timer_update(false);
} else {
}
}
if (in_game && !game_paused) {
advance_things();

16
src/game.h

@ -28,13 +28,27 @@ void next_level(); @@ -28,13 +28,27 @@ void next_level();
int step(void);
struct sg_times_list {
long *times;
int size;
int capacity;
void (*sort)(void);
char *filename;
};
int load_score_times(char *filename);
long get_best_time(void);
/* array of all the things in the world and their kinds */
extern struct sg_times_list save_times_lst;
int add_time(long time);
int write_times(void);
extern void startgame(SDL_Renderer * ren) ;
extern void process_keydown(SDL_Keysym key);
extern void process_keyup(SDL_Keysym key);
extern player_st player;
extern long level_time;
extern bool game_paused;
#endif

82
src/main.c

@ -8,6 +8,10 @@ @@ -8,6 +8,10 @@
#include <time.h>
#include <stdbool.h>
// only for mkdirat lol
#include <fcntl.h>
#include <sys/stat.h>
#include "logger.h"
#include "game.h"
#include "draw.h"
@ -18,16 +22,6 @@ const int screen_height = 600; @@ -18,16 +22,6 @@ const int screen_height = 600;
SDL_sem *resume;
long int *times;
struct sg_times_list {
long *times;
int size;
int capacity;
void (*sort)(void);
};
struct sg_times_list save_times_lst;
struct SDL_Window* make_window(void) {
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
@ -60,6 +54,8 @@ int physics_loop(void *ptr) { @@ -60,6 +54,8 @@ int physics_loop(void *ptr) {
SDL_Delay(1000);
in_game = false;
SDL_SemWait(resume);
add_time(level_time);
SDL_LockMutex(player.physics->lock);
game_paused = true;
in_game = true;
@ -142,73 +138,11 @@ int game(void) { @@ -142,73 +138,11 @@ int game(void) {
}
int long_comparator(const void *a, const void *b, void *non) {
long A = *(long *)a;
long B = *(long *)b;
return A - B;
}
void sort_times(void) {
qsort_r(save_times_lst.times, save_times_lst.size, sizeof(long), long_comparator, NULL);
}
int load_score_times(char *filename) {
FILE *f = fopen(filename, "r");
if (f) {
// get file size
fseek(f, 0L, SEEK_END);
long sz = ftell(f);
fseek(f, 0L, SEEK_SET);
char *text = malloc((sz + 1) * (sizeof(char)));
// read file
fread(text,sizeof(char),sz, f);
fclose(f);
int count = 1;
for (int i = 0; i < strlen(text); i++) {
if (text[i] == '\n') {
count++;
}
}
long *times = malloc(count * sizeof(long));
char *saveptr;
// extract times
char * token = strtok_r(text, "\n", &saveptr);
int i = 0;
while (token != NULL) {
if (strlen(token) > 2) {
times[i] = atol(token);
i++;
}
token = strtok_r(NULL, "\n", &saveptr);
}
save_times_lst = (struct sg_times_list){.size=i, .capacity = count, .times=times, .sort=sort_times};
save_times_lst.sort();
} else {
perror("loading times");
save_times_lst = (struct sg_times_list){.size=0, .capacity = 5, .times=calloc(5, sizeof(long)), .sort=sort_times};
}
for (int i = 0; i < save_times_lst.size; i++) {
printf("%ld\n", save_times_lst.times[i]);
}
return 0;
}
long get_best_time(void) {
save_times_lst.sort();
return save_times_lst.times[0];
}
int main (int argc, char** argv) {
load_score_times("savegame");
int err = mkdirat(AT_FDCWD, "saves", 0777);
game();
SDL_Quit();
//empty_cleanup_queue();

Loading…
Cancel
Save