Files
wschod/game/src/main.c
T
2025-06-01 18:26:22 +02:00

231 lines
5.4 KiB
C

#define SDL_MAIN_USE_CALLBACKS 1
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <stdio.h>
#include "chunk/chunkmesh.h"
#include "state.h"
#include "flags.h"
#include "camera.h"
#include "mesh.h"
#include "resources.h"
/* TODO: switch back to cglm.h, since it's faster or something */
static SDL_Window *window = NULL;
static SDL_GLContext context = NULL;
extern GameState game_state;
extern GameFlags game_flags;
extern Resources resources;
static ChunkMesh test_chunkmesh;
static Camera camera;
SDL_AppResult
SDL_AppInit (void **appstate, int argc, char **argv)
{
(void) appstate; (void) argc; (void) argv;
SDL_SetAppMetadata (GAME_NAME, GAME_VERSION, "eur.chopininteractive.wschod-game");
if (!SDL_Init (SDL_INIT_VIDEO))
{
FATAL ("Couldn't initialize SDL: %s", SDL_GetError ());
}
window = SDL_CreateWindow (GAME_NAME, 640, 480, SDL_WINDOW_OPENGL);
if (!window)
{
FATAL ("Couldn't create window: %s", SDL_GetError ());
}
/* We use OpenGL ES 2.0. It should support everything, and it's more
than enough for the game. */
SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 0);
context = SDL_GL_CreateContext (window);
if (!context)
{
FATAL ("Couldn't create OpenGL context: %s", SDL_GetError ());
}
SDL_GL_MakeCurrent (window, context);
SDL_SetWindowRelativeMouseMode (window, true);
INFO ("Renderer: %s", glGetString (GL_RENDERER));
INFO ("OpenGL version: %s", glGetString (GL_VERSION));
INFO ("GLSL version: %s", glGetString (GL_SHADING_LANGUAGE_VERSION));
INFO ("Max vertex attributes: %d", GL_MAX_VERTEX_ATTRIBS);
glViewport(0, 0, 640, 480);
glClearColor (0, 0.3, 0.8, 1);
glEnable (GL_CULL_FACE);
glEnable (GL_DEPTH_TEST);
/* Initialize and load resources. */
Resources_init ();
noise_seed (1337);
/* Generate a test chunk. */
Chunk chunk = Chunk_new ();
Chunk_noise (&chunk, 0, 0);
test_chunkmesh = ChunkMesh_from_Chunk_and_neighbors (&chunk, NULL, NULL, NULL);
program_use (resources.programs[1]);
int arr[4] = { 0, 1, 2, 3 };
program_set_int_array (resources.programs[1], "materials", 4, arr);
/* Set up game state. */
game_state.last_time = SDL_GetTicks ();
/* Set some basic game flags for testing. */
game_flags.can_free_look = 1;
game_flags.wireframe_enabled = 0;
/* Initialize the default camera. */
camera = Camera_default ();
camera.position.z = -1.0;
return SDL_APP_CONTINUE;
}
SDL_AppResult
SDL_AppEvent (void *appstate, SDL_Event *event)
{
(void) appstate;
if (event->type == SDL_EVENT_QUIT)
{
return SDL_APP_SUCCESS;
}
if (event->type == SDL_EVENT_MOUSE_MOTION && game_flags.can_free_look)
{
camera.rotation.x -= event->motion.xrel / 100.f;
camera.rotation.y -= event->motion.yrel / 100.f;
camera.rotation.y =
CLAMP (camera.rotation.y, -M_PI / 2 + 0.025, M_PI / 2 - 0.025);
}
if (event->type == SDL_EVENT_KEY_DOWN)
{
switch (event->key.key)
{
case SDLK_W:
game_flags.moving_forward = 1;
break;
case SDLK_A:
game_flags.moving_left = 1;
break;
case SDLK_S:
game_flags.moving_backward = 1;
break;
case SDLK_D:
game_flags.moving_right = 1;
break;
case SDLK_F1:
game_flags.wireframe_enabled = !game_flags.wireframe_enabled;
break;
}
}
if (event->type == SDL_EVENT_KEY_UP)
{
switch (event->key.key)
{
case SDLK_W:
game_flags.moving_forward = 0;
break;
case SDLK_A:
game_flags.moving_left = 0;
break;
case SDLK_S:
game_flags.moving_backward = 0;
break;
case SDLK_D:
game_flags.moving_right = 0;
break;
}
}
return SDL_APP_CONTINUE;
}
SDL_AppResult
SDL_AppIterate (void *appstate)
{
(void) appstate;
/* Caluclate stuff per frame. */
int now = SDL_GetTicks ();
game_state.delta_time = (now - game_state.last_time) / 1000.0;
game_state.last_time = now;
if (game_flags.moving_forward)
{
camera.position = v3_add
(camera.position, v3_muls
(Camera_get_direction (&camera), game_state.delta_time));
}
if (game_flags.moving_backward)
{
camera.position = v3_sub
(camera.position, v3_muls
(Camera_get_direction (&camera), game_state.delta_time));
}
if (game_flags.moving_right)
{
camera.position = v3_add
(camera.position, v3_muls
(Camera_get_right (&camera), game_state.delta_time));
}
if (game_flags.moving_left)
{
camera.position = v3_sub
(camera.position, v3_muls
(Camera_get_right (&camera), game_state.delta_time));
}
/* Render stuff. */
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
mat4_t view = Camera_get_view (&camera);
mat4_t projection = Camera_get_projection (&camera, 640.0 / 480.0);
program_use (resources.programs[1]);
for (size_t i = 0; i < resources.textures_len; ++i)
{
glActiveTexture (GL_TEXTURE0 + i);
glBindTexture (GL_TEXTURE_2D, resources.textures[i]);
}
program_set_mat4 (resources.programs[1], "view", view);
program_set_mat4 (resources.programs[1], "projection", projection);
ChunkMesh_render (&test_chunkmesh);
SDL_GL_SwapWindow (window);
return SDL_APP_CONTINUE;
}
void
SDL_AppQuit (void *appstate, SDL_AppResult result)
{
(void) appstate; (void) result;
Resources_free ();
SDL_GL_DestroyContext (context);
SDL_DestroyWindow (window);
}