#include "i_input.h"
#include "t_camera.h"
#include "t_map.h"
+#include "u_time.h"
struct lrts_config lrts_global_cfg;
}
void lrts_init(void) {
+ struct lrts_config* cfg = lrts_cfg();
struct u_vec2 res = lrts_get_render_res();
+
+ cfg->target_fps = LRTS_DEFAULT_TARGET_FPS;
+
/* init the fallback tile mask */
r_asset_init_fallback_tile();
i_input_init();
-
+
+ u_fps_timer = u_timer_init();
t_main_camera = t_camera_init(res.x, res.y);
#include "r_color.c"
#include "r_assets.c"
#include "i_input.c"
+#include "u_time.c"
#endif
*/
int p_renderer_finish(void);
+/*
+ * Caps the fps at configured target fps.
+ * This should generally be based on the time it took between
+ * begin and end of drawing.
+ * returns current fps.
+ */
+u32 p_cap_fps(void);
+
+/* returns an integer representation of
+ * the current tick rate
+ * the number itself is abstract and simply represents
+ * a unit of time
+ */
+u64 p_get_ticks(void);
+
+/* returns the ticks contained in a single
+ * second */
+u64 p_ticks_per_second(void);
+
+/* delays execution
+ * the delay time is relative to
+ * the unit ticks are in
+ */
+void p_delay(u64 time);
+
+
/**
* polls input events
* should be called once a frame
#include "p_window.h"
#include "../u_assert.h"
+
+u64 p_get_ticks(void) {
+ return SDL_GetTicksNS();
+}
+
+void p_delay(u64 time) {
+ SDL_DelayNS(time);
+}
+
+u64 p_ticks_per_second(void) {
+ return 1000000000;
+}
+
void p_draw_begin(void) {
SDL_LockSurface(r_target);
}
SDL_BlitSurfaceScaled(r_target, NULL, screen, &dst, SDL_SCALEMODE_PIXELART);
SDL_UpdateWindowSurface(p_main_window);
}
+
}
void r_render_frame() {
+ u_timer_start(&u_fps_timer);
p_draw_begin();
p_draw_end();
p_draw_present();
+ u_timer_end(&u_fps_timer);
+
+ u_cap_fps();
}
}
void t_map_draw(struct t_map *m) {
- u32 i, j;
+ i32 i, j;
+ struct u_vec2 start;
+ struct u_vec2 end;
+
+ start.x = 0;
+ start.y = 0;
+
+ end.x = m->width;
+ end.y = m->height;
- /* TODO: only draw visible tiles */
- for (i = 0; i < m->width; i++) {
- for (j = 0; j < m->height; j++) {
+ /* find start tile that is inside of camera viewport */
+
+
+ for (i = start.x; i < end.x; i++) {
+ for (j = start.y; j < end.y; j++) {
r_draw_tile(&m->tiles[j * m->width + i], i, j);
}
}
typedef short i16;
typedef unsigned int u32;
typedef int i32;
+typedef long int i64;
+typedef unsigned long int u64;
typedef unsigned char lrts_bool;
#define LRTS_TRUE 1
#include "u_math.h"
+/* in-game tick rate */
+#define LRTS_TPS 20
+#define LRTS_DEFAULT_TARGET_FPS 60
+
struct lrts_config {
lrts_bool verbose;
struct u_vec2 render_res;
struct u_vec2 screen_res;
+
+ /* visual fps target */
+ int target_fps;
char **argv;
int argc;
--- /dev/null
+#include "u_time.h"
+
+u32 u_cap_fps(void) {
+ u32 fps = 0;
+ u32 target_fps;
+ u32 delta;
+ u32 total_frame_time;
+
+ u64 per_frame, delay;
+ const u64 in_sec = p_ticks_per_second();
+ struct lrts_config* cfg = lrts_cfg();
+
+ target_fps = cfg->target_fps;
+ per_frame = in_sec / target_fps;
+
+ delta = u_timer_delta(&u_fps_timer);
+ delay = per_frame - delta;
+
+
+ /* 0 target fps means we do not delay */
+ if (target_fps > 0 && delta < per_frame) {
+ p_delay(delay);
+ }
+
+ delta = u_timer_end(&u_fps_timer);
+ total_frame_time = delta;
+
+ /* TODO: take average from pervious few frames for fps */
+ fps = in_sec / total_frame_time;
+ return (u32)fps;
+}
+
+struct u_timer u_timer_init(void) {
+ struct u_timer t;
+ t.start = 0;
+ t.end = 0;
+ return t;
+}
+
+void u_timer_start(struct u_timer *t) {
+ t->start = p_get_ticks();
+ t->end = 0;
+}
+
+u64 u_timer_end(struct u_timer *t) {
+ t->end = p_get_ticks();
+ return u_timer_delta(t);
+}
+
+u64 u_timer_delta(struct u_timer *t) {
+ return t->end - t->start;
+}
+
+struct u_timer u_fps_timer;
--- /dev/null
+#ifndef U_TIME_H__
+#define U_TIME_H__
+
+struct u_timer {
+ u64 start;
+ u64 end;
+};
+
+struct u_timer u_timer_init(void);
+
+void u_timer_start(struct u_timer *t);
+u64 u_timer_end(struct u_timer *t);
+u64 u_timer_delta(struct u_timer *t);
+
+extern struct u_timer u_fps_timer;
+
+u32 u_cap_fps(void);
+
+#endif