1
1
Fork 0
Browse Source

level end screen

emscriptem
user 4 years ago
parent
commit
759438a884
  1. 57
      src/draw.c
  2. 1
      src/draw.h
  3. 51
      src/game.c
  4. 9
      src/game.h
  5. 124
      src/main.c
  6. 3
      src/types.h

57
src/draw.c

@ -1,6 +1,7 @@
#include "draw.h" #include "draw.h"
#include "game.h" #include "game.h"
#include <SDL2/SDL_mutex.h> #include <SDL2/SDL_mutex.h>
#include <SDL2/SDL_render.h>
#include <time.h> #include <time.h>
Vect viewport_pos; Vect viewport_pos;
@ -280,7 +281,7 @@ void new_update_viewport(Body const * const pl) {
static double dirchange = 0; static double dirchange = 0;
static Vect last_plpos = {}; static Vect last_plpos = {};
if (last_plpos.x == 0 && last_plpos.y == 0) if (last_plpos.x == 0 && last_plpos.y == 0)
last_plpos = player.physics->position; last_plpos = pl->position;
static Vect lmove = {}; static Vect lmove = {};
@ -296,15 +297,16 @@ void new_update_viewport(Body const * const pl) {
Vect screen_dist = vect_add(in_view(pl->position), vect_scalar(lmove, -1)); Vect screen_dist = vect_add(in_view(pl->position), vect_scalar(lmove, -1));
static double swap = 0;
if (iv.x > width if (iv.x > width
|| (iv.x < 0 || (iv.x < 0
|| iv.y > height || iv.y > height
|| iv.y < 0)) || iv.y < 0))
recover = true; recover = true;
Vect delta = vect_add(vect_scalar(player.physics->position, -1), last_plpos); Vect delta = vect_add(vect_scalar(pl->position, -1), last_plpos);
double dist_change = vect_mag(delta); double dist_change = vect_mag(delta);
if (true || (recover) //|| vect_mag((Vect){pl->vel.x, 0}) > 0.4 if ((recover) //|| vect_mag((Vect){pl->vel.x, 0}) > 0.4
|| (dist_change > width / 100)) { || (dist_change > width / 100)) {
if (iv.x < width / 6) { if (iv.x < width / 6) {
target = right_pos; target = right_pos;
@ -313,7 +315,7 @@ void new_update_viewport(Body const * const pl) {
} }
lmove = target; lmove = target;
last_plpos = player.physics->position; last_plpos = pl->position;
} }
if (recover) if (recover)
@ -352,11 +354,11 @@ void new_update_viewport(Body const * const pl) {
v = -v; v = -v;
// move towards target a set proportion // move towards target a set proportion
Vect urgency = vect_add(target, vect_scalar(player.physics->position, -1)); Vect urgency = vect_add(target, vect_scalar(pl->position, -1));
Vect p = vect_add(target, vect_scalar(viewport_pos, -1)); Vect p = vect_add(target, vect_scalar(viewport_pos, -1));
double proportion = (sigmoid(time_delta) / 100); double proportion = (sigmoid(time_delta) / 100);
proportion = 2 * player.physics->vel.x / (width); proportion = 2 * (pl->vel.x * pl->vel.x / (width));
proportion = proportion < 0 ? -proportion : proportion; proportion = proportion < 0 ? -proportion : proportion;
proportion > 0.4 ? proportion = 0.4 : 0; proportion > 0.4 ? proportion = 0.4 : 0;
@ -496,7 +498,7 @@ void draw_text(SDL_Renderer *rend, Vect pos, struct colour colour, char *text) {
static SDL_Renderer *ren = NULL; static SDL_Renderer *ren = NULL;
static TTF_Font* font = NULL; static TTF_Font* font = NULL;
if (!font) { if (!font) {
font = TTF_OpenFont("TerminusTTF.ttf", 18); font = TTF_OpenFont("TerminusTTF.ttf", 22);
const char *err = SDL_GetError(); const char *err = SDL_GetError();
if (err) { if (err) {
printf("%s\n", err); printf("%s\n", err);
@ -521,10 +523,45 @@ void draw_text(SDL_Renderer *rend, Vect pos, struct colour colour, char *text) {
} }
int draw_end_screen(SDL_Renderer *ren) {
struct environment scene = get_scene_at(viewport_pos, level);
struct colour bg = scene.colours.bg;
struct colour colour = scene.colours.fg1;
SDL_SetRenderDrawColor(ren, bg.r, bg.g, bg.b,255);
SDL_RenderClear(ren);
int margin = height / 10;
// Vect position = {.x = width - width / 10, .y = height - margin};
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);
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);
position.y += 40;
draw_text(ren, position, colour, qual_str);
position.y += 40;
draw_text(ren, position, colour, ct_str);
SDL_RenderPresent(ren);
return 0;
}
void draw_level_time(SDL_Renderer *ren, struct environment * e) { void draw_level_time(SDL_Renderer *ren, struct environment * e) {
int margin = height / 10; int margin = height / 10;
Vect position = {.x = margin, .y = height - margin}; Vect position = {.x = width - width / 10, .y = height - margin};
struct colour colour = e->colours.fg1; struct colour colour = e->colours.fg1;
@ -558,8 +595,7 @@ void redraw_buffer(SDL_Renderer * ren) {
if (SDL_LockMutex(player.physics->lock) == 0){ if (SDL_LockMutex(player.physics->lock) == 0){
lplayer = *player.physics; lplayer = *player.physics;
new_update_viewport(&lplayer); update_viewport(&lplayer);
SDL_UnlockMutex(player.physics->lock);
} else { } else {
return; return;
} }
@ -577,6 +613,7 @@ void redraw_buffer(SDL_Renderer * ren) {
struct environment scene = get_scene_at(viewport_pos, level); struct environment scene = get_scene_at(viewport_pos, level);
draw_environment(ren, &scene); draw_environment(ren, &scene);
draw_level_time(ren, &scene); draw_level_time(ren, &scene);
SDL_UnlockMutex(player.physics->lock);
for (int i=0; i < world.items.size; i++) { for (int i=0; i < world.items.size; i++) {
world_thing thing; world_thing thing;

1
src/draw.h

@ -37,5 +37,6 @@ extern int width, height;
void draw_text(SDL_Renderer *ren, Vect pos, struct colour colour, char *text); void draw_text(SDL_Renderer *ren, Vect pos, struct colour colour, char *text);
int draw_end_screen(SDL_Renderer *ren);
#endif #endif

51
src/game.c

@ -6,6 +6,7 @@
#define FLOOR_THICKNESS 200 #define FLOOR_THICKNESS 200
#define MAX_ROPE_GRAB_LEN 80000 #define MAX_ROPE_GRAB_LEN 80000
#define MIN_PHYSICS_STEP 2.0
#define BREAKPOINT *(int *)0 = 1; #define BREAKPOINT *(int *)0 = 1;
@ -14,9 +15,14 @@ GlobWorld world;
player_st *glob_player; player_st *glob_player;
SDL_Renderer *debug_ren; SDL_Renderer *debug_ren;
bool in_game;
bool game_paused;
int level; int level;
int quality = 100;
long level_time; long level_time;
int get_floor_ceiling();
/* array of all the things in the world and their kinds */ /* array of all the things in the world and their kinds */
//world_thing *world; //world_thing *world;
@ -26,7 +32,6 @@ void process_keydown(SDL_Keysym key);
void process_keyup(SDL_Keysym key); void process_keyup(SDL_Keysym key);
void add_to_world(world_thing thing); void add_to_world(world_thing thing);
void step(int interval);
void set_motor_timeout(Body *thing, int motorID, uint32_t timeout); void set_motor_timeout(Body *thing, int motorID, uint32_t timeout);
void set_motor_status(Body *thing, int motorID, bool run); void set_motor_status(Body *thing, int motorID, bool run);
void stop_pull_rope(void); void stop_pull_rope(void);
@ -553,8 +558,9 @@ void destroy_physics_collection(struct physics_collection *s) {
free(s->items); free(s->items);
} }
int get_floor_ceiling();
void next_level() { void next_level() {
SDL_LockMutex(player.physics->lock);
Vect v; Vect v;
v.x = 0; v.x = 0;
v.y = 0; v.y = 0;
@ -588,6 +594,9 @@ void next_level() {
player.physics->position = v; player.physics->position = v;
player.physics->next_position = v; player.physics->next_position = v;
quality = 100;
level_timer_update(true);
SDL_UnlockMutex(player.physics->lock);
} }
@ -1081,15 +1090,22 @@ void advance_thing(Body * thing) {
} }
time_delta *= 0.000001; // convert to ms from ns time_delta *= 0.000001; // convert to ms from ns
thing->last_advance_time = now;
// cap the time delta: simulatino will slow down // cap the time delta: simulatino will slow down
// printf("delta: %f\n", time_delta); // printf("delta: %f\n", time_delta);
if (time_delta > 19) { if (time_delta > 19) {
printf("ERROR too slow: %f\n", time_delta); printf("ERROR too slow: %f\n", time_delta);
time_delta = 19; time_delta = 19;
quality--;
} }
if (time_delta < MIN_PHYSICS_STEP) {
SDL_Delay(MIN_PHYSICS_STEP);
advance_thing(thing);
return;
}
thing->last_advance_time = now;
// collisions // collisions
if ((numcols = process_collisions(thing, &translation))) { if ((numcols = process_collisions(thing, &translation))) {
/*double check = vect_scalar_projection(translation, thing->vel);*/ /*double check = vect_scalar_projection(translation, thing->vel);*/
@ -1266,15 +1282,16 @@ void advance_thing(Body * thing) {
(*thing).vel.y = 0; (*thing).vel.y = 0;
} }
if (thing->lock) {
SDL_LockMutex(thing->lock);
}
thing->position = thing->next_position;
double oldx = thing->position.x; double oldx = thing->position.x;
double oldy = thing->position.y; double oldy = thing->position.y;
thing->next_position.x += (thing->vel.x * 1/2 * (double)time_delta); thing->next_position.x += (thing->vel.x * 1/2 * (double)time_delta);
thing->next_position.y += (thing->vel.y * 1/2 * (double)time_delta); thing->next_position.y += (thing->vel.y * 1/2 * (double)time_delta);
if (thing->lock) {
SDL_LockMutex(thing->lock);
}
thing->position = thing->next_position;
if (!thing->collision_poly[0].y) { if (!thing->collision_poly[0].y) {
thing->updateCollisionPoly(thing); thing->updateCollisionPoly(thing);
@ -1316,7 +1333,6 @@ void get_projectile(Projectile** proj) {
void advance_things(void) { void advance_things(void) {
int numcols; int numcols;
Vect translation; Vect translation;
level_timer_update(false);
for (int i = 0; i < world.items.size; i++) { for (int i = 0; i < world.items.size; i++) {
switch (world.get(i).kind) { switch (world.get(i).kind) {
case PLAYER_W : case PLAYER_W :
@ -1458,6 +1474,7 @@ void startgame(SDL_Renderer * ren) {
viewport_pos.y = 0; viewport_pos.y = 0;
level_timer_update(true); level_timer_update(true);
game_paused = 0;
//get_room(); //get_room();
} }
@ -1548,17 +1565,21 @@ int get_rand(int seed) {
} }
void step(int interval) {
int step(void) {
if (player.physics->position.x > world.uniques_index[ROOM_W]->room if (player.physics->position.x > world.uniques_index[ROOM_W]->room
->floor.items[world.uniques_index[ROOM_W]->room->floor.numItems - 1]->position.x) { ->floor.items[world.uniques_index[ROOM_W]->room->floor.numItems - 1]->position.x) {
SDL_Delay(1000); return 1;
next_level(); }
level_timer_update(true); if (player.physics->position.x > world.uniques_index[ROOM_W]->room
->floor.items[3]->position.x) {
level_timer_update(false);
} else {
} }
advance_things(); if (in_game && !game_paused) {
advance_things();
}
return 0;
} }

9
src/game.h

@ -12,6 +12,8 @@
extern GlobWorld world; extern GlobWorld world;
extern int level; extern int level;
extern bool in_game;
extern int quality;
void handle_input_event(SDL_Event event); void handle_input_event(SDL_Event event);
@ -22,12 +24,17 @@ bool get_motor_active(Body *thing, int i);
int get_rand(int seed); int get_rand(int seed);
void next_level();
int step(void);
/* array of all the things in the world and their kinds */ /* array of all the things in the world and their kinds */
extern void startgame(SDL_Renderer * ren) ; extern void startgame(SDL_Renderer * ren) ;
extern void process_keydown(SDL_Keysym key); extern void process_keydown(SDL_Keysym key);
extern void process_keyup(SDL_Keysym key); extern void process_keyup(SDL_Keysym key);
extern void step(int interval);
extern player_st player; extern player_st player;
extern long level_time; extern long level_time;
extern bool game_paused;
#endif #endif

124
src/main.c

@ -1,3 +1,4 @@
#include <SDL2/SDL_mutex.h>
#include <SDL2/SDL_scancode.h> #include <SDL2/SDL_scancode.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -15,6 +16,19 @@
const int screen_width = 800; const int screen_width = 800;
const int screen_height = 600; 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) { struct SDL_Window* make_window(void) {
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
printf("error initializing SDL: %s\n", SDL_GetError()); printf("error initializing SDL: %s\n", SDL_GetError());
@ -30,18 +44,30 @@ struct SDL_Window* make_window(void) {
void redraw(struct SDL_Renderer * ren) { void redraw(struct SDL_Renderer * ren) {
// check time
// redraw if 1/60th of second passed
SDL_RenderClear(ren); SDL_RenderClear(ren);
redraw_buffer(ren); redraw_buffer(ren);
SDL_RenderPresent(ren); SDL_RenderPresent(ren);
} }
int physics_loop(void *ptr) { int physics_loop(void *ptr) {
while (true) { game_paused = 1;
step(10); SDL_Delay(1000);
SDL_Delay(10); game_paused = 0;
while (1) {
if (step()) {
// display end level screen
game_paused = true;
SDL_Delay(1000);
in_game = false;
SDL_SemWait(resume);
SDL_LockMutex(player.physics->lock);
game_paused = true;
in_game = true;
next_level();
SDL_UnlockMutex(player.physics->lock);
SDL_Delay(1000);
game_paused = 0;
}
} }
} }
@ -50,7 +76,7 @@ int game(void) {
LOGLEVEL = DEBUG; LOGLEVEL = DEBUG;
STDOUTLEVEL = DEBUG; STDOUTLEVEL = DEBUG;
SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "2" ); //SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "2" );
logwrite(INFO, "Starting\n"); logwrite(INFO, "Starting\n");
SDL_Window * win = make_window(); SDL_Window * win = make_window();
@ -60,12 +86,16 @@ int game(void) {
queue_for_cleanup(win, WINDOW); queue_for_cleanup(win, WINDOW);
queue_for_cleanup(ren, RENDERER); queue_for_cleanup(ren, RENDERER);
in_game = true;
resume = SDL_CreateSemaphore(0);
// IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG); // IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG);
if (ren == NULL) { if (ren == NULL) {
SDL_DestroyWindow(win); SDL_DestroyWindow(win);
SDL_Quit(); SDL_Quit();
} }
TTF_Init(); TTF_Init();
int close = 0; int close = 0;
@ -75,10 +105,9 @@ int game(void) {
SDL_Thread *physics_thread; SDL_Thread *physics_thread;
int ignore; int ignore;
bool once = true;
startgame(ren); startgame(ren);
// physics_thread = SDL_CreateThread(physics_loop, "Physics", (void *)NULL); physics_thread = SDL_CreateThread(physics_loop, "Physics", (void *)ren);
while (!close) { while (!close) {
@ -92,6 +121,9 @@ int game(void) {
if (event.key.keysym.scancode == SDL_SCANCODE_ESCAPE) { if (event.key.keysym.scancode == SDL_SCANCODE_ESCAPE) {
return 0; return 0;
} }
if (!SDL_SemValue(resume)) {
SDL_SemPost(resume);
}
case SDL_KEYUP: case SDL_KEYUP:
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONUP:
@ -99,14 +131,84 @@ int game(void) {
} }
} }
/* Redraw Screen */ /* Redraw Screen */
step(10); // step(10);
redraw(ren);
if (!in_game) {
draw_end_screen(ren);
} else {
redraw(ren);
}
} }
}
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) { int main (int argc, char** argv) {
load_score_times("savegame");
game(); game();
SDL_Quit(); SDL_Quit();
//empty_cleanup_queue(); //empty_cleanup_queue();

3
src/types.h

@ -220,10 +220,9 @@ typedef struct world GlobWorld;
enum { enum {
// E_ROOM_WIDTH = 100000, // E_ROOM_WIDTH = 100000,
E_ROOM_WIDTH = 40000, E_ROOM_WIDTH = 10000,
E_ROOM_RES = 500, E_ROOM_RES = 500,
E_ROOM_TILES = E_ROOM_WIDTH / E_ROOM_RES, E_ROOM_TILES = E_ROOM_WIDTH / E_ROOM_RES,
}; };
#endif #endif

Loading…
Cancel
Save