430 lines
12 KiB
C++
430 lines
12 KiB
C++
#include "Game.hpp"
|
|
|
|
// FPSIndicator::FPSIndicator(Node* parent) : Node(parent) {}
|
|
|
|
// FPSIndicator::update()
|
|
// {
|
|
|
|
// }
|
|
|
|
Game::Game()
|
|
{
|
|
set_framerate(get_configuration()["display"]["fps"]);
|
|
delegate.subscribe(&Game::handle_quit_event, this, SDL_QUIT);
|
|
SDL_Log("GLEW %s", glewGetString(GLEW_VERSION));
|
|
putenv("SDL_VIDEO_X11_LEGACY_FULLSCREEN=0");
|
|
putenv("SDL_VIDEO_CENTERED=0");
|
|
SDL_version version;
|
|
SDL_GetVersion(&version);
|
|
SDL_Log("SDL %d.%d.%d", version.major, version.minor, version.patch);
|
|
fprintf(stderr, "stderr test message\n");
|
|
SDL_SetMainReady();
|
|
// SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
|
print_gl_attributes();
|
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
|
|
{
|
|
print_sdl_error("SDL could not initialize");
|
|
flag_to_end();
|
|
}
|
|
// SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
|
print_gl_attributes();
|
|
std::vector<int> window_size = get_configuration()["display"]["dimensions"];
|
|
window = SDL_CreateWindow("TARE control", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
|
window_size[0], window_size[1], SDL_WINDOW_OPENGL);
|
|
if (window == NULL)
|
|
{
|
|
print_sdl_error("Could not create window");
|
|
flag_to_end();
|
|
}
|
|
SDL_ShowCursor(0);
|
|
if (TTF_Init() < 0)
|
|
{
|
|
print_sdl_error("Could not initialize SDL ttf");
|
|
flag_to_end();
|
|
}
|
|
else
|
|
{
|
|
SDL_Log("initialized SDL ttf %d.%d.%d", SDL_TTF_MAJOR_VERSION,
|
|
SDL_TTF_MINOR_VERSION, SDL_TTF_PATCHLEVEL);
|
|
}
|
|
if (Mix_Init(MIX_INIT_FLAC) == 0)
|
|
{
|
|
print_sdl_error("Could not initialize SDL mixer");
|
|
flag_to_end();
|
|
}
|
|
else
|
|
{
|
|
SDL_Log("initialized SDL mixer %d.%d.%d", SDL_MIXER_MAJOR_VERSION,
|
|
SDL_MIXER_MINOR_VERSION, SDL_MIXER_PATCHLEVEL);
|
|
}
|
|
if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT,
|
|
MIX_DEFAULT_CHANNELS, 1024) < 0)
|
|
{
|
|
print_sdl_error("Could not set up audio");
|
|
}
|
|
SDL_Log("Using audio driver: %s", SDL_GetCurrentAudioDriver());
|
|
const int audio_device_count = SDL_GetNumAudioDevices(SDL_TRUE);
|
|
for (int ii = 0; ii < audio_device_count; ii++)
|
|
{
|
|
SDL_Log("Found audio capture device %i: %s", ii,
|
|
SDL_GetAudioDeviceName(ii, SDL_TRUE));
|
|
}
|
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
|
SDL_Log("big endian, using GL_RGBA and SDL_PIXELFORMAT_ABGR8888");
|
|
#else
|
|
SDL_Log("little endian, using GL_BGRA and SDL_PIXELFORMAT_ARGB8888");
|
|
#endif
|
|
last_frame_timestamp = SDL_GetTicks();
|
|
}
|
|
|
|
Game::~Game()
|
|
{
|
|
get_delegate().unsubscribe(this);
|
|
}
|
|
|
|
void Game::print_error(std::string message)
|
|
{
|
|
std::cerr << message << std::endl;
|
|
}
|
|
|
|
void Game::print_sdl_error(std::string message)
|
|
{
|
|
std::cerr << message << " " << SDL_GetError() << std::endl;
|
|
}
|
|
|
|
void Game::print_gl_attributes()
|
|
{
|
|
int major, minor;
|
|
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
|
|
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
|
|
SDL_Log("GL CONTEXT: %i, %i", major, minor);
|
|
int r, g, b, a, buf;
|
|
SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &r);
|
|
SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &g);
|
|
SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &b);
|
|
SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &a);
|
|
SDL_GL_GetAttribute(SDL_GL_BUFFER_SIZE, &buf);
|
|
SDL_Log("GL PIXELS: red: %i green: %i blue: %i alpha: %i", r, g, b, a);
|
|
}
|
|
|
|
void Game::load_sdl_context()
|
|
{
|
|
if (glcontext != NULL)
|
|
{
|
|
SDL_GL_DeleteContext(glcontext);
|
|
glcontext = NULL;
|
|
}
|
|
if ((renderer = SDL_CreateRenderer(window, -1, 0)) == NULL)
|
|
{
|
|
print_sdl_error("Could not create renderer");
|
|
flag_to_end();
|
|
}
|
|
else
|
|
{
|
|
SDL_RendererInfo info;
|
|
SDL_GetRendererInfo(renderer, &info);
|
|
SDL_Log("renderer name: %s, flags: %i, texture formats: %i, "
|
|
"max texture w: %i, max texture h: %i", info.name, info.flags,
|
|
info.num_texture_formats, info.max_texture_width,
|
|
info.max_texture_height);
|
|
}
|
|
is_gl_context = false;
|
|
}
|
|
|
|
void Game::load_gl_context()
|
|
{
|
|
if (renderer != NULL)
|
|
{
|
|
SDL_DestroyRenderer(renderer);
|
|
renderer = NULL;
|
|
}
|
|
// SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
|
print_gl_attributes();
|
|
if ((glcontext = SDL_GL_CreateContext(window)) == NULL)
|
|
{
|
|
print_sdl_error("Could not get GL context");
|
|
flag_to_end();
|
|
}
|
|
GLenum error = glewInit();
|
|
if (error != GLEW_OK)
|
|
{
|
|
std::ostringstream message;
|
|
message << "GLEW could not initialize " << glewGetErrorString(error);
|
|
print_error(message.str());
|
|
}
|
|
SDL_Log("OpenGL %s, renderer %s, shading language %s",
|
|
glGetString(GL_VERSION), glGetString(GL_RENDERER),
|
|
glGetString(GL_SHADING_LANGUAGE_VERSION));
|
|
is_gl_context = true;
|
|
}
|
|
|
|
GLuint Game::create_gl_texture()
|
|
{
|
|
GLuint id;
|
|
glCreateTextures(GL_TEXTURE_2D, 1, &id);
|
|
glBindTexture(GL_TEXTURE_2D, id);
|
|
return id;
|
|
}
|
|
|
|
bool Game::log_gl_errors()
|
|
{
|
|
GLenum error;
|
|
bool error_logged = false;
|
|
while ((error = glGetError()) != GL_NO_ERROR)
|
|
{
|
|
error_logged = true;
|
|
if (error == GL_INVALID_ENUM)
|
|
{
|
|
SDL_LogError(
|
|
SDL_LOG_CATEGORY_APPLICATION,
|
|
"GL_INVALID_ENUM, an unacceptable value is specified for an "
|
|
"enumerated argument");
|
|
}
|
|
else if (error == GL_INVALID_VALUE)
|
|
{
|
|
SDL_LogError(
|
|
SDL_LOG_CATEGORY_APPLICATION,
|
|
"GL_INVALID_VALUE, a numeric argument is out of range");
|
|
}
|
|
else if (error == GL_INVALID_OPERATION)
|
|
{
|
|
SDL_LogError(
|
|
SDL_LOG_CATEGORY_APPLICATION,
|
|
"GL_INVALID_OPERATION, the specified operation is not allowed "
|
|
"in the current state");
|
|
}
|
|
else if (error == GL_INVALID_FRAMEBUFFER_OPERATION)
|
|
{
|
|
SDL_LogError(
|
|
SDL_LOG_CATEGORY_APPLICATION,
|
|
"GL_INVALID_FRAMEBUFFER_OPERATION, the framebuffer object is "
|
|
"not complete");
|
|
}
|
|
else if (error == GL_OUT_OF_MEMORY)
|
|
{
|
|
SDL_LogError(
|
|
SDL_LOG_CATEGORY_APPLICATION,
|
|
"GL_OUT_OF_MEMORY, there is not enough memory left to execute "
|
|
"the command");
|
|
}
|
|
else if (error == GL_STACK_UNDERFLOW)
|
|
{
|
|
SDL_LogError(
|
|
SDL_LOG_CATEGORY_APPLICATION,
|
|
"GL_STACK_UNDERFLOW, an attempt has been made to perform an "
|
|
"operation that would cause an internal stack to underflow.");
|
|
}
|
|
else if (error == GL_STACK_OVERFLOW)
|
|
{
|
|
SDL_LogError(
|
|
SDL_LOG_CATEGORY_APPLICATION,
|
|
"GL_STACK_OVERFLOW, an attempt has been made to perform an "
|
|
"operation that would cause an internal stack to overflow.");
|
|
}
|
|
}
|
|
return error_logged;
|
|
}
|
|
|
|
void Game::log_surface_format(SDL_Surface* surface, std::string preface)
|
|
{
|
|
SDL_PixelFormat* format = surface->format;
|
|
std::string pixel_format;
|
|
if (format->format == SDL_PIXELFORMAT_UNKNOWN)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_UNKNOWN";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_INDEX1LSB)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_INDEX1LSB";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_INDEX1MSB)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_INDEX1MSB";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_INDEX4LSB)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_INDEX4LSB";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_INDEX4MSB)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_INDEX4MSB";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_INDEX8)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_INDEX8";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_RGB332)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_RGB332";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_RGB444)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_RGB444";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_RGB555)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_RGB555";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_BGR555)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_BGR555";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_ARGB4444)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_ARGB4444";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_RGBA4444)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_RGBA4444";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_ABGR4444)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_ABGR4444";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_BGRA4444)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_BGRA4444";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_ARGB1555)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_ARGB1555";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_RGBA5551)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_RGBA5551";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_ABGR1555)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_ABGR1555";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_BGRA5551)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_BGRA5551";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_RGB565)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_RGB565";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_BGR565)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_BGR565";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_RGB24)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_RGB24";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_BGR24)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_BGR24";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_RGB888)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_RGB888";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_RGBX8888)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_RGBX8888";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_BGR888)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_BGR888";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_BGRX8888)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_BGRX8888";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_ARGB8888)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_ARGB8888";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_RGBA8888)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_RGBA8888";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_ABGR8888)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_ABGR8888";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_BGRA8888)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_BGRA8888";
|
|
}
|
|
else if (format->format == SDL_PIXELFORMAT_ARGB2101010)
|
|
{
|
|
pixel_format = "SDL_PIXELFORMAT_ARGB2101010";
|
|
}
|
|
SDL_Log("%s bpp: %i mask: %i %i %i %i format: %s", preface.c_str(),
|
|
format->BytesPerPixel, format->Rmask, format->Gmask, format->Bmask,
|
|
format->Amask, pixel_format.c_str());
|
|
}
|
|
|
|
void Game::run()
|
|
{
|
|
while (not done)
|
|
{
|
|
ticks = SDL_GetTicks();
|
|
if (ticks - last_frame_timestamp + frame_time_overflow >= frame_length)
|
|
{
|
|
last_frame_length = ticks - last_frame_timestamp;
|
|
frame_time_overflow = last_frame_length + frame_time_overflow - frame_length;
|
|
last_frame_timestamp = ticks;
|
|
recorder.update();
|
|
delegate.dispatch();
|
|
update();
|
|
}
|
|
SDL_Delay(8);
|
|
}
|
|
}
|
|
|
|
void Game::flag_to_end()
|
|
{
|
|
done = true;
|
|
}
|
|
|
|
void Game::set_framerate(int fps)
|
|
{
|
|
if (fps < 1)
|
|
{
|
|
fps = 1;
|
|
}
|
|
framerate = fps;
|
|
frame_length = 1000.0 / framerate;
|
|
}
|
|
|
|
void Game::handle_quit_event(SDL_Event &event)
|
|
{
|
|
if (event.type == SDL_QUIT)
|
|
{
|
|
flag_to_end();
|
|
}
|
|
}
|
|
|
|
void Game::quit()
|
|
{
|
|
if (glcontext != NULL)
|
|
{
|
|
SDL_GL_DeleteContext(glcontext);
|
|
}
|
|
if (renderer != NULL)
|
|
{
|
|
SDL_DestroyRenderer(renderer);
|
|
}
|
|
if (window != NULL)
|
|
{
|
|
SDL_DestroyWindow(window);
|
|
}
|
|
if (TTF_WasInit())
|
|
{
|
|
TTF_Quit();
|
|
}
|
|
Mix_CloseAudio();
|
|
Mix_Quit();
|
|
SDL_Quit();
|
|
}
|