diff --git a/CHANGELOG b/CHANGELOG index 66fb4bae7..6c8b2657c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,11 +1,26 @@ changelog --------- -Current Release: raylib 1.0.2 (December 2013) +Current Release: raylib 1.0.3 (December 2013) NOTE: Only versions marked as 'Release' are available on release folder, updates are only available as source. NOTE: Current Release includes all previous updates. +----------------------------------------------- +Release: raylib 1.0.3 (19 December 2013) +----------------------------------------------- +[fonts] Added 8 rBMF free fonts to be used on projects! +[text] LoadSpriteFont() - Now supports rBMF file loading (raylib Bitmap Font) +[examples] ex05a_sprite_fonts completed +[examples] ex05b_rbmf_fonts completed +[core] InitWindowEx() - InitWindow with extended parameters, resizing option and custom cursor! +[core] GetRandomValue() - Added, returns a random value within a range (int) +[core] SetExitKey() - Added, sets a key to exit program (default is ESC) +[core] Custom cursor not drawn when mouse out of screen +[shapes] CheckCollisionPointRec() - Added, check collision between point and rectangle +[shapes] CheckCollisionPointCircle() - Added, check collision between point and circle +[shapes] CheckCollisionPointTriangle() - Added, check collision between point and triangle +[shapes] DrawPoly() - Added, draw regular polygons of n sides, rotation can be defined! ----------------------------------------------- Release: raylib 1.0.2 (1 December 2013) diff --git a/LICENSE.md b/LICENSE.md index 2b608cecb..b83684ee8 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -27,4 +27,13 @@ applications, and to alter it and redistribute it freely, subject to the followi fonts ------ -...soon... \ No newline at end of file +All rBMF fonts provided with raylib are free to use (freeware) and have been designed by the following people: + +Alpha Beta - Brian Kent (AEnigma) +Setback - Brian Kent (AEnigma) +Jupiter Crash - Brian Kent (AEnigma) +Alagard - Hewett Tsoi +Romulus - Hewett Tsoi +Mecha - Captain Falcon +PixelPlay - Aleksander Shevchuk +PixAntiqua - Gerhard Großmann diff --git a/examples/ex05a_sprite_fonts.c b/examples/ex05a_sprite_fonts.c index 03d460404..f4a1c1cb8 100644 --- a/examples/ex05a_sprite_fonts.c +++ b/examples/ex05a_sprite_fonts.c @@ -17,11 +17,29 @@ int main() //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; - + + const char msg1[50] = "THIS IS A custom SPRITE FONT..."; + const char msg2[50] = "...and this is ANOTHER CUSTOM font..."; + const char msg3[50] = "...and a THIRD one! GREAT! :D"; + InitWindow(screenWidth, screenHeight, "raylib example 05a - sprite fonts"); - // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) - SpriteFont font = LoadSpriteFont("resources/custom_font.png"); // SpriteFont loading + // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) + SpriteFont font1 = LoadSpriteFont("resources/fonts/custom_mecha.png"); // SpriteFont loading + SpriteFont font2 = LoadSpriteFont("resources/fonts/custom_alagard.png"); // SpriteFont loading + SpriteFont font3 = LoadSpriteFont("resources/fonts/custom_jupiter_crash.png"); // SpriteFont loading + + Vector2 fontPosition1, fontPosition2, fontPosition3; + + fontPosition1.x = screenWidth/2 - MeasureTextEx(font1, msg1, GetFontBaseSize(font1), -3).x/2; + fontPosition1.y = screenHeight/2 - GetFontBaseSize(font1)/2 - 80; + + fontPosition2.x = screenWidth/2 - MeasureTextEx(font2, msg2, GetFontBaseSize(font2), -2).x/2; + fontPosition2.y = screenHeight/2 - GetFontBaseSize(font2)/2 - 10; + + fontPosition3.x = screenWidth/2 - MeasureTextEx(font3, msg3, GetFontBaseSize(font3), 2).x/2; + fontPosition3.y = screenHeight/2 - GetFontBaseSize(font3)/2 + 50; + //-------------------------------------------------------------------------------------- // Main game loop @@ -29,7 +47,7 @@ int main() { // Update //---------------------------------------------------------------------------------- - // TODO: Update your variables here + // TODO: Update variables here... //---------------------------------------------------------------------------------- // Draw @@ -38,18 +56,19 @@ int main() ClearBackground(RAYWHITE); - // TODO: Comming soon... - // TIP: Use DrawTextEx() function -/* -void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, int fontSize, int spacing, Color tint); -*/ + DrawTextEx(font1, msg1, fontPosition1, GetFontBaseSize(font1), -3, WHITE); + DrawTextEx(font2, msg2, fontPosition2, GetFontBaseSize(font2), -2, WHITE); + DrawTextEx(font3, msg3, fontPosition3, GetFontBaseSize(font3), 2, WHITE); + EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- - UnloadSpriteFont(font); // SpriteFont unloading + UnloadSpriteFont(font1); // SpriteFont unloading + UnloadSpriteFont(font2); // SpriteFont unloading + UnloadSpriteFont(font3); // SpriteFont unloading CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/ex05a_sprite_fonts.exe b/examples/ex05a_sprite_fonts.exe new file mode 100644 index 000000000..9f5994eb7 Binary files /dev/null and b/examples/ex05a_sprite_fonts.exe differ diff --git a/examples/ex05a_sprite_fonts.png b/examples/ex05a_sprite_fonts.png index f18ae0442..1bd4aa03d 100644 Binary files a/examples/ex05a_sprite_fonts.png and b/examples/ex05a_sprite_fonts.png differ diff --git a/examples/ex05b_rbmf_fonts.c b/examples/ex05b_rbmf_fonts.c index eeb5f61b7..bc7fc8521 100644 --- a/examples/ex05b_rbmf_fonts.c +++ b/examples/ex05b_rbmf_fonts.c @@ -9,19 +9,26 @@ * ********************************************************************************************/ -#include "raylib.h" +#include "../raylib.h" int main() { // Initialization //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; + int screenWidth = 560; + int screenHeight = 800; - InitWindow(screenWidth, screenHeight, "raylib example 04b - texture rectangle"); + InitWindow(screenWidth, screenHeight, "raylib example 05b - rBMF fonts"); // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) - SpriteFont font = LoadSpriteFont("resources/custom_font.rbmf"); // SpriteFont loading + SpriteFont font1 = LoadSpriteFont("resources/fonts/alagard.rbmf"); // SpriteFont loading + SpriteFont font2 = LoadSpriteFont("resources/fonts/pixelplay.rbmf"); // SpriteFont loading + SpriteFont font3 = LoadSpriteFont("resources/fonts/mecha.rbmf"); // SpriteFont loading + SpriteFont font4 = LoadSpriteFont("resources/fonts/setback.rbmf"); // SpriteFont loading + SpriteFont font5 = LoadSpriteFont("resources/fonts/romulus.rbmf"); // SpriteFont loading + SpriteFont font6 = LoadSpriteFont("resources/fonts/pixantiqua.rbmf"); // SpriteFont loading + SpriteFont font7 = LoadSpriteFont("resources/fonts/alpha_beta.rbmf"); // SpriteFont loading + SpriteFont font8 = LoadSpriteFont("resources/fonts/jupiter_crash.rbmf"); // SpriteFont loading //-------------------------------------------------------------------------------------- // Main game loop @@ -38,20 +45,31 @@ int main() ClearBackground(RAYWHITE); - // TODO: Comming soon... - // TIP: Use DrawTextEx() function -/* -void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, int fontSize, int spacing, Color tint); -*/ + DrawTextEx(font1, "TESTING ALAGARD FONT", (Vector2){ 100, 100 }, GetFontBaseSize(font1)*2, 2, MAROON); + DrawTextEx(font2, "TESTING PIXELPLAY FONT", (Vector2){ 100, 180 }, GetFontBaseSize(font2)*2, 4, ORANGE); + DrawTextEx(font3, "TESTING MECHA FONT", (Vector2){ 100, 260 }, GetFontBaseSize(font3)*2, 8, DARKGREEN); + DrawTextEx(font4, "TESTING SETBACK FONT", (Vector2){ 100, 350 }, GetFontBaseSize(font4)*2, 4, DARKBLUE); + DrawTextEx(font5, "TESTING ROMULUS FONT", (Vector2){ 100, 430 }, GetFontBaseSize(font5)*2, 3, DARKPURPLE); + DrawTextEx(font6, "TESTING PIXANTIQUA FONT", (Vector2){ 100, 510 }, GetFontBaseSize(font6)*2, 4, LIME); + DrawTextEx(font7, "TESTING ALPHA_BETA FONT", (Vector2){ 100, 590 }, GetFontBaseSize(font7)*2, 4, GOLD); + DrawTextEx(font8, "TESTING JUPITER_CRASH FONT", (Vector2){ 100, 660 }, GetFontBaseSize(font8)*2, 1, RED); + EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- - UnloadSpriteFont(font); // SpriteFont unloading + UnloadSpriteFont(font1); // SpriteFont unloading + UnloadSpriteFont(font2); // SpriteFont unloading + UnloadSpriteFont(font3); // SpriteFont unloading + UnloadSpriteFont(font4); // SpriteFont unloading + UnloadSpriteFont(font5); // SpriteFont unloading + UnloadSpriteFont(font6); // SpriteFont unloading + UnloadSpriteFont(font7); // SpriteFont unloading + UnloadSpriteFont(font8); // SpriteFont unloading - CloseWindow(); // Close window and OpenGL context + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; diff --git a/examples/ex05b_rbmf_fonts.exe b/examples/ex05b_rbmf_fonts.exe new file mode 100644 index 000000000..c3b21f295 Binary files /dev/null and b/examples/ex05b_rbmf_fonts.exe differ diff --git a/examples/ex05b_rbmf_fonts.png b/examples/ex05b_rbmf_fonts.png index f18ae0442..58f6d83f6 100644 Binary files a/examples/ex05b_rbmf_fonts.png and b/examples/ex05b_rbmf_fonts.png differ diff --git a/examples/ex08_audio.c b/examples/ex08_audio.c index 5d1d365de..5849b84ea 100644 --- a/examples/ex08_audio.c +++ b/examples/ex08_audio.c @@ -24,7 +24,7 @@ int main() InitAudioDevice(); // Initialize audio device - Sound fx = LoadSound("resources/weird.wav"); // Load WAV audio file + Sound fx = LoadSound("resources/audio/weird.wav"); // Load WAV audio file //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/resources/coin.wav b/examples/resources/audio/coin.wav similarity index 100% rename from examples/resources/coin.wav rename to examples/resources/audio/coin.wav diff --git a/examples/resources/spring.wav b/examples/resources/audio/spring.wav similarity index 100% rename from examples/resources/spring.wav rename to examples/resources/audio/spring.wav diff --git a/examples/resources/weird.wav b/examples/resources/audio/weird.wav similarity index 100% rename from examples/resources/weird.wav rename to examples/resources/audio/weird.wav diff --git a/examples/resources/fonts/alagard.rbmf b/examples/resources/fonts/alagard.rbmf new file mode 100644 index 000000000..8c9b68d3c Binary files /dev/null and b/examples/resources/fonts/alagard.rbmf differ diff --git a/examples/resources/fonts/alpha_beta.rbmf b/examples/resources/fonts/alpha_beta.rbmf new file mode 100644 index 000000000..bdb2e7521 Binary files /dev/null and b/examples/resources/fonts/alpha_beta.rbmf differ diff --git a/examples/resources/fonts/custom_alagard.png b/examples/resources/fonts/custom_alagard.png new file mode 100644 index 000000000..c3eb63b71 Binary files /dev/null and b/examples/resources/fonts/custom_alagard.png differ diff --git a/examples/resources/fonts/custom_jupiter_crash.png b/examples/resources/fonts/custom_jupiter_crash.png new file mode 100644 index 000000000..451b591f1 Binary files /dev/null and b/examples/resources/fonts/custom_jupiter_crash.png differ diff --git a/examples/resources/fonts/custom_mecha.png b/examples/resources/fonts/custom_mecha.png new file mode 100644 index 000000000..59caab2cc Binary files /dev/null and b/examples/resources/fonts/custom_mecha.png differ diff --git a/examples/resources/fonts/jupiter_crash.rbmf b/examples/resources/fonts/jupiter_crash.rbmf new file mode 100644 index 000000000..d797e0d65 Binary files /dev/null and b/examples/resources/fonts/jupiter_crash.rbmf differ diff --git a/examples/resources/fonts/mecha.rbmf b/examples/resources/fonts/mecha.rbmf new file mode 100644 index 000000000..0266a0654 Binary files /dev/null and b/examples/resources/fonts/mecha.rbmf differ diff --git a/examples/resources/fonts/pixantiqua.rbmf b/examples/resources/fonts/pixantiqua.rbmf new file mode 100644 index 000000000..04ef0e25e Binary files /dev/null and b/examples/resources/fonts/pixantiqua.rbmf differ diff --git a/examples/resources/fonts/pixelplay.rbmf b/examples/resources/fonts/pixelplay.rbmf new file mode 100644 index 000000000..31d14038d Binary files /dev/null and b/examples/resources/fonts/pixelplay.rbmf differ diff --git a/examples/resources/fonts/romulus.rbmf b/examples/resources/fonts/romulus.rbmf new file mode 100644 index 000000000..be9da01a3 Binary files /dev/null and b/examples/resources/fonts/romulus.rbmf differ diff --git a/examples/resources/fonts/setback.rbmf b/examples/resources/fonts/setback.rbmf new file mode 100644 index 000000000..09572215c Binary files /dev/null and b/examples/resources/fonts/setback.rbmf differ diff --git a/examples/resources/mouse.png b/examples/resources/mouse.png new file mode 100644 index 000000000..543f32b34 Binary files /dev/null and b/examples/resources/mouse.png differ diff --git a/fonts/alagard.rbmf b/fonts/alagard.rbmf new file mode 100644 index 000000000..8c9b68d3c Binary files /dev/null and b/fonts/alagard.rbmf differ diff --git a/fonts/alpha_beta.rbmf b/fonts/alpha_beta.rbmf new file mode 100644 index 000000000..bdb2e7521 Binary files /dev/null and b/fonts/alpha_beta.rbmf differ diff --git a/fonts/coming_soon b/fonts/coming_soon deleted file mode 100644 index e69de29bb..000000000 diff --git a/fonts/jupiter_crash.rbmf b/fonts/jupiter_crash.rbmf new file mode 100644 index 000000000..d797e0d65 Binary files /dev/null and b/fonts/jupiter_crash.rbmf differ diff --git a/fonts/mecha.rbmf b/fonts/mecha.rbmf new file mode 100644 index 000000000..0266a0654 Binary files /dev/null and b/fonts/mecha.rbmf differ diff --git a/fonts/pixantiqua.rbmf b/fonts/pixantiqua.rbmf new file mode 100644 index 000000000..04ef0e25e Binary files /dev/null and b/fonts/pixantiqua.rbmf differ diff --git a/fonts/pixelplay.rbmf b/fonts/pixelplay.rbmf new file mode 100644 index 000000000..31d14038d Binary files /dev/null and b/fonts/pixelplay.rbmf differ diff --git a/fonts/romulus.rbmf b/fonts/romulus.rbmf new file mode 100644 index 000000000..be9da01a3 Binary files /dev/null and b/fonts/romulus.rbmf differ diff --git a/fonts/setback.rbmf b/fonts/setback.rbmf new file mode 100644 index 000000000..09572215c Binary files /dev/null and b/fonts/setback.rbmf differ diff --git a/release/win32-mingw/include/raylib.h b/release/win32-mingw/include/raylib.h index 30838d72a..e155e355e 100644 --- a/release/win32-mingw/include/raylib.h +++ b/release/win32-mingw/include/raylib.h @@ -1,6 +1,6 @@ /********************************************************************************************* * -* raylib 1.0.2 (www.raylib.com) +* raylib 1.0.3 (www.raylib.com) * * A simple and easy-to-use library to learn C videogames programming * @@ -236,10 +236,13 @@ extern "C" { // Prevents name mangling of functions //------------------------------------------------------------------------------------ // Window and Graphics Device Functions (Module: core) //------------------------------------------------------------------------------------ -void InitWindow(int width, int height, char* title); // Initialize Window and Graphics Context (OpenGL) +void InitWindow(int width, int height, const char *title); // Initialize Window and Graphics Context (OpenGL) +void InitWindowEx(int width, int height, const char* title, bool resizable, const char *cursorImage); void CloseWindow(); // Close Window and Terminate Context bool WindowShouldClose(); // Detect if KEY_ESCAPE pressed or Close icon pressed void ToggleFullscreen(); // Fullscreen toggle (by default F11) +void SetCustomCursor(const char *cursorImage); // Set a custom cursor icon/image +void SetExitKey(int key); // Set a custom key to exit program (default is ESC) void ClearBackground(Color color); // Sets Background Color void BeginDrawing(); // Setup drawing canvas to start drawing @@ -255,6 +258,8 @@ float GetFrameTime(); // Returns time in secon Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value int GetHexValue(Color color); // Returns hexadecimal value for a Color +int GetRandomValue(int min, int max); // Returns a random value between min and max (both included) + //------------------------------------------------------------------------------------ // Input Handling Functions (Module: core) //------------------------------------------------------------------------------------ @@ -296,8 +301,9 @@ void DrawRectangleV(Vector2 position, Vector2 size, Color color); void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline -void DrawPoly(Vector2 *points, int numPoints, Color color); // Draw a closed polygon defined by points -void DrawPolyLine(Vector2 *points, int numPoints, Color color); // Draw polygon lines +void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version) +void DrawPolyEx(Vector2 *points, int numPoints, Color color); // Draw a closed polygon defined by points +void DrawPolyExLines(Vector2 *points, int numPoints, Color color); // Draw polygon lines bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles @@ -323,6 +329,7 @@ Texture2D CreateTexture2D(Image image); //------------------------------------------------------------------------------------ SpriteFont GetDefaultFont(); // Get the default SpriteFont SpriteFont LoadSpriteFont(const char *fileName); // Load a SpriteFont image into GPU memory +SpriteFont LoadFontRBMF(const char *fileName); void UnloadSpriteFont(SpriteFont spriteFont); // Unload SpriteFont from GPU memory void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, int fontSize, int spacing, Color tint); // Draw text using SpriteFont diff --git a/release/win32-mingw/lib/libraylib.a b/release/win32-mingw/lib/libraylib.a index 5e001c1be..7fd583631 100644 Binary files a/release/win32-mingw/lib/libraylib.a and b/release/win32-mingw/lib/libraylib.a differ diff --git a/src/core.c b/src/core.c index 4041aa86f..7261aaaf9 100644 --- a/src/core.c +++ b/src/core.c @@ -31,7 +31,8 @@ #include // GLFW3 lib: Windows, OpenGL context and Input management //#include // OpenGL functions (GLFW3 already includes gl.h) #include // Standard input / output lib -#include // Declares malloc() and free() for memory management +#include // Declares malloc() and free() for memory management, rand() +#include // Useful to initialize random seed #include // Math related functions, tan() on SetPerspective #include "vector3.h" // Basic Vector3 functions @@ -59,7 +60,12 @@ static double frameTime; // Time measure for one frame static double targetTime = 0; // Desired time for one frame, if 0 not applied static int windowWidth, windowHeight; // Required to switch between windowed/fullscren mode (F11) -static char *windowTitle; // Required to switch between windowed/fullscren mode (F11) +static const char *windowTitle; // Required to switch between windowed/fullscren mode (F11) +static int exitKey = GLFW_KEY_ESCAPE; + +static bool customCursor = false; // Tracks if custom cursor has been set +static bool cursorOnScreen = false; // Tracks if cursor is inside client area +static Texture2D cursor; // Cursor texture static char previousKeyState[512] = { 0 }; // Required to check if key pressed/released once static char currentKeyState[512] = { 0 }; // Required to check if key pressed/released once @@ -83,6 +89,7 @@ extern void WriteBitmap(const char *fileName, const pixel *imgDataPixel, int wid static void InitGraphicsDevice(); // Initialize Graphics Device (OpenGL stuff) static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed +static void CursorEnterCallback(GLFWwindow* window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area static void WindowSizeCallback(GLFWwindow* window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized static void CameraLookAt(Vector3 position, Vector3 target, Vector3 up); // Setup camera view (updates MODELVIEW matrix) static void SetPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar); // Setup view projection (updates PROJECTION matrix) @@ -93,13 +100,21 @@ static void TakeScreenshot(); //---------------------------------------------------------------------------------- // Initialize Window and Graphics Context (OpenGL) -void InitWindow(int width, int height, char* title) +void InitWindow(int width, int height, const char *title) +{ + InitWindowEx(width, height, title, true, NULL); +} + +// Initialize Window and Graphics Context (OpenGL) with extended parameters +void InitWindowEx(int width, int height, const char* title, bool resizable, const char *cursorImage) { glfwSetErrorCallback(ErrorCallback); if (!glfwInit()) exit(1); - //glfwWindowHint(GLFW_SAMPLES, 4); // If called before windows creation, enables multisampling x4 (MSAA), default is 0 + //glfwDefaultWindowHints() // Set default windows hints + //glfwWindowHint(GLFW_SAMPLES, 4); // If called before windows creation, enables multisampling x4 (MSAA), default is 0 + if (!resizable) glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable window = glfwCreateWindow(width, height, title, NULL, NULL); @@ -114,6 +129,7 @@ void InitWindow(int width, int height, char* title) } glfwSetWindowSizeCallback(window, WindowSizeCallback); + glfwSetCursorEnterCallback(window, CursorEnterCallback); glfwMakeContextCurrent(window); glfwSetKeyCallback(window, KeyCallback); @@ -125,6 +141,17 @@ void InitWindow(int width, int height, char* title) previousTime = glfwGetTime(); LoadDefaultFont(); + + if (cursorImage != NULL) + { + // Load image as texture + cursor = LoadTexture(cursorImage); + + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + customCursor = true; + } + + srand(time(NULL)); // Initialize random seed } // Close Window and Terminate Context @@ -136,6 +163,24 @@ void CloseWindow() glfwTerminate(); } +// Set a custom cursor icon/image +void SetCustomCursor(const char *cursorImage) +{ + if (customCursor) UnloadTexture(cursor); + + cursor = LoadTexture(cursorImage); + + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + customCursor = true; +} + +// Set a custom key to exit program +// NOTE: default exitKey is ESCAPE +void SetExitKey(int key) +{ + exitKey = key; +} + // Detect if KEY_ESCAPE pressed or Close icon pressed bool WindowShouldClose() { @@ -197,6 +242,8 @@ void BeginDrawing() // End canvas drawing and Swap Buffers (Double Buffering) void EndDrawing() { + if (customCursor && cursorOnScreen) DrawTexture(cursor, GetMouseX(), GetMouseY(), WHITE); + glfwSwapBuffers(window); // Swap back and front buffers glfwPollEvents(); // Register keyboard/mouse events @@ -294,6 +341,12 @@ int GetHexValue(Color color) return ((color.a << 24) + (color.r << 16) + (color.g << 8) + color.b); } +// Returns a random value between min and max (both included) +int GetRandomValue(int min, int max) +{ + return (rand()%(abs(max-min)+1) - abs(min)); +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions //---------------------------------------------------------------------------------- @@ -529,14 +582,14 @@ bool IsGamepadButtonUp(int gamepad, int button) // GLFW3 Error Callback, runs on GLFW3 error static void ErrorCallback(int error, const char *description) { - //printf(description); - fprintf(stderr, "%s", description); + printf(description); + //fprintf(stderr, description); } // GLFW3 Keyboard Callback, runs on key pressed static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { - if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) + if (key == exitKey && action == GLFW_PRESS) { glfwSetWindowShouldClose(window, GL_TRUE); @@ -552,6 +605,12 @@ static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, i } } +static void CursorEnterCallback(GLFWwindow* window, int enter) +{ + if (enter == GL_TRUE) cursorOnScreen = true; + else cursorOnScreen = false; +} + // GLFW3 WindowSize Callback, runs when window is resized static void WindowSizeCallback(GLFWwindow* window, int width, int height) { @@ -688,4 +747,4 @@ static void TakeScreenshot() free(imgDataPixel); shotNum++; -} +} \ No newline at end of file diff --git a/src/models.c b/src/models.c index 8e4f35553..1f145523c 100644 --- a/src/models.c +++ b/src/models.c @@ -181,8 +181,6 @@ void DrawSphereWires(Vector3 centerPos, float radius, Color color) // Draw a cylinder/cone void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color) // Could be used for pyramid and cone! { - static int count = 0; - Vector3 a = { position.x, position.y + height, position.z }; Vector3 d = { 0.0f, 1.0f, 0.0f }; Vector3 p; @@ -202,7 +200,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h glPushMatrix(); //glTranslatef(centerPos.x, centerPos.y, centerPos.z); - glRotatef(DEG2RAD*count, 0.0f, 1.0f, 0.0f); + //glRotatef(degrees, 0.0f, 1.0f, 0.0f); //glScalef(1.0f, 1.0f, 1.0f); // Draw cone top @@ -239,7 +237,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h { glPushMatrix(); //glTranslatef(centerPos.x, centerPos.y, centerPos.z); - glRotatef(DEG2RAD*count, 0.0f, 1.0f, 0.0f); + //glRotatef(degrees, 0.0f, 1.0f, 0.0f); //glScalef(1.0f, 1.0f, 1.0f); // Draw cylinder top (pointed cap) @@ -290,8 +288,6 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h glPopMatrix(); } - - count += 1; } // Draw a cylinder/cone wires diff --git a/src/raylib.h b/src/raylib.h index 30838d72a..e155e355e 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1,6 +1,6 @@ /********************************************************************************************* * -* raylib 1.0.2 (www.raylib.com) +* raylib 1.0.3 (www.raylib.com) * * A simple and easy-to-use library to learn C videogames programming * @@ -236,10 +236,13 @@ extern "C" { // Prevents name mangling of functions //------------------------------------------------------------------------------------ // Window and Graphics Device Functions (Module: core) //------------------------------------------------------------------------------------ -void InitWindow(int width, int height, char* title); // Initialize Window and Graphics Context (OpenGL) +void InitWindow(int width, int height, const char *title); // Initialize Window and Graphics Context (OpenGL) +void InitWindowEx(int width, int height, const char* title, bool resizable, const char *cursorImage); void CloseWindow(); // Close Window and Terminate Context bool WindowShouldClose(); // Detect if KEY_ESCAPE pressed or Close icon pressed void ToggleFullscreen(); // Fullscreen toggle (by default F11) +void SetCustomCursor(const char *cursorImage); // Set a custom cursor icon/image +void SetExitKey(int key); // Set a custom key to exit program (default is ESC) void ClearBackground(Color color); // Sets Background Color void BeginDrawing(); // Setup drawing canvas to start drawing @@ -255,6 +258,8 @@ float GetFrameTime(); // Returns time in secon Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value int GetHexValue(Color color); // Returns hexadecimal value for a Color +int GetRandomValue(int min, int max); // Returns a random value between min and max (both included) + //------------------------------------------------------------------------------------ // Input Handling Functions (Module: core) //------------------------------------------------------------------------------------ @@ -296,8 +301,9 @@ void DrawRectangleV(Vector2 position, Vector2 size, Color color); void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline -void DrawPoly(Vector2 *points, int numPoints, Color color); // Draw a closed polygon defined by points -void DrawPolyLine(Vector2 *points, int numPoints, Color color); // Draw polygon lines +void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version) +void DrawPolyEx(Vector2 *points, int numPoints, Color color); // Draw a closed polygon defined by points +void DrawPolyExLines(Vector2 *points, int numPoints, Color color); // Draw polygon lines bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles @@ -323,6 +329,7 @@ Texture2D CreateTexture2D(Image image); //------------------------------------------------------------------------------------ SpriteFont GetDefaultFont(); // Get the default SpriteFont SpriteFont LoadSpriteFont(const char *fileName); // Load a SpriteFont image into GPU memory +SpriteFont LoadFontRBMF(const char *fileName); void UnloadSpriteFont(SpriteFont spriteFont); // Unload SpriteFont from GPU memory void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, int fontSize, int spacing, Color tint); // Draw text using SpriteFont diff --git a/src/shapes.c b/src/shapes.c index 564676654..b033cde99 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -102,23 +102,13 @@ void DrawLineV(Vector2 startPos, Vector2 endPos, Color color) } // Draw a color-filled circle +// TODO: Review, on some GPUs is drawn with a weird transparency (GL_POLYGON_SMOOTH issue?) void DrawCircle(int centerX, int centerY, float radius, Color color) { glEnable(GL_POLYGON_SMOOTH); - glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); // Deprecated on OGL 3.0 - glBegin(GL_TRIANGLE_FAN); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2i(centerX, centerY); - - for (int i=0; i <= 360; i++) //i++ --> Step = 1.0 pixels - { - float degInRad = i*DEG2RAD; - //glVertex2f(cos(degInRad)*radius,sin(degInRad)*radius); - - glVertex2f(centerX + sin(degInRad) * radius, centerY + cos(degInRad) * radius); - } - glEnd(); + DrawPoly((Vector2){centerX, centerY}, 360, radius, 0, color); glDisable(GL_POLYGON_SMOOTH); @@ -283,9 +273,30 @@ void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color) glEnd(); } +// Draw a regular polygon of n sides (Vector version) +void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color) +{ + if (sides < 3) sides = 3; + + glPushMatrix(); + glTranslatef(center.x, center.y, 0); + glRotatef(rotation, 0, 0, 1); + + glBegin(GL_TRIANGLE_FAN); + glColor4ub(color.r, color.g, color.b, color.a); + glVertex2f(0, 0); + + for (int i=0; i <= sides; i++) + { + glVertex2f(radius*cos(i*2*PI/sides), radius*sin(i*2*PI/sides)); + } + glEnd(); + glPopMatrix(); +} + // Draw a closed polygon defined by points // NOTE: Array num elements MUST be passed as parameter to function -void DrawPoly(Vector2 *points, int numPoints, Color color) +void DrawPolyEx(Vector2 *points, int numPoints, Color color) { if (numPoints >= 3) { @@ -307,7 +318,7 @@ void DrawPoly(Vector2 *points, int numPoints, Color color) // Draw polygon lines // NOTE: Array num elements MUST be passed as parameter to function -void DrawPolyLine(Vector2 *points, int numPoints, Color color) +void DrawPolyExLines(Vector2 *points, int numPoints, Color color) { if (numPoints >= 2) { @@ -327,6 +338,40 @@ void DrawPolyLine(Vector2 *points, int numPoints, Color color) } } +// Check if point is inside rectangle +bool CheckCollisionPointRec(Vector2 point, Rectangle rec) +{ + bool collision = false; + + if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) && (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true; + + return collision; +} + +// Check if point is inside circle +bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius) +{ + return CheckCollisionCircles(point, 0, center, radius); +} + +// Check if point is inside a triangle defined by three points (p1, p2, p3) +bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3) +{ + bool collision = false; + + float alpha = ((p2.y - p3.y)*(point.x - p3.x) + (p3.x - p2.x)*(point.y - p3.y)) / + ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y)); + + float beta = ((p3.y - p1.y)*(point.x - p3.x) + (p1.x - p3.x)*(point.y - p3.y)) / + ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y)); + + float gamma = 1.0f - alpha - beta; + + if ((alpha > 0) && (beta > 0) & (gamma > 0)) collision = true; + + return collision; +} + // Check collision between two rectangles bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2) { diff --git a/src/text.c b/src/text.c index ff9234a97..6b2480e25 100644 --- a/src/text.c +++ b/src/text.c @@ -65,9 +65,11 @@ static SpriteFont defaultFont; // Default font provided by raylib //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- -static bool PixelIsMagenta(Color p); // Check if a pixel is magenta +static bool PixelIsMagenta(Color p); // Check if a pixel is magenta static int ParseImageData(Color *imgDataPixel, int imgWidth, int imgHeight, Character **charSet); // Parse image pixel data to obtain character set measures -static int GetNextPOT(int num); // Calculate next power-of-two value for a given value +static int GetNextPOT(int num); // Calculate next power-of-two value for a given value +static SpriteFont LoadRBMF(const char *fileName); // Load a rBMF font file (raylib BitMap Font) +static const char *GetExtension(const char *fileName); //---------------------------------------------------------------------------------- // Module Functions Definition @@ -203,80 +205,90 @@ SpriteFont LoadSpriteFont(const char* fileName) { SpriteFont spriteFont; - // Use stb_image to load image data! - int imgWidth; - int imgHeight; - int imgBpp; - - byte *imgData = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4); // Force loading to 4 components (RGBA) - - // Convert array to pixel array for working convenience - Color *imgDataPixel = (Color *)malloc(imgWidth * imgHeight * sizeof(Color)); - Color *imgDataPixelPOT = NULL; - - int pix = 0; - - for (int i = 0; i < (imgWidth * imgHeight * 4); i += 4) - { - imgDataPixel[pix].r = imgData[i]; - imgDataPixel[pix].g = imgData[i+1]; - imgDataPixel[pix].b = imgData[i+2]; - imgDataPixel[pix].a = imgData[i+3]; - pix++; - } - - stbi_image_free(imgData); - - // At this point we have a pixel array with all the data... - - // Process bitmap Font pixel data to get measures (Character array) - // spriteFont.charSet data is filled inside the function and memory is allocated! - int numChars = ParseImageData(imgDataPixel, imgWidth, imgHeight, &spriteFont.charSet); - - spriteFont.numChars = numChars; - - // Convert image font to POT image before conversion to texture - // Just add the required amount of pixels at the right and bottom sides of image... - int potWidth = GetNextPOT(imgWidth); - int potHeight = GetNextPOT(imgHeight); - - // Check if POT texture generation is required (if texture is not already POT) - if ((potWidth != imgWidth) || (potHeight != imgWidth)) - { - // Generate POT array from NPOT data - imgDataPixelPOT = (Color *)malloc(potWidth * potHeight * sizeof(Color)); + // Check file extension + if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName); + else + { + // Use stb_image to load image data! + int imgWidth; + int imgHeight; + int imgBpp; - for (int j = 0; j < potHeight; j++) + byte *imgData = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4); // Force loading to 4 components (RGBA) + + // Convert array to pixel array for working convenience + Color *imgDataPixel = (Color *)malloc(imgWidth * imgHeight * sizeof(Color)); + Color *imgDataPixelPOT = NULL; + + int pix = 0; + + for (int i = 0; i < (imgWidth * imgHeight * 4); i += 4) { - for (int i = 0; i < potWidth; i++) + imgDataPixel[pix].r = imgData[i]; + imgDataPixel[pix].g = imgData[i+1]; + imgDataPixel[pix].b = imgData[i+2]; + imgDataPixel[pix].a = imgData[i+3]; + pix++; + } + + stbi_image_free(imgData); + + // At this point we have a pixel array with all the data... + + // Process bitmap Font pixel data to get measures (Character array) + // spriteFont.charSet data is filled inside the function and memory is allocated! + int numChars = ParseImageData(imgDataPixel, imgWidth, imgHeight, &spriteFont.charSet); + + fprintf(stderr, "SpriteFont data parsed correctly!\n"); + fprintf(stderr, "SpriteFont num chars: %i\n", numChars); + + spriteFont.numChars = numChars; + + // Convert image font to POT image before conversion to texture + // Just add the required amount of pixels at the right and bottom sides of image... + int potWidth = GetNextPOT(imgWidth); + int potHeight = GetNextPOT(imgHeight); + + // Check if POT texture generation is required (if texture is not already POT) + if ((potWidth != imgWidth) || (potHeight != imgHeight)) + { + // Generate POT array from NPOT data + imgDataPixelPOT = (Color *)malloc(potWidth * potHeight * sizeof(Color)); + + for (int j = 0; j < potHeight; j++) { - if ((j < imgHeight) && (i < imgWidth)) imgDataPixelPOT[j*potWidth + i] = imgDataPixel[j*imgWidth + i]; - else imgDataPixelPOT[j*potWidth + i] = MAGENTA; + for (int i = 0; i < potWidth; i++) + { + if ((j < imgHeight) && (i < imgWidth)) imgDataPixelPOT[j*potWidth + i] = imgDataPixel[j*imgWidth + i]; + else imgDataPixelPOT[j*potWidth + i] = MAGENTA; + } } + + fprintf(stderr, "SpriteFont texture converted to POT: %i %i\n", potWidth, potHeight); } - } - - free(imgDataPixel); + + free(imgDataPixel); - // Convert loaded data to OpenGL texture - //---------------------------------------- - GLuint id; - glGenTextures(1, &id); // Generate pointer to the texture - - glBindTexture(GL_TEXTURE_2D, id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, potWidth, potHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgDataPixelPOT); - - // NOTE: Not using mipmappings (texture for 2D drawing) - // At this point we have the image converted to texture and uploaded to GPU - - free(imgDataPixelPOT); // Now we can free loaded data from RAM memory + // Convert loaded data to OpenGL texture + //---------------------------------------- + GLuint id; + glGenTextures(1, &id); // Generate pointer to the texture + + glBindTexture(GL_TEXTURE_2D, id); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, potWidth, potHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgDataPixelPOT); + + // NOTE: Not using mipmappings (texture for 2D drawing) + // At this point we have the image converted to texture and uploaded to GPU + + free(imgDataPixelPOT); // Now we can free loaded data from RAM memory + + spriteFont.texture.glId = id; + spriteFont.texture.width = potWidth; + spriteFont.texture.height = potHeight; + } - spriteFont.texture.glId = id; - spriteFont.texture.width = potWidth; - spriteFont.texture.height = potHeight; - return spriteFont; } @@ -289,31 +301,23 @@ void UnloadSpriteFont(SpriteFont spriteFont) // Draw text (using default font) // NOTE: fontSize work like in any drawing program but if fontSize is lower than font-base-size, then font-base-size is used +// NOTE: chars spacing is proportional to fontSize void DrawText(const char* text, int posX, int posY, int fontSize, Color color) { Vector2 position = { (float)posX, (float)posY }; + + int defaultFontSize = 10; // Default Font chars height in pixel - DrawTextEx(defaultFont, text, position, fontSize, 1, color); -} - -// Formatting of text with variables to 'embed' -const char *FormatText(const char *text, ...) -{ - int length = strlen(text); - char *buffer = malloc(length + 20); // We add 20 extra characters, should be enough... :P - - va_list args; - va_start(args, text); - vsprintf(buffer, text, args); // NOTE: We use vsprintf() defined in - va_end(args); + if (fontSize < defaultFontSize) fontSize = defaultFontSize; - //strcat(buffer, "\0"); // We add a end-of-string mark at the end (not needed) + int spacing = fontSize / defaultFontSize; - return buffer; + DrawTextEx(defaultFont, text, position, fontSize, spacing, color); } // Draw text using SpriteFont // NOTE: If font size is lower than base size, base size is used +// NOTE: chars spacing is NOT proportional to fontSize void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, int fontSize, int spacing, Color tint) { int length = strlen(text); @@ -345,7 +349,7 @@ void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, int f glTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height); glVertex2f(positionX + (c.w) * scaleFactor, position.y + (c.h) * scaleFactor); glTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)c.y / spriteFont.texture.height); glVertex2f(positionX + (c.w) * scaleFactor, position.y); - positionX += (spriteFont.charSet[(int)text[i] - FIRST_CHAR].w + spacing) * scaleFactor; + positionX += ((spriteFont.charSet[(int)text[i] - FIRST_CHAR].w) * scaleFactor + spacing); } glEnd(); @@ -354,6 +358,22 @@ void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, int f glDisable(GL_TEXTURE_2D); } +// Formatting of text with variables to 'embed' +const char *FormatText(const char *text, ...) +{ + int length = strlen(text); + char *buffer = malloc(length + 20); // We add 20 extra characters, should be enough... :P + + va_list args; + va_start(args, text); + vsprintf(buffer, text, args); // NOTE: We use vsprintf() defined in + va_end(args); + + //strcat(buffer, "\0"); // We add a end-of-string mark at the end (not needed) + + return buffer; +} + // Measure string width for default font int MeasureText(const char *text, int fontSize) { @@ -517,4 +537,132 @@ static int GetNextPOT(int num) } return num; +} + +// Load a rBMF font file (raylib BitMap Font) +static SpriteFont LoadRBMF(const char *fileName) +{ + // rBMF Info Header (16 bytes) + typedef struct { + char id[4]; // rBMF file identifier + char version; // rBMF file version + // 4 MSB --> main version + // 4 LSB --> subversion + char firstChar; // First character in the font + // NOTE: Depending on charDataType, it could be useless + short imgWidth; // Image width - always POT (power-of-two) + short imgHeight; // Image height - always POT (power-of-two) + short numChars; // Number of characters contained + short charHeight; // Characters height - the same for all characters + char compType; // Compression type: + // 4 MSB --> image data compression + // 4 LSB --> chars data compression + char charsDataType; // Char data type provided + } rbmfInfoHeader; + + SpriteFont spriteFont; + Image image; + + rbmfInfoHeader rbmfHeader; + unsigned int *rbmfFileData; + unsigned char *rbmfCharWidthData; + + int charsDivisor = 1; // Every char is separated from the consecutive by a 1 pixel divisor, horizontally and vertically + + FILE *rbmfFile = fopen(fileName, "rb"); // Define a pointer to bitmap file and open it in read-binary mode + + fread(&rbmfHeader, sizeof(rbmfInfoHeader), 1, rbmfFile); + + //printf("rBMF info: %i %i %i %i\n", rbmfHeader.imgWidth, rbmfHeader.imgHeight, rbmfHeader.numChars, rbmfHeader.charHeight); + + spriteFont.numChars = (int)rbmfHeader.numChars; + + image.width = (int)rbmfHeader.imgWidth; + image.height = (int)rbmfHeader.imgHeight; + + int numPixelBits = rbmfHeader.imgWidth * rbmfHeader.imgHeight / 32; + + rbmfFileData = (unsigned int *)malloc(numPixelBits * sizeof(unsigned int)); + + for(int i = 0; i < numPixelBits; i++) fread(&rbmfFileData[i], sizeof(unsigned int), 1, rbmfFile); + + rbmfCharWidthData = (unsigned char *)malloc(spriteFont.numChars * sizeof(unsigned char)); + + for(int i = 0; i < spriteFont.numChars; i++) fread(&rbmfCharWidthData[i], sizeof(unsigned char), 1, rbmfFile); + + printf("Just read image data and width data... Starting image reconstruction..."); + + // Re-construct image from rbmfFileData + //----------------------------------------- + image.pixels = (Color *)malloc(image.width * image.height * sizeof(Color)); + + for (int i = 0; i < image.width * image.height; i++) image.pixels[i] = BLANK; // Initialize array + + int counter = 0; // Font data elements counter + + // Fill image data (convert from bit to pixel!) + for (int i = 0; i < image.width * image.height; i += 32) + { + for (int j = 31; j >= 0; j--) + { + if (BIT_CHECK(rbmfFileData[counter], j)) image.pixels[i+j] = WHITE; + } + + counter++; + } + + printf("Image reconstructed correctly... now converting it to texture..."); + + spriteFont.texture = CreateTexture2D(image); + + UnloadImage(image); // Unload image data + + printf("Starting charSet reconstruction...\n"); + + // Reconstruct charSet using rbmfCharWidthData, rbmfHeader.charHeight, charsDivisor, rbmfHeader.numChars + spriteFont.charSet = (Character *)malloc(spriteFont.numChars * sizeof(Character)); // Allocate space for our character data + + int currentLine = 0; + int currentPosX = charsDivisor; + int testPosX = charsDivisor; + + for (int i = 0; i < spriteFont.numChars; i++) + { + spriteFont.charSet[i].value = (int)rbmfHeader.firstChar + i; + spriteFont.charSet[i].x = currentPosX; + spriteFont.charSet[i].y = charsDivisor + currentLine * ((int)rbmfHeader.charHeight + charsDivisor); + spriteFont.charSet[i].w = (int)rbmfCharWidthData[i]; + spriteFont.charSet[i].h = (int)rbmfHeader.charHeight; + + testPosX += (spriteFont.charSet[i].w + charsDivisor); + + if (testPosX > spriteFont.texture.width) + { + currentLine++; + currentPosX = 2 * charsDivisor + (int)rbmfCharWidthData[i]; + testPosX = currentPosX; + + spriteFont.charSet[i].x = charsDivisor; + spriteFont.charSet[i].y = charsDivisor + currentLine * (rbmfHeader.charHeight + charsDivisor); + } + else currentPosX = testPosX; + + //printf("Char %i data: %i %i %i %i\n", spriteFont.charSet[i].value, spriteFont.charSet[i].x, spriteFont.charSet[i].y, spriteFont.charSet[i].w, spriteFont.charSet[i].h); + } + + printf("CharSet reconstructed correctly... Data should be ready...\n"); + + fclose(rbmfFile); + + free(rbmfFileData); // Now we can free loaded data from RAM memory + free(rbmfCharWidthData); + + return spriteFont; +} + +static const char *GetExtension(const char *fileName) +{ + const char *dot = strrchr(fileName, '.'); + if(!dot || dot == fileName) return ""; + return dot + 1; } \ No newline at end of file