#include "main.h" #include #include #include #include #include #include "player.h" #include "input.h" #include "characters.h" #define DEFAULT_SCREEN_WIDTH 800 #define DEFAULT_SCREEN_HEIGHT 600 #define SCREEN_FPS 60 #define DELTA_TIME_SEC (1.0f / SCREEN_FPS) #define DELTA_TIME_MS ((Uint32)floorf(DELTA_TIME_SEC * 1000.0f)) #define SIMULATION_STEP_MS 10 #define RENDER_ENABLED 1 #define SHOW_FPS 1 int main() { SDL_Window *window; SDL_Renderer *renderer; /* SDL_Texture *fps_texture; */ TTF_Font *Sans; if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "SDL ERROR: %s\n", SDL_GetError()); exit(1); } window = SDL_CreateWindow("Space Battle", 100, 100, DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT, SDL_WINDOW_RESIZABLE); if (window == NULL) { fprintf(stderr, "COULD NOT CREATE SDL WINDOW: %s\n", SDL_GetError()); exit(1); } if (RENDER_ENABLED) { renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); if (renderer == NULL) { fprintf(stderr, "COULD NOT CREATE SDL RENDERER: %s\n", SDL_GetError()); exit(1); } TTF_Init(); Sans = TTF_OpenFont("resources/OpenSans-Regular.ttf", 12); if (!Sans) { fprintf(stderr, "COULD NOT OPEN FONT: %s\n", SDL_GetError()); exit(1); } } // TODO: outsource shape definitions SDL_Vertex vert[3]; // center vert[0].position.x = 400; vert[0].position.y = 0; vert[0].color.r = 255; vert[0].color.g = 0; vert[0].color.b = 0; vert[0].color.a = 255; // left vert[1].position.x = 200; vert[1].position.y = 450; vert[1].color.r = 0; vert[1].color.g = 0; vert[1].color.b = 255; vert[1].color.a = 255; // right vert[2].position.x = 600; vert[2].position.y = 450; vert[2].color.r = 0; vert[2].color.g = 255; vert[2].color.b = 0; vert[2].color.a = 255; struct Player player_1 = TEMPLATE_1; player_1.geometry = vert; player_1.geometry_len = 3; int action_states[ACTION_STATE_COUNT]; for (int i = 0; i < ACTION_STATE_COUNT; i++) { action_states[i] = 0; } int win_x = DEFAULT_SCREEN_WIDTH; int win_y = DEFAULT_SCREEN_HEIGHT; int quit = 0; // based on: // https://gafferongames.com/post/fix_your_timestep/ // doesn't include state-interpolation (yet?) double physics_total_time = 0.0; const double physics_timestep = 1 / 60.0; const double render_timestep = 1 / 60.0; double current_time = current_sdl_time_in_seconds(); double physics_time_accumulator = 0.0; double render_time_accumulator = 0.0; float fps = 0.0f; char fps_text[123] = "start"; while (!quit) { double new_time = current_sdl_time_in_seconds(); double frame_time = new_time - current_time; current_time = new_time; physics_time_accumulator += frame_time; render_time_accumulator += frame_time; while (physics_time_accumulator >= physics_timestep) { SDL_Event event; while (!quit && SDL_PollEvent(&event)) { /* // e.g. https://stackoverflow.com/a/1252996 */ handleKeyboardEvent(action_states, event); if (action_states[ACTION_QUIT]) quit = 1; } execute_actions(&player_1, action_states, physics_timestep); /* player_move(&player_1, physics_timestep); */ physics_time_accumulator -= physics_timestep; physics_total_time += physics_timestep; } if (RENDER_ENABLED && render_time_accumulator >= render_timestep) { /* SDL_SetRenderDrawColor(renderer, HEX_COLOR(BACKGROUND_COLOR)); */ SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); SDL_RenderClear(renderer); /* render_my_stuff(renderer); */ /* hexagon_draw(&hex, renderer); */ SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); /* SDL_Rect box = { player_1.pos_x, player_1.pos_y, */ /* player_1.pos_x + 200, */ /* player_1.pos_y + 200 }; */ /* SDL_RenderFillRect(renderer, &box); */ /* SDL_RenderDrawLine(renderer, 0, 0, 1000, 1000); */ SDL_RenderGeometry(renderer, NULL, player_1.geometry, player_1.geometry_len, NULL, 0); SDL_GetWindowSize(window, &win_x, &win_y); if (SHOW_FPS) { fps = round(1.0f / render_time_accumulator); sprintf(fps_text, "FPS:%.0f", fps); SDL_Rect fps_pos = { 0, 0, 0, 0 }; render_text(fps_text, fps_pos, Sans, renderer); // show action states if (action_states[ACTION_MOVE_UP]) { SDL_Rect up_text = { 100, 600, 120, 620 }; render_text("UP", up_text, Sans, renderer); } if (action_states[ACTION_MOVE_DOWN]) { SDL_Rect up_text = { 100, 620, 120, 640 }; render_text("DOWN", up_text, Sans, renderer); } if (action_states[ACTION_MOVE_LEFT]) { SDL_Rect up_text = { 60, 620, 80, 640 }; render_text("LEFT", up_text, Sans, renderer); } if (action_states[ACTION_MOVE_RIGHT]) { SDL_Rect up_text = { 140, 620, 160, 640 }; render_text("RIGHT", up_text, Sans, renderer); } // show player attributes char x_speed_text[123]; sprintf(x_speed_text, "x-speed: %f", player_1.vel_x); SDL_Rect x_speed_text_pos = { 900, 900, 910, 910 }; render_text(x_speed_text, x_speed_text_pos, Sans, renderer); char y_speed_text[123]; sprintf(y_speed_text, "y-speed: %f", player_1.vel_y); SDL_Rect y_speed_text_pos = { 900, 920, 910, 930 }; render_text(y_speed_text, y_speed_text_pos, Sans, renderer); } render_time_accumulator = 0; SDL_RenderPresent(renderer); } } if (RENDER_ENABLED) { TTF_CloseFont(Sans); TTF_Quit(); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); } SDL_Quit(); return 0; } void execute_actions(struct Player *player, int *action_states, float delta) { if (action_states[ACTION_MOVE_UP]) { player_move(player, UP, delta); } if (action_states[ACTION_MOVE_DOWN]) { player_move(player, DOWN, delta); } if (action_states[ACTION_MOVE_LEFT]) { player_move(player, LEFT, delta); } if (action_states[ACTION_MOVE_RIGHT]) { player_move(player, RIGHT, delta); } } void render_text(char *text, SDL_Rect dest, TTF_Font *Sans, SDL_Renderer *renderer) { SDL_Color fps_color = { 0, 255, 0, 255 }; SDL_Surface *surf = TTF_RenderText_Solid(Sans, text, fps_color); dest.w = surf->w; dest.h = surf->h; SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surf); SDL_RenderCopy(renderer, texture, NULL, &dest); SDL_DestroyTexture(texture); SDL_FreeSurface(surf); } double current_sdl_time_in_seconds() { return ((double)SDL_GetPerformanceCounter() / (double)SDL_GetPerformanceFrequency()); }