a-game

2D platformer written from scratch.
git clone git://git.amin.space/a-game.git
Log | Files | Refs | README | LICENSE

commit 9b48857eac063a406f73886d2fc5a6a1fb41213b
parent b6e05f959cb88b8794b8d8db35ee5b61be741ac7
Author: amin <dev@aminmesbah.com>
Date:   Fri,  8 Jun 2018 08:32:42 +0000

Render a bunch of stars drifting in the background

FossilOrigin-Name: bfe9224ce4cb52c95c8bc8799726ddbfe9f49dddd027a660a73e8115a4880891
Diffstat:
Ashader/star_f.glsl | 10++++++++++
Ashader/star_v.glsl | 14++++++++++++++
Msrc/game.c | 212+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Msrc/game.h | 18++++++++++++++++--
Msrc/platform_linux.c | 6++++++
5 files changed, 205 insertions(+), 55 deletions(-)

diff --git a/shader/star_f.glsl b/shader/star_f.glsl @@ -0,0 +1,10 @@ +#version 330 core + +in vec4 vertex_color; + +out vec4 frag_color; + +void main() +{ + frag_color = vertex_color; +} diff --git a/shader/star_v.glsl b/shader/star_v.glsl @@ -0,0 +1,14 @@ +#version 330 core + +layout (location = 0) in vec2 position; + +out vec4 vertex_color; + +uniform mat4 model; +uniform mat4 projection; + +void main() +{ + gl_Position = projection * model * vec4(position, 0.0f, 1.0f); + vertex_color = vec4(1.0f, 1.0f, 1.0f, 1.0f); +} diff --git a/src/game.c b/src/game.c @@ -1,8 +1,10 @@ #include "game.h" -#include <glad/glad.h> +#include <assert.h> #include <math.h> +#include <glad/glad.h> + #ifdef PLATFORM_HOTLOAD_GAME_CODE void game_load_opengl_symbols(void) @@ -12,73 +14,177 @@ void game_load_opengl_symbols(void) #endif +float wrap(float n, float min, float max) +{ + if (n > max) + { + return min; + } + else if (n < min) + { + return max; + } + else + { + return n; + } +} + + +float randf(float min, float max) +{ + assert(min < max); + float random = ((float) rand()) / (float) RAND_MAX; + float diff = max - min; + float r = random * diff; + return min + r; +} + + void game_init(struct GameState *game_state, uint32_t screen_width, uint32_t screen_height) { - glViewport(0, 0, screen_width, screen_height); - - float circumradius = 10.0f; - float inradius = circumradius * sinf(glmth_rad(30.0f)); - float half_side_length = circumradius * cosf(glmth_rad(30.0f)); - - GLfloat triangle_vertices[] = { - // positions // colors - -half_side_length, -inradius, 1.0f, 0.0f, 0.0f, - half_side_length, -inradius, 0.0f, 1.0f, 0.0f, - 0.0f, circumradius, 0.0f, 0.0f, 1.0f, - }; - - GLuint vbo_id; - GLuint vao_id; - glGenVertexArrays(1, &vao_id); - glGenBuffers(1, &vbo_id); - - glBindVertexArray(vao_id); - glBindBuffer(GL_ARRAY_BUFFER, vbo_id); - glBufferData(GL_ARRAY_BUFFER, sizeof(triangle_vertices), triangle_vertices, GL_STATIC_DRAW); - - // positions - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(*triangle_vertices), (GLvoid*)0); - glEnableVertexAttribArray(0); - - // colors - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(*triangle_vertices), (GLvoid*)(2 * sizeof(*triangle_vertices))); - glEnableVertexAttribArray(1); - glBindVertexArray(0); - - game_state->vao_id = vao_id; + // set up and load star vertex data + { + float max_speed = 0.3f; + game_state->stars.num_stars = NUM_STARS; + for (size_t i = 0; i < game_state->stars.num_stars; ++i) + { + game_state->stars.velocities[i].x = randf(-max_speed, max_speed); + game_state->stars.velocities[i].y = randf(-max_speed, max_speed); + } + + for (size_t i = 0; i < game_state->stars.num_stars; ++i) + { + game_state->stars.positions[i].x = (float)(rand() % screen_width); + game_state->stars.positions[i].y = (float)(rand() % screen_height); + } + + GLuint star_vao_id; + GLuint star_vbo_id; + glGenVertexArrays(1, &star_vao_id); + glGenBuffers(1, &star_vbo_id); + + glBindVertexArray(star_vao_id); + glBindBuffer(GL_ARRAY_BUFFER, star_vbo_id); + glBufferData(GL_ARRAY_BUFFER, sizeof(game_state->stars.positions), game_state->stars.positions, GL_DYNAMIC_DRAW); + + // positions + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(0); + glBindVertexArray(0); + + game_state->star_vao_id = star_vao_id; + game_state->star_vbo_id = star_vbo_id; + } + + // load triangle vertex data + { + float circumradius = 10.0f; + float inradius = circumradius * sinf(glmth_rad(30.0f)); + float half_side_length = circumradius * cosf(glmth_rad(30.0f)); + + GLfloat triangle_vertices[] = { + // positions // colors + -half_side_length, -inradius, 1.0f, 0.0f, 0.0f, + half_side_length, -inradius, 0.0f, 1.0f, 0.0f, + 0.0f, circumradius, 0.0f, 0.0f, 1.0f, + }; + + GLuint triangle_vao_id; + GLuint triangle_vbo_id; + glGenVertexArrays(1, &triangle_vao_id); + glGenBuffers(1, &triangle_vbo_id); + + glBindVertexArray(triangle_vao_id); + glBindBuffer(GL_ARRAY_BUFFER, triangle_vbo_id); + glBufferData(GL_ARRAY_BUFFER, sizeof(triangle_vertices), triangle_vertices, GL_STATIC_DRAW); + + // positions + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(*triangle_vertices), (GLvoid*)0); + glEnableVertexAttribArray(0); + + // colors + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(*triangle_vertices), (GLvoid*)(2 * sizeof(*triangle_vertices))); + glEnableVertexAttribArray(1); + glBindVertexArray(0); + + game_state->triangle_vao_id = triangle_vao_id; + game_state->triangle_vbo_id = triangle_vbo_id; + } + + game_state->star_shader = shader_compile("shader/star_v.glsl", "shader/star_f.glsl"); game_state->triangle_shader = shader_compile("shader/triangle_v.glsl", "shader/triangle_f.glsl"); } void game_update_and_render(struct GameState *game_state, float dt, uint32_t screen_width, uint32_t screen_height) { + // update stars + { + for (size_t i = 0; i < game_state->stars.num_stars; ++i) + { + game_state->stars.positions[i].x += game_state->stars.velocities[i].x; + game_state->stars.positions[i].x = wrap(game_state->stars.positions[i].x, 0, screen_width); + + game_state->stars.positions[i].y += game_state->stars.velocities[i].y; + game_state->stars.positions[i].y = wrap(game_state->stars.positions[i].y, 0, screen_height); + } + + glBindVertexArray(game_state->star_vao_id); + glBindBuffer(GL_ARRAY_BUFFER, game_state->star_vbo_id); + glBufferData(GL_ARRAY_BUFFER, sizeof(game_state->stars.positions), game_state->stars.positions, GL_DYNAMIC_DRAW); + glBindVertexArray(0); + } + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - m4 model = glmth_m4_init_id(); - model = glmth_translate(model, glmth_v3_init(300.0f, 300.0f, 0.0f)); - model = glmth_translate(model, glmth_v3_init(100.0f * cosf(dt), 100.0f * sinf(dt), 0.0f)); - model = glmth_rotate_z(model, -dt); - model = glmth_scale(model, glmth_v3_init(10.0f, 10.0f, 10.0f)); - float scale_factor = fabs(1.0f * sinf(dt)); - model = glmth_scale(model, glmth_v3_init(scale_factor, scale_factor, scale_factor)); - - shader_use(&game_state->triangle_shader); - shader_setm4(&game_state->triangle_shader, "model", &model); - - m4 projection = glmth_m4_init_id(); - projection = glmth_projection_ortho(0.0f, screen_width, screen_height, 0.0f, -1.0f, 1.0f); - shader_setm4(&game_state->triangle_shader, "projection", &projection); - - glBindVertexArray(game_state->vao_id); - glDrawArrays(GL_TRIANGLES, 0, 3); - glBindVertexArray(0); + + // render stars + { + m4 model = glmth_m4_init_id(); + + shader_use(&game_state->star_shader); + shader_setm4(&game_state->star_shader, "model", &model); + + m4 projection = glmth_m4_init_id(); + projection = glmth_projection_ortho(0.0f, screen_width, screen_height, 0.0f, -1.0f, 1.0f); + shader_setm4(&game_state->star_shader, "projection", &projection); + + glBindVertexArray(game_state->star_vao_id); + glDrawArrays(GL_POINTS, 0, game_state->stars.num_stars - 1); + glBindVertexArray(0); + } + + // render triangle + { + m4 model = glmth_m4_init_id(); + model = glmth_translate(model, glmth_v3_init(screen_width / 2.0f, screen_height / 2.0f, 0.0f)); + model = glmth_translate(model, glmth_v3_init(100.0f * cosf(dt), 100.0f * sinf(dt), 0.0f)); + model = glmth_rotate_z(model, -dt); + model = glmth_scale(model, glmth_v3_init(10.0f, 10.0f, 10.0f)); + float scale_factor = fabs(1.0f * sinf(dt)); + model = glmth_scale(model, glmth_v3_init(scale_factor, scale_factor, scale_factor)); + + shader_use(&game_state->triangle_shader); + shader_setm4(&game_state->triangle_shader, "model", &model); + + m4 projection = glmth_m4_init_id(); + projection = glmth_projection_ortho(0.0f, screen_width, screen_height, 0.0f, -1.0f, 1.0f); + shader_setm4(&game_state->triangle_shader, "projection", &projection); + + glBindVertexArray(game_state->triangle_vao_id); + glDrawArrays(GL_TRIANGLES, 0, 3); + glBindVertexArray(0); + } } void game_cleanup(struct GameState *game_state) { - glDeleteVertexArrays(1, &game_state->vao_id); - glDeleteBuffers(1, &game_state->vbo_id); + glDeleteVertexArrays(1, &game_state->star_vao_id); + glDeleteVertexArrays(1, &game_state->triangle_vao_id); + glDeleteBuffers(1, &game_state->star_vbo_id); + glDeleteBuffers(1, &game_state->triangle_vbo_id); } diff --git a/src/game.h b/src/game.h @@ -2,13 +2,27 @@ #define GAME_H #include "glad/glad.h" +#include "glmth.h" #include "shader.h" +#define NUM_STARS 10000 + +struct Stars +{ + uint32_t num_stars; + v2 velocities[NUM_STARS]; + v2 positions[NUM_STARS]; +}; + struct GameState { - GLuint vao_id; - GLuint vbo_id; + GLuint star_vao_id; + GLuint star_vbo_id; + GLuint triangle_vao_id; + GLuint triangle_vbo_id; + struct Shader star_shader; struct Shader triangle_shader; + struct Stars stars; }; #ifdef PLATFORM_HOTLOAD_GAME_CODE diff --git a/src/platform_linux.c b/src/platform_linux.c @@ -62,6 +62,12 @@ int main(void) return -1; } +#ifdef USE_TEST_SEED + srand((uint32_t)0); +#else + srand((uint32_t)time(NULL)); +#endif + struct GameState game_state = {0}; game_init(&game_state, PLATFORM_SCR_WIDTH, PLATFORM_SCR_HEIGHT);