]> git.lizzy.rs Git - nothing.git/blob - src/main.c
(#184) Fix FPS
[nothing.git] / src / main.c
1 #include <SDL2/SDL.h>
2 #include <SDL2/SDL_mixer.h>
3
4 #include <stdint.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <time.h>
8
9 #include "game.h"
10 #include "game/level/platforms.h"
11 #include "game/level/player.h"
12 #include "game/sound_samples.h"
13 #include "math/minmax.h"
14 #include "math/point.h"
15 #include "system/error.h"
16 #include "system/lt.h"
17
18 #define SCREEN_WIDTH 800
19 #define SCREEN_HEIGHT 600
20 #define GAME_FPS 60
21
22 /* LT module adapter for Mix_CloseAudio */
23 static void Mix_CloseAudio_lt(void* ignored)
24 {
25     (void) ignored;
26     Mix_CloseAudio();
27 }
28
29 /* LT module adapter for SDL_Quit */
30 static void SDL_Quit_lt(void* ignored)
31 {
32     (void) ignored;
33     SDL_Quit();
34 }
35
36 static void print_usage(FILE *stream)
37 {
38     fprintf(stream, "Usage: nothing <level-file>\n");
39 }
40
41 int main(int argc, char *argv[])
42 {
43     srand((unsigned int) time(NULL));
44
45     lt_t *const lt = create_lt();
46
47     if (argc < 2) {
48         print_usage(stderr);
49         RETURN_LT(lt, -1);
50     }
51
52     if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
53         print_error_msg(ERROR_TYPE_SDL2, "Could not initialize SDL");
54         RETURN_LT(lt, -1);
55     }
56     PUSH_LT(lt, 42, SDL_Quit_lt);
57
58     SDL_ShowCursor(SDL_DISABLE);
59
60     SDL_Window *const window = PUSH_LT(
61         lt,
62         SDL_CreateWindow(
63             "Nothing",
64             100, 100,
65             SCREEN_WIDTH, SCREEN_HEIGHT,
66             SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE),
67         SDL_DestroyWindow);
68
69     if (window == NULL) {
70         print_error_msg(ERROR_TYPE_SDL2, "Could not create SDL window");
71         RETURN_LT(lt, -1);
72     }
73
74     SDL_Renderer *const renderer = PUSH_LT(
75         lt,
76         SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
77         SDL_DestroyRenderer);
78     if (renderer == NULL) {
79         print_error_msg(ERROR_TYPE_SDL2, "Could not create SDL renderer");
80         RETURN_LT(lt, -1);
81     }
82     if (SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND) < 0) {
83         print_error_msg(ERROR_TYPE_SDL2, "Could not set up blending mode for the renderer");
84         RETURN_LT(lt, -1);
85     }
86
87     SDL_Joystick *the_stick_of_joy = NULL;
88
89     if (SDL_NumJoysticks() > 0) {
90         the_stick_of_joy = PUSH_LT(lt, SDL_JoystickOpen(0), SDL_JoystickClose);
91
92         if (the_stick_of_joy == NULL) {
93             print_error_msg(ERROR_TYPE_SDL2, "Could not open 0th Stick of the Joy: %s\n");
94             RETURN_LT(lt, -1);
95         }
96
97         printf("Opened Joystick 0\n");
98         printf("Name: %s\n", SDL_JoystickNameForIndex(0));
99         printf("Number of Axes: %d\n", SDL_JoystickNumAxes(the_stick_of_joy));
100         printf("Number of Buttons: %d\n", SDL_JoystickNumButtons(the_stick_of_joy));
101         printf("Number of Balls: %d\n", SDL_JoystickNumBalls(the_stick_of_joy));
102
103         SDL_JoystickEventState(SDL_ENABLE);
104     } else {
105         fprintf(stderr, "[WARNING] Could not find any Sticks of the Joy\n");
106     }
107
108     if (Mix_OpenAudio(
109             MIX_DEFAULT_FREQUENCY,
110             MIX_DEFAULT_FORMAT,
111             2,
112             1024) < 0) {
113         print_error_msg(ERROR_TYPE_SDL2_MIXER, "Could not initialize the audio\n");
114         RETURN_LT(lt, -1);
115     }
116     PUSH_LT(lt, 42, Mix_CloseAudio_lt);
117
118     // ------------------------------
119
120     const char * sound_sample_files[] = {
121         "./sounds/nothing.wav",
122         "./sounds/something.wav"
123     };
124     const size_t sound_sample_files_count = sizeof(sound_sample_files) / sizeof(char*);
125
126     game_t *const game = PUSH_LT(
127         lt,
128         create_game(
129             argv[1],
130             sound_sample_files,
131             sound_sample_files_count,
132             renderer),
133         destroy_game);
134     if (game == NULL) {
135         print_current_error_msg("Could not create the game object");
136         RETURN_LT(lt, -1);
137     }
138
139     const Uint8 *const keyboard_state = SDL_GetKeyboardState(NULL);
140
141     SDL_Event e;
142     int64_t last_time = (int64_t) SDL_GetTicks();
143     const int64_t expected_delay_ms = (int64_t) (1000.0f / GAME_FPS);
144     while (!game_over_check(game)) {
145         const int64_t current_time = (int64_t) SDL_GetTicks();
146
147         if (current_time == last_time) {
148             SDL_Delay((int) expected_delay_ms);
149             last_time = current_time;
150             continue;
151         }
152
153         const int64_t actual_delta_ms = current_time - last_time;
154
155
156         while (!game_over_check(game) && SDL_PollEvent(&e)) {
157             if (game_event(game, &e) < 0) {
158                 print_current_error_msg("Failed handling event");
159                 RETURN_LT(lt, -1);
160             }
161         }
162
163         if (game_input(game, keyboard_state, the_stick_of_joy) < 0) {
164             print_current_error_msg("Failed handling input");
165             RETURN_LT(lt, -1);
166         }
167
168         if (game_render(game) < 0) {
169             print_current_error_msg("Failed rendering the game");
170             RETURN_LT(lt, -1);
171         }
172
173         int64_t effective_delta_ms = max_int64(actual_delta_ms, expected_delay_ms);
174         while (effective_delta_ms > 0) {
175             if (game_update(game, (float) min_int64(expected_delay_ms, effective_delta_ms) * 0.001f) < 0) {
176                 print_current_error_msg("Failed handling updating");
177                 RETURN_LT(lt, -1);
178             }
179
180             effective_delta_ms -= expected_delay_ms;
181         }
182
183         if (game_sound(game) < 0) {
184             print_current_error_msg("Failed handling the sound");
185             RETURN_LT(lt, -1);
186         }
187
188         SDL_Delay((unsigned int) max_int64(0, expected_delay_ms - actual_delta_ms));
189         last_time = current_time;
190     }
191
192     RETURN_LT(lt, 0);
193 }