From 724383a8c031d9aebced04c751b54cb1b2dd6aff Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Fri, 5 Dec 2025 11:28:35 -0600 Subject: [PATCH] add timer --- Makefile | 1 + include/render.hpp | 4 +- include/state.h | 3 ++ include/unparse.h | 14 +++++++ src/main.c | 14 +++++-- src/render.cpp | 59 ++++++++++++++++++++++++--- src/shader/font.fp.glsl | 3 ++ src/shader/font.vp.glsl | 13 +++++- src/unparse.c | 88 +++++++++++++++++++++++++++++++++++++++++ src/update.cpp | 1 + 10 files changed, 190 insertions(+), 10 deletions(-) create mode 100644 include/unparse.h create mode 100644 src/unparse.c diff --git a/Makefile b/Makefile index b94ddea..bd42a52 100644 --- a/Makefile +++ b/Makefile @@ -105,6 +105,7 @@ MAIN_OBJS = \ src/render.o \ src/collision.o \ src/update.o \ + src/unparse.o \ $(patsubst %.glsl,%.glsl.o,$(wildcard src/shader/*.glsl)) \ $(patsubst %.data,%.data.o,$(wildcard src/level/*.data)) \ $(patsubst %.data,%.data.o,$(wildcard src/font/*.data)) \ diff --git a/include/render.hpp b/include/render.hpp index 0d82edc..8f0ceab 100644 --- a/include/render.hpp +++ b/include/render.hpp @@ -31,7 +31,9 @@ extern "C" { uint attrib_texture, uint attrib_normal, uint uniform_trans, - uint uniform_texture0); + uint uniform_texture_trans, + uint uniform_texture0, + struct game_state * state); #ifdef __cplusplus } diff --git a/include/state.h b/include/state.h index a640e50..e2510b2 100644 --- a/include/state.h +++ b/include/state.h @@ -12,6 +12,9 @@ extern "C" { float ball_y; float ball_dx; float ball_dy; + + double start_time; + double remaining; }; #ifdef __cplusplus diff --git a/include/unparse.h b/include/unparse.h new file mode 100644 index 0000000..43135aa --- /dev/null +++ b/include/unparse.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + int unparse_base10_64(char * s, int64_t n, int len); + int unparse_double(double num, int whole_pad, int fract_pad, char * dst); + +#ifdef __cplusplus +} +#endif diff --git a/src/main.c b/src/main.c index e95bd38..5dfbe22 100644 --- a/src/main.c +++ b/src/main.c @@ -139,6 +139,7 @@ int main() uint font__attrib_texture = glGetAttribLocation(font_program, "_texture"); uint font__attrib_normal = glGetAttribLocation(font_program, "normal"); uint font__uniform_trans = glGetUniformLocation(font_program, "trans"); + uint font__uniform_texture_trans = glGetUniformLocation(font_program, "texture_trans"); uint font__uniform_texture0 = glGetUniformLocation(font_program, "texture0"); ////////////////////////////////////////////////////////////////////// @@ -150,6 +151,7 @@ int main() 256, 256, GL_RED); + (void)terminus_font; ////////////////////////////////////////////////////////////////////// // main loop @@ -171,11 +173,12 @@ int main() state.ball_dx = 0.1; state.ball_dy = 0.1; + state.start_time = glfwGetTime(); + while(!glfwWindowShouldClose(window)) { if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); - glEnable(GL_DEPTH_TEST); glClearDepth(-1000.0f); glClearColor(0.1, 0.2, 0.3, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -215,6 +218,8 @@ int main() state.paddle_x = 12 - extent; update(&state); + double time = glfwGetTime(); + state.remaining = 20.0 - (time - state.start_time); if ((state.ball_x + state.ball_dx * 0.4) > 12.25f) { state.ball_x = 12.25f; @@ -232,6 +237,7 @@ int main() state.ball_dy = -state.ball_dy; } + glEnable(GL_DEPTH_TEST); glDepthFunc(GL_GREATER); glUseProgram(program); @@ -247,6 +253,7 @@ int main() uniform_light_pos, &state); + glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); glUseProgram(font_program); @@ -255,8 +262,9 @@ int main() font__attrib_texture, font__attrib_normal, font__uniform_trans, - font__uniform_texture0 - ); + font__uniform_texture_trans, + font__uniform_texture0, + &state); glfwSwapBuffers(window); glfwPollEvents(); diff --git a/src/render.cpp b/src/render.cpp index 5d216f3..cd7994a 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -4,6 +4,7 @@ #include "glad/glad.h" +#include "unparse.h" #include "collision.hpp" #include "render.hpp" #include "math/float_types.hpp" @@ -266,12 +267,43 @@ void render(mesh paddle_mesh, } } +const int grid_width = 16; +const int grid_height = 32; +const int grid_stride = 256 / grid_width; +const int first_character = 0x20; +const float grid_scale = 1.0f / 256.0f; + +static inline mat4x4 char_tex_trans(char c) +{ + int cc = c - first_character; + int x = cc % grid_stride; + int y = cc / grid_stride; + + mat4x4 tex_t = translate(vec3((float)(x * grid_width) * grid_scale, + (float)(y * grid_height) * grid_scale, + 0)); + mat4x4 tex_s = scale(vec3(grid_width * grid_scale, grid_height * grid_scale, 1.0f)); + mat4x4 texture_trans = tex_t * tex_s; + + return texture_trans; +} + +static inline int max(int a, int b) +{ + if (a > b) + return a; + else + return b; +} + void render_font(struct mesh plane_mesh, uint attrib_position, uint attrib_texture, uint attrib_normal, uint uniform_trans, - uint uniform_texture0) + uint uniform_texture_trans, + uint uniform_texture0, + struct game_state * state) { glBindBuffer(GL_ARRAY_BUFFER, plane_mesh.vtx); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, plane_mesh.idx); @@ -301,12 +333,29 @@ void render_font(struct mesh plane_mesh, glEnableVertexAttribArray(attrib_texture); glEnableVertexAttribArray(attrib_normal); + float aspect = (float)vp_height / (float)vp_width; + + mat4x4 a = scale(vec3(aspect, 1.0f, 1.0f)); + mat4x4 s = scale(vec3(1, 2, 1)); mat4x4 r = rotate_y(PI / 1.0f) * rotate_z(PI / 1.0f) * rotate_x(PI / 2.0f); - mat4x4 trans = scale(0.5f) * r; - - glUniform4fv(uniform_trans, 4, &trans[0][0]); glUniform1i(uniform_texture0, 0); - glDrawElements(GL_TRIANGLES, plane_mesh.length, GL_UNSIGNED_INT, 0); + char dst[64]; + int len = unparse_double(state->remaining, 4, 3, dst); + + int advance = 0; + for (int i = 0; i < len; i++) { + if (dst[i] != ' ') { + mat4x4 texture_trans = char_tex_trans(dst[i]); + + mat4x4 char_t = translate(vec3(advance / 8.0f, -8.0f * aspect, 0)); + mat4x4 trans = a * scale(32.0f / vp_height) * s * char_t * r; + + glUniform4fv(uniform_trans, 4, &trans[0][0]); + glUniform4fv(uniform_texture_trans, 4, &texture_trans[0][0]); + glDrawElements(GL_TRIANGLES, plane_mesh.length, GL_UNSIGNED_INT, 0); + } + advance += grid_width; + } } diff --git a/src/shader/font.fp.glsl b/src/shader/font.fp.glsl index b82c282..291941e 100644 --- a/src/shader/font.fp.glsl +++ b/src/shader/font.fp.glsl @@ -8,6 +8,9 @@ void main() { vec4 c = texture2D(texture0, fp_texture); + if (c.x == 0) + discard; + float i = c.x == 0 ? 0.0 : 1.0; gl_FragColor = vec4(i, i, i, 1.0); diff --git a/src/shader/font.vp.glsl b/src/shader/font.vp.glsl index cd81711..0809cb9 100644 --- a/src/shader/font.vp.glsl +++ b/src/shader/font.vp.glsl @@ -5,8 +5,10 @@ attribute vec2 _texture; attribute vec3 normal; varying vec2 fp_texture; +varying vec2 fp_texture_trans; uniform vec4 trans[4]; +uniform vec4 texture_trans[4]; vec4 transform4(vec4 v) { @@ -16,11 +18,20 @@ vec4 transform4(vec4 v) dot(trans[3], v)); } +vec4 transform4t(vec4 v) +{ + return vec4(dot(texture_trans[0], v), + dot(texture_trans[1], v), + dot(texture_trans[2], v), + dot(texture_trans[3], v)); +} + void main() { vec4 pos = transform4(vec4(position, 1)); + vec4 tt = transform4t(vec4(_texture, 0, 1)); - fp_texture = _texture; + fp_texture = tt.xy; gl_Position = pos; } diff --git a/src/unparse.c b/src/unparse.c new file mode 100644 index 0000000..8b046a4 --- /dev/null +++ b/src/unparse.c @@ -0,0 +1,88 @@ +#include + +#include "unparse.h" + +static inline int digits_base10_64(uint64_t n) +{ + if (n >= 10000000000000000000ull) return 20; + if (n >= 1000000000000000000ull) return 19; + if (n >= 100000000000000000ull) return 18; + if (n >= 10000000000000000ull) return 17; + if (n >= 1000000000000000ull) return 16; + if (n >= 100000000000000ull) return 15; + if (n >= 10000000000000ull) return 14; + if (n >= 1000000000000ull) return 13; + if (n >= 100000000000ull) return 12; + if (n >= 10000000000ull) return 11; + if (n >= 1000000000ull) return 10; + if (n >= 100000000ull) return 9; + if (n >= 10000000ull) return 8; + if (n >= 1000000ull) return 7; + if (n >= 100000ull) return 6; + if (n >= 10000ull) return 5; + if (n >= 1000ull) return 4; + if (n >= 100ull) return 3; + if (n >= 10ull) return 2; + return 1; +} + +static inline int min(int a, int b) +{ + if (a < b) + return a; + else + return b; +} + +int unparse_base10_64(char * s, int64_t n, int len) +{ + int digits = 0; + if (n < 0) { + digits += 1; + n = -n; + } + + digits += digits_base10_64(n); + len = min(digits, len); + int ret = len; + + while (len > 0) { + const uint32_t digit = n % 10; + n = n / 10; + s[--len] = digit + 48; + } + + return ret; +} + +int unparse_double(double num, int whole_pad, int fract_pad, char * dst) +{ + bool negative = num < 0; + double n = negative ? -num : num; + double whole = floor(n); + double fract = n - whole; + int64_t wholei = whole; + int64_t fracti = fract * pow(10.0, fract_pad); + + char wbuf[20]; + int wret = unparse_base10_64(wbuf, wholei, 20); + char fbuf[20]; + int fret = unparse_base10_64(fbuf, fracti, 20); + int ix = 0; + for (int i = 0; i < whole_pad - wret; i++) { + dst[ix++] = ' '; + } + dst[ix++] = negative ? '-' : ' '; + for (int i = 0; i < wret; i++) { + dst[ix++] = wbuf[i]; + } + dst[ix++] = '.'; + for (int i = 0; i < fract_pad - fret; i++) { + dst[ix++] = '0'; + } + for (int i = 0; i < fret; i++) { + dst[ix++] = fbuf[i]; + } + + return ix; +} diff --git a/src/update.cpp b/src/update.cpp index 4a35809..d05fc25 100644 --- a/src/update.cpp +++ b/src/update.cpp @@ -13,4 +13,5 @@ void update(struct game_state * state) { + }