/* * Create text */ Text *S2D_CreateText(const char *font, const char *msg, int size) { #if GLES S2D_Log("S2D_DrawText not yet implemented!", S2D_WARN); #endif Text *txt; txt = (Text *)malloc(sizeof(Text)); if(!txt) { S2D_Error("S2D_CreateText", "Out of memory!"); return NULL; } // `msg` cannot be an empty string; if so, return if (strlen(msg) == 0) { S2D_Error("S2D_CreateText", "Text message cannot be empty!"); return NULL; } else { txt->msg = msg; } txt->x = 0; txt->y = 0; txt->color.r = 1.0; txt->color.g = 1.0; txt->color.b = 1.0; txt->color.a = 1.0; txt->texture_id = 0; txt->font = TTF_OpenFont(font, size); if (!txt->font) { S2D_Error("TTF_OpenFont", TTF_GetError()); free(txt); return NULL; } // Save the width and height of the text TTF_SizeText(txt->font, txt->msg, &txt->w, &txt->h); SDL_Surface *surface; SDL_Color color = { 255, 255, 255 }; surface = TTF_RenderText_Blended(txt->font, txt->msg, color); S2D_GL_SetUpTexture(&txt->texture_id, GL_RGBA, txt->w, txt->h, surface->pixels, GL_NEAREST); // Free the surface data, no longer needed SDL_FreeSurface(surface); return txt; }
/* * Create an image */ Image *S2D_CreateImage(const char *path) { if(!path) return NULL; // TODO: Implement images in GLES #if GLES S2D_Log("S2D_DrawImage not yet implemented!", S2D_INFO); #endif Image *img; SDL_Surface *surface; // Load image from file as SDL_Surface surface = IMG_Load(path); if (!surface) { S2D_Error("IMG_Load", IMG_GetError()); return NULL; } img = (Image *)malloc(sizeof(Image)); if(!img) { S2D_Error("IMG_Load", "Out of memory!"); SDL_FreeSurface(surface); return NULL; } // Initialize values img->x = 0; img->y = 0; img->w = surface->w; img->h = surface->h; img->texture_id = 0; // Detect image mode // TODO: BMP is in BGR...? int format = GL_RGB; if(surface->format->BytesPerPixel == 4) { format = GL_RGBA; } S2D_GL_SetUpTexture(&img->texture_id, format, img->w, img->h, surface->pixels, GL_NEAREST); // Free the surface data, no longer needed SDL_FreeSurface(surface); return img; }
/* * Play the music */ void S2D_PlayMusic(Music *music, int times) { if(!music) return; // times: 0 == once, -1 == forever if (Mix_PlayMusic(music->data, times) == -1) { // No music for you S2D_Error("S2D_PlayMusic", Mix_GetError()); } }
/* * Create the music */ Music *S2D_CreateMusic(const char *path) { Music *music; music = (Music *)malloc(sizeof(Music)); if(!music) { S2D_Error("S2D_CreateMusic", "Out of memory!"); return NULL; } music->data = Mix_LoadMUS(path); if (!music->data) { S2D_Error("Mix_LoadMUS", Mix_GetError()); free(music); return NULL; } return music; }
/* * Create a sound, given an audio file path */ S2D_Sound *S2D_CreateSound(const char *path) { S2D_Init(); // Check if sound file exists if (!S2D_FileExists(path)) { S2D_Error("S2D_CreateSound", "Sound file not found"); return NULL; } // Allocate the sound structure S2D_Sound *sound = (S2D_Sound *) malloc(sizeof(S2D_Sound)); // Load the sound data from file sound->data = Mix_LoadWAV(path); if (!sound->data) { S2D_Error("Mix_LoadWAV", Mix_GetError()); free(sound); return NULL; } return sound; }
/* * Create a sound */ Sound *S2D_CreateSound(const char *path) { Sound *sound; sound = (Sound *)malloc(sizeof(Sound)); sound->data = Mix_LoadWAV(path); if (!sound->data) { S2D_Error("Mix_LoadWAV", Mix_GetError()); free(sound); } return sound; }
/* * Add controller mappings from the specified file */ void S2D_AddControllerMappingsFromFile(const char *path) { if (!S2D_FileExists(path)) { S2D_Log(S2D_WARN, "Controller mappings file not found: %s", path); return; } int mappings_added = SDL_GameControllerAddMappingsFromFile(path); if (mappings_added == -1) { S2D_Error("SDL_GameControllerAddMappingsFromFile", SDL_GetError()); } else { S2D_Log(S2D_INFO, "Added %i controller mapping(s)", mappings_added); } }
/* * Add controller mapping from string */ void S2D_AddControllerMapping(const char *map) { int result = SDL_GameControllerAddMapping(map); char guid[33]; strncpy(guid, map, 32); switch (result) { case 1: S2D_Log(S2D_INFO, "Mapping added for GUID: %s", guid); break; case 0: S2D_Log(S2D_INFO, "Mapping updated for GUID: %s", guid); break; case -1: S2D_Error("SDL_GameControllerAddMapping", SDL_GetError()); break; } }
void on_controller(S2D_Event e) { puts("=== Controller Event ==="); printf("Controller #%i\n", e.which); // Axes if (e.type == S2D_AXIS) { printf("Axis movement: #%i ", e.axis); switch (e.axis) { case S2D_AXIS_INVALID: S2D_Error("Controller", "Invalid axis!"); break; case S2D_AXIS_LEFTX: puts("(LEFTX)"); axis_LEFTX = to_d(e.value) * scale; break; case S2D_AXIS_LEFTY: puts("(LEFTY)"); axis_LEFTY = to_d(e.value) * scale; break; case S2D_AXIS_RIGHTX: puts("(RIGHTX)"); axis_RIGHTX = to_d(e.value) * scale; break; case S2D_AXIS_RIGHTY: puts("(RIGHTY)"); axis_RIGHTY = to_d(e.value) * scale; break; case S2D_AXIS_TRIGGERLEFT: puts("(TRIGGERLEFT)"); axis_TRIGGERLEFT = to_d(e.value) * scale; break; case S2D_AXIS_TRIGGERRIGHT: puts("(TRIGGERRIGHT)"); axis_TRIGGERRIGHT = to_d(e.value) * scale; break; case S2D_AXIS_MAX: puts("(MAX)"); break; } printf("Value: %i\n", e.value); // Buttons } else { switch (e.type) { case S2D_BUTTON_DOWN: printf("Button down: #%i ", e.button); break; case S2D_BUTTON_UP: printf("Button up: #%i ", e.button); break; } bool pressed = e.type == S2D_BUTTON_DOWN ? true : false; switch (e.button) { case S2D_BUTTON_INVALID: S2D_Error("Controller", "Invalid button!"); case S2D_BUTTON_A: puts("(A)"); btn_A = pressed; break; case S2D_BUTTON_B: puts("(B)"); btn_B = pressed; break; case S2D_BUTTON_X: puts("(X)"); btn_X = pressed; break; case S2D_BUTTON_Y: puts("(Y)"); btn_Y = pressed; break; case S2D_BUTTON_BACK: puts("(BACK)"); btn_BACK = pressed; break; case S2D_BUTTON_GUIDE: puts("(GUIDE)"); btn_GUIDE = pressed; break; case S2D_BUTTON_START: puts("(START)"); btn_START = pressed; break; case S2D_BUTTON_LEFTSTICK: puts("(LEFTSTICK)"); btn_LEFTSTICK = pressed; break; case S2D_BUTTON_RIGHTSTICK: puts("(RIGHTSTICK)"); btn_RIGHTSTICK = pressed; break; case S2D_BUTTON_LEFTSHOULDER: puts("(LEFTSHOULDER)"); btn_LEFTSHOULDER = pressed; break; case S2D_BUTTON_RIGHTSHOULDER: puts("(RIGHTSHOULDER)"); btn_RIGHTSHOULDER = pressed; break; case S2D_BUTTON_DPAD_UP: puts("(DPAD_UP)"); btn_DPAD_UP = pressed; break; case S2D_BUTTON_DPAD_DOWN: puts("(DPAD_DOWN)"); btn_DPAD_DOWN = pressed; break; case S2D_BUTTON_DPAD_LEFT: puts("(DPAD_LEFT)"); btn_DPAD_LEFT = pressed; break; case S2D_BUTTON_DPAD_RIGHT: puts("(DPAD_RIGHT)"); btn_DPAD_RIGHT = pressed; break; case S2D_BUTTON_MAX: puts("(MAX)"); btn_MAX = pressed; break; } } }
/* * Create a window */ Window* S2D_CreateWindow(const char *title, int width, int height, Update update, Render render, int flags) { // Allocate window and set default values Window *window = (Window*)malloc(sizeof(Window)); window->title = title; window->width = width; window->height = height; window->fps_cap = 60; window->vsync = true; window->update = update; window->render = render; window->on_key = NULL; window->on_key_down = NULL; window->on_mouse = NULL; window->on_controller = NULL; window->background.r = 0.0; window->background.g = 0.0; window->background.b = 0.0; window->background.a = 1.0; // SDL Initialization //////////////////////////////////////////////////////// // Initialize SDL if (SDL_Init(SDL_INIT_EVERYTHING) != 0) S2D_Error("SDL_Init", SDL_GetError()); // Initialize SDL_ttf if (TTF_Init() != 0) { S2D_Error("TTF_Init", TTF_GetError()); free(window); return NULL; } // Initialize SDL_mixer int mix_flags = MIX_INIT_FLAC|MIX_INIT_OGG|MIX_INIT_MP3; int mix_initted = Mix_Init(mix_flags); if ((mix_initted&mix_flags) != mix_flags) { S2D_Error("Mix_Init", Mix_GetError()); } int audio_rate = 44100; Uint16 audio_format = AUDIO_S16SYS; int audio_channels = 2; int audio_buffers = 4096; if (Mix_OpenAudio(audio_rate, MIX_DEFAULT_FORMAT, audio_channels, audio_buffers) != 0) { S2D_Error("Mix_OpenAudio", Mix_GetError()); free(window); return NULL; } // Create SDL window window->sdl = SDL_CreateWindow( window->title, // title SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, // window position window->width, window->height, // window size SDL_WINDOW_OPENGL | flags // flags ); if (!window->sdl) S2D_Error("SDL_CreateWindow", SDL_GetError()); // Window created by SDL might not actually be the requested size. // If not, retrieve and set the actual window size. window->s_width = window->width; window->s_height = window->height; SDL_GetWindowSize(window->sdl, &window->width, &window->height); if ((window->width != window->s_width) || (window->height != window->s_height)) { sprintf(S2D_msg, "Resolution %dx%d unsupported by driver, scaling to %dx%d", window->s_width, window->s_height, window->width, window->height); S2D_Log(S2D_msg, S2D_WARN); } // Init OpenGL / GLES //////////////////////////////////////////////////////// // Specify the OpenGL Context #if !GLES if (FORCE_GL2) { // Use legacy OpenGL 2.1 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); } else { // Request an OpenGL 3.3 forward-compatible core profile 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, 3); } #endif // Create and store the OpenGL context if (FORCE_GL2) { window->glcontext = NULL; } else { // Ask SDL to create an OpenGL context window->glcontext = SDL_GL_CreateContext(window->sdl); } // Check if a valid OpenGL context was created if (window->glcontext) { // Valid context found #if GLES // Initialize OpenGL ES 2.0 gles_init(window->width, window->height, window->s_width, window->s_height); #else // Initialize OpenGL 3.3+ gl3_init(window->width, window->height); #endif } else { // Context could not be created #if GLES S2D_Error("GLES / SDL_GL_CreateContext", SDL_GetError()); #else // Try to fallback using an OpenGL 2.1 context SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); // Try creating the context again window->glcontext = SDL_GL_CreateContext(window->sdl); // Check if this context was created if (window->glcontext) { // Valid context found S2D_GL2 = true; gl2_init(window->width, window->height); } else { // Could not create any OpenGL contexts, hard failure S2D_Error("GL2 / SDL_GL_CreateContext", SDL_GetError()); S2D_Log("An OpenGL context could not be created", S2D_ERROR); free(window); return NULL; } #endif } // Store the context and print it if diagnostics is enabled S2D_GL_StoreContextInfo(window); if (diagnostics) S2D_GL_PrintContextInfo(window); return window; }
/* * Initialize OpenGL */ int S2D_GL_Init(S2D_Window *window) { // Specify OpenGL contexts and set attributes #if GLES SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); #else // Use legacy OpenGL 2.1 if (FORCE_GL2) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); // Request an OpenGL 3.3 forward-compatible core profile } else { 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, 3); } #endif // Create and store the OpenGL context if (FORCE_GL2) { window->glcontext = NULL; } else { // Ask SDL to create an OpenGL context window->glcontext = SDL_GL_CreateContext(window->sdl); } // Check if a valid OpenGL context was created if (window->glcontext) { // Valid context found // Initialize OpenGL ES 2.0 #if GLES S2D_GLES_Init(); S2D_GL_SetViewport(window); // Initialize OpenGL 3.3+ #else // Initialize GLEW on Windows #if WINDOWS GLenum err = glewInit(); if (GLEW_OK != err) S2D_Error("GLEW", glewGetErrorString(err)); #endif S2D_GL3_Init(); S2D_GL_SetViewport(window); #endif // Context could not be created } else { #if GLES S2D_Error("GLES / SDL_GL_CreateContext", SDL_GetError()); #else // Try to fallback using an OpenGL 2.1 context SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); // Try creating the context again window->glcontext = SDL_GL_CreateContext(window->sdl); // Check if this context was created if (window->glcontext) { // Valid context found S2D_GL2 = true; S2D_GL2_Init(); S2D_GL_SetViewport(window); // Could not create any OpenGL contexts, hard failure } else { S2D_Error("GL2 / SDL_GL_CreateContext", SDL_GetError()); S2D_Log(S2D_ERROR, "An OpenGL context could not be created"); return -1; } #endif } // Store the context and print it if diagnostics is enabled S2D_GL_StoreContextInfo(window); if (S2D_diagnostics) S2D_GL_PrintContextInfo(window); return 0; }