summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpryazha <pryadeiniv@mail.ru>2025-02-20 15:10:59 +0500
committerpryazha <pryadeiniv@mail.ru>2025-02-20 15:10:59 +0500
commit60bd06ced6de9f1272e31da323996db2d8b8a531 (patch)
tree1c076b26f26f57351f7572495ba9160b6f8c4a57
initial
l---------lib/prb1
l---------lib/prge1
-rwxr-xr-xsrc/build.sh7
-rw-r--r--src/engine/sdl_linux.c203
-rw-r--r--src/game/game.c41
-rw-r--r--src/game/game.h11
-rwxr-xr-xsrc/prge_game_examplebin0 -> 88904 bytes
-rw-r--r--src/shaders/default.frag8
-rw-r--r--src/shaders/default.vert9
9 files changed, 281 insertions, 0 deletions
diff --git a/lib/prb b/lib/prb
new file mode 120000
index 0000000..87a2bbf
--- /dev/null
+++ b/lib/prb
@@ -0,0 +1 @@
+/home/pryazha/srvgit/prb \ No newline at end of file
diff --git a/lib/prge b/lib/prge
new file mode 120000
index 0000000..591954b
--- /dev/null
+++ b/lib/prge
@@ -0,0 +1 @@
+/home/pryazha/srvgit/prge \ No newline at end of file
diff --git a/src/build.sh b/src/build.sh
new file mode 100755
index 0000000..9a18dff
--- /dev/null
+++ b/src/build.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+CFLAGS='-g -Wall -Wextra'
+INCLUDE='-I../lib/prge -I../lib/prb -Igame'
+LIBS='-lm -lSDL2 -lGL -lGLEW'
+TARGET=prge_game_example
+set -x
+gcc -o $TARGET $CFLAGS $INCLUDE $LFLAGS engine/sdl_linux.c $LIBS && ./$TARGET
diff --git a/src/engine/sdl_linux.c b/src/engine/sdl_linux.c
new file mode 100644
index 0000000..76851df
--- /dev/null
+++ b/src/engine/sdl_linux.c
@@ -0,0 +1,203 @@
+#include "GL/glew.h"
+#include "SDL2/SDL.h"
+
+#include "prge.h"
+
+#include "game.h"
+#include "game.c"
+
+void process_mouse_pos(Input *input, S32 x, S32 y)
+{
+ V2 pos = v2((F32)x, (F32)y);
+ if (input->first_mouse) {
+ input->mouse_pos = pos;
+ input->first_mouse = 0;
+ }
+ input->last_mouse_pos = input->mouse_pos;
+ input->mouse_pos = pos;
+ input->mouse_offset = v2sub(input->mouse_pos,
+ input->last_mouse_pos);
+}
+
+void process_window_resize()
+{
+}
+
+void process_key(U8 state, Key *key)
+{
+ key->state = (state == SDL_PRESSED) ? KeyState_PRESS : KeyState_RELEASE;
+}
+
+void process_keyboard(Input *input, SDL_KeyboardEvent *key)
+{
+ switch (key->keysym.scancode) {
+ case SDL_SCANCODE_D:
+ process_key(key->state, &input->move_right);
+ break;
+ case SDL_SCANCODE_W:
+ process_key(key->state, &input->move_forward);
+ break;
+ case SDL_SCANCODE_A:
+ process_key(key->state, &input->move_left);
+ break;
+ case SDL_SCANCODE_S:
+ process_key(key->state, &input->move_backward);
+ break;
+ case SDL_SCANCODE_E:
+ process_key(key->state, &input->move_up);
+ break;
+ case SDL_SCANCODE_Q:
+ process_key(key->state, &input->move_down);
+ break;
+ case SDL_SCANCODE_SPACE:
+ process_key(key->state, &input->jump);
+ break;
+ case SDL_SCANCODE_RIGHT:
+ process_key(key->state, &input->action_right);
+ break;
+ case SDL_SCANCODE_UP:
+ process_key(key->state, &input->action_up);
+ break;
+ case SDL_SCANCODE_LEFT:
+ process_key(key->state, &input->action_left);
+ break;
+ case SDL_SCANCODE_DOWN:
+ process_key(key->state, &input->action_down);
+ break;
+ case SDL_SCANCODE_ESCAPE:
+ process_key(key->state, &input->exit);
+ break;
+ default:
+ break;
+ }
+}
+
+void handle_events(Input *input)
+{
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {
+ switch (event.type) {
+ case SDL_KEYDOWN:
+ case SDL_KEYUP:
+ process_keyboard(input, &event.key);
+ break;
+ case SDL_MOUSEMOTION:
+ process_mouse_pos(input, event.motion.x, event.motion.y);
+ break;
+ case SDL_WINDOWEVENT_RESIZED:
+ process_window_resize();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+F32 get_elapsed_seconds(U64 cur, U64 last)
+{
+ F32 result = ((F32)cur-(F32)last)/1000.0f;
+ return result;
+}
+
+F32 lock_framerate(U64 last, F32 target)
+{
+ F32 target_mspf = 1000.0f/target;
+
+ F32 elapsed = get_elapsed_seconds(SDL_GetTicks64(), last)*1000.0f;
+
+ if (elapsed < target_mspf) {
+ /* F32 sleep = target_mspf-elapsed-1.0f; */
+ F32 sleep = target_mspf-elapsed;
+ if (sleep > 0.0f)
+ SDL_Delay(sleep);
+ /*
+ do {
+ elapsed = get_elapsed_seconds(SDL_GetTicks64(), last)*1000.0f;
+ } while (elapsed < target_mspf);
+ */
+ }
+
+ F32 dt = get_elapsed_seconds(SDL_GetTicks64(), last);
+
+ return dt;
+}
+
+B32 sdl_init(S32 width, S32 height,
+ SDL_Window **window,
+ SDL_GLContext **context)
+{
+ if (SDL_Init(SDL_INIT_VIDEO)) {
+ SDL_Log("[ERROR] : SDL : %s\n", SDL_GetError());
+ return 0;
+ }
+
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
+ SDL_GL_CONTEXT_PROFILE_CORE);
+
+ U32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
+ (*window) = SDL_CreateWindow("prge game example",
+ SDL_WINDOWPOS_CENTERED,
+ SDL_WINDOWPOS_CENTERED,
+ width, height, flags);
+
+ if (!(*window)) {
+ SDL_Log("[ERROR] : SDL : %s\n", SDL_GetError());
+ return 0;
+ }
+
+ (*context) = SDL_GL_CreateContext((*window));
+ if (!(*context)) {
+ SDL_Log("[ERROR] : SDL : %s\n", SDL_GetError());
+ return 0;
+ }
+
+ GLenum error = glewInit();
+ if (error != GLEW_OK) {
+ SDL_Log("[ERROR] : GLEW : %s\n", glewGetErrorString(error));
+ return 0;
+ }
+
+ return 1;
+}
+
+int main(void)
+{
+ /* NOTE(pryazha): Engine init */
+ Input input = input_init();
+ S32 width = 800, height = 600;
+
+ /* NOTE(pryazha): SDL init */
+ SDL_Window *window;
+ SDL_GLContext *context;
+ if (!sdl_init(width, height, &window, &context)) {
+ SDL_Quit();
+ return 1;
+ }
+
+ /* NOTE(pryazha): Game init */
+ State state = {0};
+ game_init(&state);
+
+ U64 last = SDL_GetTicks64();
+ while (input.is_running) {
+ handle_events(&input);
+
+ input.dt = lock_framerate(last, 60.0f);
+ last = SDL_GetTicks64();
+
+ game_update_and_render(&state, &input);
+
+ input_update(&input);
+
+ SDL_GL_SwapWindow(window);
+ }
+
+ game_clear(&state);
+
+ SDL_GL_DeleteContext(context);
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+ return 0;
+}
diff --git a/src/game/game.c b/src/game/game.c
new file mode 100644
index 0000000..25c71fa
--- /dev/null
+++ b/src/game/game.c
@@ -0,0 +1,41 @@
+void game_init(State *state)
+{
+ U64 persistent_size = Megabytes(1);
+ state->persistent_arena = arena_alloc(persistent_size);
+ state->shader = create_shader_program(str8lit("shaders/default.vert"),
+ str8lit("shaders/default.frag"));
+ Vertex verts[] = {
+ vertex(v3(-0.5f, -0.5f, 0.0f)),
+ vertex(v3(0.0f, 0.5f, 0.0f)),
+ vertex(v3(0.5f, -0.5f, 0.0f))
+ };
+
+ U32 indices[] = { 0, 1, 2 };
+
+ state->the_mesh = mesh(state->persistent_arena, verts, ArrayCount(verts), indices, ArrayCount(indices));
+}
+
+void game_update_and_render(State *state, Input *input)
+{
+ /* NOTE(pryazha): Update */
+ if (key_is_pressed(input->exit))
+ input->is_running = 0;
+
+ /* NOTE(pryazha): Render */
+ glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glUseProgram(state->shader);
+ F32 angle = 20.0f*state->t;
+ Mat4 model = mat4rotate(MAT4_IDENTITY, v3(0.0f, 0.0f, angle));
+ shader_set_mat4fv(state->shader, "model", model);
+ mesh_draw(*state->the_mesh);
+ glUseProgram(0);
+
+ state->t += input->dt;
+}
+
+void game_clear(State *state)
+{
+ arena_release(state->persistent_arena);
+}
diff --git a/src/game/game.h b/src/game/game.h
new file mode 100644
index 0000000..b37798d
--- /dev/null
+++ b/src/game/game.h
@@ -0,0 +1,11 @@
+#ifndef GAME_H
+#define GAME_H
+
+typedef struct {
+ Arena *persistent_arena;
+ U32 shader;
+ Mesh *the_mesh;
+ F32 t;
+} State;
+
+#endif /* GAME_H */
diff --git a/src/prge_game_example b/src/prge_game_example
new file mode 100755
index 0000000..bbf178d
--- /dev/null
+++ b/src/prge_game_example
Binary files differ
diff --git a/src/shaders/default.frag b/src/shaders/default.frag
new file mode 100644
index 0000000..9a5018d
--- /dev/null
+++ b/src/shaders/default.frag
@@ -0,0 +1,8 @@
+#version 330 core
+
+out vec4 frag_color;
+
+void main(void)
+{
+ frag_color = vec4(1.0);
+}
diff --git a/src/shaders/default.vert b/src/shaders/default.vert
new file mode 100644
index 0000000..637c7c1
--- /dev/null
+++ b/src/shaders/default.vert
@@ -0,0 +1,9 @@
+#version 330 core
+layout(location = 0) in vec3 apos;
+
+uniform mat4 model;
+
+void main(void)
+{
+ gl_Position = model*vec4(apos, 1.0);
+}