#include #include #include #include "app.hpp" #ifdef EMSCRIPTEN #include #include #endif #include "gl.hpp" static SDL_Window *s_window = nullptr; static SDL_GLContext s_context = nullptr; static bool s_quit = false; static std::unique_ptr s_app; static bool InitSDL() { std::cout << "Initializing SDL..." << std::endl; if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cerr << "SDL_Init Error: " << SDL_GetError() << std::endl; return false; } #ifdef EMSCRIPTEN SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); #else SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); #endif SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); std::cout << "Creating SDL window..." << std::endl; s_window = SDL_CreateWindow("PortalGame", 100, 100, 640, 480, SDL_WINDOW_SHOWN | SDL_WINDOW_MAXIMIZED | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); if (!s_window) { std::cerr << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl; SDL_Quit(); return false; } return true; } #ifndef EMSCRIPTEN static void APIENTRY GLDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) { //if (severity == 0x826b) // return; // ////std::cout << message << std::endl; fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), type, severity, message); } #endif // EMSCRIPTEN static bool InitGL() { std::cout << "Creating OpenGL context..." << std::endl; s_context = SDL_GL_CreateContext(s_window); if (!s_context) { std::cerr << "SDL_GL_CreateContext Error: " << SDL_GetError() << std::endl; return false; } // Make context current if (SDL_GL_MakeCurrent(s_window, s_context) != 0) { std::cerr << "SDL_GL_MakeCurrent Error: " << SDL_GetError() << std::endl; SDL_GL_DeleteContext(s_context); return false; } #ifndef EMSCRIPTEN // Initialize GLAD std::cout << "Initializing GLAD..." << std::endl; if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) { std::cerr << "Failed to initialize GLAD" << std::endl; SDL_GL_DeleteContext(s_context); return false; } glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback(GLDebugCallback, 0); SDL_GL_SetSwapInterval(1); #endif return true; } static void ShutdownGL() { if (s_context) { SDL_GL_DeleteContext(s_context); s_context = nullptr; } } static void ShutdownSDL() { if (s_window) { SDL_DestroyWindow(s_window); s_window = nullptr; } SDL_Quit(); } static void PollEvents() { SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: s_quit = true; return; case SDL_MOUSEMOTION: int xrel = event.motion.xrel; int yrel = event.motion.yrel; if (xrel != 0 || yrel != 0) { s_app->MouseMove(glm::vec2(static_cast(xrel), static_cast(yrel))); } break; } } } static void Frame() { Uint32 current_time = SDL_GetTicks(); s_app->SetTime(current_time / 1000.0f); // Set time in seconds PollEvents(); int width, height; SDL_GetWindowSize(s_window, &width, &height); s_app->SetViewportSize(width, height); game::PlayerInputFlags input = 0; const uint8_t* state = SDL_GetKeyboardState(nullptr); if (state[SDL_GetScancodeFromKey(SDLK_w)]) input |= game::PI_FORWARD; if (state[SDL_GetScancodeFromKey(SDLK_s)]) input |= game::PI_BACKWARD; if (state[SDL_GetScancodeFromKey(SDLK_a)]) input |= game::PI_LEFT; if (state[SDL_GetScancodeFromKey(SDLK_d)]) input |= game::PI_RIGHT; if (state[SDL_GetScancodeFromKey(SDLK_SPACE)]) input |= game::PI_JUMP; if (state[SDL_GetScancodeFromKey(SDLK_LCTRL)]) input |= game::PI_CROUCH; if (state[SDL_GetScancodeFromKey(SDLK_e)]) input |= game::PI_USE; s_app->SetInput(input); s_app->Frame(); SDL_GL_SwapWindow(s_window); } static void Main() { if (!InitSDL()) { throw std::runtime_error("Failed to initialize SDL"); } if (!InitGL()) { ShutdownSDL(); throw std::runtime_error("Failed to initialize OpenGL"); } SDL_SetRelativeMouseMode(SDL_TRUE); s_app = std::make_unique(); #ifdef EMSCRIPTEN emscripten_set_main_loop(Frame, 0, true); #else while (!s_quit) { Frame(); } s_app.reset(); ShutdownGL(); ShutdownSDL(); #endif } int main(int argc, char *argv[]) { try { Main(); } catch (const std::exception& e) { std::cerr << "[ERROR] " << e.what() << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }