Merge pull request #23 from raysan5/develop

Integrate develop branch
This commit is contained in:
Ray 2015-07-03 20:49:16 +02:00
commit a59433e7a3
69 changed files with 13413 additions and 2531 deletions

10
.gitignore vendored
View File

@ -1,13 +1,6 @@
# Ignore generated files
# ...
# Ignore compiled binaries
src/*.o
src/*.exe
examples/*.o
examples/*.exe
templates/*.exe
# Ignore Android generated files and folders
src_android/obj/
templates/android_project/bin/
@ -48,6 +41,9 @@ _ReSharper*/
[Tt]est[Rr]esult*
ipch/
*.opensdf
# Ignore compiled binaries
*.o
*.exe
!tools/rrem.exe

View File

@ -23,7 +23,7 @@
# define raylib platform to compile for
# possible platforms: PLATFORM_DESKTOP PLATFORM_RPI PLATFORM_WEB
# WARNING: To compile examples to HTML5, they must be redesigned to use emscripten.h and emscripten_set_main_loop()
# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop()
PLATFORM ?= PLATFORM_DESKTOP
# determine PLATFORM_OS in case PLATFORM_DESKTOP selected
@ -113,20 +113,20 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),LINUX)
# libraries for Debian GNU/Linux desktop compiling
# requires the following packages:
# libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
LIBS = -lraylib -lglfw -lGLEW -lGL -lopenal
endif
# libopenal-dev libglew-dev libegl1-mesa-dev
LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lm -pthread
else
ifeq ($(PLATFORM_OS),OSX)
# libraries for OS X 10.9 desktop compiling
# requires the following packages:
# libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
LIBS = -lraylib -lglfw -framework OpenGL -framework OpenAl -framework Cocoa
# libraries for OS X 10.9 desktop compiling
# requires the following packages:
# libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
LIBS = -lraylib -lglfw -framework OpenGL -framework OpenAl -framework Cocoa
else
# libraries for Windows desktop compiling
# NOTE: GLFW3 and OpenAL Soft libraries should be installed
LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32
endif
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
# libraries for Raspberry Pi compiling
@ -327,8 +327,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
rm -f *.o
else
ifeq ($(PLATFORM_OS),LINUX)
find . -type f -executable -delete
rm -f *.o
find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f
else
del *.o *.exe
endif

View File

@ -0,0 +1,86 @@
/*******************************************************************************************
*
* raylib [models] example - Load and draw a 3d model (OBJ)
*
* This example has been created using raylib 1.0 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
********************************************************************************************/
#include "raylib.h"
int main()
{
// Initialization
//--------------------------------------------------------------------------------------
int screenWidth = 1280;
int screenHeight = 720;
InitWindow(screenWidth, screenHeight, "raylib [models] example - custom shader");
// Define the camera to look into our 3d world
Camera camera = {{ 10.0, 8.0, 10.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }};
Texture2D texture = LoadTexture("resources/catsham.png"); // Load model texture
Shader shader = LoadShader("resources/shaders/custom.vs", "resources/shaders/custom.fs");
//Shader poste = LoadShader("resources/shaders/custom.vs", "resources/shaders/pixel.fs");
Model cat = LoadModel("resources/cat.obj"); // Load OBJ model
SetModelTexture(&cat, texture); // Bind texture to model
//SetModelShader(&cat, poste);
Vector3 catPosition = { 0.0, 0.0, 0.0 }; // Set model position
SetPostproShader(shader);
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyDown(KEY_LEFT)) catPosition.x -= 0.2;
if (IsKeyDown(KEY_RIGHT)) catPosition.x += 0.2;
if (IsKeyDown(KEY_UP)) catPosition.z -= 0.2;
if (IsKeyDown(KEY_DOWN)) catPosition.z += 0.2;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
Begin3dMode(camera);
DrawModel(cat, catPosition, 0.1f, WHITE); // Draw 3d model with texture
DrawGrid(10.0, 1.0); // Draw a grid
DrawGizmo(catPosition); // Draw gizmo
End3dMode();
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Unload texture
UnloadModel(cat); // Unload model
UnloadShader(shader);
//UnloadShader(poste);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -0,0 +1,19 @@
#version 110
attribute vec3 vertexPosition;
attribute vec2 vertexTexCoord;
attribute vec4 vertexColor;
uniform mat4 projectionMatrix;
uniform mat4 modelviewMatrix;
varying vec2 fragTexCoord;
varying vec4 fragColor;
void main()
{
fragTexCoord = vertexTexCoord;
fragColor = vertexColor;
gl_Position = projectionMatrix*modelviewMatrix*vec4(vertexPosition, 1.0);
}

View File

@ -0,0 +1,16 @@
#version 330
uniform sampler2D texture0;
varying vec2 fragTexCoord;
uniform vec4 tintColor;
void main()
{
vec4 base = texture2D(texture0, fragTexCoord)*tintColor;
// Convert to grayscale using NTSC conversion weights
float gray = dot(base.rgb, vec3(0.299, 0.587, 0.114));
gl_FragColor = vec4(gray, gray, gray, tintColor.a);
}

View File

@ -0,0 +1,16 @@
#version 330
attribute vec3 vertexPosition;
attribute vec2 vertexTexCoord;
attribute vec3 vertexNormal;
uniform mat4 projectionMatrix;
uniform mat4 modelviewMatrix;
varying vec2 fragTexCoord;
void main()
{
fragTexCoord = vertexTexCoord;
gl_Position = projectionMatrix*modelviewMatrix*vec4(vertexPosition, 1.0);
}

View File

@ -0,0 +1,15 @@
#version 110
uniform sampler2D texture0;
varying vec2 fragTexCoord;
varying vec4 fragColor;
void main()
{
vec4 base = texture2D(texture0, fragTexCoord)*fragColor;
// Convert to grayscale using NTSC conversion weights
float gray = dot(base.rgb, vec3(0.299, 0.587, 0.114));
gl_FragColor = vec4(gray, gray, gray, base.a);
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*************************************************************************
* GLFW 3.0 - www.glfw.org
* GLFW 3.1 - www.glfw.org
* A library for OpenGL, window and input
*------------------------------------------------------------------------
* Copyright (c) 2002-2006 Marcus Geelnard
@ -40,13 +40,13 @@ extern "C" {
/*! @defgroup native Native access
*
* **By using the native API, you assert that you know what you're doing and
* how to fix problems caused by using it. If you don't, you shouldn't be
* using it.**
* **By using the native access functions you assert that you know what you're
* doing and how to fix problems caused by using them. If you don't, you
* shouldn't be using them.**
*
* Before the inclusion of @ref glfw3native.h, you must define exactly one
* window API macro and exactly one context API macro. Failure to do this
* will cause a compile-time error.
* window system API macro and exactly one context creation API macro. Failure
* to do this will cause a compile-time error.
*
* The available window API macros are:
* * `GLFW_EXPOSE_NATIVE_WIN32`
@ -71,8 +71,13 @@ extern "C" {
*************************************************************************/
#if defined(GLFW_EXPOSE_NATIVE_WIN32)
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
// example to allow applications to correctly declare a GL_ARB_debug_output
// callback) but windows.h assumes no one will define APIENTRY before it does
#undef APIENTRY
#include <windows.h>
#elif defined(GLFW_EXPOSE_NATIVE_COCOA)
#include <ApplicationServices/ApplicationServices.h>
#if defined(__OBJC__)
#import <Cocoa/Cocoa.h>
#else
@ -80,8 +85,9 @@ extern "C" {
#endif
#elif defined(GLFW_EXPOSE_NATIVE_X11)
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#else
#error "No window API specified"
#error "No window API selected"
#endif
#if defined(GLFW_EXPOSE_NATIVE_WGL)
@ -93,7 +99,7 @@ extern "C" {
#elif defined(GLFW_EXPOSE_NATIVE_EGL)
#include <EGL/egl.h>
#else
#error "No context API specified"
#error "No context API selected"
#endif
@ -102,8 +108,49 @@ extern "C" {
*************************************************************************/
#if defined(GLFW_EXPOSE_NATIVE_WIN32)
/*! @brief Returns the adapter device name of the specified monitor.
*
* @return The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`)
* of the specified monitor, or `NULL` if an [error](@ref error_handling)
* occurred.
*
* @par Thread Safety
* This function may be called from any thread. Access is not synchronized.
*
* @par History
* Added in GLFW 3.1.
*
* @ingroup native
*/
GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor);
/*! @brief Returns the display device name of the specified monitor.
*
* @return The UTF-8 encoded display device name (for example
* `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @par Thread Safety
* This function may be called from any thread. Access is not synchronized.
*
* @par History
* Added in GLFW 3.1.
*
* @ingroup native
*/
GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor);
/*! @brief Returns the `HWND` of the specified window.
* @return The `HWND` of the specified window.
*
* @return The `HWND` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @par Thread Safety
* This function may be called from any thread. Access is not synchronized.
*
* @par History
* Added in GLFW 3.0.
*
* @ingroup native
*/
GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window);
@ -111,15 +158,48 @@ GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window);
#if defined(GLFW_EXPOSE_NATIVE_WGL)
/*! @brief Returns the `HGLRC` of the specified window.
* @return The `HGLRC` of the specified window.
*
* @return The `HGLRC` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @par Thread Safety
* This function may be called from any thread. Access is not synchronized.
*
* @par History
* Added in GLFW 3.0.
*
* @ingroup native
*/
GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_COCOA)
/*! @brief Returns the `CGDirectDisplayID` of the specified monitor.
*
* @return The `CGDirectDisplayID` of the specified monitor, or
* `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred.
*
* @par Thread Safety
* This function may be called from any thread. Access is not synchronized.
*
* @par History
* Added in GLFW 3.1.
*
* @ingroup native
*/
GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor);
/*! @brief Returns the `NSWindow` of the specified window.
* @return The `NSWindow` of the specified window.
*
* @return The `NSWindow` of the specified window, or `nil` if an
* [error](@ref error_handling) occurred.
*
* @par Thread Safety
* This function may be called from any thread. Access is not synchronized.
*
* @par History
* Added in GLFW 3.0.
*
* @ingroup native
*/
GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window);
@ -127,7 +207,16 @@ GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window);
#if defined(GLFW_EXPOSE_NATIVE_NSGL)
/*! @brief Returns the `NSOpenGLContext` of the specified window.
* @return The `NSOpenGLContext` of the specified window.
*
* @return The `NSOpenGLContext` of the specified window, or `nil` if an
* [error](@ref error_handling) occurred.
*
* @par Thread Safety
* This function may be called from any thread. Access is not synchronized.
*
* @par History
* Added in GLFW 3.0.
*
* @ingroup native
*/
GLFWAPI id glfwGetNSGLContext(GLFWwindow* window);
@ -135,12 +224,61 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* window);
#if defined(GLFW_EXPOSE_NATIVE_X11)
/*! @brief Returns the `Display` used by GLFW.
* @return The `Display` used by GLFW.
*
* @return The `Display` used by GLFW, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @par Thread Safety
* This function may be called from any thread. Access is not synchronized.
*
* @par History
* Added in GLFW 3.0.
*
* @ingroup native
*/
GLFWAPI Display* glfwGetX11Display(void);
/*! @brief Returns the `RRCrtc` of the specified monitor.
*
* @return The `RRCrtc` of the specified monitor, or `None` if an
* [error](@ref error_handling) occurred.
*
* @par Thread Safety
* This function may be called from any thread. Access is not synchronized.
*
* @par History
* Added in GLFW 3.1.
*
* @ingroup native
*/
GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
/*! @brief Returns the `RROutput` of the specified monitor.
*
* @return The `RROutput` of the specified monitor, or `None` if an
* [error](@ref error_handling) occurred.
*
* @par Thread Safety
* This function may be called from any thread. Access is not synchronized.
*
* @par History
* Added in GLFW 3.1.
*
* @ingroup native
*/
GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
/*! @brief Returns the `Window` of the specified window.
* @return The `Window` of the specified window.
*
* @return The `Window` of the specified window, or `None` if an
* [error](@ref error_handling) occurred.
*
* @par Thread Safety
* This function may be called from any thread. Access is not synchronized.
*
* @par History
* Added in GLFW 3.0.
*
* @ingroup native
*/
GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
@ -148,7 +286,16 @@ GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
#if defined(GLFW_EXPOSE_NATIVE_GLX)
/*! @brief Returns the `GLXContext` of the specified window.
* @return The `GLXContext` of the specified window.
*
* @return The `GLXContext` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @par Thread Safety
* This function may be called from any thread. Access is not synchronized.
*
* @par History
* Added in GLFW 3.0.
*
* @ingroup native
*/
GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);
@ -156,17 +303,46 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);
#if defined(GLFW_EXPOSE_NATIVE_EGL)
/*! @brief Returns the `EGLDisplay` used by GLFW.
* @return The `EGLDisplay` used by GLFW.
*
* @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an
* [error](@ref error_handling) occurred.
*
* @par Thread Safety
* This function may be called from any thread. Access is not synchronized.
*
* @par History
* Added in GLFW 3.0.
*
* @ingroup native
*/
GLFWAPI EGLDisplay glfwGetEGLDisplay(void);
/*! @brief Returns the `EGLContext` of the specified window.
* @return The `EGLContext` of the specified window.
*
* @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an
* [error](@ref error_handling) occurred.
*
* @par Thread Safety
* This function may be called from any thread. Access is not synchronized.
*
* @par History
* Added in GLFW 3.0.
*
* @ingroup native
*/
GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
/*! @brief Returns the `EGLSurface` of the specified window.
* @return The `EGLSurface` of the specified window.
*
* @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an
* [error](@ref error_handling) occurred.
*
* @par Thread Safety
* This function may be called from any thread. Access is not synchronized.
*
* @par History
* Added in GLFW 3.0.
*
* @ingroup native
*/
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);

BIN
external/glfw3/lib/linux/libglfw3.a vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,358 @@
/*******************************************************************************************
*
* JUST DO - Global Game Jam 2015 Videogame
* Experimental puzzle game that lets the user try to find a logic solution to
* different shape-color-based situations.
*
* Developed by: Ramon Santamaria (Ray San)
*
* This game has been created using raylib (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* raylib - Copyright (c) 2015 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
********************************************************************************************/
#include "raylib.h"
#include "screens/screens.h" // NOTE: Defines currentScreen
#if defined(PLATFORM_WEB)
#include <emscripten/emscripten.h>
#endif
//----------------------------------------------------------------------------------
// Global Variables Definition (local to this module)
//----------------------------------------------------------------------------------
const int screenWidth = 1280; // Moved to screens.h
const int screenHeight = 720; // Moved to screens.h
// Required variables to manage screen transitions (fade-in, fade-out)
float transAlpha = 0;
bool onTransition = false;
bool transFadeOut = false;
int transFromScreen = -1;
int transToScreen = -1;
int framesCounter = 0;
//static Sound levelWin;
//----------------------------------------------------------------------------------
// Local Functions Declaration
//----------------------------------------------------------------------------------
void TransitionToScreen(int screen);
void UpdateTransition(void);
void DrawTransition(void);
void UpdateDrawFrame(void); // Update and Draw one frame
//----------------------------------------------------------------------------------
// Main entry point
//----------------------------------------------------------------------------------
int main(void)
{
// Initialization
//---------------------------------------------------------
const char windowTitle[30] = "JUST DO";
//SetupFlags(FLAG_FULLSCREEN_MODE);
InitWindow(screenWidth, screenHeight, windowTitle);
// TODO: Load global data here (assets that must be available in all screens, i.e. fonts)
InitAudioDevice();
levelWin = LoadSound("resources/win.wav");
// Setup and Init first screen
currentScreen = LOGO;
InitLogoScreen();
#if defined(PLATFORM_WEB)
emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
#else
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
if (IsKeyPressed(KEY_SPACE)) PlaySound(levelWin);
UpdateDrawFrame();
}
#endif
// De-Initialization
//--------------------------------------------------------------------------------------
// TODO: Unload all global loaded data (i.e. fonts) here!
UnloadSound(levelWin);
CloseAudioDevice();
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Local Functions Definition
//----------------------------------------------------------------------------------
void TransitionToScreen(int screen)
{
onTransition = true;
transFromScreen = currentScreen;
transToScreen = screen;
}
void UpdateTransition(void)
{
if (!transFadeOut)
{
transAlpha += 0.02f;
if (transAlpha >= 1.0)
{
transAlpha = 1.0;
currentScreen = transToScreen;
transFadeOut = true;
framesCounter = 0;
}
}
else // Transition fade out logic
{
transAlpha -= 0.02f;
if (transAlpha <= 0)
{
transAlpha = 0;
transFadeOut = false;
onTransition = false;
transFromScreen = -1;
transToScreen = -1;
}
}
}
void DrawTransition(void)
{
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(RAYWHITE, transAlpha));
}
void UpdateDrawFrame(void)
{
// Update
//----------------------------------------------------------------------------------
if (!onTransition)
{
if (IsKeyPressed('0'))
{
TransitionToScreen(LEVEL00);
InitLevel00Screen();
}
else if (IsKeyPressed('1'))
{
TransitionToScreen(LEVEL01);
InitLevel01Screen();
}
else if (IsKeyPressed('2'))
{
TransitionToScreen(LEVEL02);
InitLevel02Screen();
}
else if (IsKeyPressed('3'))
{
TransitionToScreen(LEVEL03);
InitLevel03Screen();
}
else if (IsKeyPressed('4'))
{
TransitionToScreen(LEVEL04);
InitLevel04Screen();
}
else if (IsKeyPressed('5'))
{
TransitionToScreen(LEVEL05);
InitLevel05Screen();
}
else if (IsKeyPressed('6'))
{
TransitionToScreen(LEVEL06);
InitLevel06Screen();
}
else if (IsKeyPressed('7'))
{
TransitionToScreen(LEVEL07);
InitLevel07Screen();
}
else if (IsKeyPressed('8'))
{
TransitionToScreen(LEVEL08);
InitLevel08Screen();
}
else if (IsKeyPressed('9'))
{
TransitionToScreen(LEVEL09);
InitLevel08Screen();
}
switch(currentScreen)
{
case LOGO:
{
UpdateLogoScreen();
if (FinishLogoScreen())
{
UnloadLogoScreen();
TransitionToScreen(LEVEL00);
InitLevel00Screen();
PlayMusicStream("resources/ambient.ogg");
SetMusicVolume(0.6f);
}
} break;
case LEVEL00:
{
UpdateLevel00Screen();
if (FinishLevel00Screen())
{
UnloadLevel00Screen();
TransitionToScreen(LEVEL01);
InitLevel01Screen();
}
} break;
case LEVEL01:
{
UpdateLevel01Screen();
if (FinishLevel01Screen())
{
UnloadLevel01Screen();
TransitionToScreen(LEVEL02);
InitLevel02Screen();
}
} break;
case LEVEL02:
{
UpdateLevel02Screen();
if (FinishLevel02Screen())
{
UnloadLevel02Screen();
TransitionToScreen(LEVEL03);
InitLevel03Screen();
}
} break;
case LEVEL03:
{
UpdateLevel03Screen();
if (FinishLevel03Screen())
{
UnloadLevel03Screen();
TransitionToScreen(LEVEL04);
InitLevel04Screen();
}
} break;
case LEVEL04:
{
UpdateLevel04Screen();
if (FinishLevel04Screen())
{
UnloadLevel04Screen();
TransitionToScreen(LEVEL05);
InitLevel05Screen();
}
} break;
case LEVEL05:
{
UpdateLevel05Screen();
if (FinishLevel05Screen())
{
UnloadLevel05Screen();
TransitionToScreen(LEVEL06);
InitLevel06Screen();
}
} break;
case LEVEL06:
{
UpdateLevel06Screen();
if (FinishLevel06Screen())
{
UnloadLevel06Screen();
TransitionToScreen(LEVEL07);
InitLevel07Screen();
}
} break;
case LEVEL07:
{
UpdateLevel07Screen();
if (FinishLevel07Screen())
{
UnloadLevel07Screen();
TransitionToScreen(LEVEL08);
InitLevel08Screen();
}
} break;
case LEVEL08:
{
UpdateLevel08Screen();
if (FinishLevel08Screen())
{
UnloadLevel08Screen();
TransitionToScreen(LEVEL09);
InitLevel09Screen();
}
} break;
case LEVEL09:
{
UpdateLevel09Screen();
if (FinishLevel09Screen())
{
UnloadLevel09Screen();
TransitionToScreen(LEVEL00);
InitLevel00Screen();
}
} break;
default: break;
}
}
else UpdateTransition(); // Update transition (fade-in, fade-out)
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
switch(currentScreen)
{
case LOGO: DrawLogoScreen(); break;
case LEVEL00: DrawLevel00Screen(); break;
case LEVEL01: DrawLevel01Screen(); break;
case LEVEL02: DrawLevel02Screen(); break;
case LEVEL03: DrawLevel03Screen(); break;
case LEVEL04: DrawLevel04Screen(); break;
case LEVEL05: DrawLevel05Screen(); break;
case LEVEL06: DrawLevel06Screen(); break;
case LEVEL07: DrawLevel07Screen(); break;
case LEVEL08: DrawLevel08Screen(); break;
case LEVEL09: DrawLevel09Screen(); break;
default: break;
}
if (onTransition) DrawTransition();
EndDrawing();
//----------------------------------------------------------------------------------
}

View File

@ -0,0 +1,246 @@
#**************************************************************************************************
#
# raylib - Advance Game
#
# makefile to compile advance game for desktop platforms, Raspberry Pi and HTML5 (emscripten)
#
# Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
#
# This software is provided "as-is", without any express or implied warranty. In no event
# will the authors be held liable for any damages arising from the use of this software.
#
# Permission is granted to anyone to use this software for any purpose, including commercial
# applications, and to alter it and redistribute it freely, subject to the following restrictions:
#
# 1. The origin of this software must not be misrepresented; you must not claim that you
# wrote the original software. If you use this software in a product, an acknowledgment
# in the product documentation would be appreciated but is not required.
#
# 2. Altered source versions must be plainly marked as such, and must not be misrepresented
# as being the original software.
#
# 3. This notice may not be removed or altered from any source distribution.
#
#**************************************************************************************************
# define raylib platform to compile for
# possible platforms: PLATFORM_DESKTOP PLATFORM_RPI PLATFORM_WEB
# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop()
PLATFORM ?= PLATFORM_DESKTOP
# determine PLATFORM_OS in case PLATFORM_DESKTOP selected
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
# No uname.exe on MinGW!, but OS=Windows_NT on Windows! ifeq ($(UNAME),Msys) -> Windows
ifeq ($(OS),Windows_NT)
PLATFORM_OS=WINDOWS
LIBPATH=win32
else
UNAMEOS:=$(shell uname)
ifeq ($(UNAMEOS),Linux)
PLATFORM_OS=LINUX
LIBPATH=linux
else
ifeq ($(UNAMEOS),Darwin)
PLATFORM_OS=OSX
LIBPATH=osx
endif
endif
endif
endif
# define compiler: gcc for C program, define as g++ for C++
ifeq ($(PLATFORM),PLATFORM_WEB)
# define emscripten compiler
CC = emcc
else
ifeq ($(PLATFORM_OS),OSX)
# define llvm compiler for mac
CC = clang
else
# define default gcc compiler
CC = gcc
endif
endif
# define compiler flags:
# -O2 defines optimization level
# -Wall turns on most, but not all, compiler warnings
# -std=c99 use standard C from 1999 revision
ifeq ($(PLATFORM),PLATFORM_RPI)
CFLAGS = -O2 -Wall -std=gnu99 -fgnu89-inline
else
CFLAGS = -O2 -Wall -std=c99
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
CFLAGS = -O2 -Wall -std=c99 -s USE_GLFW=3
#-s ASSERTIONS=1 --preload-file resources
#-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing
#-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
endif
#CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes
# define any directories containing required header files
ifeq ($(PLATFORM),PLATFORM_RPI)
INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
else
INCLUDES = -I. -I../../src -I../../../src
# external libraries headers
# GLFW3
INCLUDES += -I../../external/glfw3/include
# GLEW
INCLUDES += -I../../external/glew/include
# OpenAL Soft
INCLUDES += -I../../external/openal_soft/include
endif
# define library paths containing required libs
ifeq ($(PLATFORM),PLATFORM_RPI)
LFLAGS = -L. -L../../src -L/opt/vc/lib
else
LFLAGS = -L. -L../../src -L../../../src
# external libraries to link with
# GLFW3
LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
ifneq ($(PLATFORM_OS),OSX)
# OpenAL Soft
LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
# GLEW
LFLAGS += -L../../external/glew/lib/$(LIBPATH)
endif
endif
# define any libraries to link into executable
# if you want to link libraries (libname.so or libname.a), use the -lname
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),LINUX)
# libraries for Debian GNU/Linux desktop compiling
# requires the following packages:
# libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
LIBS = -lraylib -lglfw -lGLEW -lGL -lopenal
endif
ifeq ($(PLATFORM_OS),OSX)
# libraries for OS X 10.9 desktop compiling
# requires the following packages:
# libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
LIBS = -lraylib -lglfw -framework OpenGL -framework OpenAl -framework Cocoa
else
# libraries for Windows desktop compiling
# NOTE: GLFW3 and OpenAL Soft libraries should be installed
LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
# libraries for Raspberry Pi compiling
# NOTE: OpenAL Soft library should be installed (libopenal1 package)
LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
LIBS = ../../src/libraylib.bc
endif
# define additional parameters and flags for windows
ifeq ($(PLATFORM_OS),WINDOWS)
# resources file contains windows exe icon
# -Wl,--subsystem,windows hides the console window
WINFLAGS = ../../src/resources -Wl,--subsystem,windows
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
EXT = .html
endif
# define all screen object files required
SCREENS = \
screens/screen_logo.o \
screens/screen_level00.o \
screens/screen_level01.o \
screens/screen_level02.o \
screens/screen_level03.o \
screens/screen_level04.o \
screens/screen_level05.o \
screens/screen_level06.o \
screens/screen_level07.o \
screens/screen_level08.o \
screens/screen_level09.o \
# typing 'make' will invoke the first target entry in the file,
# in this case, the 'default' target entry is just_do
default: just_do
# compile just_do
just_do: just_do.c $(SCREENS)
$(CC) -o $@$(EXT) $< $(SCREENS) $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
# compile screen LOGO
screens/screen_logo.o: screens/screen_logo.c
$(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
# compile screen LEVEL00
screens/screen_level00.o: screens/screen_level00.c
$(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
# compile screen LEVEL01
screens/screen_level01.o: screens/screen_level01.c
$(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
# compile screen LEVEL02
screens/screen_level02.o: screens/screen_level02.c
$(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
# compile screen LEVEL03
screens/screen_level03.o: screens/screen_level03.c
$(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
# compile screen LEVEL04
screens/screen_level04.o: screens/screen_level04.c
$(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
# compile screen LEVEL05
screens/screen_level05.o: screens/screen_level05.c
$(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
# compile screen LEVEL06
screens/screen_level06.o: screens/screen_level06.c
$(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
# compile screen LEVEL07
screens/screen_level07.o: screens/screen_level07.c
$(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
# compile screen LEVEL08
screens/screen_level08.o: screens/screen_level08.c
$(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
# compile screen LEVEL09
screens/screen_level09.o: screens/screen_level09.c
$(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
# clean everything
clean:
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),OSX)
find . -type f -perm +ugo+x -delete
rm -f *.o
else
ifeq ($(PLATFORM_OS),LINUX)
find . -type f -executable -delete
rm -f *.o
else
del *.o *.exe
endif
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
find . -type f -executable -delete
rm -f *.o
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
del *.o *.html *.js
endif
@echo Cleaning done
# instead of defining every module one by one, we can define a pattern
# this pattern below will automatically compile every module defined on $(OBJS)
#%.exe : %.c
# $(CC) -o $@ $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM)

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,167 @@
/**********************************************************************************************
*
* raylib - Standard Game template
*
* Level00 Screen Functions Definitions (Init, Update, Draw, Unload)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "raylib.h"
#include "screens.h"
//----------------------------------------------------------------------------------
// Global Variables Definition (local to this module)
//----------------------------------------------------------------------------------
// Level00 screen global variables
static int framesCounter;
static int finishScreen;
static Rectangle boundsU, boundsO;
static bool mouseOverU = false;
static bool mouseOverO = false;
static bool placedU = false;
static bool placedO = false;
static bool done = false;
static int levelTimeSec = 0;
static bool levelFinished = false;
//----------------------------------------------------------------------------------
// Level00 Screen Functions Definition
//----------------------------------------------------------------------------------
// Level00 Screen Initialization logic
void InitLevel00Screen(void)
{
// Initialize Level00 screen variables here!
framesCounter = 0;
finishScreen = 0;
boundsU = (Rectangle){GetScreenWidth()/2 - 265, -200, MeasureText("U", 160) + 40, 160 };
boundsO = (Rectangle){GetScreenWidth() - 370, -30, MeasureText("O", 160) + 40, 160 };
}
// Level00 Screen Update logic
void UpdateLevel00Screen(void)
{
// Update Level00 screen variables here!
if (!done) framesCounter++;
if (!done)
{
if (!placedU) boundsU.y += 2;
if (boundsU.y >= GetScreenHeight()) boundsU.y = -boundsU.height;
Vector2 mousePos = GetMousePosition();
if (CheckCollisionPointRec(mousePos, boundsU))
{
mouseOverU = true;
if (!placedU && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
if ((boundsU.y > GetScreenHeight()/2 - 110) && ((boundsU.y + boundsU.height) < (GetScreenHeight()/2 + 100)))
{
placedU = true;
}
}
}
else mouseOverU = false;
if (CheckCollisionPointRec(mousePos, boundsO))
{
mouseOverO = true;
if (!placedO && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) boundsO.y += 100;
if (boundsO.y >= (GetScreenHeight()/2 - 130)) placedO = true;
}
else mouseOverO = false;
if (placedO && placedU)
{
done = true;
PlaySound(levelWin);
}
}
if (done && !levelFinished)
{
levelTimeSec = framesCounter/60;
levelFinished = true;
framesCounter = 0;
}
if (levelFinished)
{
framesCounter++;
if ((framesCounter > 30) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true;
}
}
// Level00 Screen Draw logic
void DrawLevel00Screen(void)
{
// Draw Level00 screen
DrawText("U", boundsU.x, boundsU.y + 10, 160, GRAY);
DrawText("J", GetScreenWidth()/2 - MeasureText("JUST DO", 160)/2, GetScreenHeight()/2 - 80, 160, GRAY);
DrawText("ST D", GetScreenWidth()/2 - MeasureText("JUST DO", 160)/2 + 210, GetScreenHeight()/2 - 80, 160, GRAY);
DrawText("O", boundsO.x, boundsO.y + 10, 160, GRAY);
DrawText("by RAMON SANTAMARIA (@raysan5)", 370, GetScreenHeight()/2 + 100, 30, Fade(LIGHTGRAY, 0.4f));
if (mouseOverU && !placedU) DrawRectangleLines(boundsU.x - 20, boundsU.y, boundsU.width, boundsU.height, Fade(LIGHTGRAY, 0.8f));
//DrawRectangleBordersRec(boundsU, -20, 0, 20, Fade(RED, 0.3f));
if (mouseOverO && !placedO) DrawRectangleLines(boundsO.x - 20, boundsO.y, boundsO.width, boundsO.height, Fade(LIGHTGRAY, 0.8f));
//DrawRectangleBordersRec(boundsO, -20, 0, 20, Fade(RED, 0.3f));
if (levelFinished)
{
DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f));
DrawText("LEVEL 00", GetScreenWidth()/2 - MeasureText("LEVEL 00", 30)/2, 20, 30, GRAY);
DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY);
}
else DrawText("LEVEL 00", GetScreenWidth()/2 - MeasureText("LEVEL 00", 30)/2, 20, 30, LIGHTGRAY);
}
// Level00 Screen Unload logic
void UnloadLevel00Screen(void)
{
// TODO: Unload Level00 screen variables here!
}
// Level00 Screen should finish?
int FinishLevel00Screen(void)
{
return finishScreen;
}
void DrawRectangleBordersRec(Rectangle rec, int offsetX, int offsetY, int borderSize, Color col)
{
DrawRectangle(rec.x + offsetX, rec.y + offsetY, rec.width, borderSize, col);
DrawRectangle(rec.x + offsetX, rec.y + borderSize + offsetY, borderSize, rec.height - borderSize*2, col);
DrawRectangle(rec.x + rec.width - borderSize + offsetX, rec.y + borderSize + offsetY, borderSize, rec.height - borderSize*2, col);
DrawRectangle(rec.x + offsetX, rec.y + rec.height - borderSize + offsetY, rec.width, borderSize, col);
}

View File

@ -0,0 +1,163 @@
/**********************************************************************************************
*
* raylib - Standard Game template
*
* Level01 Screen Functions Definitions (Init, Update, Draw, Unload)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "raylib.h"
#include "screens.h"
//----------------------------------------------------------------------------------
// Global Variables Definition (local to this module)
//----------------------------------------------------------------------------------
// Level01 screen global variables
static int framesCounter;
static int finishScreen;
static Rectangle innerLeftRec, outerLeftRec;
static Rectangle innerRightRec, outerRightRec;
static bool done = false;
static int levelTimeSec = 0;
static bool levelFinished = false;
//----------------------------------------------------------------------------------
// Level01 Screen Functions Definition
//----------------------------------------------------------------------------------
// Level01 Screen Initialization logic
void InitLevel01Screen(void)
{
// Initialize Level01 screen variables here!
framesCounter = 0;
finishScreen = 0;
outerLeftRec = (Rectangle){ 0, 0, GetScreenWidth()/2, GetScreenHeight() };
outerRightRec = (Rectangle){ GetScreenWidth()/2, 0, GetScreenWidth()/2, GetScreenHeight() };
innerLeftRec = (Rectangle){ GetScreenWidth()/4 - 200, GetScreenHeight()/2 - 200, 400, 400};
innerRightRec = (Rectangle){ GetScreenWidth()/2 + GetScreenWidth()/4 - 200, GetScreenHeight()/2 - 200, 400, 400};
}
// Level01 Screen Update logic
void UpdateLevel01Screen(void)
{
// Update Level01 screen
framesCounter++;
if (!done)
{
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
if (CheckCollisionPointRec(GetMousePosition(), innerLeftRec))
{
if (innerRightRec.width > 0)
{
innerRightRec.x += 20;
innerRightRec.y += 20;
innerRightRec.width -= 40;
innerRightRec.height -= 40;
}
}
else if (CheckCollisionPointRec(GetMousePosition(), innerRightRec))
{
if (innerLeftRec.width > 0)
{
innerLeftRec.x += 20;
innerLeftRec.y += 20;
innerLeftRec.width -= 40;
innerLeftRec.height -= 40;
}
}
else if (CheckCollisionPointRec(GetMousePosition(), outerLeftRec))
{
innerLeftRec.x -= 20;
innerLeftRec.y -= 20;
innerLeftRec.width += 40;
innerLeftRec.height += 40;
}
else if (CheckCollisionPointRec(GetMousePosition(), outerRightRec))
{
innerRightRec.x -= 20;
innerRightRec.y -= 20;
innerRightRec.width += 40;
innerRightRec.height += 40;
}
}
if (((innerRightRec.width == 0) && (innerLeftRec.height >= GetScreenHeight())) ||
((innerLeftRec.width == 0) && (innerRightRec.height >= GetScreenHeight())))
{
done = true;
PlaySound(levelWin);
}
}
if (done && !levelFinished)
{
levelTimeSec = framesCounter/60;
levelFinished = true;
framesCounter = 0;
}
if (levelFinished)
{
framesCounter++;
if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true;
}
}
// Level01 Screen Draw logic
void DrawLevel01Screen(void)
{
// Draw Level01 screen
if (!levelFinished) DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), LIGHTGRAY);
else DrawRectangle(60, 60, GetScreenWidth() - 120, GetScreenHeight() - 120, LIGHTGRAY);
DrawRectangleRec(outerLeftRec, GRAY);
DrawRectangleRec(innerLeftRec, RAYWHITE);
DrawRectangleRec(outerRightRec, RAYWHITE);
DrawRectangleRec(innerRightRec, GRAY);
if (levelFinished)
{
DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f));
DrawText("LEVEL 01", GetScreenWidth()/2 - MeasureText("LEVEL 01", 30)/2, 20, 30, GRAY);
DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY);
}
else DrawText("LEVEL 01", GetScreenWidth()/2 - MeasureText("LEVEL 01", 30)/2, 20, 30, LIGHTGRAY);
}
// Level01 Screen Unload logic
void UnloadLevel01Screen(void)
{
// TODO: Unload Level01 screen variables here!
}
// Level01 Screen should finish?
int FinishLevel01Screen(void)
{
return finishScreen;
}

View File

@ -0,0 +1,170 @@
/**********************************************************************************************
*
* raylib - Standard Game template
*
* Level02 Screen Functions Definitions (Init, Update, Draw, Unload)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "raylib.h"
#include "screens.h"
#include <math.h>
//----------------------------------------------------------------------------------
// Global Variables Definition (local to this module)
//----------------------------------------------------------------------------------
// Level02 screen global variables
static int framesCounter;
static int finishScreen;
static Vector2 bouncingBallPos;
static float bouncingBallRadius = 40;
static Vector2 bouncingBallSpeed;
static Vector2 holeCirclePos;
static float holeCircleRadius = 50;
static bool ballOnHole = false;
static int levelTimeSec = 0;
static bool levelFinished = false;
//----------------------------------------------------------------------------------
// Level02 Screen Functions Definition
//----------------------------------------------------------------------------------
float Vector2Distance(Vector2 v1, Vector2 v2);
// Level02 Screen Initialization logic
void InitLevel02Screen(void)
{
// TODO: Initialize Level02 screen variables here!
framesCounter = 0;
finishScreen = 0;
bouncingBallPos = (Vector2){ 120, 80 };
bouncingBallSpeed = (Vector2){ 6, 8 };
holeCirclePos = (Vector2){ GetScreenWidth()/2, GetScreenHeight()/2 };
}
// Level02 Screen Update logic
void UpdateLevel02Screen(void)
{
// Update Level02 screen
framesCounter++;
if (!ballOnHole)
{
bouncingBallPos.x += bouncingBallSpeed.x;
bouncingBallPos.y += bouncingBallSpeed.y;
if (((bouncingBallPos.x - bouncingBallRadius) <= 0) || ((bouncingBallPos.x + bouncingBallRadius) >= GetScreenWidth())) bouncingBallSpeed.x *= -1;
if (((bouncingBallPos.y - bouncingBallRadius) <= 0) || ((bouncingBallPos.y + bouncingBallRadius) >= GetScreenHeight())) bouncingBallSpeed.y *= -1;
Vector2 mousePos = GetMousePosition();
if (CheckCollisionPointCircle(mousePos, bouncingBallPos, 120))
{
bouncingBallPos.x = GetRandomValue(80, 1200);
bouncingBallPos.y = GetRandomValue(80, 650);
}
if (CheckCollisionPointCircle(mousePos, holeCirclePos, 120))
{
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
{
holeCirclePos = mousePos;
if ((holeCirclePos.x - holeCircleRadius) <= 0) holeCirclePos.x = holeCircleRadius;
else if ((holeCirclePos.x + holeCircleRadius) >= GetScreenWidth()) holeCirclePos.x = GetScreenWidth() - holeCircleRadius;
if ((holeCirclePos.y - holeCircleRadius) <= 0) holeCirclePos.y = holeCircleRadius;
else if ((holeCirclePos.y + holeCircleRadius) >= GetScreenHeight()) holeCirclePos.y = GetScreenHeight() - holeCircleRadius;
}
}
if (Vector2Distance(bouncingBallPos, holeCirclePos) < 20)
{
ballOnHole = true;
PlaySound(levelWin);
}
}
if (ballOnHole && !levelFinished)
{
levelTimeSec = framesCounter/60;
levelFinished = true;
framesCounter = 0;
}
if (levelFinished)
{
framesCounter++;
if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true;
}
}
// Level02 Screen Draw logic
void DrawLevel02Screen(void)
{
// Draw Level02 screen
DrawCircleV(holeCirclePos, holeCircleRadius, LIGHTGRAY);
DrawCircleV(bouncingBallPos, bouncingBallRadius, DARKGRAY);
DrawCircleLines(bouncingBallPos.x, bouncingBallPos.y, 120, Fade(LIGHTGRAY, 0.8f));
if (levelFinished)
{
DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f));
DrawText("LEVEL 02", GetScreenWidth()/2 - MeasureText("LEVEL 02", 30)/2, 20, 30, GRAY);
DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY);
}
else DrawText("LEVEL 02", GetScreenWidth()/2 - MeasureText("LEVEL 02", 30)/2, 20, 30, LIGHTGRAY);
}
// Level02 Screen Unload logic
void UnloadLevel02Screen(void)
{
// TODO: Unload Level02 screen variables here!
}
// Level02 Screen should finish?
int FinishLevel02Screen(void)
{
return finishScreen;
}
// Calculate distance between two points
float Vector2Distance(Vector2 v1, Vector2 v2)
{
float result;
float dx = v2.x - v1.x;
float dy = v2.y - v1.y;
result = sqrt(dx*dx + dy*dy);
return result;
}

View File

@ -0,0 +1,134 @@
/**********************************************************************************************
*
* raylib - Standard Game template
*
* Level03 Screen Functions Definitions (Init, Update, Draw, Unload)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "raylib.h"
#include "screens.h"
//----------------------------------------------------------------------------------
// Global Variables Definition (local to this module)
//----------------------------------------------------------------------------------
// Level03 screen global variables
static int framesCounter;
static int finishScreen;
static Rectangle holeRec, pieceRec;
static bool showPiece = false;
static bool pieceSelected = false;
static bool done = false;
static int levelTimeSec = 0;
static bool levelFinished = false;
//----------------------------------------------------------------------------------
// Level03 Screen Functions Definition
//----------------------------------------------------------------------------------
// Level03 Screen Initialization logic
void InitLevel03Screen(void)
{
// Initialize Level03 screen variables here!
framesCounter = 0;
finishScreen = 0;
holeRec = (Rectangle){ GetScreenWidth()/2 - 50, GetScreenHeight()/2 - 50, 100, 100 };
pieceRec = (Rectangle){ 200, 400, 100, 100 };
}
// Level03 Screen Update logic
void UpdateLevel03Screen(void)
{
// Update Level03 screen variables here!
framesCounter++;
Vector2 mousePos = GetMousePosition();
if (!done)
{
if (CheckCollisionPointRec(mousePos, holeRec)) showPiece = true;
else showPiece = false;
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
{
if (CheckCollisionPointRec(mousePos, pieceRec))
{
pieceSelected = true;
pieceRec.x = ((int)mousePos.x - 50);
pieceRec.y = ((int)mousePos.y - 50);
}
}
if ((pieceRec.x == holeRec.x) && !(CheckCollisionPointRec(mousePos, holeRec)))
{
done = true;
PlaySound(levelWin);
}
}
if (done && !levelFinished)
{
levelTimeSec = framesCounter/60;
levelFinished = true;
framesCounter = 0;
}
if (levelFinished)
{
framesCounter++;
if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true;
}
}
// Level03 Screen Draw logic
void DrawLevel03Screen(void)
{
// Draw Level03 screen
DrawRectangleRec(holeRec, GRAY);
DrawRectangleRec(pieceRec, RAYWHITE);
if (showPiece) DrawRectangleLines(pieceRec.x, pieceRec.y, pieceRec.width, pieceRec.height, Fade(LIGHTGRAY, 0.8f));
if (levelFinished)
{
DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f));
DrawText("LEVEL 03", GetScreenWidth()/2 - MeasureText("LEVEL 03", 30)/2, 20, 30, GRAY);
DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY);
}
else DrawText("LEVEL 03", GetScreenWidth()/2 - MeasureText("LEVEL 03", 30)/2, 20, 30, LIGHTGRAY);
}
// Level03 Screen Unload logic
void UnloadLevel03Screen(void)
{
// TODO: Unload Level03 screen variables here!
}
// Level03 Screen should finish?
int FinishLevel03Screen(void)
{
return finishScreen;
}

View File

@ -0,0 +1,147 @@
/**********************************************************************************************
*
* raylib - Standard Game template
*
* Level04 Screen Functions Definitions (Init, Update, Draw, Unload)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "raylib.h"
#include "screens.h"
//----------------------------------------------------------------------------------
// Global Variables Definition (local to this module)
//----------------------------------------------------------------------------------
// Level04 screen global variables
static int framesCounter;
static int finishScreen;
static Vector2 circlesCenter;
static float innerCircleRadius = 40;
static float outerCircleRadius = 300;
static bool done = false;
static int levelTimeSec = 0;
static bool levelFinished = false;
//----------------------------------------------------------------------------------
// Level04 Screen Functions Definition
//----------------------------------------------------------------------------------
// Level04 Screen Initialization logic
void InitLevel04Screen(void)
{
// Initialize Level04 screen variables here!
framesCounter = 0;
finishScreen = 0;
circlesCenter = (Vector2){ GetScreenWidth()/2, GetScreenHeight()/2 };
}
// Level04 Screen Update logic
void UpdateLevel04Screen(void)
{
// Update Level04 screen variables here!
framesCounter++;
if (!done)
{
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
{
if (CheckCollisionPointCircle(GetMousePosition(), circlesCenter, innerCircleRadius))
{
innerCircleRadius += 2;
}
else if (CheckCollisionPointCircle(GetMousePosition(), circlesCenter, outerCircleRadius))
{
outerCircleRadius += 2;
}
else
{
outerCircleRadius -= 2;
if (outerCircleRadius <= 260) outerCircleRadius = 260;
}
}
else
{
if (!done)
{
innerCircleRadius -= 2;
if (outerCircleRadius > 300) outerCircleRadius -= 2;
}
}
if (innerCircleRadius >= 270) innerCircleRadius = 270;
else if (innerCircleRadius <= 40) innerCircleRadius = 40;
if (outerCircleRadius >= 600) outerCircleRadius = 600;
if (innerCircleRadius >= outerCircleRadius)
{
done = true;
PlaySound(levelWin);
}
}
if (done && !levelFinished)
{
levelTimeSec = framesCounter/60;
levelFinished = true;
framesCounter = 0;
}
if (levelFinished)
{
framesCounter++;
if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true;
}
}
// Level04 Screen Draw logic
void DrawLevel04Screen(void)
{
// Draw Level04 screen here!
//DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), GRAY);
DrawCircleV(circlesCenter, outerCircleRadius, GRAY);
DrawCircleV(circlesCenter, innerCircleRadius, RAYWHITE);
if (levelFinished)
{
DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f));
DrawText("LEVEL 04", GetScreenWidth()/2 - MeasureText("LEVEL 04", 30)/2, 20, 30, GRAY);
DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY);
}
else DrawText("LEVEL 04", GetScreenWidth()/2 - MeasureText("LEVEL 04", 30)/2, 20, 30, LIGHTGRAY);
}
// Level04 Screen Unload logic
void UnloadLevel04Screen(void)
{
// TODO: Unload Level04 screen variables here!
}
// Level04 Screen should finish?
int FinishLevel04Screen(void)
{
return finishScreen;
}

View File

@ -0,0 +1,185 @@
/**********************************************************************************************
*
* raylib - Standard Game template
*
* Level05 Screen Functions Definitions (Init, Update, Draw, Unload)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "raylib.h"
#include "screens.h"
#define NUM_CIRCLES 10
//----------------------------------------------------------------------------------
// Global Variables Definition (local to this module)
//----------------------------------------------------------------------------------
// Level05 screen global variables
static int framesCounter;
static int finishScreen;
static Vector2 circleCenter;
static float circleRadius[NUM_CIRCLES];
static bool circleLocked[NUM_CIRCLES];
static Color circleColor[NUM_CIRCLES];
static bool done = false;
static int levelTimeSec = 0;
static bool levelFinished = false;
//----------------------------------------------------------------------------------
// Level05 Screen Functions Definition
//----------------------------------------------------------------------------------
static bool CheckColor(Color col1, Color col2);
// Level05 Screen Initialization logic
void InitLevel05Screen(void)
{
// Initialize Level05 screen variables here!
framesCounter = 0;
finishScreen = 0;
circleCenter = (Vector2){ GetScreenWidth()/2, GetScreenHeight()/2 };
for (int i = 0; i < NUM_CIRCLES; i++)
{
circleRadius[i] = 760/NUM_CIRCLES*(NUM_CIRCLES - i);
circleLocked[i] = false;
}
// That's a dirty hack to give sonme coherence to this puzzle...
circleColor[9] = GRAY;
circleColor[8] = RAYWHITE;
circleColor[7] = RAYWHITE;
circleColor[6] = GRAY;
circleColor[5] = RAYWHITE;
circleColor[4] = GRAY;
circleColor[3] = GRAY;
circleColor[2] = GRAY;
circleColor[1] = RAYWHITE;
circleColor[0] = GRAY;
}
// Level05 Screen Update logic
void UpdateLevel05Screen(void)
{
// Update Level05 screen variables here!
framesCounter++;
if (!done)
{
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
for (int i = NUM_CIRCLES - 1; i >= 0; i--)
{
if (CheckCollisionPointCircle(GetMousePosition(), circleCenter, circleRadius[i]))
{
if (i == 0)
{
if (CheckColor(circleColor[8], GRAY)) circleColor[8] = RAYWHITE;
else circleColor[8] = GRAY;
}
else if (i == 2)
{
if (CheckColor(circleColor[5], GRAY)) circleColor[5] = RAYWHITE;
else circleColor[5] = GRAY;
}
else if (i == 3)
{
if (CheckColor(circleColor[6], GRAY)) circleColor[6] = RAYWHITE;
else circleColor[6] = GRAY;
}
else
{
if (CheckColor(circleColor[i], GRAY)) circleColor[i] = RAYWHITE;
else circleColor[i] = GRAY;
}
return;
}
}
}
// Check all cicles done
for (int i = 0; i < NUM_CIRCLES; i++)
{
done = true;
if (CheckColor(circleColor[i], RAYWHITE))
{
done = false;
return;
}
//if (done) PlaySound(levelWin);
}
}
if (done && !levelFinished)
{
levelTimeSec = framesCounter/60;
levelFinished = true;
framesCounter = 0;
}
if (levelFinished)
{
framesCounter++;
if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true;
}
}
// Level05 Screen Draw logic
void DrawLevel05Screen(void)
{
// Draw Level05 screen
for (int i = 0; i < NUM_CIRCLES; i++)
{
DrawPoly(circleCenter, 64, circleRadius[i], 0.0f, circleColor[i]);
}
if (levelFinished)
{
DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f));
DrawText("LEVEL 05", GetScreenWidth()/2 - MeasureText("LEVEL 05", 30)/2, 20, 30, GRAY);
DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY);
}
else DrawText("LEVEL 05", GetScreenWidth()/2 - MeasureText("LEVEL 05", 30)/2, 20, 30, LIGHTGRAY);
}
// Level05 Screen Unload logic
void UnloadLevel05Screen(void)
{
// TODO: Unload Level05 screen variables here!
}
// Level05 Screen should finish?
int FinishLevel05Screen(void)
{
return finishScreen;
}
static bool CheckColor(Color col1, Color col2)
{
return ((col1.r == col2.r) && (col1.g == col2.g) && (col1.b == col2.b) && (col1.a == col2.a));
}

View File

@ -0,0 +1,156 @@
/**********************************************************************************************
*
* raylib - Standard Game template
*
* Level06 Screen Functions Definitions (Init, Update, Draw, Unload)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "raylib.h"
#include "screens.h"
//----------------------------------------------------------------------------------
// Global Variables Definition (local to this module)
//----------------------------------------------------------------------------------
// Level06 screen global variables
static int framesCounter;
static int finishScreen;
static Rectangle centerRec;
static Rectangle movingRecs[4];
static int speedRecs[4];
static bool stoppedRec[4];
static int mouseOverNum = -1;
static bool done = false;
static int levelTimeSec = 0;
static bool levelFinished = false;
//----------------------------------------------------------------------------------
// Level06 Screen Functions Definition
//----------------------------------------------------------------------------------
// Level06 Screen Initialization logic
void InitLevel06Screen(void)
{
// Initialize Level06 screen variables here!
framesCounter = 0;
finishScreen = 0;
centerRec = (Rectangle){ GetScreenWidth()/2 - 100, 0, 200, GetScreenHeight() };
for (int i = 0; i < 4; i++)
{
movingRecs[i] = (Rectangle){ GetRandomValue(0, 5)*150, (i*150) + 90, 100, 100 };
stoppedRec[i] = false;
speedRecs[i] = GetRandomValue(4, 8);
}
}
// Level06 Screen Update logic
void UpdateLevel06Screen(void)
{
// Update Level06 screen variables here!
framesCounter++;
if (!done)
{
for (int i = 0; i < 4; i++)
{
if (!stoppedRec[i]) movingRecs[i].x += speedRecs[i];
if (movingRecs[i].x >= GetScreenWidth()) movingRecs[i].x = -movingRecs[i].width;
if (CheckCollisionPointRec(GetMousePosition(), movingRecs[i]))
{
mouseOverNum = i;
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
if (i == 0) stoppedRec[3] = !stoppedRec[3];
else if (i == 1) stoppedRec[2] = !stoppedRec[2];
else if (i == 2) stoppedRec[0] = !stoppedRec[0];
else if (i == 3) stoppedRec[1] = !stoppedRec[1];
}
}
}
// Check if all boxes are aligned
if (((movingRecs[0].x > centerRec.x) && ((movingRecs[0].x + movingRecs[0].width) < (centerRec.x + centerRec.width))) &&
((movingRecs[1].x > centerRec.x) && ((movingRecs[1].x + movingRecs[1].width) < (centerRec.x + centerRec.width))) &&
((movingRecs[2].x > centerRec.x) && ((movingRecs[2].x + movingRecs[2].width) < (centerRec.x + centerRec.width))) &&
((movingRecs[3].x > centerRec.x) && ((movingRecs[3].x + movingRecs[3].width) < (centerRec.x + centerRec.width))))
{
done = true;
PlaySound(levelWin);
}
}
if (done && !levelFinished)
{
levelTimeSec = framesCounter/60;
levelFinished = true;
framesCounter = 0;
}
if (levelFinished)
{
framesCounter++;
if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true;
}
}
// Level06 Screen Draw logic
void DrawLevel06Screen(void)
{
// Draw Level06 screen
DrawRectangleRec(centerRec, LIGHTGRAY);
for (int i = 0; i < 4; i++)
{
DrawRectangleRec(movingRecs[i], GRAY);
}
if (!done & (mouseOverNum >= 0)) DrawRectangleLines(movingRecs[mouseOverNum].x - 5, movingRecs[mouseOverNum].y - 5, movingRecs[mouseOverNum].width + 10, movingRecs[mouseOverNum].height + 10, Fade(LIGHTGRAY, 0.8f));
if (levelFinished)
{
DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f));
DrawText("LEVEL 06", GetScreenWidth()/2 - MeasureText("LEVEL 06", 30)/2, 20, 30, GRAY);
DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY);
}
else DrawText("LEVEL 06", GetScreenWidth()/2 - MeasureText("LEVEL 06", 30)/2, 20, 30, LIGHTGRAY);
}
// Level06 Screen Unload logic
void UnloadLevel06Screen(void)
{
// TODO: Unload Level06 screen variables here!
}
// Level06 Screen should finish?
int FinishLevel06Screen(void)
{
return finishScreen;
}

View File

@ -0,0 +1,178 @@
/**********************************************************************************************
*
* raylib - Standard Game template
*
* Level07 Screen Functions Definitions (Init, Update, Draw, Unload)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "raylib.h"
#include "screens.h"
//----------------------------------------------------------------------------------
// Global Variables Definition (local to this module)
//----------------------------------------------------------------------------------
// Level07 screen global variables
static int framesCounter;
static int finishScreen;
static Vector2 leftCirclePos, middleCirclePos, rightCirclePos;
static Vector2 leftBtnPos, middleBtnPos, rightBtnPos;
static float circleRadius = 100;
static float btnRadius = 80;
static bool leftCircleActive, middleCircleActive, rightCircleActive;
static Color leftCircleColor, middleCircleColor, rightCircleColor;
static bool done = false;
static int levelTimeSec = 0;
static bool levelFinished = false;
//----------------------------------------------------------------------------------
// Level07 Screen Functions Definition
//----------------------------------------------------------------------------------
static bool CheckColor(Color col1, Color col2);
// Level07 Screen Initialization logic
void InitLevel07Screen(void)
{
// Initialize Level07 screen variables here!
framesCounter = 0;
finishScreen = 0;
leftCirclePos = (Vector2){ GetScreenWidth()/2 - 340, GetScreenHeight()/2 - 100 };
middleCirclePos = (Vector2){ GetScreenWidth()/2, GetScreenHeight()/2 - 100 };
rightCirclePos = (Vector2){ GetScreenWidth()/2 + 340, GetScreenHeight()/2 - 100 };
leftBtnPos = (Vector2){ GetScreenWidth()/2 - 340, GetScreenHeight()/2 + 120 };
middleBtnPos = (Vector2){ GetScreenWidth()/2, GetScreenHeight()/2 + 120 };
rightBtnPos = (Vector2){ GetScreenWidth()/2 + 340, GetScreenHeight()/2 + 120 };
leftCircleActive = false;
middleCircleActive = true;
rightCircleActive = false;
leftCircleColor = GRAY;
middleCircleColor = GRAY;
rightCircleColor = GRAY;
}
// Level07 Screen Update logic
void UpdateLevel07Screen(void)
{
// Update Level07 screen variables here!
framesCounter++;
if (!done)
{
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
if (CheckCollisionPointCircle(GetMousePosition(), leftBtnPos, btnRadius)) leftCircleActive = !leftCircleActive;
else if (CheckCollisionPointCircle(GetMousePosition(), middleBtnPos, btnRadius)) middleCircleActive = !middleCircleActive;
else if (CheckCollisionPointCircle(GetMousePosition(), rightBtnPos, btnRadius)) rightCircleActive = !rightCircleActive;
if (rightCircleActive && CheckCollisionPointCircle(GetMousePosition(), leftCirclePos, circleRadius))
{
if (CheckColor(leftCircleColor, GRAY)) leftCircleColor = LIGHTGRAY;
else leftCircleColor = GRAY;
}
if (middleCircleActive && CheckCollisionPointCircle(GetMousePosition(), middleCirclePos, circleRadius))
{
if (CheckColor(middleCircleColor, GRAY)) middleCircleColor = LIGHTGRAY;
else middleCircleColor = GRAY;
}
if (rightCircleActive && leftCircleActive && CheckCollisionPointCircle(GetMousePosition(), rightCirclePos, circleRadius))
{
if (CheckColor(rightCircleColor, GRAY)) rightCircleColor = LIGHTGRAY;
else rightCircleColor = GRAY;
}
}
// Check all cicles done
if (CheckColor(leftCircleColor, LIGHTGRAY) && CheckColor(middleCircleColor, LIGHTGRAY) && CheckColor(rightCircleColor, LIGHTGRAY) &&
!leftCircleActive && !middleCircleActive && !rightCircleActive)
{
done = true;
PlaySound(levelWin);
}
}
if (done && !levelFinished)
{
levelTimeSec = framesCounter/60;
levelFinished = true;
framesCounter = 0;
}
if (levelFinished)
{
framesCounter++;
if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true;
}
}
// Level07 Screen Draw logic
void DrawLevel07Screen(void)
{
// Draw Level07 screen here!
DrawCircleV(leftCirclePos, circleRadius, leftCircleColor);
DrawCircleV(middleCirclePos, circleRadius, middleCircleColor);
DrawCircleV(rightCirclePos, circleRadius, rightCircleColor);
if (leftCircleActive) DrawCircleV(leftBtnPos, btnRadius, GRAY);
else DrawCircleV(leftBtnPos, btnRadius, LIGHTGRAY);
if (middleCircleActive) DrawCircleV(middleBtnPos, btnRadius, GRAY);
else DrawCircleV(middleBtnPos, btnRadius, LIGHTGRAY);
if (rightCircleActive) DrawCircleV(rightBtnPos, btnRadius, GRAY);
else DrawCircleV(rightBtnPos, btnRadius, LIGHTGRAY);
if (levelFinished)
{
DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f));
DrawText("LEVEL 07", GetScreenWidth()/2 - MeasureText("LEVEL 07", 30)/2, 20, 30, GRAY);
DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY);
}
else DrawText("LEVEL 07", GetScreenWidth()/2 - MeasureText("LEVEL 07", 30)/2, 20, 30, LIGHTGRAY);
}
// Level07 Screen Unload logic
void UnloadLevel07Screen(void)
{
// TODO: Unload Level07 screen variables here!
}
// Level07 Screen should finish?
int FinishLevel07Screen(void)
{
return finishScreen;
}
static bool CheckColor(Color col1, Color col2)
{
return ((col1.r == col2.r) && (col1.g == col2.g) && (col1.b == col2.b) && (col1.a == col2.a));
}

View File

@ -0,0 +1,157 @@
/**********************************************************************************************
*
* raylib - Standard Game template
*
* Level08 Screen Functions Definitions (Init, Update, Draw, Unload)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "raylib.h"
#include "screens.h"
//----------------------------------------------------------------------------------
// Global Variables Definition (local to this module)
//----------------------------------------------------------------------------------
// Level08 screen global variables
static int framesCounter;
static int finishScreen;
static Rectangle leftColumnRec, middleColumnRec, rightColumnRec;
static Rectangle movingBox;
static int moveSpeed = 4;
static bool leftColumnActive, middleColumnActive, rightColumnActive;
static bool done = false;
static int levelTimeSec = 0;
static bool levelFinished = false;
//----------------------------------------------------------------------------------
// Level08 Screen Functions Definition
//----------------------------------------------------------------------------------
// Level08 Screen Initialization logic
void InitLevel08Screen(void)
{
// TODO: Initialize Level08 screen variables here!
framesCounter = 0;
finishScreen = 0;
movingBox = (Rectangle){ 20, GetScreenHeight()/2 - 20, 40, 40 };
leftColumnRec = (Rectangle){ 240, 0, 100, GetScreenHeight() };
middleColumnRec = (Rectangle){ GetScreenWidth()/2 - 50, 0, 100, GetScreenHeight() };
rightColumnRec = (Rectangle){ 920, 0, 100, GetScreenHeight() };
leftColumnActive = true;
middleColumnActive = false;
rightColumnActive = true;
}
// Level08 Screen Update logic
void UpdateLevel08Screen(void)
{
// Update Level08 screen variables here!
framesCounter++;
if (!done)
{
movingBox.x += moveSpeed;
if (movingBox.x <= 0) moveSpeed *= -1;
if ((leftColumnActive && (CheckCollisionRecs(leftColumnRec, movingBox))) ||
(middleColumnActive && (CheckCollisionRecs(middleColumnRec, movingBox))) ||
(rightColumnActive && (CheckCollisionRecs(rightColumnRec, movingBox)))) moveSpeed *= -1;
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
if (CheckCollisionPointRec(GetMousePosition(), leftColumnRec))
{
middleColumnActive = false;
rightColumnActive = true;
}
else if (CheckCollisionPointRec(GetMousePosition(), middleColumnRec))
{
rightColumnActive = false;
leftColumnActive = true;
}
else if (CheckCollisionPointRec(GetMousePosition(), rightColumnRec))
{
leftColumnActive = false;
middleColumnActive = true;
}
}
if (movingBox.x >= 1100)
{
done = true;
PlaySound(levelWin);
}
}
if (done && !levelFinished)
{
levelTimeSec = framesCounter/60;
levelFinished = true;
framesCounter = 0;
}
if (levelFinished)
{
framesCounter++;
if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true;
}
}
// Level08 Screen Draw logic
void DrawLevel08Screen(void)
{
// Draw Level08 screen
DrawRectangle(1100, GetScreenHeight()/2 - 20, 40, 40, GRAY);
DrawRectangleRec(movingBox, LIGHTGRAY);
if (leftColumnActive) DrawRectangleRec(leftColumnRec, GRAY);
if (middleColumnActive) DrawRectangleRec(middleColumnRec, GRAY);
if (rightColumnActive) DrawRectangleRec(rightColumnRec, GRAY);
if (levelFinished)
{
DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f));
DrawText("LEVEL 08", GetScreenWidth()/2 - MeasureText("LEVEL 08", 30)/2, 20, 30, GRAY);
DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY);
}
else DrawText("LEVEL 08", GetScreenWidth()/2 - MeasureText("LEVEL 08", 30)/2, 20, 30, LIGHTGRAY);
}
// Level08 Screen Unload logic
void UnloadLevel08Screen(void)
{
// TODO: Unload Level08 screen variables here!
}
// Level08 Screen should finish?
int FinishLevel08Screen(void)
{
return finishScreen;
}

View File

@ -0,0 +1,199 @@
/**********************************************************************************************
*
* raylib - Standard Game template
*
* Level09 Screen Functions Definitions (Init, Update, Draw, Unload)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "raylib.h"
#include "screens.h"
#define NUM_BOXES 21
//----------------------------------------------------------------------------------
// Global Variables Definition (local to this module)
//----------------------------------------------------------------------------------
// Level09 screen global variables
static int framesCounter;
static int finishScreen;
static Rectangle bwRecs[NUM_BOXES];
static Color bwColors[NUM_BOXES];
static bool activated[NUM_BOXES];
static int resetCounter = 0;
static bool enableCounter = 0;
static bool done = false;
static int levelTimeSec = 0;
static bool levelFinished = false;
//----------------------------------------------------------------------------------
// Level09 Screen Functions Definition
//----------------------------------------------------------------------------------
static bool CheckColor(Color col1, Color col2);
// Level09 Screen Initialization logic
void InitLevel09Screen(void)
{
// Initialize Level09 screen variables here!
framesCounter = 0;
finishScreen = 0;
for (int i = 0; i < NUM_BOXES; i++)
{
bwRecs[i].x = GetScreenWidth()/7*(i%7);
bwRecs[i].y = GetScreenHeight()/3*(i/7);
bwRecs[i].width = GetScreenWidth()/7;
bwRecs[i].height = GetScreenHeight()/3;
activated[i] = false;
if (i%2 == 0) bwColors[i] = LIGHTGRAY;
else bwColors[i] = GRAY;
}
bwColors[10] = RAYWHITE;
}
// Level09 Screen Update logic
void UpdateLevel09Screen(void)
{
// Update Level09 screen variables here!
framesCounter++;
if (enableCounter) resetCounter++;
if (!done)
{
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
for (int i = 0; i < NUM_BOXES; i++)
{
if (CheckCollisionPointRec(GetMousePosition(), bwRecs[i]))
{
if (i == 10)
{
if (CheckColor(bwColors[i], RAYWHITE))
{
bwColors[i] = LIGHTGRAY;
enableCounter = true;
resetCounter = 0;
activated[1] = true;
}
else
{
bwColors[i] = RAYWHITE;
enableCounter = false;
resetCounter = 5*60;
for (int i = 0; i < NUM_BOXES; i++) activated[i] = false;
}
}
else if ((i%2 == 1) && enableCounter)
{
if (activated[i])
{
bwColors[i] = LIGHTGRAY;
if (i != 19) activated[i + 2] = true;
}
}
}
}
}
if (resetCounter > (4*60 + 10))
{
for (int i = 0; i < NUM_BOXES; i++)
{
if (i%2 == 0) bwColors[i] = LIGHTGRAY;
else bwColors[i] = GRAY;
activated[i] = false;
}
bwColors[10] = RAYWHITE;
enableCounter = false;
resetCounter = 0;
}
for (int i = 0; i < NUM_BOXES; i++)
{
done = true;
if (!CheckColor(bwColors[i], LIGHTGRAY))
{
done = false;
return;
}
//if (done) PlaySound(levelWin);
}
}
if (done && !levelFinished)
{
levelTimeSec = framesCounter/60;
levelFinished = true;
framesCounter = 0;
}
if (levelFinished)
{
framesCounter++;
if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true;
}
}
// Level09 Screen Draw logic
void DrawLevel09Screen(void)
{
// Draw Level09 screen
for (int i = 0; i < NUM_BOXES; i++)
{
DrawRectangleRec(bwRecs[i], bwColors[i]);
}
if (levelFinished)
{
DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(RAYWHITE, 0.6f));
DrawText("LEVEL 09", GetScreenWidth()/2 - MeasureText("LEVEL 09", 30)/2, 20, 30, GRAY);
DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY);
}
else DrawText("LEVEL 09", GetScreenWidth()/2 - MeasureText("LEVEL 09", 30)/2, 20, 30, LIGHTGRAY);
}
// Level09 Screen Unload logic
void UnloadLevel09Screen(void)
{
// TODO: Unload Level09 screen variables here!
}
// Level09 Screen should finish?
int FinishLevel09Screen(void)
{
return finishScreen;
}
static bool CheckColor(Color col1, Color col2)
{
return ((col1.r == col2.r) && (col1.g == col2.g) && (col1.b == col2.b) && (col1.a == col2.a));
}

View File

@ -0,0 +1,153 @@
/**********************************************************************************************
*
* raylib - Standard Game template
*
* Level10 Screen Functions Definitions (Init, Update, Draw, Unload)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "raylib.h"
#include "screens.h"
//----------------------------------------------------------------------------------
// Global Variables Definition (local to this module)
//----------------------------------------------------------------------------------
// Level10 screen global variables
static int framesCounter;
static int finishScreen;
static Rectangle leftColumnRec, middleColumnRec, rightColumnRec;
static Rectangle movingBox;
static int moveSpeed = 4;
static bool leftColumnActive, middleColumnActive, rightColumnActive;
static bool done = false;
static int levelTimeSec = 0;
static bool levelFinished = false;
//----------------------------------------------------------------------------------
// Level10 Screen Functions Definition
//----------------------------------------------------------------------------------
// Level10 Screen Initialization logic
void InitLevel10Screen(void)
{
// TODO: Initialize Level10 screen variables here!
framesCounter = 0;
finishScreen = 0;
movingBox = (Rectangle){ 20, GetScreenHeight()/2 - 20, 40, 40 };
leftColumnRec = (Rectangle){ 240, 0, 100, GetScreenHeight() };
middleColumnRec = (Rectangle){ GetScreenWidth()/2 - 50, 0, 100, GetScreenHeight() };
rightColumnRec = (Rectangle){ 920, 0, 100, GetScreenHeight() };
leftColumnActive = true;
middleColumnActive = false;
rightColumnActive = true;
}
// Level10 Screen Update logic
void UpdateLevel10Screen(void)
{
// Update Level10 screen variables here!
framesCounter++;
if (!done)
{
movingBox.x += moveSpeed;
if (movingBox.x <= 0) moveSpeed *= -1;
if ((leftColumnActive && (CheckCollisionRecs(leftColumnRec, movingBox))) ||
(middleColumnActive && (CheckCollisionRecs(middleColumnRec, movingBox))) ||
(rightColumnActive && (CheckCollisionRecs(rightColumnRec, movingBox)))) moveSpeed *= -1;
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
if (CheckCollisionPointRec(GetMousePosition(), leftColumnRec))
{
middleColumnActive = false;
rightColumnActive = true;
}
else if (CheckCollisionPointRec(GetMousePosition(), middleColumnRec))
{
rightColumnActive = false;
leftColumnActive = true;
}
else if (CheckCollisionPointRec(GetMousePosition(), rightColumnRec))
{
leftColumnActive = false;
middleColumnActive = true;
}
}
}
if (movingBox.x >= 1100) done = true;
if (done && !levelFinished)
{
levelTimeSec = framesCounter/60;
levelFinished = true;
framesCounter = 0;
}
if (levelFinished)
{
framesCounter++;
if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true;
}
}
// Level10 Screen Draw logic
void DrawLevel10Screen(void)
{
// Draw Level10 screen
DrawRectangle(1100, GetScreenHeight()/2 - 20, 40, 40, GRAY);
DrawRectangleRec(movingBox, LIGHTGRAY);
if (leftColumnActive) DrawRectangleRec(leftColumnRec, GRAY);
if (middleColumnActive) DrawRectangleRec(middleColumnRec, GRAY);
if (rightColumnActive) DrawRectangleRec(rightColumnRec, GRAY);
if (levelFinished)
{
DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f));
DrawText("LEVEL 08", GetScreenWidth()/2 - MeasureText("LEVEL 08", 30)/2, 20, 30, GRAY);
DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY);
}
else DrawText("LEVEL 08", GetScreenWidth()/2 - MeasureText("LEVEL 08", 30)/2, 20, 30, LIGHTGRAY);
}
// Level10 Screen Unload logic
void UnloadLevel10Screen(void)
{
// TODO: Unload Level10 screen variables here!
}
// Level10 Screen should finish?
int FinishLevel10Screen(void)
{
return finishScreen;
}

View File

@ -0,0 +1,227 @@
/**********************************************************************************************
*
* raylib - Standard Game template
*
* Logo Screen Functions Definitions (Init, Update, Draw, Unload)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "raylib.h"
#include "screens.h"
#include <string.h>
//----------------------------------------------------------------------------------
// Global Variables Definition (local to this module)
//----------------------------------------------------------------------------------
// Logo screen global variables
static int framesCounter;
static int finishScreen;
const char msgLogoA[64] = "A simple and easy-to-use library";
const char msgLogoB[64] = "to learn videogames programming";
int logoPositionX;
int logoPositionY;
int raylibLettersCount = 0;
int topSideRecWidth = 16;
int leftSideRecHeight = 16;
int bottomSideRecWidth = 16;
int rightSideRecHeight = 16;
char raylib[8] = " \0"; // raylib text array, max 8 letters
int logoScreenState = 0; // Tracking animation states (State Machine)
bool msgLogoADone = false;
bool msgLogoBDone = false;
int lettersCounter = 0;
char msgBuffer[128] = { ' ' };
//----------------------------------------------------------------------------------
// Logo Screen Functions Definition
//----------------------------------------------------------------------------------
// Logo Screen Initialization logic
void InitLogoScreen(void)
{
// Initialize LOGO screen variables here!
framesCounter = 0;
finishScreen = 0;
logoPositionX = GetScreenWidth()/2 - 128;
logoPositionY = GetScreenHeight()/2 - 128;
}
// Logo Screen Update logic
void UpdateLogoScreen(void)
{
// Update LOGO screen
framesCounter++; // Count frames
// Update LOGO screen variables
if (logoScreenState == 0) // State 0: Small box blinking
{
framesCounter++;
if (framesCounter == 120)
{
logoScreenState = 1;
framesCounter = 0; // Reset counter... will be used later...
}
}
else if (logoScreenState == 1) // State 1: Top and left bars growing
{
topSideRecWidth += 4;
leftSideRecHeight += 4;
if (topSideRecWidth == 256) logoScreenState = 2;
}
else if (logoScreenState == 2) // State 2: Bottom and right bars growing
{
bottomSideRecWidth += 4;
rightSideRecHeight += 4;
if (bottomSideRecWidth == 256)
{
lettersCounter = 0;
for (int i = 0; i < strlen(msgBuffer); i++) msgBuffer[i] = ' ';
logoScreenState = 3;
}
}
else if (logoScreenState == 3) // State 3: Letters appearing (one by one)
{
framesCounter++;
// Every 12 frames, one more letter!
if ((framesCounter%12) == 0) raylibLettersCount++;
switch (raylibLettersCount)
{
case 1: raylib[0] = 'r'; break;
case 2: raylib[1] = 'a'; break;
case 3: raylib[2] = 'y'; break;
case 4: raylib[3] = 'l'; break;
case 5: raylib[4] = 'i'; break;
case 6: raylib[5] = 'b'; break;
default: break;
}
if (raylibLettersCount >= 10)
{
// Write raylib description messages
if ((framesCounter%2) == 0) lettersCounter++;
if (!msgLogoADone)
{
if (lettersCounter <= strlen(msgLogoA)) strncpy(msgBuffer, msgLogoA, lettersCounter);
else
{
for (int i = 0; i < strlen(msgBuffer); i++) msgBuffer[i] = ' ';
lettersCounter = 0;
msgLogoADone = true;
}
}
else if (!msgLogoBDone)
{
if (lettersCounter <= strlen(msgLogoB)) strncpy(msgBuffer, msgLogoB, lettersCounter);
else
{
msgLogoBDone = true;
framesCounter = 0;
PlaySound(levelWin);
}
}
}
}
// Wait for 2 seconds (60 frames) before jumping to TITLE screen
if (msgLogoBDone)
{
framesCounter++;
if (framesCounter > 90) finishScreen = true;
}
}
// Logo Screen Draw logic
void DrawLogoScreen(void)
{
// Draw LOGO screen
if (logoScreenState == 0)
{
if ((framesCounter/15)%2) DrawRectangle(logoPositionX, logoPositionY - 60, 16, 16, BLACK);
}
else if (logoScreenState == 1)
{
DrawRectangle(logoPositionX, logoPositionY - 60, topSideRecWidth, 16, BLACK);
DrawRectangle(logoPositionX, logoPositionY - 60, 16, leftSideRecHeight, BLACK);
}
else if (logoScreenState == 2)
{
DrawRectangle(logoPositionX, logoPositionY - 60, topSideRecWidth, 16, BLACK);
DrawRectangle(logoPositionX, logoPositionY - 60, 16, leftSideRecHeight, BLACK);
DrawRectangle(logoPositionX + 240, logoPositionY - 60, 16, rightSideRecHeight, BLACK);
DrawRectangle(logoPositionX, logoPositionY + 240 - 60, bottomSideRecWidth, 16, BLACK);
}
else if (logoScreenState == 3)
{
DrawRectangle(logoPositionX, logoPositionY - 60, topSideRecWidth, 16, BLACK);
DrawRectangle(logoPositionX, logoPositionY + 16 - 60, 16, leftSideRecHeight - 32, BLACK);
DrawRectangle(logoPositionX + 240, logoPositionY + 16 - 60, 16, rightSideRecHeight - 32, BLACK);
DrawRectangle(logoPositionX, logoPositionY + 240 - 60, bottomSideRecWidth, 16, BLACK);
DrawRectangle(GetScreenWidth()/2 - 112, GetScreenHeight()/2 - 112 - 60, 224, 224, RAYWHITE);
DrawText(raylib, GetScreenWidth()/2 - 44, GetScreenHeight()/2 + 48 - 60, 50, BLACK);
if (!msgLogoADone) DrawText(msgBuffer, GetScreenWidth()/2 - MeasureText(msgLogoA, 30)/2, logoPositionY + 230, 30, GRAY);
else
{
DrawText(msgLogoA, GetScreenWidth()/2 - MeasureText(msgLogoA, 30)/2, logoPositionY + 230, 30, GRAY);
if (!msgLogoBDone) DrawText(msgBuffer, GetScreenWidth()/2 - MeasureText(msgLogoB, 30)/2, logoPositionY + 280, 30, GRAY);
else
{
DrawText(msgLogoB, GetScreenWidth()/2 - MeasureText(msgLogoA, 30)/2, logoPositionY + 280, 30, GRAY);
}
}
}
}
// Logo Screen Unload logic
void UnloadLogoScreen(void)
{
// TODO: Unload LOGO screen variables here!
}
// Logo Screen should finish?
int FinishLogoScreen(void)
{
return finishScreen;
}

View File

@ -0,0 +1,150 @@
/**********************************************************************************************
*
* raylib - Standard Game template
*
* Screens Functions Declarations (Init, Update, Draw, Unload)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#ifndef SCREENS_H
#define SCREENS_H
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef enum GameScreen { LOGO, LEVEL00, LEVEL01, LEVEL02, LEVEL03, LEVEL04, LEVEL05, LEVEL06, LEVEL07, LEVEL08, LEVEL09 } GameScreen;
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
GameScreen currentScreen;
Sound levelWin;
#ifdef __cplusplus
extern "C" { // Prevents name mangling of functions
#endif
//----------------------------------------------------------------------------------
// Logo Screen Functions Declaration
//----------------------------------------------------------------------------------
void InitLogoScreen(void);
void UpdateLogoScreen(void);
void DrawLogoScreen(void);
void UnloadLogoScreen(void);
int FinishLogoScreen(void);
//----------------------------------------------------------------------------------
// Level00 Screen Functions Declaration
//----------------------------------------------------------------------------------
void InitLevel00Screen(void);
void UpdateLevel00Screen(void);
void DrawLevel00Screen(void);
void UnloadLevel00Screen(void);
int FinishLevel00Screen(void);
//----------------------------------------------------------------------------------
// Level01 Screen Functions Declaration
//----------------------------------------------------------------------------------
void InitLevel01Screen(void);
void UpdateLevel01Screen(void);
void DrawLevel01Screen(void);
void UnloadLevel01Screen(void);
int FinishLevel01Screen(void);
//----------------------------------------------------------------------------------
// Level02 Screen Functions Declaration
//----------------------------------------------------------------------------------
void InitLevel02Screen(void);
void UpdateLevel02Screen(void);
void DrawLevel02Screen(void);
void UnloadLevel02Screen(void);
int FinishLevel02Screen(void);
//----------------------------------------------------------------------------------
// Level03 Screen Functions Declaration
//----------------------------------------------------------------------------------
void InitLevel03Screen(void);
void UpdateLevel03Screen(void);
void DrawLevel03Screen(void);
void UnloadLevel03Screen(void);
int FinishLevel03Screen(void);
//----------------------------------------------------------------------------------
// Level04 Screen Functions Declaration
//----------------------------------------------------------------------------------
void InitLevel04Screen(void);
void UpdateLevel04Screen(void);
void DrawLevel04Screen(void);
void UnloadLevel04Screen(void);
int FinishLevel04Screen(void);
//----------------------------------------------------------------------------------
// Level05 Screen Functions Declaration
//----------------------------------------------------------------------------------
void InitLevel05Screen(void);
void UpdateLevel05Screen(void);
void DrawLevel05Screen(void);
void UnloadLevel05Screen(void);
int FinishLevel05Screen(void);
//----------------------------------------------------------------------------------
// Level06 Screen Functions Declaration
//----------------------------------------------------------------------------------
void InitLevel06Screen(void);
void UpdateLevel06Screen(void);
void DrawLevel06Screen(void);
void UnloadLevel06Screen(void);
int FinishLevel06Screen(void);
//----------------------------------------------------------------------------------
// Level07 Screen Functions Declaration
//----------------------------------------------------------------------------------
void InitLevel07Screen(void);
void UpdateLevel07Screen(void);
void DrawLevel07Screen(void);
void UnloadLevel07Screen(void);
int FinishLevel07Screen(void);
//----------------------------------------------------------------------------------
// Level08 Screen Functions Declaration
//----------------------------------------------------------------------------------
void InitLevel08Screen(void);
void UpdateLevel08Screen(void);
void DrawLevel08Screen(void);
void UnloadLevel08Screen(void);
int FinishLevel08Screen(void);
//----------------------------------------------------------------------------------
// Level09 Screen Functions Declaration
//----------------------------------------------------------------------------------
void InitLevel09Screen(void);
void UpdateLevel09Screen(void);
void DrawLevel09Screen(void);
void UnloadLevel09Screen(void);
int FinishLevel09Screen(void);
void DrawRectangleBordersRec(Rectangle rec, int offsetX, int offsetY, int borderSize, Color col);
#ifdef __cplusplus
}
#endif
#endif // SCREENS_H

View File

@ -39,7 +39,8 @@
#include "utils.h" // rRES data decompression utility function
// NOTE: Includes Android fopen function map
#include "stb_vorbis.h" // OGG loading functions
//#define STB_VORBIS_HEADER_ONLY
#include "stb_vorbis.h" // OGG loading functions
//----------------------------------------------------------------------------------
// Defines and Macros
@ -49,7 +50,7 @@
#if defined(PLATFORM_RPI)
// NOTE: On RPI should be lower to avoid frame-stalls
#define MUSIC_BUFFER_SIZE 4096*2 // PCM data buffer (short) - 16Kb (RPI)
#else
#else
// NOTE: On HTML5 (emscripten) this is allocated on heap, by default it's only 16MB!...just take care...
#define MUSIC_BUFFER_SIZE 4096*8 // PCM data buffer (short) - 64Kb
#endif
@ -201,7 +202,7 @@ Sound LoadSound(char *fileName)
// Attach sound buffer to source
alSourcei(source, AL_BUFFER, buffer);
TraceLog(INFO, "[%s] Sound file loaded successfully (SampleRate: %i, BitRate: %i, Channels: %i)", fileName, wave.sampleRate, wave.bitsPerSample, wave.channels);
// Unallocate WAV data
@ -283,7 +284,7 @@ Sound LoadSoundFromRES(const char *rresName, int resId)
FILE *rresFile = fopen(rresName, "rb");
if (rresFile == NULL)
if (rresFile == NULL)
{
TraceLog(WARNING, "[%s] rRES raylib resource file could not be opened", rresName);
}
@ -378,7 +379,7 @@ Sound LoadSoundFromRES(const char *rresName, int resId)
// Attach sound buffer to source
alSourcei(source, AL_BUFFER, buffer);
TraceLog(INFO, "[%s] Sound loaded successfully from resource (SampleRate: %i, BitRate: %i, Channels: %i)", rresName, wave.sampleRate, wave.bitsPerSample, wave.channels);
// Unallocate WAV data
@ -574,6 +575,7 @@ void PauseMusicStream(void)
{
TraceLog(INFO, "Pausing music stream");
alSourcePause(currentMusic.source);
musicEnabled = false;
}
}
@ -581,10 +583,14 @@ void PauseMusicStream(void)
void ResumeMusicStream(void)
{
// Resume music playing... if music available!
if (musicEnabled)
ALenum state;
alGetSourcei(currentMusic.source, AL_SOURCE_STATE, &state);
if (state == AL_PAUSED)
{
TraceLog(INFO, "Resume music stream");
TraceLog(INFO, "Resuming music stream");
alSourcePlay(currentMusic.source);
musicEnabled = true;
}
}
@ -865,13 +871,12 @@ static Wave LoadOGG(char *fileName)
TraceLog(DEBUG, "[%s] Total samples calculated: %i", fileName, totalSamples);
//short *data
wave.data = malloc(sizeof(short)*totalSamplesLength);
int samplesObtained = stb_vorbis_get_samples_short_interleaved(oggFile, info.channels, wave.data, totalSamplesLength);
TraceLog(DEBUG, "[%s] Samples obtained: %i", fileName, samplesObtained);
TraceLog(INFO, "[%s] OGG file loaded successfully (SampleRate: %i, BitRate: %i, Channels: %i)", fileName, wave.sampleRate, wave.bitsPerSample, wave.channels);
stb_vorbis_close(oggFile);

455
src/camera.c Normal file
View File

@ -0,0 +1,455 @@
/**********************************************************************************************
*
* raylib.camera
*
* Camera Modes Setup and Control Functions
*
* Copyright (c) 2015 Marc Palau and Ramon Santamaria
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "raylib.h"
#include <math.h>
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
// CAMERA_GENERIC
#define CAMERA_SCROLL_SENSITIVITY 1.5
// FREE_CAMERA
#define FREE_CAMERA_MOUSE_SENSITIVITY 0.01
#define FREE_CAMERA_DISTANCE_MIN_CLAMP 0.3
#define FREE_CAMERA_DISTANCE_MAX_CLAMP 120
#define FREE_CAMERA_MIN_CLAMP 85
#define FREE_CAMERA_MAX_CLAMP -85
#define FREE_CAMERA_SMOOTH_ZOOM_SENSITIVITY 0.05
#define FREE_CAMERA_PANNING_DIVIDER 5.1
// ORBITAL_CAMERA
#define ORBITAL_CAMERA_SPEED 0.01
// FIRST_PERSON
//#define FIRST_PERSON_MOUSE_SENSITIVITY 0.003
#define FIRST_PERSON_FOCUS_DISTANCE 25
#define FIRST_PERSON_MIN_CLAMP 85
#define FIRST_PERSON_MAX_CLAMP -85
#define FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER 5.0
#define FIRST_PERSON_STEP_DIVIDER 30.0
#define FIRST_PERSON_WAVING_DIVIDER 200.0
#define FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION 0.85
// THIRD_PERSON
//#define THIRD_PERSON_MOUSE_SENSITIVITY 0.003
#define THIRD_PERSON_DISTANCE_CLAMP 1.2
#define THIRD_PERSON_MIN_CLAMP 5
#define THIRD_PERSON_MAX_CLAMP -85
#define THIRD_PERSON_OFFSET (Vector3){ 0.4, 0, 0 }
// PLAYER (used by camera)
#define PLAYER_WIDTH 0.4
#define PLAYER_HEIGHT 0.9
#define PLAYER_DEPTH 0.4
#define PLAYER_MOVEMENT_DIVIDER 20.0
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
static Camera internalCamera = {{2,0,2},{0,0,0},{0,1,0}};
static Vector2 cameraAngle = { 0, 0 };
static float cameraTargetDistance = 5;
static Vector3 resetingPosition = { 0, 0, 0 };
static int resetingKey = 'Z';
static Vector2 cameraMousePosition = { 0, 0 };
static Vector2 cameraMouseVariation = { 0, 0 };
static float mouseSensitivity = 0.003;
static int cameraMovementController[6] = { 'W', 'A', 'S', 'D', 'E', 'Q' };
static int cameraMovementCounter = 0;
static bool cameraUseGravity = true;
static int pawnControllingKey = MOUSE_MIDDLE_BUTTON;
static int fnControllingKey = KEY_LEFT_ALT;
static int smoothZoomControllingKey = KEY_LEFT_CONTROL;
static int cameraMode = CAMERA_CUSTOM;
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
static void ProcessCamera(Camera *camera, Vector3 *playerPosition);
/*
static void SetCameraControls(int front, int left, int back, right, up, down);
static void SetMouseSensitivity(int sensitivity);
static void SetResetPosition(Vector3 resetPosition);
static void SetResetControl(int resetKey);
static void SetPawnControl(int pawnControlKey);
static void SetFnControl(int fnControlKey);
static void SetSmoothZoomControl(int smoothZoomControlKey);
*/
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Select camera mode (multiple camera modes available)
void SetCameraMode(int mode)
{
if ((cameraMode == CAMERA_FIRST_PERSON) && (mode == CAMERA_FREE))
{
cameraMode = CAMERA_THIRD_PERSON;
cameraTargetDistance = 5;
cameraAngle.y = -40 * DEG2RAD;
ProcessCamera(&internalCamera, &internalCamera.position);
}
else if ((cameraMode == CAMERA_FIRST_PERSON) && (mode == CAMERA_ORBITAL))
{
cameraMode = CAMERA_THIRD_PERSON;
cameraTargetDistance = 5;
cameraAngle.y = -40 * DEG2RAD;
ProcessCamera(&internalCamera, &internalCamera.position);
}
else if ((cameraMode == CAMERA_CUSTOM) && (mode == CAMERA_FREE))
{
cameraTargetDistance = 10;
cameraAngle.x = 45 * DEG2RAD;
cameraAngle.y = -40 * DEG2RAD;
internalCamera.target = (Vector3){ 0, 0, 0};
ProcessCamera(&internalCamera, &internalCamera.position);
}
else if ((cameraMode == CAMERA_CUSTOM) && (mode == CAMERA_ORBITAL))
{
cameraTargetDistance = 10;
cameraAngle.x = 225 * DEG2RAD;
cameraAngle.y = -40 * DEG2RAD;
internalCamera.target = (Vector3){ 3, 0, 3};
ProcessCamera(&internalCamera, &internalCamera.position);
}
cameraMode = mode;
}
// Update camera with position
Camera UpdateCamera(Vector3 *position)
{
// Calculate camera
if (cameraMode != CAMERA_CUSTOM) ProcessCamera(&internalCamera, position);
return internalCamera;
}
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
// Process desired camera mode and controls
static void ProcessCamera(Camera *camera, Vector3 *playerPosition)
{
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) || defined(PLATFORM_RPI)
// Mouse movement detection
if ((cameraMode != CAMERA_FREE) && (cameraMode != CAMERA_ORBITAL))
{
HideCursor();
if (GetMousePosition().x < GetScreenHeight() / 3) SetMousePosition((Vector2){ GetScreenWidth() - GetScreenHeight() / 3, GetMousePosition().y});
else if (GetMousePosition().y < GetScreenHeight() / 3) SetMousePosition((Vector2){ GetMousePosition().x, GetScreenHeight() - GetScreenHeight() / 3});
else if (GetMousePosition().x > GetScreenWidth() - GetScreenHeight() / 3) SetMousePosition((Vector2) { GetScreenHeight() / 3, GetMousePosition().y});
else if (GetMousePosition().y > GetScreenHeight() - GetScreenHeight() / 3) SetMousePosition((Vector2){ GetMousePosition().x, GetScreenHeight() / 3});
else
{
cameraMouseVariation.x = GetMousePosition().x - cameraMousePosition.x;
cameraMouseVariation.y = GetMousePosition().y - cameraMousePosition.y;
}
}
else
{
ShowCursor();
cameraMouseVariation.x = GetMousePosition().x - cameraMousePosition.x;
cameraMouseVariation.y = GetMousePosition().y - cameraMousePosition.y;
}
cameraMousePosition = GetMousePosition();
// Support for multiple automatic camera modes
switch (cameraMode)
{
case CAMERA_FREE:
{
// Camera zoom
if ((cameraTargetDistance < FREE_CAMERA_DISTANCE_MAX_CLAMP) && (GetMouseWheelMove() < 0))
{
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
if (cameraTargetDistance > FREE_CAMERA_DISTANCE_MAX_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MAX_CLAMP;
}
// Camera looking down
else if ((camera->position.y > camera->target.y) && (cameraTargetDistance == FREE_CAMERA_DISTANCE_MAX_CLAMP) && (GetMouseWheelMove() < 0))
{
camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
}
else if ((camera->position.y > camera->target.y) && (camera->target.y >= 0))
{
camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
if (camera->target.y < 0) camera->target.y = -0.001;
}
else if ((camera->position.y > camera->target.y) && (camera->target.y < 0) && (GetMouseWheelMove() > 0))
{
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
if (cameraTargetDistance < FREE_CAMERA_DISTANCE_MIN_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MIN_CLAMP;
}
// Camera looking up
else if ((camera->position.y < camera->target.y) && (cameraTargetDistance == FREE_CAMERA_DISTANCE_MAX_CLAMP) && (GetMouseWheelMove() < 0))
{
camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
}
else if ((camera->position.y < camera->target.y) && (camera->target.y <= 0))
{
camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
if (camera->target.y > 0) camera->target.y = 0.001;
}
else if ((camera->position.y < camera->target.y) && (camera->target.y > 0) && (GetMouseWheelMove() > 0))
{
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
if (cameraTargetDistance < FREE_CAMERA_DISTANCE_MIN_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MIN_CLAMP;
}
// Inputs
if (IsKeyDown(fnControllingKey))
{
if (IsKeyDown(smoothZoomControllingKey))
{
// Camera smooth zoom
if (IsMouseButtonDown(pawnControllingKey)) cameraTargetDistance += (cameraMouseVariation.y * FREE_CAMERA_SMOOTH_ZOOM_SENSITIVITY);
}
// Camera orientation calculation
else if (IsMouseButtonDown(pawnControllingKey))
{
// Camera orientation calculation
// Get the mouse sensitivity
cameraAngle.x += cameraMouseVariation.x * -FREE_CAMERA_MOUSE_SENSITIVITY;
cameraAngle.y += cameraMouseVariation.y * -FREE_CAMERA_MOUSE_SENSITIVITY;
// Angle clamp
if (cameraAngle.y > FREE_CAMERA_MIN_CLAMP * DEG2RAD) cameraAngle.y = FREE_CAMERA_MIN_CLAMP * DEG2RAD;
else if (cameraAngle.y < FREE_CAMERA_MAX_CLAMP * DEG2RAD) cameraAngle.y = FREE_CAMERA_MAX_CLAMP * DEG2RAD;
}
}
// Paning
else if (IsMouseButtonDown(pawnControllingKey))
{
camera->target.x += ((cameraMouseVariation.x * -FREE_CAMERA_MOUSE_SENSITIVITY) * cos(cameraAngle.x) + (cameraMouseVariation.y * FREE_CAMERA_MOUSE_SENSITIVITY) * sin(cameraAngle.x) * sin(cameraAngle.y)) * (cameraTargetDistance / FREE_CAMERA_PANNING_DIVIDER);
camera->target.y += ((cameraMouseVariation.y * FREE_CAMERA_MOUSE_SENSITIVITY) * cos(cameraAngle.y)) * (cameraTargetDistance / FREE_CAMERA_PANNING_DIVIDER);
camera->target.z += ((cameraMouseVariation.x * FREE_CAMERA_MOUSE_SENSITIVITY) * sin(cameraAngle.x) + (cameraMouseVariation.y * FREE_CAMERA_MOUSE_SENSITIVITY) * cos(cameraAngle.x) * sin(cameraAngle.y)) * (cameraTargetDistance / FREE_CAMERA_PANNING_DIVIDER);
}
// Focus to center
if (IsKeyDown(resetingKey)) camera->target = resetingPosition;
// Camera position update
camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x;
if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
camera->position.z = cos(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.z;
} break;
case CAMERA_ORBITAL:
{
cameraAngle.x += ORBITAL_CAMERA_SPEED;
// Camera zoom
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
// Camera distance clamp
if (cameraTargetDistance < THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = THIRD_PERSON_DISTANCE_CLAMP;
// Focus to center
if (IsKeyDown('Z')) camera->target = (Vector3) { 0, 0, 0 };
// Camera position update
camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x;
if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
camera->position.z = cos(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.z;
} break;
case CAMERA_FIRST_PERSON:
case CAMERA_THIRD_PERSON:
{
bool isMoving = false;
// Keyboard inputs
if (IsKeyDown(cameraMovementController[0]))
{
playerPosition->x -= sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
playerPosition->z -= cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
if (!cameraUseGravity) camera->position.y += sin(cameraAngle.y) / PLAYER_MOVEMENT_DIVIDER;
isMoving = true;
}
else if (IsKeyDown(cameraMovementController[2]))
{
playerPosition->x += sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
playerPosition->z += cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
if (!cameraUseGravity) camera->position.y -= sin(cameraAngle.y) / PLAYER_MOVEMENT_DIVIDER;
isMoving = true;
}
if (IsKeyDown(cameraMovementController[1]))
{
playerPosition->x -= cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
playerPosition->z += sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
isMoving = true;
}
else if (IsKeyDown(cameraMovementController[3]))
{
playerPosition->x += cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
playerPosition->z -= sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
isMoving = true;
}
if (IsKeyDown(cameraMovementController[4]))
{
if (!cameraUseGravity) playerPosition->y += 1 / PLAYER_MOVEMENT_DIVIDER;
}
else if (IsKeyDown(cameraMovementController[5]))
{
if (!cameraUseGravity) playerPosition->y -= 1 / PLAYER_MOVEMENT_DIVIDER;
}
if (cameraMode == CAMERA_THIRD_PERSON)
{
// Camera orientation calculation
// Get the mouse sensitivity
cameraAngle.x += cameraMouseVariation.x * -mouseSensitivity;
cameraAngle.y += cameraMouseVariation.y * -mouseSensitivity;
// Angle clamp
if (cameraAngle.y > THIRD_PERSON_MIN_CLAMP * DEG2RAD) cameraAngle.y = THIRD_PERSON_MIN_CLAMP * DEG2RAD;
else if (cameraAngle.y < THIRD_PERSON_MAX_CLAMP * DEG2RAD) cameraAngle.y = THIRD_PERSON_MAX_CLAMP * DEG2RAD;
// Camera zoom
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
// Camera distance clamp
if (cameraTargetDistance < THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = THIRD_PERSON_DISTANCE_CLAMP;
// Camera is always looking at player
camera->target.x = playerPosition->x + THIRD_PERSON_OFFSET.x * cos(cameraAngle.x) + THIRD_PERSON_OFFSET.z * sin(cameraAngle.x);
camera->target.y = playerPosition->y + PLAYER_HEIGHT * FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION + THIRD_PERSON_OFFSET.y;
camera->target.z = playerPosition->z + THIRD_PERSON_OFFSET.z * sin(cameraAngle.x) - THIRD_PERSON_OFFSET.x * sin(cameraAngle.x);
// Camera position update
camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x;
if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
camera->position.z = cos(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.z;
}
else
{
if (isMoving) cameraMovementCounter++;
// Camera orientation calculation
// Get the mouse sensitivity
cameraAngle.x += cameraMouseVariation.x * -mouseSensitivity;
cameraAngle.y += cameraMouseVariation.y * -mouseSensitivity;
// Angle clamp
if (cameraAngle.y > FIRST_PERSON_MIN_CLAMP * DEG2RAD) cameraAngle.y = FIRST_PERSON_MIN_CLAMP * DEG2RAD;
else if (cameraAngle.y < FIRST_PERSON_MAX_CLAMP * DEG2RAD) cameraAngle.y = FIRST_PERSON_MAX_CLAMP * DEG2RAD;
// Camera is always looking at player
camera->target.x = camera->position.x - sin(cameraAngle.x) * FIRST_PERSON_FOCUS_DISTANCE;
camera->target.y = camera->position.y + sin(cameraAngle.y) * FIRST_PERSON_FOCUS_DISTANCE;
camera->target.z = camera->position.z - cos(cameraAngle.x) * FIRST_PERSON_FOCUS_DISTANCE;
camera->position.x = playerPosition->x;
camera->position.y = (playerPosition->y + PLAYER_HEIGHT * FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION) - sin(cameraMovementCounter / FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER) / FIRST_PERSON_STEP_DIVIDER;
camera->position.z = playerPosition->z;
camera->up.x = sin(cameraMovementCounter / (FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER * 2)) / FIRST_PERSON_WAVING_DIVIDER;
camera->up.z = -sin(cameraMovementCounter / (FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER * 2)) / FIRST_PERSON_WAVING_DIVIDER;
}
} break;
default: break;
}
#endif
}
void SetCameraControls(int frontKey, int leftKey, int backKey, int rightKey, int upKey, int downKey)
{
cameraMovementController[0] = frontKey;
cameraMovementController[1] = leftKey;
cameraMovementController[2] = backKey;
cameraMovementController[3] = rightKey;
cameraMovementController[4] = upKey;
cameraMovementController[5] = downKey;
}
void SetMouseSensitivity(float sensitivity)
{
mouseSensitivity = (sensitivity / 10000.0);
}
void SetResetPosition(Vector3 resetPosition)
{
resetingPosition = resetPosition;
}
void SetResetControl(int resetKey)
{
resetingKey = resetKey;
}
void SetPawnControl(int pawnControlKey)
{
pawnControllingKey = pawnControlKey;
}
void SetFnControl(int fnControlKey)
{
fnControllingKey = fnControlKey;
}
void SetSmoothZoomControl(int smoothZoomControlKey)
{
smoothZoomControllingKey = smoothZoomControlKey;
}
void SetOrbitalTarget(Vector3 target)
{
internalCamera.target = target;
}

View File

@ -45,13 +45,18 @@
#include <stdio.h> // Standard input / output lib
#include <stdlib.h> // Declares malloc() and free() for memory management, rand(), atexit()
#include <stdint.h> // Required for typedef unsigned long long int uint64_t, used by hi-res timer
#include <time.h> // Useful to initialize random seed - Android/RPI hi-res timer
#include <time.h> // Useful to initialize random seed - Android/RPI hi-res timer (NOTE: Linux only!)
#include <math.h> // Math related functions, tan() used to set perspective
#include <string.h> // String function definitions, memset()
#include <errno.h> // Macros for reporting and retrieving error conditions through error codes
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
#include <GLFW/glfw3.h> // GLFW3 library: Windows, OpenGL context and Input management
#ifdef __linux
#define GLFW_EXPOSE_NATIVE_X11 // Linux specific definitions for getting
#define GLFW_EXPOSE_NATIVE_GLX // native functions like glfwGetX11Window
#include <GLFW/glfw3native.h> // which are required for hiding mouse
#endif
//#include <GL/gl.h> // OpenGL functions (GLFW3 already includes gl.h)
//#define GLFW_DLL // Using GLFW DLL on Windows -> No, we use static version!
#endif
@ -104,28 +109,13 @@
//----------------------------------------------------------------------------------
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
static GLFWwindow *window; // Native window (graphic device)
static bool windowMinimized = false;
#elif defined(PLATFORM_ANDROID)
static struct android_app *app; // Android activity
static struct android_poll_source *source; // Android events polling source
static int ident, events;
static bool windowReady = false; // Used to detect display initialization
// Gestures detection variables
static float tapTouchX, tapTouchY;
static int64_t lastTapTime = 0;
static float lastTapX = 0, lastTapY = 0;
static bool touchTap = false;
static bool doubleTap = false;
static bool drag = false;
static int stdVector[MAX_TOUCH_POINTS];
static int indexPosition = 0;
const AInputEvent* eventDrag;
static int32_t touchId;
const int32_t DOUBLE_TAP_TIMEOUT = 300*1000000;
const int32_t DOUBLE_TAP_SLOP = 100;
const int32_t TAP_TIMEOUT = 180*1000000;
const int32_t TOUCH_SLOP = 8;
#elif defined(PLATFORM_RPI)
static EGL_DISPMANX_WINDOW_T nativeWindow; // Native window (graphic device)
@ -152,8 +142,7 @@ static int gamepadStream = -1; // Gamepad device file descripto
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
static EGLDisplay display; // Native display device (physical screen connection)
static EGLSurface surface; // Surface to draw on, framebuffers (connected to context)
static EGLContext context; // Graphic context, mode in which drawing can be done
static EGLContext context; // Graphic context, mode in which drawing can be done
static uint64_t baseTime; // Base time measure for hi-res timer
static bool windowShouldClose = false; // Flag to set window for closing
#endif
@ -191,11 +180,8 @@ static int currentMouseWheelY = 0; // Required to track mouse wheel var
static int exitKey = KEY_ESCAPE; // Default exit key (ESC)
static int lastKeyPressed = -1;
#endif
#if defined(PLATFORM_ANDROID)
static float touchX; // Touch position X
static float touchY; // Touch position Y
static bool cursorHidden;
#endif
static double currentTime, previousTime; // Used to track timmings
@ -206,6 +192,9 @@ static double targetTime = 0.0; // Desired time for one frame, if 0
static char configFlags = 0;
static bool showLogo = false;
// Shaders variables
static bool enabledPostpro = false;
//----------------------------------------------------------------------------------
// Other Modules Functions Declaration (required by core)
//----------------------------------------------------------------------------------
@ -214,6 +203,17 @@ extern void UnloadDefaultFont(void); // [Module: text] Unloads defaul
extern void UpdateMusicStream(void); // [Module: audio] Updates buffers for music streaming
extern Vector2 GetRawPosition(void);
extern void ResetGestures(void);
#if defined(PLATFORM_ANDROID)
extern void InitAndroidGestures(struct android_app *app);
#endif
#if defined(PLATFORM_WEB)
extern void InitWebGestures(void); // [Module: gestures] Initializes emscripten gestures for web
#endif
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
@ -227,6 +227,7 @@ static void SwapBuffers(void); // Copy back buffer to f
static void PollInputEvents(void); // Register user events
static void LogoAnimation(void); // Plays raylib logo appearing animation
static void SetupFramebufferSize(int displayWidth, int displayHeight);
#if defined(PLATFORM_RPI)
static void InitMouse(void); // Mouse initialization (including mouse thread)
static void *MouseThread(void *arg); // Mouse reading thread
@ -243,6 +244,7 @@ static void CharCallback(GLFWwindow *window, unsigned int key);
static void ScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel
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 WindowIconifyCallback(GLFWwindow* window, int iconified); // GLFW3 WindowIconify Callback, runs when window is minimized/restored
#endif
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
@ -250,8 +252,7 @@ static void TakeScreenshot(void);
#endif
#if defined(PLATFORM_ANDROID)
static int32_t InputCallback(struct android_app *app, AInputEvent *event); // Process Android activity input events
static void CommandCallback(struct android_app *app, int32_t cmd); // Process Android activity lifecycle commands
static void AndroidCommandCallback(struct android_app *app, int32_t cmd); // Process Android activity lifecycle commands
#endif
//----------------------------------------------------------------------------------
@ -261,8 +262,8 @@ static void CommandCallback(struct android_app *app, int32_t cmd); //
// Initialize Window and Graphics Context (OpenGL)
void InitWindow(int width, int height, const char *title)
{
TraceLog(INFO, "Initializing raylib...");
TraceLog(INFO, "Initializing raylib (v1.3.0)");
// Store window title (could be useful...)
windowTitle = title;
@ -285,6 +286,11 @@ void InitWindow(int width, int height, const char *title)
InitKeyboard(); // Keyboard init
InitGamepad(); // Gamepad init
#endif
#if defined(PLATFORM_WEB)
InitWebGestures(); // Init touch input events for web
#endif
mousePosition.x = screenWidth/2;
mousePosition.y = screenHeight/2;
@ -300,8 +306,8 @@ void InitWindow(int width, int height, const char *title)
// Android activity initialization
void InitWindow(int width, int height, struct android_app *state)
{
TraceLog(INFO, "Initializing raylib...");
TraceLog(INFO, "Initializing raylib (v1.3.0)");
app_dummy();
screenWidth = width;
@ -336,8 +342,9 @@ void InitWindow(int width, int height, struct android_app *state)
//AConfiguration_getScreenLong(app->config);
//state->userData = &engine;
app->onAppCmd = CommandCallback;
app->onInputEvent = InputCallback;
app->onAppCmd = AndroidCommandCallback;
InitAndroidGestures(app);
InitAssetManager(app->activity->assetManager);
@ -399,6 +406,9 @@ void CloseWindow(void)
bool WindowShouldClose(void)
{
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
// While window minimized, stop loop execution
while (windowMinimized) glfwPollEvents();
return (glfwWindowShouldClose(window));
#elif defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
return windowShouldClose;
@ -429,7 +439,7 @@ void SetCustomCursor(const char *cursorImage)
cursor = LoadTexture(cursorImage);
#if defined(PLATFORM_DESKTOP)
// NOTE: emscripten not implemented
// NOTE: emscripten not implemented
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
#endif
customCursor = true;
@ -469,22 +479,31 @@ void BeginDrawing(void)
updateTime = currentTime - previousTime;
previousTime = currentTime;
if (enabledPostpro) rlEnableFBO();
rlClearScreenBuffers();
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
rlMultMatrixf(GetMatrixVector(downscaleView)); // If downscale required, apply it here
// rlTranslatef(0.375, 0.375, 0); // HACK to have 2D pixel-perfect drawing on OpenGL 1.1
//rlTranslatef(0.375, 0.375, 0); // HACK to have 2D pixel-perfect drawing on OpenGL 1.1
// NOTE: Not required with OpenGL 3.3+
}
// End canvas drawing and Swap Buffers (Double Buffering)
void EndDrawing(void)
{
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
if (enabledPostpro) rlglDrawPostpro(); // Draw postprocessing effect (shader)
SwapBuffers(); // Copy back buffer to front buffer
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
ResetGestures();
#endif
PollInputEvents(); // Poll user events
UpdateMusicStream(); // NOTE: Function checks if music is enabled
@ -510,7 +529,7 @@ void EndDrawing(void)
// Initializes 3D mode for drawing (Camera setup)
void Begin3dMode(Camera camera)
{
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
rlMatrixMode(RL_PROJECTION); // Switch to projection matrix
@ -528,14 +547,14 @@ void Begin3dMode(Camera camera)
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
// Setup Camera view
Matrix matLookAt = MatrixLookAt(camera.position, camera.target, camera.up);
rlMultMatrixf(GetMatrixVector(matLookAt)); // Multiply MODELVIEW matrix by view matrix (camera)
Matrix view = MatrixLookAt(camera.position, camera.target, camera.up);
rlMultMatrixf(GetMatrixVector(view)); // Multiply MODELVIEW matrix by view matrix (camera)
}
// Ends 3D mode and returns to default 2D orthographic mode
void End3dMode(void)
{
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
rlMatrixMode(RL_PROJECTION); // Switch to projection matrix
rlPopMatrix(); // Restore previous matrix (PROJECTION) from matrix stack
@ -612,9 +631,8 @@ Color Fade(Color color, float alpha)
return (Color){color.r, color.g, color.b, color.a*alpha};
}
// Enable some window configurations (SetWindowFlags()?)
// TODO: Review function name and usage
void SetupFlags(char flags)
// Enable some window/system configurations
void SetConfigFlags(char flags)
{
configFlags = flags;
@ -628,6 +646,41 @@ void ShowLogo(void)
showLogo = true;
}
Ray GetMouseRay(Vector2 mousePosition, Camera camera)
{
Ray ray;
Matrix proj = MatrixIdentity();
Matrix view = MatrixLookAt(camera.position, camera.target, camera.up);
float aspect = (GLfloat)GetScreenWidth()/(GLfloat)GetScreenHeight();
double top = 0.1f*tanf(45.0f*PI / 360.0f);
double right = top*aspect;
proj = MatrixFrustum(-right, right, -top, top, 0.01f, 1000.0f);
MatrixTranspose(&proj);
float realy = (float)GetScreenHeight() - mousePosition.y;
//float z;
// glReadPixels(mousePosition.x, mousePosition.y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);
//http://www.bfilipek.com/2012/06/select-mouse-opengl.html
Vector3 nearPoint = { mousePosition.x, realy, 0.0f };
Vector3 farPoint = { mousePosition.x, realy, 1.0f };
//nearPoint = internalCamera.position;
farPoint = rlglUnproject(farPoint, proj, view);
Vector3 direction = VectorSubtract(farPoint, nearPoint);
VectorNormalize(&direction);
ray.position = nearPoint;
ray.direction = direction;
return ray;
}
//----------------------------------------------------------------------------------
// Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions
//----------------------------------------------------------------------------------
@ -733,7 +786,7 @@ void SetMousePosition(Vector2 position)
{
mousePosition = position;
#if defined(PLATFORM_DESKTOP)
// NOTE: emscripten not implemented
// NOTE: emscripten not implemented
glfwSetCursorPos(window, position.x, position.y);
#endif
}
@ -741,17 +794,52 @@ void SetMousePosition(Vector2 position)
// Returns mouse wheel movement Y
int GetMouseWheelMove(void)
{
previousMouseWheelY = currentMouseWheelY;
currentMouseWheelY = 0;
return previousMouseWheelY;
}
// Hide mouse cursor
void HideCursor()
{
#if defined(PLATFORM_DESKTOP)
#ifdef __linux
XColor Col;
const char Nil[] = {0};
Pixmap Pix = XCreateBitmapFromData(glfwGetX11Display(), glfwGetX11Window(window), Nil, 1, 1);
Cursor Cur = XCreatePixmapCursor(glfwGetX11Display(), Pix, Pix, &Col, &Col, 0, 0);
XDefineCursor(glfwGetX11Display(), glfwGetX11Window(window), Cur);
XFreeCursor(glfwGetX11Display(), Cur);
#else
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
#endif
#endif
cursorHidden = true;
}
// Show mouse cursor
void ShowCursor()
{
#if defined(PLATFORM_DESKTOP)
#ifdef __linux
XUndefineCursor(glfwGetX11Display(), glfwGetX11Window(window));
#else
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
#endif
#endif
cursorHidden = false;
}
// Check if mouse cursor is hidden
bool IsCursorHidden()
{
return cursorHidden;
}
#endif
// TODO: Enable gamepad usage on Rapsberry Pi
// NOTE: emscripten not implemented
#if defined(PLATFORM_DESKTOP)
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
// Detect if a gamepad is available
bool IsGamepadAvailable(int gamepad)
{
@ -848,66 +936,73 @@ bool IsGamepadButtonUp(int gamepad, int button)
}
#endif
#if defined(PLATFORM_ANDROID)
bool IsScreenTouched(void)
{
return touchTap;
}
bool IsDoubleTap(void)
{
if (doubleTap) TraceLog(INFO, "DOUBLE TAP gesture detected");
return doubleTap;
}
bool IsDragGesture(void)
{
return drag;
}
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
// Returns touch position X
int GetTouchX(void)
{
return (int)touchX;
return (int)GetRawPosition().x;
}
// Returns touch position Y
int GetTouchY(void)
{
return (int)touchY;
return (int)GetRawPosition().y;
}
// Returns touch position XY
Vector2 GetTouchPosition(void)
{
Vector2 position = { touchX, touchY };
Vector2 position = GetRawPosition();
if ((screenWidth > displayWidth) || (screenHeight > displayHeight))
{
// TODO: Seems to work ok but... review!
position.x = position.x*((float)screenWidth / (float)(displayWidth - renderOffsetX)) - renderOffsetX/2;
position.y = position.y*((float)screenHeight / (float)(displayHeight - renderOffsetY)) - renderOffsetY/2;
}
else
{
position.x = position.x*((float)renderWidth / (float)displayWidth) - renderOffsetX/2;
position.y = position.y*((float)renderHeight / (float)displayHeight) - renderOffsetY/2;
}
return position;
}
/*bool GetPointer(Vector2 *dragPositions)
{
//static int stdVector[MAX_TOUCH_POINTS];
//static int indexPosition = 0;
//if (indexPosition == 0) return false;
Vector2 vec_pointers_[];
//eventDrag
int32_t iIndex = FindIndex( eventDrag, vec_pointers_[0] );
if (iIndex == -1) return false;
float x = AMotionEvent_getX(eventDrag, iIndex);
float y = AMotionEvent_getY(eventDrag, iIndex);
*dragPositions = Vector2( x, y );
return true;
}*/
#endif
// Set postprocessing shader
void SetPostproShader(Shader shader)
{
if (rlGetVersion() == OPENGL_11) TraceLog(WARNING, "Postprocessing shaders not supported on OpenGL 1.1");
else
{
if (!enabledPostpro)
{
enabledPostpro = true;
rlglInitPostpro();
rlglSetPostproShader(shader);
}
else
{
rlglSetPostproShader(shader);
}
}
}
// Set custom shader to be used in batch draw
void SetCustomShader(Shader shader)
{
rlglSetCustomShader(shader);
}
// Set default shader to be used in batch draw
void SetDefaultShader(void)
{
rlglSetDefaultShader();
enabledPostpro = false;
}
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
@ -946,7 +1041,7 @@ static void InitDisplay(int width, int height)
displayWidth = screenWidth;
displayHeight = screenHeight;
#endif
glfwDefaultWindowHints(); // Set default windows hints
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable
@ -956,13 +1051,18 @@ static void InitDisplay(int width, int height)
//glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); // Default OpenGL API to use. Alternative: GLFW_OPENGL_ES_API
//glfwWindowHint(GLFW_AUX_BUFFERS, 0); // Number of auxiliar buffers
// NOTE: When asking for an OpenGL context version, most drivers provide highest supported version
// NOTE: When asking for an OpenGL context version, most drivers provide highest supported version
// with forward compatibility to older OpenGL versions.
// For example, if using OpenGL 1.1, driver can provide a 3.3 context fordward compatible.
if (rlGetVersion() == OPENGL_33)
{
//glfwWindowHint(GLFW_SAMPLES, 4); // Enables multisampling x4 (MSAA), default is 0
if (configFlags & FLAG_MSAA_4X_HINT)
{
glfwWindowHint(GLFW_SAMPLES, 4); // Enables multisampling x4 (MSAA), default is 0
TraceLog(INFO, "Enabled MSAA x4");
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // Choose OpenGL major version (just hint)
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Choose OpenGL minor version (just hint)
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Profiles Hint: Only 3.2 and above!
@ -1009,12 +1109,18 @@ static void InitDisplay(int width, int height)
glfwSetMouseButtonCallback(window, MouseButtonCallback);
glfwSetCharCallback(window, CharCallback);
glfwSetScrollCallback(window, ScrollCallback);
glfwSetWindowIconifyCallback(window, WindowIconifyCallback);
glfwMakeContextCurrent(window);
//glfwSwapInterval(0); // Disables GPU v-sync (if set), so frames are not limited to screen refresh rate (60Hz -> 60 FPS)
// If not set, swap interval uses GPU v-sync configuration
// Framerate can be setup using SetTargetFPS()
// Enables GPU v-sync, so frames are not limited to screen refresh rate (60Hz -> 60 FPS)
// If not set, swap interval uses GPU v-sync configuration
// Framerate can be setup using SetTargetFPS()
if (configFlags & FLAG_VSYNC_HINT)
{
glfwSwapInterval(1);
TraceLog(INFO, "Trying to enable VSYNC");
}
//glfwGetFramebufferSize(window, &renderWidth, &renderHeight); // Get framebuffer size of current window
@ -1036,6 +1142,7 @@ static void InitDisplay(int width, int height)
VC_RECT_T srcRect;
#endif
// TODO: if (configFlags & FLAG_MSAA_4X_HINT) activate (EGL_SAMPLES, 4)
const EGLint framebufferAttribs[] =
{
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // Type of context support -> Required on RPI?
@ -1158,7 +1265,7 @@ static void InitDisplay(int width, int height)
}
// Initialize OpenGL graphics
void InitGraphics(void)
static void InitGraphics(void)
{
rlglInit(); // Init rlgl
@ -1216,7 +1323,7 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int
static void CharCallback(GLFWwindow *window, unsigned int key)
{
lastKeyPressed = key;
//TraceLog(INFO, "Char Callback Key pressed: %i\n", key);
}
@ -1242,212 +1349,30 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height)
// Background must be also re-cleared
ClearBackground(RAYWHITE);
}
// GLFW3 WindowIconify Callback, runs when window is minimized/restored
static void WindowIconifyCallback(GLFWwindow* window, int iconified)
{
if (iconified)
{
// The window was iconified
PauseMusicStream();
windowMinimized = true;
}
else
{
// The window was restored
ResumeMusicStream();
windowMinimized = false;
}
}
#endif
#if defined(PLATFORM_ANDROID)
// Android: Process activity input events
static int32_t InputCallback(struct android_app *app, AInputEvent *event)
{
int type = AInputEvent_getType(event);
//int32_t key = 0;
if (type == AINPUT_EVENT_TYPE_MOTION)
{
// Detect TOUCH position
if ((screenWidth > displayWidth) || (screenHeight > displayHeight))
{
// TODO: Seems to work ok but... review!
touchX = AMotionEvent_getX(event, 0) * ((float)screenWidth / (float)(displayWidth - renderOffsetX)) - renderOffsetX/2;
touchY = AMotionEvent_getY(event, 0) * ((float)screenHeight / (float)(displayHeight - renderOffsetY)) - renderOffsetY/2;
}
else
{
touchX = AMotionEvent_getX(event, 0) * ((float)renderWidth / (float)displayWidth) - renderOffsetX/2;
touchY = AMotionEvent_getY(event, 0) * ((float)renderHeight / (float)displayHeight) - renderOffsetY/2;
}
// Detect TAP event
/*
if (AMotionEvent_getPointerCount(event) > 1 )
{
// Only support single touch
return false;
}
*/
int32_t action = AMotionEvent_getAction(event);
unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
switch (flags)
{
case AMOTION_EVENT_ACTION_DOWN:
{
touchId = AMotionEvent_getPointerId(event, 0);
tapTouchX = AMotionEvent_getX(event, 0);
tapTouchY = AMotionEvent_getY(event, 0);
} break;
case AMOTION_EVENT_ACTION_UP:
{
int64_t eventTime = AMotionEvent_getEventTime(event);
int64_t downTime = AMotionEvent_getDownTime(event);
if (eventTime - downTime <= TAP_TIMEOUT)
{
if (touchId == AMotionEvent_getPointerId(event, 0))
{
float x = AMotionEvent_getX(event, 0) - tapTouchX;
float y = AMotionEvent_getY(event, 0) - tapTouchY;
float densityFactor = 1.0f;
if ( x*x + y*y < TOUCH_SLOP*TOUCH_SLOP * densityFactor)
{
// TAP Detected
touchTap = true;
}
}
}
break;
}
}
//float AMotionEvent_getX(event, size_t pointer_index);
//int32_t AMotionEvent_getButtonState(event); // Pressed buttons
//int32_t AMotionEvent_getPointerId(event, size_t pointer_index);
//size_t pointerCount = AMotionEvent_getPointerCount(event);
//float AMotionEvent_getPressure(const AInputEvent *motion_event, size_t pointer_index); // 0 to 1
//float AMotionEvent_getSize(const AInputEvent *motion_event, size_t pointer_index); // Pressed area
// Detect DOUBLE TAP event
bool tapDetected = touchTap;
switch (flags)
{
case AMOTION_EVENT_ACTION_DOWN:
{
int64_t eventTime = AMotionEvent_getEventTime(event);
if (eventTime - lastTapTime <= DOUBLE_TAP_TIMEOUT)
{
float x = AMotionEvent_getX(event, 0) - lastTapX;
float y = AMotionEvent_getY(event, 0) - lastTapY;
float densityFactor = 1.0f;
if ((x*x + y*y) < (DOUBLE_TAP_SLOP*DOUBLE_TAP_SLOP*densityFactor))
{
// Doubletap detected
doubleTap = true;
}
}
} break;
case AMOTION_EVENT_ACTION_UP:
{
if (tapDetected)
{
lastTapTime = AMotionEvent_getEventTime(event);
lastTapX = AMotionEvent_getX(event, 0);
lastTapY = AMotionEvent_getY(event, 0);
}
} break;
}
// Detect DRAG event
//int32_t action = AMotionEvent_getAction(event);
int32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
//uint32_t flags = action & AMOTION_EVENT_ACTION_MASK;
//event_ = event;
int32_t count = AMotionEvent_getPointerCount(event);
switch (flags)
{
case AMOTION_EVENT_ACTION_DOWN:
{
stdVector[indexPosition] = AMotionEvent_getPointerId(event, 0);
indexPosition++;
TraceLog(INFO, "ACTION_DOWN");
//ret = GESTURE_STATE_START;
} break;
case AMOTION_EVENT_ACTION_POINTER_DOWN:
{
stdVector[indexPosition] = AMotionEvent_getPointerId(event, index);
indexPosition++;
TraceLog(INFO, "ACTION_POINTER_DOWN");
} break;
case AMOTION_EVENT_ACTION_UP:
{
//int value = stdVector[indexPosition];
indexPosition--;
//ret = GESTURE_STATE_END;
TraceLog(INFO, "ACTION_UP");
} break;
case AMOTION_EVENT_ACTION_POINTER_UP:
{
int32_t releasedPointerId = AMotionEvent_getPointerId(event, index);
int i = 0;
for (i = 0; i < MAX_TOUCH_POINTS; i++)
{
if (stdVector[i] == releasedPointerId)
{
for (int k = i; k < indexPosition - 1; k++)
{
stdVector[k] = stdVector[k + 1];
}
//indexPosition--;
indexPosition = 0;
break;
}
}
if (i <= 1)
{
// Reset pinch or drag
//if (count == 2) //ret = GESTURE_STATE_START;
}
TraceLog(INFO, "ACTION_POINTER_UP");
} break;
case AMOTION_EVENT_ACTION_MOVE:
{
if (count == 1)
{
//TraceLog(INFO, "DRAG gesture detected");
drag = true; //ret = GESTURE_STATE_MOVE;
}
else break;
TraceLog(INFO, "ACTION_MOVE");
} break;
case AMOTION_EVENT_ACTION_CANCEL: break;
default: break;
}
//--------------------------------------------------------------------
return 1;
}
else if (type == AINPUT_EVENT_TYPE_KEY)
{
//key = AKeyEvent_getKeyCode(event);
//int32_t AKeyEvent_getMetaState(event);
}
return 0;
}
// Android: Process activity lifecycle commands
static void CommandCallback(struct android_app *app, int32_t cmd)
static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
{
switch (cmd)
{
@ -1636,24 +1561,24 @@ static void PollInputEvents(void)
// Keyboard polling
// Automatically managed by GLFW3 through callback
lastKeyPressed = -1;
// Register previous keys states
for (int i = 0; i < 512; i++) previousKeyState[i] = currentKeyState[i];
// Register previous mouse states
for (int i = 0; i < 3; i++) previousMouseState[i] = currentMouseState[i];
glfwPollEvents(); // Register keyboard/mouse events
previousMouseWheelY = currentMouseWheelY;
currentMouseWheelY = 0;
glfwPollEvents(); // Register keyboard/mouse events... and window events!
#elif defined(PLATFORM_ANDROID)
// TODO: Check virtual keyboard (?)
// Reset touch events
touchTap = false;
doubleTap = false;
drag = false;
// Poll Events (registered events)
// TODO: Enable/disable activityMinimized to block activity if minimized
//while ((ident = ALooper_pollAll(activityMinimized ? 0 : -1, NULL, &events,(void**)&source)) >= 0)
while ((ident = ALooper_pollAll(0, NULL, &events,(void**)&source)) >= 0)
{
// Process this event
@ -1664,8 +1589,8 @@ static void PollInputEvents(void)
{
// NOTE: Never close window, native activity is controlled by the system!
//TraceLog(INFO, "Closing Window...");
//windowShouldClose = true;
//windowShouldClose = true;
//ANativeActivity_finish(app->activity);
}
}
@ -1952,13 +1877,13 @@ static void SetupFramebufferSize(int displayWidth, int displayHeight)
if (widthRatio <= heightRatio)
{
renderWidth = displayWidth;
renderHeight = (int)((float)screenHeight*widthRatio);
renderHeight = (int)round((float)screenHeight*widthRatio);
renderOffsetX = 0;
renderOffsetY = (displayHeight - renderHeight);
}
else
{
renderWidth = (int)((float)screenWidth*heightRatio);
renderWidth = (int)round((float)screenWidth*heightRatio);
renderHeight = displayHeight;
renderOffsetX = (displayWidth - renderWidth);
renderOffsetY = 0;
@ -1988,13 +1913,13 @@ static void SetupFramebufferSize(int displayWidth, int displayHeight)
if (displayRatio <= screenRatio)
{
renderWidth = screenWidth;
renderHeight = (int)((float)screenWidth/displayRatio);
renderHeight = (int)round((float)screenWidth/displayRatio);
renderOffsetX = 0;
renderOffsetY = (renderHeight - screenHeight);
}
else
{
renderWidth = (int)((float)screenHeight*displayRatio);
renderWidth = (int)round((float)screenHeight*displayRatio);
renderHeight = screenHeight;
renderOffsetX = (renderWidth - screenWidth);
renderOffsetY = 0;
@ -2134,4 +2059,3 @@ static void LogoAnimation(void)
showLogo = false; // Prevent for repeating when reloading window (Android)
}

645
src/gestures.c Normal file
View File

@ -0,0 +1,645 @@
/**********************************************************************************************
*
* raylib.gestures
*
* Gestures Detection and Usage Functions Definitions
*
* Copyright (c) 2015 Marc Palau and Ramon Santamaria
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#include "utils.h"
#include <stdlib.h> // malloc(), free()
#include <stdio.h> // printf(), fprintf()
#include <math.h> // Used for ...
#include <stdint.h> // Defines int32_t, int64_t
#if defined(_WIN32)
//#include <Windows.h>
#elif defined(__linux)
#include <time.h> // Used for clock functions
#endif
#if defined(PLATFORM_ANDROID)
#include <jni.h> // Java native interface
#include <android/sensor.h> // Android sensors functions
#include <android/window.h> // Defines AWINDOW_FLAG_FULLSCREEN and others
#endif
#if defined(PLATFORM_WEB)
#include <emscripten/emscripten.h>
#include <emscripten/html5.h>
#endif
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
#define FORCE_TO_SWIPE 20
#define TAP_TIMEOUT 300
#define MAX_TOUCH_POINTS 4
typedef enum {
TYPE_MOTIONLESS,
TYPE_DRAG,
TYPE_DUAL_INPUT
} GestureType;
typedef enum {
UP,
DOWN,
MOVE
} ActionType;
typedef struct {
ActionType action;
int pointCount;
int pointerId[MAX_TOUCH_POINTS];
Vector2 position[MAX_TOUCH_POINTS];
} GestureEvent;
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
static GestureType gestureType = TYPE_MOTIONLESS;
static double eventTime = 0;
//static int32_t touchId; // Not used...
// Tap
// Our initial press position on tap
static Vector2 initialTapPosition = { 0, 0 };
// Double tap
// If we are double tapping or not
static bool doubleTapping = false;
// If we recently made a tap
static bool untap = false;
// Drag
// Our initial press position on drag
static Vector2 initialDragPosition = { 0, 0 };
// Position that will compare itself with the mouse one
static Vector2 endDragPosition = { 0, 0 };
// Position of the last event detection
static Vector2 lastDragPosition = { 0, 0 };
// The total drag vector
static Vector2 dragVector = { 0, 0 };
// The distance traveled dragging
static float magnitude = 0;
// The angle direction of the drag
static float angle = 0;
// A magnitude to calculate how fast we did the drag ( pixels per frame )
static float intensity = 0;
// Time that have passed while dragging
static int draggingTimeCounter = 0;
// Pinch
// First initial pinch position
static Vector2 firstInitialPinchPosition = { 0, 0 };
// Second initial pinch position
static Vector2 secondInitialPinchPosition = { 0, 0 };
// First end pinch position
static Vector2 firstEndPinchPosition = { 0, 0 };
// Second end pinch position
static Vector2 secondEndPinchPosition = { 0, 0 };
// Delta Displacement
static float pinchDelta = 0;
// Detected gesture
static int currentGesture = GESTURE_NONE;
static Vector2 touchPosition;
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
extern void ProcessMotionEvent(GestureEvent event);
extern void ResetGestures(void);
extern Vector2 GetRawPosition(void);
static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, float magnitude);
static float OnPinch();
static void SetDualInput(GestureEvent event);
static float Distance(Vector2 v1, Vector2 v2);
static float DotProduct(Vector2 v1, Vector2 v2);
static double GetCurrentTime();
#if defined(PLATFORM_WEB)
static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
#endif
#if defined(PLATFORM_ANDROID)
static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event);
#endif
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Returns tap position XY
extern Vector2 GetRawPosition(void)
{
return touchPosition;
}
// Check if a gesture have been detected
bool IsGestureDetected(void)
{
if (currentGesture == GESTURE_DRAG) TraceLog(INFO, "DRAG");
else if (currentGesture == GESTURE_TAP) TraceLog(INFO, "TAP");
else if (currentGesture == GESTURE_DOUBLETAP) TraceLog(INFO, "DOUBLE");
else if (currentGesture == GESTURE_HOLD) TraceLog(INFO, "HOLD");
else if (currentGesture == GESTURE_SWIPE_RIGHT) TraceLog(INFO, "RIGHT");
else if (currentGesture == GESTURE_SWIPE_UP) TraceLog(INFO, "UP");
else if (currentGesture == GESTURE_SWIPE_LEFT) TraceLog(INFO, "LEFT");
else if (currentGesture == GESTURE_SWIPE_DOWN) TraceLog(INFO, "DOWN");
else if (currentGesture == GESTURE_PINCH_IN) TraceLog(INFO, "PINCH IN");
else if (currentGesture == GESTURE_PINCH_OUT) TraceLog(INFO, "PINCH OUT");
if (currentGesture != GESTURE_NONE) return true;
else return false;
}
// Check gesture type
int GetGestureType(void)
{
return currentGesture;
}
// Get drag intensity (pixels per frame)
float GetDragIntensity(void)
{
return intensity;
}
// Get drag angle
// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
float GetDragAngle(void)
{
return angle;
}
// Get drag vector (between initial and final position)
Vector2 GetDragVector(void)
{
return dragVector;
}
// Hold time measured in frames
int GetHoldDuration(void)
{
return 0;
}
// Get magnitude between two pinch points
float GetPinchDelta(void)
{
return pinchDelta;
}
// Get angle beween two pinch points
// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
float GetPinchAngle(void)
{
return 0;
}
extern void ResetGestures(void)
{
if (currentGesture == GESTURE_TAP) currentGesture = GESTURE_HOLD;
else if (currentGesture != GESTURE_HOLD) currentGesture = GESTURE_NONE;
}
#if defined(PLATFORM_WEB)
extern void InitWebGestures(void)
{
/*
emscripten_set_touchstart_callback("#canvas", data, 0, Emscripten_HandleTouch);
emscripten_set_touchend_callback("#canvas", data, 0, Emscripten_HandleTouch);
emscripten_set_touchmove_callback("#canvas", data, 0, Emscripten_HandleTouch);
emscripten_set_touchcancel_callback("#canvas", data, 0, Emscripten_HandleTouch);
*/
//emscripten_set_touchstart_callback(0, NULL, 1, Emscripten_HandleTouch);
emscripten_set_touchstart_callback("#canvas", NULL, 1, EmscriptenInputCallback);
emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenInputCallback);
emscripten_set_touchmove_callback("#canvas", NULL, 1, EmscriptenInputCallback);
emscripten_set_touchcancel_callback("#canvas", NULL, 1, EmscriptenInputCallback);
}
#endif
#if defined(PLATFORM_ANDROID)
extern void InitAndroidGestures(struct android_app *app)
{
app->onInputEvent = AndroidInputCallback;
// TODO: Receive frameBuffer data: displayWidth/displayHeight, renderWidth/renderHeight, screenWidth/screenHeight
}
#endif
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
extern void ProcessMotionEvent(GestureEvent event)
{
// Resets
dragVector = (Vector2){ 0, 0 };
pinchDelta = 0;
switch (gestureType)
{
case TYPE_MOTIONLESS: // Detect TAP, DOUBLE_TAP and HOLD events
{
if (event.action == DOWN)
{
if (event.pointCount > 1) SetDualInput(event);
else
{
// Set the press position
initialTapPosition = event.position[0];
// If too much time have passed, we reset the double tap
if (GetCurrentTime() - eventTime > TAP_TIMEOUT) untap = false;
// If we are in time, we detect the double tap
if (untap) doubleTapping = true;
// Update our event time
eventTime = GetCurrentTime();
// Set hold
if (doubleTapping) currentGesture = GESTURE_DOUBLETAP;
else currentGesture = GESTURE_TAP;
}
}
else if (event.action == UP)
{
currentGesture = GESTURE_NONE;
// Detect that we are tapping instead of holding
if (GetCurrentTime() - eventTime < TAP_TIMEOUT)
{
if (doubleTapping) untap = false;
else untap = true;
}
// Tap finished
doubleTapping = false;
// Update our event time
eventTime = GetCurrentTime();
}
// Begin dragging
else if (event.action == MOVE)
{
if (event.pointCount > 1) SetDualInput(event);
else
{
// Set the drag starting position
initialDragPosition = initialTapPosition;
endDragPosition = initialDragPosition;
// Initialize drag
draggingTimeCounter = 0;
gestureType = TYPE_DRAG;
currentGesture = GESTURE_NONE;
}
}
} break;
case TYPE_DRAG: // Detect DRAG and SWIPE events
{
// end of the drag
if (event.action == UP)
{
// Return Swipe if we have enough sensitivity
if (intensity > FORCE_TO_SWIPE)
{
if (angle < 30 || angle > 330) currentGesture = GESTURE_SWIPE_RIGHT; // Right
else if (angle > 60 && angle < 120) currentGesture = GESTURE_SWIPE_UP; // Up
else if (angle > 150 && angle < 210) currentGesture = GESTURE_SWIPE_LEFT; // Left
else if (angle > 240 && angle < 300) currentGesture = GESTURE_SWIPE_DOWN; // Down
}
magnitude = 0;
angle = 0;
intensity = 0;
gestureType = TYPE_MOTIONLESS;
}
// Update while we are dragging
else if (event.action == MOVE)
{
if (event.pointCount > 1) SetDualInput(event);
else
{
lastDragPosition = endDragPosition;
endDragPosition = GetRawPosition();
//endDragPosition.x = AMotionEvent_getX(event, 0);
//endDragPosition.y = AMotionEvent_getY(event, 0);
// Calculate attributes
dragVector = (Vector2){ endDragPosition.x - lastDragPosition.x, endDragPosition.y - lastDragPosition.y };
magnitude = sqrt(pow(endDragPosition.x - initialDragPosition.x, 2) + pow(endDragPosition.y - initialDragPosition.y, 2));
angle = CalculateAngle(initialDragPosition, endDragPosition, magnitude);
intensity = magnitude / (float)draggingTimeCounter;
currentGesture = GESTURE_DRAG;
draggingTimeCounter++;
}
}
} break;
case TYPE_DUAL_INPUT:
{
if (event.action == UP)
{
if (event.pointCount == 1)
{
// Set the drag starting position
initialTapPosition = event.position[0];
}
gestureType = TYPE_MOTIONLESS;
}
else if (event.action == MOVE)
{
// Adapt the ending position of the inputs
firstEndPinchPosition = event.position[0];
secondEndPinchPosition = event.position[1];
// If there is no more than two inputs
if (event.pointCount == 2)
{
// Detect pinch delta
pinchDelta = OnPinch();
// Pinch gesture resolution
if (pinchDelta != 0)
{
if (pinchDelta > 0) currentGesture = GESTURE_PINCH_IN;
else currentGesture = GESTURE_PINCH_OUT;
}
}
else
{
// Set the drag starting position
initialTapPosition = event.position[0];
gestureType = TYPE_MOTIONLESS;
}
// Readapt the initial position of the inputs
firstInitialPinchPosition = firstEndPinchPosition;
secondInitialPinchPosition = secondEndPinchPosition;
}
} break;
}
//--------------------------------------------------------------------
}
static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, float magnitude)
{
float angle;
// Calculate arcsinus of the movement ( Our sinus is (actualPosition.y - initialPosition.y) / magnitude)
angle = asin((actualPosition.y - initialPosition.y) / magnitude);
angle *= RAD2DEG;
// Calculate angle depending on the sector
if (actualPosition.x - initialPosition.x >= 0)
{
// Sector 4
if (actualPosition.y - initialPosition.y >= 0)
{
angle *= -1;
angle += 360;
}
// Sector 1
else
{
angle *= -1;
}
}
else
{
// Sector 3
if (actualPosition.y - initialPosition.y >= 0)
{
angle += 180;
}
// Sector 2
else
{
angle *= -1;
angle = 180 - angle;
}
}
return angle;
}
static float OnPinch()
{
// Calculate distances
float initialDistance = Distance(firstInitialPinchPosition, secondInitialPinchPosition);
float endDistance = Distance(firstEndPinchPosition, secondEndPinchPosition);
// Calculate Vectors
Vector2 firstTouchVector = { firstEndPinchPosition.x - firstInitialPinchPosition.x, firstEndPinchPosition.y - firstInitialPinchPosition.y };
Vector2 secondTouchVector = { secondEndPinchPosition.x - secondInitialPinchPosition.x, secondEndPinchPosition.y - secondInitialPinchPosition.y };
// Detect the pinch gesture
// Calculate Distances
if (DotProduct(firstTouchVector, secondTouchVector) < -0.5) return initialDistance - endDistance;
else return 0;
}
static void SetDualInput(GestureEvent event)
{
initialDragPosition = (Vector2){ 0, 0 };
endDragPosition = (Vector2){ 0, 0 };
lastDragPosition = (Vector2){ 0, 0 };
// Initialize positions
firstInitialPinchPosition = event.position[0];
secondInitialPinchPosition = event.position[1];
firstEndPinchPosition = firstInitialPinchPosition;
secondEndPinchPosition = secondInitialPinchPosition;
// Resets
magnitude = 0;
angle = 0;
intensity = 0;
gestureType = TYPE_DUAL_INPUT;
}
static float Distance(Vector2 v1, Vector2 v2)
{
float result;
float dx = v2.x - v1.x;
float dy = v2.y - v1.y;
result = sqrt(dx*dx + dy*dy);
return result;
}
static float DotProduct(Vector2 v1, Vector2 v2)
{
float result;
float v1Module = sqrt(v1.x*v1.x + v1.y*v1.y);
float v2Module = sqrt(v2.x*v2.x + v2.y*v2.y);
Vector2 v1Normalized = { v1.x / v1Module, v1.y / v1Module };
Vector2 v2Normalized = { v2.x / v2Module, v2.y / v2Module };
result = v1Normalized.x*v2Normalized.x + v1Normalized.y*v2Normalized.y;
return result;
}
static double GetCurrentTime()
{
double time = 0;
#if defined(_WIN32)
/*
// NOTE: Requires Windows.h
FILETIME tm;
GetSystemTimePreciseAsFileTime(&tm);
ULONGLONG nowTime = ((ULONGLONG)tm.dwHighDateTime << 32) | (ULONGLONG)tm.dwLowDateTime; // Time provided in 100-nanosecond intervals
time = ((double)nowTime/10000000.0); // time in seconds
*/
#endif
#if defined(__linux)
// NOTE: Only for Linux-based systems
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
uint64_t nowTime = (uint64_t)now.tv_sec*1000000000LLU + (uint64_t)now.tv_nsec; // Time provided in nanoseconds
time = ((double)nowTime/1000000.0); // time in miliseconds
#endif
return time;
}
#if defined(PLATFORM_ANDROID)
// Android: Get input events
static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
{
int type = AInputEvent_getType(event);
if (type == AINPUT_EVENT_TYPE_MOTION)
{
touchPosition.x = AMotionEvent_getX(event, 0);
touchPosition.y = AMotionEvent_getY(event, 0);
}
else if (type == AINPUT_EVENT_TYPE_KEY)
{
//int32_t key = AKeyEvent_getKeyCode(event);
//int32_t AKeyEvent_getMetaState(event);
}
int32_t action = AMotionEvent_getAction(event);
unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
GestureEvent gestureEvent;
// Action
if (flags == AMOTION_EVENT_ACTION_DOWN) gestureEvent.action = DOWN;
else if (flags == AMOTION_EVENT_ACTION_UP) gestureEvent.action = UP;
else if (flags == AMOTION_EVENT_ACTION_MOVE) gestureEvent.action = MOVE;
// Points
gestureEvent.pointCount = AMotionEvent_getPointerCount(event);
// Position
gestureEvent.position[0] = (Vector2){ AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0) };
gestureEvent.position[1] = (Vector2){ AMotionEvent_getX(event, 1), AMotionEvent_getY(event, 1) };
ProcessMotionEvent(gestureEvent);
return 0;
}
#endif
#if defined(PLATFORM_WEB)
// Web: Get input events
static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
{
/*
for (int i = 0; i < touchEvent->numTouches; i++)
{
long x, y, id;
if (!touchEvent->touches[i].isChanged) continue;
id = touchEvent->touches[i].identifier;
x = touchEvent->touches[i].canvasX;
y = touchEvent->touches[i].canvasY;
}
printf("%s, numTouches: %d %s%s%s%s\n", emscripten_event_type_to_string(eventType), event->numTouches,
event->ctrlKey ? " CTRL" : "", event->shiftKey ? " SHIFT" : "", event->altKey ? " ALT" : "", event->metaKey ? " META" : "");
for(int i = 0; i < event->numTouches; ++i)
{
const EmscriptenTouchPoint *t = &event->touches[i];
printf(" %ld: screen: (%ld,%ld), client: (%ld,%ld), page: (%ld,%ld), isChanged: %d, onTarget: %d, canvas: (%ld, %ld)\n",
t->identifier, t->screenX, t->screenY, t->clientX, t->clientY, t->pageX, t->pageY, t->isChanged, t->onTarget, t->canvasX, t->canvasY);
}
*/
GestureEvent gestureEvent;
// Action
if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) gestureEvent.action = DOWN;
else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) gestureEvent.action = UP;
else if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) gestureEvent.action = MOVE;
// Points
gestureEvent.pointCount = touchEvent->numTouches;
// Position
gestureEvent.position[0] = (Vector2){ touchEvent->touches[0].canvasX, touchEvent->touches[0].canvasY };
gestureEvent.position[1] = (Vector2){ touchEvent->touches[1].canvasX, touchEvent->touches[1].canvasY };
touchPosition = gestureEvent.position[0];
ProcessMotionEvent(gestureEvent);
return 1;
}
#endif

View File

@ -93,7 +93,7 @@ else
endif
# define all object files required
OBJS = core.o rlgl.o raymath.o shapes.o text.o textures.o models.o audio.o utils.o stb_vorbis.o
OBJS = core.o rlgl.o raymath.o shapes.o text.o textures.o models.o audio.o utils.o camera.o gestures.o
# typing 'make' will invoke the first target entry in the file,
# in this case, the 'default' target entry is raylib
@ -144,9 +144,13 @@ audio.o: audio.c
utils.o: utils.c
$(CC) -c utils.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
# compile stb_vorbis library
stb_vorbis.o: stb_vorbis.c
$(CC) -c stb_vorbis.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
# compile camera module
camera.o: camera.c
$(CC) -c camera.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
# compile gestures module
gestures.o: gestures.c
$(CC) -c gestures.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
# clean everything
clean:
@ -155,8 +159,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
rm -f *.o libraylib.a
else
ifeq ($(PLATFORM_OS),LINUX)
find . -type f -executable -delete
rm -f *.o libraylib.a
find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f
else
del *.o libraylib.a
endif

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/**********************************************************************************************
*
* raylib 1.2 (www.raylib.com)
* raylib 1.3.0 (www.raylib.com)
*
* A simple and easy-to-use library to learn videogames programming
*
@ -27,7 +27,6 @@
*
* Some design decisions:
* 32bit Colors - All defined color are always RGBA
* 32bit Textures - All loaded images are converted automatically to RGBA textures
* SpriteFonts - All loaded sprite-font images are converted to RGBA and POT textures
* One custom default font is loaded automatically when InitWindow()
* If using OpenGL 3.3+ or ES2, one default shader is loaded automatically (internally defined)
@ -78,7 +77,7 @@
// Some basic Defines
//----------------------------------------------------------------------------------
#ifndef PI
#define PI 3.14159265358979323846
#define PI 3.14159265358979323846
#endif
#define DEG2RAD (PI / 180.0f)
@ -90,8 +89,9 @@
#define FLAG_SHOW_MOUSE_CURSOR 4
#define FLAG_CENTERED_MODE 8
#define FLAG_MSAA_4X_HINT 16
#define FLAG_VSYNC_HINT 32
// Keyboard Function Keys
// Keyboard Function Keys
#define KEY_SPACE 32
#define KEY_ESCAPE 256
#define KEY_ENTER 257
@ -177,8 +177,10 @@
// Types and Structures Definition
//----------------------------------------------------------------------------------
#ifndef __cplusplus
// Boolean type
typedef enum { false, true } bool;
#endif
// byte type
typedef unsigned char byte;
@ -196,6 +198,14 @@ typedef struct Vector3 {
float z;
} Vector3;
// Matrix type (OpenGL style 4x4 - right handed, column major)
typedef struct Matrix {
float m0, m4, m8, m12;
float m1, m5, m9, m13;
float m2, m6, m10, m14;
float m3, m7, m11, m15;
} Matrix;
// Color type, RGBA (32bit)
typedef struct Color {
unsigned char r;
@ -215,17 +225,21 @@ typedef struct Rectangle {
// Image type, bpp always RGBA (32bit)
// NOTE: Data stored in CPU memory (RAM)
typedef struct Image {
Color *pixels;
int width;
int height;
void *data; // Image raw data
int width; // Image base width
int height; // Image base height
int mipmaps; // Mipmap levels, 1 by default
int format; // Data format (TextureFormat)
} Image;
// Texture2D type, bpp always RGBA (32bit)
// NOTE: Data stored in GPU memory
typedef struct Texture2D {
unsigned int id; // OpenGL id
int width;
int height;
unsigned int id; // OpenGL texture id
int width; // Texture base width
int height; // Texture base height
int mipmaps; // Mipmap levels, 1 by default
int format; // Data format (TextureFormat)
} Texture2D;
// Character type (one font glyph)
@ -251,25 +265,60 @@ typedef struct Camera {
Vector3 up;
} Camera;
// Camera modes
typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
// Vertex data definning a mesh
// NOTE: If using OpenGL 1.1, data loaded in CPU; if OpenGL 3.3+ data loaded in GPU (vaoId)
typedef struct VertexData {
int vertexCount;
float *vertices; // 3 components per vertex
float *texcoords; // 2 components per vertex
float *normals; // 3 components per vertex
unsigned char *colors; // 4 components per vertex
} VertexData;
// 3d Model type
// NOTE: If using OpenGL 1.1, loaded in CPU (mesh); if OpenGL 3.3+ loaded in GPU (vaoId)
typedef struct Model {
VertexData mesh;
unsigned int vaoId;
unsigned int vboId[4];
unsigned int textureId;
//Matrix transform;
} VertexData;
// Shader type
typedef struct Shader {
unsigned int id; // Shader program id
unsigned int texDiffuseId; // Diffuse texture id
unsigned int texNormalId; // Normal texture id
unsigned int texSpecularId; // Specular texture id
// Variable attributes
int vertexLoc; // Vertex attribute location point (vertex shader)
int texcoordLoc; // Texcoord attribute location point (vertex shader)
int normalLoc; // Normal attribute location point (vertex shader)
int colorLoc; // Color attibute location point (vertex shader)
// Uniforms
int projectionLoc; // Projection matrix uniform location point (vertex shader)
int modelviewLoc; // ModeView matrix uniform location point (vertex shader)
int tintColorLoc; // Color uniform location point (fragment shader)
int mapDiffuseLoc; // Diffuse map texture uniform location point (fragment shader)
int mapNormalLoc; // Normal map texture uniform location point (fragment shader)
int mapSpecularLoc; // Specular map texture uniform location point (fragment shader)
} Shader;
// 3d Model type
typedef struct Model {
VertexData mesh;
Matrix transform;
Texture2D texture; // Only for OpenGL 1.1, on newer versions this should be in the shader
Shader shader;
} Model;
// Ray type (useful for raycast)
typedef struct Ray {
Vector3 position;
Vector3 direction;
} Ray;
// Sound source type
typedef struct Sound {
unsigned int source;
@ -285,6 +334,44 @@ typedef struct Wave {
short channels;
} Wave;
// Texture formats
// NOTE: Support depends on OpenGL version and platform
typedef enum {
UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
UNCOMPRESSED_GRAY_ALPHA, // 16 bpp (2 channels)
UNCOMPRESSED_R5G6B5, // 16 bpp
UNCOMPRESSED_R8G8B8, // 24 bpp
UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
UNCOMPRESSED_R8G8B8A8, // 32 bpp
COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
COMPRESSED_DXT3_RGBA, // 8 bpp
COMPRESSED_DXT5_RGBA, // 8 bpp
COMPRESSED_ETC1_RGB, // 4 bpp
COMPRESSED_ETC2_RGB, // 4 bpp
COMPRESSED_ETC2_EAC_RGBA, // 8 bpp
COMPRESSED_PVRT_RGB, // 4 bpp
COMPRESSED_PVRT_RGBA, // 4 bpp
COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
COMPRESSED_ASTC_8x8_RGBA // 2 bpp
} TextureFormat;
// Gestures type
typedef enum {
GESTURE_NONE = 0,
GESTURE_TAP,
GESTURE_DOUBLETAP,
GESTURE_HOLD,
GESTURE_DRAG,
GESTURE_SWIPE_RIGHT,
GESTURE_SWIPE_LEFT,
GESTURE_SWIPE_UP,
GESTURE_SWIPE_DOWN,
GESTURE_PINCH_IN,
GESTURE_PINCH_OUT
} Gestures;
#ifdef __cplusplus
extern "C" { // Prevents name mangling of functions
#endif
@ -312,7 +399,6 @@ void SetExitKey(int key); // Set a custom key
#endif
int GetScreenWidth(void); // Get current screen width
int GetScreenHeight(void); // Get current screen height
int GetKeyPressed(void); // Get latest key pressed
void ClearBackground(Color color); // Sets Background Color
void BeginDrawing(void); // Setup drawing canvas to start drawing
@ -331,9 +417,35 @@ int GetHexValue(Color color); // Returns hexadecim
int GetRandomValue(int min, int max); // Returns a random value between min and max (both included)
Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
void SetupFlags(char flags); // Enable some window configurations
void SetConfigFlags(char flags); // Enable some window configurations
void ShowLogo(void); // Activates raylib logo at startup (can be done with flags)
void SetPostproShader(Shader shader); // Set fullscreen postproduction shader
void SetCustomShader(Shader shader); // Set custom shader to be used in batch draw
void SetDefaultShader(void); // Set default shader to be used in batch draw
Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Gives the rayTrace from mouse position
// Camera modes setup and control functions (module: camera)
void SetCameraMode(int mode); // Select camera mode (multiple camera modes available)
Camera UpdateCamera(Vector3 *position); // Update camera with position
void SetCameraControls(int front, int left, int back, int right, int up, int down);
void SetMouseSensitivity(float sensitivity);
void SetResetPosition(Vector3 resetPosition);
void SetResetControl(int resetKey);
void SetPawnControl(int pawnControlKey);
void SetFnControl(int fnControlKey);
void SetSmoothZoomControl(int smoothZoomControlKey);
void SetOrbitalTarget(Vector3 target);
int GetShaderLocation(Shader shader, const char *uniformName);
void SetShaderValue(Shader shader, int uniformLoc, float *value, int size);
void SetShaderMapDiffuse(Shader *shader, Texture2D texture);
void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture);
void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture);
//------------------------------------------------------------------------------------
// Input Handling Functions (Module: core)
//------------------------------------------------------------------------------------
@ -342,6 +454,7 @@ bool IsKeyPressed(int key); // Detect if a key has b
bool IsKeyDown(int key); // Detect if a key is being pressed
bool IsKeyReleased(int key); // Detect if a key has been released once
bool IsKeyUp(int key); // Detect if a key is NOT being pressed
int GetKeyPressed(void); // Get latest key pressed
bool IsMouseButtonPressed(int button); // Detect if a mouse button has been pressed once
bool IsMouseButtonDown(int button); // Detect if a mouse button is being pressed
@ -352,9 +465,13 @@ int GetMouseY(void); // Returns mouse positio
Vector2 GetMousePosition(void); // Returns mouse position XY
void SetMousePosition(Vector2 position); // Set mouse position XY
int GetMouseWheelMove(void); // Returns mouse wheel movement Y
void ShowCursor(void); // Shows cursor
void HideCursor(void); // Hides cursor
bool IsCursorHidden(void); // Returns true if cursor is not visible
#endif
#if defined(PLATFORM_DESKTOP)
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
bool IsGamepadAvailable(int gamepad); // Detect if a gamepad is available
Vector2 GetGamepadMovement(int gamepad); // Return axis movement vector for a gamepad
bool IsGamepadButtonPressed(int gamepad, int button); // Detect if a gamepad button has been pressed once
@ -363,11 +480,20 @@ bool IsGamepadButtonReleased(int gamepad, int button); // Detect if a gamepad b
bool IsGamepadButtonUp(int gamepad, int button); // Detect if a gamepad button is NOT being pressed
#endif
#if defined(PLATFORM_ANDROID)
bool IsScreenTouched(void); // Detect screen touch event
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
int GetTouchX(void); // Returns touch position X
int GetTouchY(void); // Returns touch position Y
Vector2 GetTouchPosition(void); // Returns touch position XY
// Gestures System (module: gestures)
bool IsGestureDetected(void);
int GetGestureType(void);
float GetDragIntensity(void);
float GetDragAngle(void);
Vector2 GetDragVector(void);
int GetHoldDuration(void); // Hold time in frames
float GetPinchDelta(void);
float GetPinchAngle(void);
#endif
//------------------------------------------------------------------------------------
@ -405,13 +531,15 @@ bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2
//------------------------------------------------------------------------------------
Image LoadImage(const char *fileName); // Load an image into CPU memory (RAM)
Image LoadImageFromRES(const char *rresName, int resId); // Load an image from rRES file (raylib Resource)
Image LoadImageFromData(Color *pixels, int width, int height, int format); // Load image from Color array data
Texture2D LoadTexture(const char *fileName); // Load an image as texture into GPU memory
Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, int mipmapCount, bool genMipmaps); // Load a texture from raw data into GPU memory
Texture2D LoadTextureFromRES(const char *rresName, int resId); // Load an image as texture from rRES file (raylib Resource)
Texture2D LoadTextureFromImage(Image image, bool genMipmaps); // Load a texture from image data (and generate mipmaps)
Texture2D CreateTexture(Image image, bool genMipmaps); // [DEPRECATED] Same as LoadTextureFromImage()
void UnloadImage(Image image); // Unload image from CPU memory (RAM)
void UnloadTexture(Texture2D texture); // Unload texture from GPU memory
void ConvertToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two)
Color *GetPixelData(Image image); // Get pixel data from image as a Color struct array
void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D
void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2
@ -448,31 +576,40 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color
void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere wires
void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone
void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires
void DrawQuad(Vector3 vertices[4], Vector2 textcoords[4], Vector3 normals[4], Color colors[4]); // Draw a quad
void DrawPlane(Vector3 centerPos, Vector2 size, Vector3 rotation, Color color); // Draw a plane
void DrawPlaneEx(Vector3 centerPos, Vector2 size, Vector3 rotation, int slicesX, int slicesZ, Color color); // Draw a plane with divisions
void DrawPlane(Vector3 centerPos, Vector2 size, Color color); // Draw a plane XZ
void DrawQuad(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, Color color); // Draw a quad
void DrawRay(Ray ray, Color color); // Draw a ray line
void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0))
void DrawGizmo(Vector3 position); // Draw simple gizmo
void DrawGizmoEx(Vector3 position, Vector3 rotation, float scale); // Draw gizmo with extended parameters
//DrawTorus(), DrawTeapot() are useless...
//------------------------------------------------------------------------------------
// Model 3d Loading and Drawing Functions (Module: models)
//------------------------------------------------------------------------------------
Model LoadModel(const char *fileName); // Load a 3d model (.OBJ)
Model LoadModelEx(VertexData data); // Load a 3d model (from vertex data)
//Model LoadModelFromRES(const char *rresName, int resId); // TODO: Load a 3d model from rRES file (raylib Resource)
Model LoadHeightmap(Image heightmap, float maxHeight); // Load a heightmap image as a 3d model
Model LoadCubicmap(Image cubicmap); // Load a map image as a 3d model (cubes based)
void UnloadModel(Model model); // Unload 3d model from memory
void SetModelTexture(Model *model, Texture2D texture); // Link a texture to a model
void SetModelShader(Model *model, Shader shader); // Link a shader to a model (not available on OpenGL 1.1)
void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set)
void DrawModelEx(Model model, Vector3 position, Vector3 rotation, Vector3 scale, Color tint); // Draw a model with extended parameters
void DrawModelEx(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color tint); // Draw a model with extended parameters
void DrawModelWires(Model model, Vector3 position, float scale, Color color); // Draw a model wires (with texture if set)
void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint); // Draw a billboard texture
void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec
Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader (vertex shader + fragment shader)
void UnloadShader(Shader shader); // Unload a custom shader from memory
bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB);
bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, Vector3 maxBBox2);
bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSphere, float radiusSphere);
Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius); // Return the normal vector of the impacted surface
//------------------------------------------------------------------------------------
// Audio Loading and Playing Functions (Module: audio)
//------------------------------------------------------------------------------------

View File

@ -346,8 +346,6 @@ void MatrixInvert(Matrix *mat)
temp.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet;
temp.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet;
PrintMatrix(temp);
*mat = temp;
}
@ -433,72 +431,78 @@ Matrix MatrixSubstract(Matrix left, Matrix right)
}
// Returns translation matrix
// TODO: Review this function
Matrix MatrixTranslate(float x, float y, float z)
{
/*
For OpenGL
1, 0, 0, 0
0, 1, 0, 0
0, 0, 1, 0
x, y, z, 1
Is the correct Translation Matrix. Why? Opengl Uses column-major matrix ordering.
Which is the Transpose of the Matrix you initially presented, which is in row-major ordering.
Row major is used in most math text-books and also DirectX, so it is a common
point of confusion for those new to OpenGL.
* matrix notation used in opengl documentation does not describe in-memory layout for OpenGL matrices
Translation matrix should be laid out in memory like this:
{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, trabsX, transY, transZ, 1 }
9.005 Are OpenGL matrices column-major or row-major?
For programming purposes, OpenGL matrices are 16-value arrays with base vectors laid out
contiguously in memory. The translation components occupy the 13th, 14th, and 15th elements
of the 16-element matrix, where indices are numbered from 1 to 16 as described in section
2.11.2 of the OpenGL 2.1 Specification.
Column-major versus row-major is purely a notational convention. Note that post-multiplying
with column-major matrices produces the same result as pre-multiplying with row-major matrices.
The OpenGL Specification and the OpenGL Reference Manual both use column-major notation.
You can use any notation, as long as it's clearly stated.
Sadly, the use of column-major format in the spec and blue book has resulted in endless confusion
in the OpenGL programming community. Column-major notation suggests that matrices
are not laid out in memory as a programmer would expect.
*/
Matrix result = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 };
return result;
}
// Returns rotation matrix
// TODO: Review this function
Matrix MatrixRotate(float angleX, float angleY, float angleZ)
// Create rotation matrix from axis and angle
// NOTE: Angle should be provided in radians
Matrix MatrixRotate(float angle, Vector3 axis)
{
Matrix result;
Matrix rotX = MatrixRotateX(angleX);
Matrix rotY = MatrixRotateY(angleY);
Matrix rotZ = MatrixRotateZ(angleZ);
Matrix mat = MatrixIdentity();
result = MatrixMultiply(MatrixMultiply(rotX, rotY), rotZ);
float x = axis.x, y = axis.y, z = axis.z;
float length = sqrt(x*x + y*y + z*z);
if ((length != 1) && (length != 0))
{
length = 1/length;
x *= length;
y *= length;
z *= length;
}
float s = sinf(angle);
float c = cosf(angle);
float t = 1.0f - c;
// Cache some matrix values (speed optimization)
float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
// Construct the elements of the rotation matrix
float b00 = x*x*t + c, b01 = y*x*t + z*s, b02 = z*x*t - y*s;
float b10 = x*y*t - z*s, b11 = y*y*t + c, b12 = z*y*t + x*s;
float b20 = x*z*t + y*s, b21 = y*z*t - x*s, b22 = z*z*t + c;
// Perform rotation-specific matrix multiplication
result.m0 = a00*b00 + a10*b01 + a20*b02;
result.m1 = a01*b00 + a11*b01 + a21*b02;
result.m2 = a02*b00 + a12*b01 + a22*b02;
result.m3 = a03*b00 + a13*b01 + a23*b02;
result.m4 = a00*b10 + a10*b11 + a20*b12;
result.m5 = a01*b10 + a11*b11 + a21*b12;
result.m6 = a02*b10 + a12*b11 + a22*b12;
result.m7 = a03*b10 + a13*b11 + a23*b12;
result.m8 = a00*b20 + a10*b21 + a20*b22;
result.m9 = a01*b20 + a11*b21 + a21*b22;
result.m10 = a02*b20 + a12*b21 + a22*b22;
result.m11 = a03*b20 + a13*b21 + a23*b22;
result.m12 = mat.m12;
result.m13 = mat.m13;
result.m14 = mat.m14;
result.m15 = mat.m15;
return result;
}
/*
// Another implementation for MatrixRotate...
Matrix MatrixRotate(float angle, float x, float y, float z)
{
Matrix result = MatrixIdentity();
float c = cosf(angle*DEG2RAD); // cosine
float s = sinf(angle*DEG2RAD); // sine
float c1 = 1.0f - c; // 1 - c
float c = cosf(angle); // cosine
float s = sinf(angle); // sine
float c1 = 1.0f - c; // 1 - c
float m0 = result.m0, m4 = result.m4, m8 = result.m8, m12 = result.m12,
m1 = result.m1, m5 = result.m5, m9 = result.m9, m13 = result.m13,
m2 = result.m2, m6 = result.m6, m10 = result.m10, m14 = result.m14;
@ -532,124 +536,6 @@ Matrix MatrixRotate(float angle, float x, float y, float z)
}
*/
// Create rotation matrix from axis and angle
// TODO: Test this function
// NOTE: NO prototype defined!
Matrix MatrixFromAxisAngle(Vector3 axis, float angle)
{
Matrix result;
Matrix mat = MatrixIdentity();
float x = axis.x, y = axis.y, z = axis.z;
float length = sqrt(x*x + y*y + z*z);
if ((length != 1) && (length != 0))
{
length = 1 / length;
x *= length;
y *= length;
z *= length;
}
float s = sin(angle);
float c = cos(angle);
float t = 1-c;
// Cache some matrix values (speed optimization)
float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
// Construct the elements of the rotation matrix
float b00 = x*x*t + c, b01 = y*x*t + z*s, b02 = z*x*t - y*s;
float b10 = x*y*t - z*s, b11 = y*y*t + c, b12 = z*y*t + x*s;
float b20 = x*z*t + y*s, b21 = y*z*t - x*s, b22 = z*z*t + c;
// Perform rotation-specific matrix multiplication
result.m0 = a00*b00 + a10*b01 + a20*b02;
result.m1 = a01*b00 + a11*b01 + a21*b02;
result.m2 = a02*b00 + a12*b01 + a22*b02;
result.m3 = a03*b00 + a13*b01 + a23*b02;
result.m4 = a00*b10 + a10*b11 + a20*b12;
result.m5 = a01*b10 + a11*b11 + a21*b12;
result.m6 = a02*b10 + a12*b11 + a22*b12;
result.m7 = a03*b10 + a13*b11 + a23*b12;
result.m8 = a00*b20 + a10*b21 + a20*b22;
result.m9 = a01*b20 + a11*b21 + a21*b22;
result.m10 = a02*b20 + a12*b21 + a22*b22;
result.m11 = a03*b20 + a13*b21 + a23*b22;
result.m12 = mat.m12;
result.m13 = mat.m13;
result.m14 = mat.m14;
result.m15 = mat.m15;
return result;
};
// Create rotation matrix from axis and angle (version 2)
// TODO: Test this function
// NOTE: NO prototype defined!
Matrix MatrixFromAxisAngle2(Vector3 axis, float angle)
{
Matrix result;
VectorNormalize(&axis);
float axisX = axis.x, axisY = axis.y, axisZ = axis.y;
// Calculate angles
float cosres = (float)cos(angle);
float sinres = (float)sin(angle);
float t = 1.0f - cosres;
// Do the conversion math once
float tXX = t * axisX * axisX;
float tXY = t * axisX * axisY;
float tXZ = t * axisX * axisZ;
float tYY = t * axisY * axisY;
float tYZ = t * axisY * axisZ;
float tZZ = t * axisZ * axisZ;
float sinX = sinres * axisX;
float sinY = sinres * axisY;
float sinZ = sinres * axisZ;
result.m0 = tXX + cosres;
result.m1 = tXY + sinZ;
result.m2 = tXZ - sinY;
result.m3 = 0;
result.m4 = tXY - sinZ;
result.m5 = tYY + cosres;
result.m6 = tYZ + sinX;
result.m7 = 0;
result.m8 = tXZ + sinY;
result.m9 = tYZ - sinX;
result.m10 = tZZ + cosres;
result.m11 = 0;
result.m12 = 0;
result.m13 = 0;
result.m14 = 0;
result.m15 = 1;
return result;
}
// Returns rotation matrix for a given quaternion
Matrix MatrixFromQuaternion(Quaternion q)
{
Matrix result = MatrixIdentity();
Vector3 axis;
float angle;
QuaternionToAxisAngle(q, &axis, &angle);
result = MatrixFromAxisAngle2(axis, angle);
return result;
}
// Returns x-rotation matrix (angle in radians)
Matrix MatrixRotateX(float angle)
{
@ -671,8 +557,8 @@ Matrix MatrixRotateY(float angle)
{
Matrix result = MatrixIdentity();
float cosres = (float)cos(angle);
float sinres = (float)sin(angle);
float cosres = cosf(angle);
float sinres = sinf(angle);
result.m0 = cosres;
result.m2 = sinres;
@ -706,22 +592,6 @@ Matrix MatrixScale(float x, float y, float z)
return result;
}
// Returns transformation matrix for a given translation, rotation and scale
// NOTE: Transformation order is rotation -> scale -> translation
// NOTE: Rotation angles should come in radians
Matrix MatrixTransform(Vector3 translation, Vector3 rotation, Vector3 scale)
{
Matrix result = MatrixIdentity();
Matrix mRotation = MatrixRotate(rotation.x, rotation.y, rotation.z);
Matrix mScale = MatrixScale(scale.x, scale.y, scale.z);
Matrix mTranslate = MatrixTranslate(translation.x, translation.y, translation.z);
result = MatrixMultiply(MatrixMultiply(mRotation, mScale), mTranslate);
return result;
}
// Returns two matrix multiplication
// NOTE: When multiplying matrices... the order matters!
Matrix MatrixMultiply(Matrix left, Matrix right)
@ -876,7 +746,7 @@ void PrintMatrix(Matrix m)
// Module Functions Definition - Quaternion math
//----------------------------------------------------------------------------------
// Calculates the length of a quaternion
// Computes the length of a quaternion
float QuaternionLength(Quaternion quat)
{
return sqrt(quat.x*quat.x + quat.y*quat.y + quat.z*quat.z + quat.w*quat.w);
@ -922,13 +792,13 @@ Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w;
if (abs(cosHalfTheta) >= 1.0f) result = q1;
if (fabs(cosHalfTheta) >= 1.0f) result = q1;
else
{
float halfTheta = acos(cosHalfTheta);
float sinHalfTheta = sqrt(1.0f - cosHalfTheta*cosHalfTheta);
if (abs(sinHalfTheta) < 0.001f)
if (fabs(sinHalfTheta) < 0.001f)
{
result.x = (q1.x*0.5f + q2.x*0.5f);
result.y = (q1.y*0.5f + q2.y*0.5f);
@ -950,7 +820,7 @@ Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
return result;
}
// Returns a quaternion from a given rotation matrix
// Returns a quaternion for a given rotation matrix
Quaternion QuaternionFromMatrix(Matrix matrix)
{
Quaternion result;
@ -1006,29 +876,7 @@ Quaternion QuaternionFromMatrix(Matrix matrix)
return result;
}
// Returns rotation quaternion for an angle around an axis
// NOTE: angle must be provided in radians
Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle)
{
Quaternion result = { 0, 0, 0, 1 };
if (VectorLength(axis) != 0.0)
angle *= 0.5;
VectorNormalize(&axis);
result.x = axis.x * (float)sin(angle);
result.y = axis.y * (float)sin(angle);
result.z = axis.z * (float)sin(angle);
result.w = (float)cos(angle);
QuaternionNormalize(&result);
return result;
}
// Calculates the matrix from the given quaternion
// Returns a matrix for a given quaternion
Matrix QuaternionToMatrix(Quaternion q)
{
Matrix result;
@ -1067,14 +915,36 @@ Matrix QuaternionToMatrix(Quaternion q)
result.m13 = 0;
result.m14 = 0;
result.m15 = 1;
return result;
}
// Returns rotation quaternion for an angle and axis
// NOTE: angle must be provided in radians
Quaternion QuaternionFromAxisAngle(float angle, Vector3 axis)
{
Quaternion result = { 0, 0, 0, 1 };
if (VectorLength(axis) != 0.0)
angle *= 0.5;
VectorNormalize(&axis);
result.x = axis.x * (float)sin(angle);
result.y = axis.y * (float)sin(angle);
result.z = axis.z * (float)sin(angle);
result.w = (float)cos(angle);
QuaternionNormalize(&result);
return result;
}
// Returns the axis and the angle for a given quaternion
void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle)
// Returns the rotation angle and axis for a given quaternion
void QuaternionToAxisAngle(Quaternion q, float *outAngle, Vector3 *outAxis)
{
if (abs(q.w) > 1.0f) QuaternionNormalize(&q);
if (fabs(q.w) > 1.0f) QuaternionNormalize(&q);
Vector3 resAxis = { 0, 0, 0 };
float resAngle = 0;
@ -1097,4 +967,18 @@ void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle)
*outAxis = resAxis;
*outAngle = resAngle;
}
// Transform a quaternion given a transformation matrix
void QuaternionTransform(Quaternion *q, Matrix mat)
{
float x = q->x;
float y = q->y;
float z = q->z;
float w = q->w;
q->x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12*w;
q->y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13*w;
q->z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14*w;
q->w = mat.m3*x + mat.m7*y + mat.m11*z + mat.m15*w;
}

View File

@ -53,15 +53,15 @@
float y;
float z;
} Vector3;
#endif
// Matrix type (OpenGL style 4x4 - right handed, column major)
typedef struct Matrix {
float m0, m4, m8, m12;
float m1, m5, m9, m13;
float m2, m6, m10, m14;
float m3, m7, m11, m15;
} Matrix;
// Matrix type (OpenGL style 4x4 - right handed, column major)
typedef struct Matrix {
float m0, m4, m8, m12;
float m1, m5, m9, m13;
float m2, m6, m10, m14;
float m3, m7, m11, m15;
} Matrix;
#endif
// Quaternion type
typedef struct Quaternion {
@ -91,7 +91,7 @@ void VectorNormalize(Vector3 *v); // Normalize provided ve
float VectorDistance(Vector3 v1, Vector3 v2); // Calculate distance between two points
Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount); // Calculate linear interpolation between two vectors
Vector3 VectorReflect(Vector3 vector, Vector3 normal); // Calculate reflected vector to normal
void VectorTransform(Vector3 *v, Matrix mat); // Transforms a Vector3 with a given Matrix
void VectorTransform(Vector3 *v, Matrix mat); // Transforms a Vector3 by a given Matrix
Vector3 VectorZero(void); // Return a Vector3 init to zero
//------------------------------------------------------------------------------------
@ -107,15 +107,11 @@ Matrix MatrixIdentity(void); // Returns identity matr
Matrix MatrixAdd(Matrix left, Matrix right); // Add two matrices
Matrix MatrixSubstract(Matrix left, Matrix right); // Substract two matrices (left - right)
Matrix MatrixTranslate(float x, float y, float z); // Returns translation matrix
Matrix MatrixRotate(float axisX, float axisY, float axisZ); // Returns rotation matrix
Matrix MatrixFromAxisAngle(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis
Matrix MatrixFromAxisAngle2(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis (test another implemntation)
Matrix MatrixFromQuaternion(Quaternion q); // Returns rotation matrix for a given quaternion
Matrix MatrixRotate(float angle, Vector3 axis); // Returns rotation matrix for an angle around an specified axis (angle in radians)
Matrix MatrixRotateX(float angle); // Returns x-rotation matrix (angle in radians)
Matrix MatrixRotateY(float angle); // Returns y-rotation matrix (angle in radians)
Matrix MatrixRotateZ(float angle); // Returns z-rotation matrix (angle in radians)
Matrix MatrixScale(float x, float y, float z); // Returns scaling matrix
Matrix MatrixTransform(Vector3 translation, Vector3 rotation, Vector3 scale); // Returns transformation matrix for a given translation, rotation and scale
Matrix MatrixMultiply(Matrix left, Matrix right); // Returns two matrix multiplication
Matrix MatrixFrustum(double left, double right, double bottom, double top, double near, double far); // Returns perspective projection matrix
Matrix MatrixPerspective(double fovy, double aspect, double near, double far); // Returns perspective projection matrix
@ -126,14 +122,15 @@ void PrintMatrix(Matrix m); // Print matrix utility
//------------------------------------------------------------------------------------
// Functions Declaration to work with Quaternions
//------------------------------------------------------------------------------------
float QuaternionLength(Quaternion quat); // Calculates the length of a quaternion
float QuaternionLength(Quaternion quat); // Compute the length of a quaternion
void QuaternionNormalize(Quaternion *q); // Normalize provided quaternion
Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2); // Calculate two quaternion multiplication
Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float slerp); // Calculates spherical linear interpolation between two quaternions
Quaternion QuaternionFromMatrix(Matrix matrix); // Returns a quaternion from a given rotation matrix
Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle); // Returns rotation quaternion for an angle around an axis
Matrix QuaternionToMatrix(Quaternion q); // Calculates the matrix from the given quaternion
void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle); // Returns the axis and the angle for a given quaternion
Quaternion QuaternionFromMatrix(Matrix matrix); // Returns a quaternion for a given rotation matrix
Matrix QuaternionToMatrix(Quaternion q); // Returns a matrix for a given quaternion
Quaternion QuaternionFromAxisAngle(float angle, Vector3 axis); // Returns rotation quaternion for an angle and axis
void QuaternionToAxisAngle(Quaternion q, float *outAngle, Vector3 *outAxis); // Returns the rotation angle and axis for a given quaternion
void QuaternionTransform(Quaternion *q, Matrix mat); // Transform a quaternion given a transformation matrix
#ifdef __cplusplus
}

1793
src/rlgl.c

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,7 @@
//#define RLGL_STANDALONE // NOTE: To use rlgl as standalone lib, just uncomment this line
#ifndef RLGL_STANDALONE
#include "raylib.h" // Required for typedef: Model
#include "raylib.h" // Required for typedef(s): Model, Shader, Texture2D
#include "utils.h" // Required for function TraceLog()
#endif
@ -89,21 +89,69 @@ typedef enum { RL_LINES, RL_TRIANGLES, RL_QUADS } DrawMode;
typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
#ifdef RLGL_STANDALONE
typedef struct {
// Texture formats (support depends on OpenGL version)
typedef enum {
UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
UNCOMPRESSED_R5G6B5, // 16 bpp
UNCOMPRESSED_R8G8B8, // 24 bpp
UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
UNCOMPRESSED_R8G8B8A8, // 32 bpp
COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
COMPRESSED_DXT3_RGBA, // 8 bpp
COMPRESSED_DXT5_RGBA, // 8 bpp
COMPRESSED_ETC1_RGB, // 4 bpp
COMPRESSED_ETC2_RGB, // 4 bpp
COMPRESSED_ETC2_EAC_RGBA, // 8 bpp
COMPRESSED_PVRT_RGB, // 4 bpp
COMPRESSED_PVRT_RGBA, // 4 bpp
/*COMPRESSED_ASTC_RGBA_4x4*/ // 8 bpp
} TextureFormat;
// VertexData type
// NOTE: If using OpenGL 1.1, data loaded in CPU; if OpenGL 3.3+ data loaded in GPU (vaoId)
typedef struct VertexData {
int vertexCount;
float *vertices; // 3 components per vertex
float *texcoords; // 2 components per vertex
float *normals; // 3 components per vertex
unsigned char *colors;
} VertexData;
typedef struct Model {
VertexData mesh;
unsigned int vaoId;
unsigned int vboId[4];
unsigned int textureId;
//Matrix transform;
} VertexData;
// Shader type
typedef struct Shader {
unsigned int id; // Shader program id
// Variable attributes
unsigned int vertexLoc; // Vertex attribute location point (vertex shader)
unsigned int texcoordLoc; // Texcoord attribute location point (vertex shader)
unsigned int normalLoc; // Normal attribute location point (vertex shader)
unsigned int colorLoc; // Color attibute location point (vertex shader)
// Uniforms
unsigned int projectionLoc; // Projection matrix uniform location point (vertex shader)
unsigned int modelviewLoc; // ModeView matrix uniform location point (vertex shader)
unsigned int textureLoc; // Texture uniform location point (fragment shader)
unsigned int tintColorLoc; // Color uniform location point (fragment shader)
} Shader;
// 3d Model type
typedef struct Model {
VertexData mesh;
Matrix transform;
Texture2D texture;
Shader shader;
} Model;
// Texture2D type
typedef struct Texture2D {
unsigned int id; // Texture id
int width;
int height;
} Texture2D;
#endif
#ifdef __cplusplus
@ -145,11 +193,13 @@ void rlColor4f(float x, float y, float z, float w); // Define one vertex (color)
void rlEnableTexture(unsigned int id); // Enable texture usage
void rlDisableTexture(void); // Disable texture usage
void rlDeleteTextures(unsigned int id); // Delete OpenGL texture from GPU
void rlDeleteShader(unsigned int id); // Delete OpenGL shader program from GPU
void rlDeleteVertexArrays(unsigned int id); // Unload vertex data (VAO) from GPU memory
void rlDeleteBuffers(unsigned int id); // Unload vertex data (VBO) from GPU memory
void rlClearColor(byte r, byte g, byte b, byte a); // Clear color buffer with color
void rlClearScreenBuffers(void); // Clear used screen buffers (color and depth)
int rlGetVersion(void); // Returns current OpenGL version
void rlEnableFBO(void); // Enable rendering to postprocessing FBO
//------------------------------------------------------------------------------------
// Functions Declaration - rlgl functionality
@ -159,11 +209,20 @@ void rlglClose(void); // De-init rlgl
void rlglDraw(void); // Draw VAO/VBO
void rlglInitGraphics(int offsetX, int offsetY, int width, int height); // Initialize Graphics (OpenGL stuff)
unsigned int rlglLoadTexture(unsigned char *data, int width, int height, bool genMipmaps); // Load in GPU OpenGL texture
unsigned int rlglLoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int format);
unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount, bool genMipmaps); // Load in GPU OpenGL texture
Shader rlglLoadShader(char *vsFileName, char *fsFileName); // Load a shader (vertex shader + fragment shader) from files
unsigned int rlglLoadShaderFromText(char *vShaderStr, char *fShaderStr); // Load a shader from text data
void rlglInitPostpro(void); // Initialize postprocessing system
void rlglDrawPostpro(void); // Draw with postprocessing shader
void rlglSetPostproShader(Shader shader); // Set postprocessing shader
void rlglSetModelShader(Model *model, Shader shader); // Set shader for a model
void rlglSetCustomShader(Shader shader); // Set custom shader to be used on batch draw
void rlglSetDefaultShader(void); // Set default shader to be used on batch draw
Model rlglLoadModel(VertexData mesh); // Upload vertex data into GPU and provided VAO/VBO ids
void rlglDrawModel(Model model, Vector3 position, Vector3 rotation, Vector3 scale, Color color, bool wires);
void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color color, bool wires);
Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates
byte *rlglReadScreenPixels(int width, int height); // Read screen pixel data (color buffer)

View File

@ -98,7 +98,7 @@ void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
// Draw a color-filled circle
void DrawCircle(int centerX, int centerY, float radius, Color color)
{
DrawPoly((Vector2){centerX, centerY}, 360, radius, 0, color);
DrawPoly((Vector2){ centerX, centerY }, 36, radius, 0, color);
}
// Draw a gradient-filled circle
@ -106,14 +106,14 @@ void DrawCircle(int centerX, int centerY, float radius, Color color)
void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2)
{
rlBegin(RL_TRIANGLES);
for (int i=0; i < 360; i += 2)
for (int i = 0; i < 360; i += 10)
{
rlColor4ub(color1.r, color1.g, color1.b, color1.a);
rlVertex2i(centerX, centerY);
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
rlVertex2f(centerX + sin(DEG2RAD*i) * radius, centerY + cos(DEG2RAD*i) * radius);
rlVertex2f(centerX + sin(DEG2RAD*i)*radius, centerY + cos(DEG2RAD*i)*radius);
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
rlVertex2f(centerX + sin(DEG2RAD*(i+2)) * radius, centerY + cos(DEG2RAD*(i+2)) * radius);
rlVertex2f(centerX + sin(DEG2RAD*(i + 10)) * radius, centerY + cos(DEG2RAD*(i + 10))*radius);
}
rlEnd();
}
@ -122,12 +122,12 @@ void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Co
void DrawCircleV(Vector2 center, float radius, Color color)
{
rlBegin(RL_TRIANGLES);
for (int i=0; i < 360; i += 2)
for (int i = 0; i < 360; i += 10)
{
rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex2i(center.x, center.y);
rlVertex2f(center.x + sin(DEG2RAD*i) * radius, center.y + cos(DEG2RAD*i) * radius);
rlVertex2f(center.x + sin(DEG2RAD*(i+2)) * radius, center.y + cos(DEG2RAD*(i+2)) * radius);
rlVertex2f(center.x + sin(DEG2RAD*i)*radius, center.y + cos(DEG2RAD*i)*radius);
rlVertex2f(center.x + sin(DEG2RAD*(i + 10)) * radius, center.y + cos(DEG2RAD*(i + 10)) * radius);
}
rlEnd();
}
@ -139,10 +139,10 @@ void DrawCircleLines(int centerX, int centerY, float radius, Color color)
rlColor4ub(color.r, color.g, color.b, color.a);
// NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
for (int i=0; i < 360; i++)
for (int i = 0; i < 360; i += 10)
{
rlVertex2f(centerX + sin(DEG2RAD*i) * radius, centerY + cos(DEG2RAD*i) * radius);
rlVertex2f(centerX + sin(DEG2RAD*(i+1)) * radius, centerY + cos(DEG2RAD*(i+1)) * radius);
rlVertex2f(centerX + sin(DEG2RAD*i)*radius, centerY + cos(DEG2RAD*i)*radius);
rlVertex2f(centerX + sin(DEG2RAD*(i + 10)) * radius, centerY + cos(DEG2RAD*(i + 10))*radius);
}
rlEnd();
}
@ -201,7 +201,7 @@ void DrawRectangleV(Vector2 position, Vector2 size, Color color)
rlBegin(RL_QUADS);
rlColor4ub(color.r, color.g, color.b, color.a);
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
rlNormal3f(0.0f, 0.0f, 1.0f);
rlTexCoord2f(0.0f, 0.0f);
rlVertex2f(position.x, position.y);
@ -275,13 +275,13 @@ void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color col
rlRotatef(rotation, 0, 0, 1);
rlBegin(RL_TRIANGLES);
for (int i=0; i < 360; i += 360/sides)
for (int i = 0; i < 360; i += 360/sides)
{
rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex2i(0, 0);
rlVertex2f(sin(DEG2RAD*i) * radius, cos(DEG2RAD*i) * radius);
rlVertex2f(sin(DEG2RAD*(i+360/sides)) * radius, cos(DEG2RAD*(i+360/sides)) * radius);
rlVertex2f(sin(DEG2RAD*i)*radius, cos(DEG2RAD*i)*radius);
rlVertex2f(sin(DEG2RAD*(i + 360/sides))*radius, cos(DEG2RAD*(i + 360/sides))*radius);
}
rlEnd();
rlPopMatrix();
@ -299,8 +299,8 @@ void DrawPolyEx(Vector2 *points, int numPoints, Color color)
for (int i = 0; i < numPoints - 2; i++)
{
rlVertex2f(points[i].x, points[i].y);
rlVertex2f(points[i+1].x, points[i+1].y);
rlVertex2f(points[i+2].x, points[i+2].y);
rlVertex2f(points[i + 1].x, points[i + 1].y);
rlVertex2f(points[i + 2].x, points[i + 2].y);
}
rlEnd();
}
@ -318,7 +318,7 @@ void DrawPolyExLines(Vector2 *points, int numPoints, Color color)
for (int i = 0; i < numPoints - 1; i++)
{
rlVertex2f(points[i].x, points[i].y);
rlVertex2f(points[i+1].x, points[i+1].y);
rlVertex2f(points[i + 1].x, points[i + 1].y);
}
rlEnd();
}
@ -367,10 +367,10 @@ bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2)
{
bool collision = false;
int dx = abs((rec1.x + rec1.width / 2) - (rec2.x + rec2.width / 2));
int dy = abs((rec1.y + rec1.height / 2) - (rec2.y + rec2.height / 2));
int dx = abs((rec1.x + rec1.width/2) - (rec2.x + rec2.width/2));
int dy = abs((rec1.y + rec1.height/2) - (rec2.y + rec2.height/2));
if ((dx <= (rec1.width / 2 + rec2.width / 2)) && ((dy <= (rec1.height / 2 + rec2.height / 2)))) collision = true;
if ((dx <= (rec1.width/2 + rec2.width/2)) && ((dy <= (rec1.height/2 + rec2.height/2)))) collision = true;
return collision;
}
@ -395,10 +395,10 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
{
bool collision = false;
float dx = abs((rec.x + rec.width / 2) - center.x);
float dy = abs((rec.y + rec.height / 2) - center.y);
float dx = fabs((rec.x + rec.width/2) - center.x);
float dy = fabs((rec.y + rec.height/2) - center.y);
if ((dx <= (rec.width / 2 + radius)) && (dy <= (rec.height / 2 + radius))) collision = true;
if ((dx <= (rec.width/2 + radius)) && (dy <= (rec.height/2 + radius))) collision = true;
return collision;
}

View File

@ -1,14 +0,0 @@
#version 150
uniform sampler2D texture0;
in vec2 fragTexCoord;
in vec4 fragColor;
out vec4 pixelColor;
void main()
{
// Output pixel color
pixelColor = texture(texture0, fragTexCoord) * fragColor;
}

View File

@ -1,21 +0,0 @@
#version 150
uniform mat4 projectionMatrix;
uniform mat4 modelviewMatrix;
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec4 vertexColor;
out vec2 fragTexCoord;
out vec4 fragColor;
void main()
{
// Pass some variables to the fragment shader
fragTexCoord = vertexTexCoord;
fragColor = vertexColor;
// Apply all matrix transformations to vertex
gl_Position = projectionMatrix * modelviewMatrix * vec4(vertexPosition, 1.0);
}

View File

@ -1,4 +1,4 @@
/* stb_image - v2.00b - public domain image loader - http://nothings.org/stb_image.h
/* stb_image - v2.05 - public domain image loader - http://nothings.org/stb_image.h
no warranty implied; use at your own risk
Do this:
@ -143,6 +143,13 @@
Latest revision history:
2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning
2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit
2.03 (2015-04-12) additional corruption checking
stbi_set_flip_vertically_on_load
fix NEON support; fix mingw support
2.02 (2015-01-19) fix incorrect assert, fix warning
2.01 (2015-01-17) fix various warnings
2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG
2.00 (2014-12-25) optimize JPEG, including x86 SSE2 & ARM NEON SIMD
progressive JPEG
@ -154,8 +161,6 @@
1.47 (2014-12-14) 1/2/4-bit PNG support (both grayscale and paletted)
optimize PNG
fix bug in interlaced PNG with user-specified channel count
1.46 (2014-08-26) fix broken tRNS chunk in non-paletted PNG
1.45 (2014-08-16) workaround MSVC-ARM internal compiler error by wrapping malloc
See end of file for full revision history.
@ -178,7 +183,7 @@
James "moose2000" Brown (iPhone PNG) Roy Eltham
Ben "Disch" Wenger (io callbacks) Luke Graham
Omar Cornut (1/2/4-bit PNG) Thomas Ruf
John Bartholomew
Nicolas Guillemot (vertical flip) John Bartholomew
Ken Hamada
Optimizations & bugfixes Cort Stratton
Fabian "ryg" Giesen Blazej Dariusz Roszkowski
@ -191,6 +196,12 @@
Ronny Chevalier
Michal Cichon
Tero Hanninen
Sergio Gonzalez
Cass Everitt
Engin Manap
Martins Mozeiko
Joseph Thomson
Phil Jordan
License:
This software is in the public domain. Where that dedication is not
@ -371,6 +382,7 @@ License:
// and only if iPhone convert-to-rgb processing is on).
//
#define STBI_NO_HDR // RaySan: not required by raylib
#define STBI_NO_SIMD // RaySan: issues when compiling with GCC 4.7.2
@ -489,6 +501,8 @@ STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultipl
// or just pass them through "as-is"
STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert);
// flip the image vertically, so the first pixel in the output array is the bottom left
STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip);
// ZLIB client - used by PNG, available for other purposes
@ -626,7 +640,38 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
#define STBI_FREE(p) free(p)
#endif
#if !defined(STBI_NO_SIMD) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86))
// x86/x64 detection
#if defined(__x86_64__) || defined(_M_X64)
#define STBI__X64_TARGET
#elif defined(__i386) || defined(_M_IX86)
#define STBI__X86_TARGET
#endif
#if defined(__GNUC__) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) && !defined(__SSE2__) && !defined(STBI_NO_SIMD)
// NOTE: not clear do we actually need this for the 64-bit path?
// gcc doesn't support sse2 intrinsics unless you compile with -msse2,
// (but compiling with -msse2 allows the compiler to use SSE2 everywhere;
// this is just broken and gcc are jerks for not fixing it properly
// http://www.virtualdub.org/blog/pivot/entry.php?id=363 )
#define STBI_NO_SIMD
#endif
#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD)
// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET
//
// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the
// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant.
// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not
// simultaneously enabling "-mstackrealign".
//
// See https://github.com/nothings/stb/issues/81 for more information.
//
// So default to no SSE2 on 32-bit MinGW. If you've read this far and added
// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2.
#define STBI_NO_SIMD
#endif
#if !defined(STBI_NO_SIMD) && defined(STBI__X86_TARGET)
#define STBI_SSE2
#include <emmintrin.h>
@ -879,7 +924,14 @@ static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp);
static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp);
#endif
static unsigned char *stbi_load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp)
static int stbi__vertically_flip_on_load = 0;
STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)
{
stbi__vertically_flip_on_load = flag_true_if_should_flip;
}
static unsigned char *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp)
{
#ifndef STBI_NO_JPEG
if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp);
@ -919,6 +971,53 @@ static unsigned char *stbi_load_main(stbi__context *s, int *x, int *y, int *comp
return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt");
}
static unsigned char *stbi__load_flip(stbi__context *s, int *x, int *y, int *comp, int req_comp)
{
unsigned char *result = stbi__load_main(s, x, y, comp, req_comp);
if (stbi__vertically_flip_on_load && result != NULL) {
int w = *x, h = *y;
int depth = req_comp ? req_comp : *comp;
int row,col,z;
stbi_uc temp;
// @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once
for (row = 0; row < (h>>1); row++) {
for (col = 0; col < w; col++) {
for (z = 0; z < depth; z++) {
temp = result[(row * w + col) * depth + z];
result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z];
result[((h - row - 1) * w + col) * depth + z] = temp;
}
}
}
}
return result;
}
static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp)
{
if (stbi__vertically_flip_on_load && result != NULL) {
int w = *x, h = *y;
int depth = req_comp ? req_comp : *comp;
int row,col,z;
float temp;
// @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once
for (row = 0; row < (h>>1); row++) {
for (col = 0; col < w; col++) {
for (z = 0; z < depth; z++) {
temp = result[(row * w + col) * depth + z];
result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z];
result[((h - row - 1) * w + col) * depth + z] = temp;
}
}
}
}
}
#ifndef STBI_NO_STDIO
static FILE *stbi__fopen(char const *filename, char const *mode)
@ -949,7 +1048,7 @@ STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req
unsigned char *result;
stbi__context s;
stbi__start_file(&s,f);
result = stbi_load_main(&s,x,y,comp,req_comp);
result = stbi__load_flip(&s,x,y,comp,req_comp);
if (result) {
// need to 'unget' all the characters in the IO buffer
fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
@ -962,25 +1061,29 @@ STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, i
{
stbi__context s;
stbi__start_mem(&s,buffer,len);
return stbi_load_main(&s,x,y,comp,req_comp);
return stbi__load_flip(&s,x,y,comp,req_comp);
}
STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
{
stbi__context s;
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
return stbi_load_main(&s,x,y,comp,req_comp);
return stbi__load_flip(&s,x,y,comp,req_comp);
}
#ifndef STBI_NO_LINEAR
static float *stbi_loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp)
static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp)
{
unsigned char *data;
#ifndef STBI_NO_HDR
if (stbi__hdr_test(s))
return stbi__hdr_load(s,x,y,comp,req_comp);
if (stbi__hdr_test(s)) {
float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp);
if (hdr_data)
stbi__float_postprocess(hdr_data,x,y,comp,req_comp);
return hdr_data;
}
#endif
data = stbi_load_main(s, x, y, comp, req_comp);
data = stbi__load_flip(s, x, y, comp, req_comp);
if (data)
return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp);
return stbi__errpf("unknown image type", "Image not of any known type, or corrupt");
@ -990,14 +1093,14 @@ STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, in
{
stbi__context s;
stbi__start_mem(&s,buffer,len);
return stbi_loadf_main(&s,x,y,comp,req_comp);
return stbi__loadf_main(&s,x,y,comp,req_comp);
}
STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
{
stbi__context s;
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
return stbi_loadf_main(&s,x,y,comp,req_comp);
return stbi__loadf_main(&s,x,y,comp,req_comp);
}
#ifndef STBI_NO_STDIO
@ -1015,7 +1118,7 @@ STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_
{
stbi__context s;
stbi__start_file(&s,f);
return stbi_loadf_main(&s,x,y,comp,req_comp);
return stbi__loadf_main(&s,x,y,comp,req_comp);
}
#endif // !STBI_NO_STDIO
@ -1138,6 +1241,10 @@ stbi_inline static int stbi__at_eof(stbi__context *s)
static void stbi__skip(stbi__context *s, int n)
{
if (n < 0) {
s->img_buffer = s->img_buffer_end;
return;
}
if (s->io.read) {
int blen = (int) (s->img_buffer_end - s->img_buffer);
if (blen < n) {
@ -1546,6 +1653,7 @@ stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n)
sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB
k = stbi_lrot(j->code_buffer, n);
STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask)));
j->code_buffer = k & ~stbi__bmask[n];
k &= stbi__bmask[n];
j->code_bits -= n;
@ -1730,15 +1838,12 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__
short *p = &data[stbi__jpeg_dezigzag[k]];
if (*p != 0)
if (stbi__jpeg_get_bit(j))
{
if ((*p & bit)==0)
{
if ((*p & bit)==0) {
if (*p > 0)
*p += bit;
else
*p -= bit;
}
}
}
} else {
k = j->spec_start;
@ -1754,8 +1859,11 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__
if (r)
j->eob_run += stbi__jpeg_get_bits(j, r);
r = 64; // force end of block
} else
r = 16; // r=15 is the code for 16 0s
} else {
// r=15 s=0 should write 16 0s, so we just do
// a run of 15 0s and then write s (which is 0),
// so we don't have to do anything special here
}
} else {
if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG");
// sign bit
@ -1767,27 +1875,21 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__
// advance by r
while (k <= j->spec_end) {
short *p = &data[stbi__jpeg_dezigzag[k]];
short *p = &data[stbi__jpeg_dezigzag[k++]];
if (*p != 0) {
if (stbi__jpeg_get_bit(j))
{
if ((*p & bit)==0)
{
if ((*p & bit)==0) {
if (*p > 0)
*p += bit;
else
*p -= bit;
}
}
++k;
} else {
if (r == 0) {
if (s)
data[stbi__jpeg_dezigzag[k++]] = s;
*p = (short) s;
break;
}
--r;
++k;
}
}
} while (k <= j->spec_end);
@ -2207,7 +2309,7 @@ static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64])
// pass 1
dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6
dct_trn16(row2, row3);
dct_trn16(row4, row5);
dct_trn16(row4, row5);
dct_trn16(row6, row7);
// pass 2
@ -2434,7 +2536,6 @@ static int stbi__parse_entropy_coded_data(stbi__jpeg *z)
for (x=0; x < z->img_comp[n].h; ++x) {
int x2 = (i*z->img_comp[n].h + x);
int y2 = (j*z->img_comp[n].v + y);
//int ha = z->img_comp[n].ha; // RaySan: Unused, commented to avoid warning
short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w);
if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n))
return 0;
@ -2701,6 +2802,10 @@ static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan)
static int stbi__decode_jpeg_image(stbi__jpeg *j)
{
int m;
for (m = 0; m < 4; m++) {
j->img_comp[m].raw_data = NULL;
j->img_comp[m].raw_coeff = NULL;
}
j->restart_interval = 0;
if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0;
m = stbi__get_marker(j);
@ -3013,7 +3118,7 @@ static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc cons
__m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f));
__m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f));
__m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f));
__m128i y_bias = _mm_set1_epi8((char) 128);
__m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128);
__m128i xw = _mm_set1_epi16(255); // alpha channel
for (; i+7 < count; i += 8) {
@ -3380,7 +3485,8 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num)
++sizes[sizelist[i]];
sizes[0] = 0;
for (i=1; i < 16; ++i)
STBI_ASSERT(sizes[i] <= (1 << i));
if (sizes[i] > (1 << i))
return stbi__err("bad sizes", "Corrupt PNG");
code = 0;
for (i=1; i < 16; ++i) {
next_code[i] = code;
@ -3388,7 +3494,7 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num)
z->firstsymbol[i] = (stbi__uint16) k;
code = (code + sizes[i]);
if (sizes[i])
if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt JPEG");
if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG");
z->maxcode[i] = code << (16-i); // preshift for inner loop
code <<= 1;
k += sizes[i];
@ -3557,9 +3663,9 @@ static int stbi__parse_huffman_block(stbi__zbuf *a)
p = (stbi_uc *) (zout - dist);
if (dist == 1) { // run of one byte; common in images.
stbi_uc v = *p;
do *zout++ = v; while (--len);
if (len) { do *zout++ = v; while (--len); }
} else {
do *zout++ = *p++; while (--len);
if (len) { do *zout++ = *p++; while (--len); }
}
}
}
@ -3587,7 +3693,7 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a)
n = 0;
while (n < hlit + hdist) {
int c = stbi__zhuffman_decode(a, &z_codelength);
STBI_ASSERT(c >= 0 && c < 19);
if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG");
if (c < 16)
lencodes[n++] = (stbi_uc) c;
else if (c == 16) {
@ -4019,7 +4125,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
cur[i*2+0] = cur[i];
}
} else {
assert(img_n == 3);
STBI_ASSERT(img_n == 3);
for (i=x-1; i >= 0; --i) {
cur[i*4+3] = 255;
cur[i*4+2] = cur[i*3+2];
@ -4284,6 +4390,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
if (first) return stbi__err("first not IHDR", "Corrupt PNG");
if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG");
if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; }
if ((int)(ioff + c.length) < (int)ioff) return 0;
if (ioff + c.length > idata_limit) {
stbi_uc *p;
if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096;
@ -4643,7 +4750,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
}
} else {
for (i=0; i < (int) s->img_x; ++i) {
stbi__uint32 v = (stbi__uint32) (bpp == 16 ? stbi__get16le(s) : stbi__get32le(s));
stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s));
int a;
out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount));
out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount));
@ -4800,7 +4907,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
*y = tga_height;
if (comp) *comp = tga_comp;
tga_data = (unsigned char*)stbi__malloc( tga_width * tga_height * tga_comp );
tga_data = (unsigned char*)stbi__malloc( (size_t)tga_width * tga_height * tga_comp );
if (!tga_data) return stbi__errpuc("outofmem", "Out of memory");
// skip to the data's starting position (offset usually = 0)
@ -5461,6 +5568,7 @@ static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g)
stbi__gif_lzw *p;
lzw_cs = stbi__get8(s);
if (lzw_cs > 12) return NULL;
clear = 1 << lzw_cs;
first = 1;
codesize = lzw_cs + 1;
@ -6130,7 +6238,7 @@ static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp)
#ifndef STBI_NO_PSD
if (stbi__psd_info(s, x, y, comp)) return 1;
#endif
#ifndef STBI_NO_PIC
if (stbi__pic_info(s, x, y, comp)) return 1;
#endif
@ -6192,6 +6300,13 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
/*
revision history:
2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning
2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit
2.03 (2015-04-12) extra corruption checking (mmozeiko)
stbi_set_flip_vertically_on_load (nguillemot)
fix NEON support; fix mingw support
2.02 (2015-01-19) fix incorrect assert, fix warning
2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2
2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG
2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg)
progressive JPEG (stb)
@ -6276,7 +6391,7 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
1.21 fix use of 'stbi_uc' in header (reported by jon blow)
1.20 added support for Softimage PIC, by Tom Seddon
1.19 bug in interlaced PNG corruption check (found by ryg)
1.18 2008-08-02
1.18 (2008-08-02)
fix a threading bug (local mutable static)
1.17 support interlaced PNG
1.16 major bugfix - stbi__convert_format converted one too many pixels
@ -6321,5 +6436,6 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments
0.51 obey req_comp requests, 1-component jpegs return as 1-component,
on 'test' only check type, not whether we support this variant
0.50 first released version
0.50 (2006-11-19)
first released version
*/

View File

@ -1,16 +1,15 @@
/* stb_image_write - v0.95 - public domain - http://nothings.org/stb/stb_image_write.h
/* stb_image_write - v0.98 - public domain - http://nothings.org/stb/stb_image_write.h
writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010
no warranty implied; use at your own risk
Before including,
Before #including,
#define STB_IMAGE_WRITE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
in the file that you want to have the implementation.
Will probably not work correctly with strict-aliasing optimizations.
in the file that you want to have the implementation.
Will probably not work correctly with strict-aliasing optimizations.
ABOUT:
@ -22,16 +21,24 @@ ABOUT:
for source code compactness and simplicitly, not optimal image file size
or run-time performance.
BUILDING:
You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h.
You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace
malloc,realloc,free.
You can define STBIW_MEMMOVE() to replace memmove()
USAGE:
There are three functions, one for each image file format:
There are four functions, one for each image file format:
int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
int stbi_write_hdr(char const *filename, int w, int h, int comp, const void *data);
Each function returns 0 on failure and non-0 on success.
The functions create an image file defined by the parameters. The image
is a rectangle of pixels stored from left-to-right, top-to-bottom.
Each pixel contains 'comp' channels of data stored interleaved with 8-bits
@ -44,13 +51,30 @@ USAGE:
PNG creates output files with the same number of components as the input.
The BMP format expands Y to RGB in the file format and does not
output alpha.
PNG supports writing rectangles of data even when the bytes storing rows of
data are not consecutive in memory (e.g. sub-rectangles of a larger image),
by supplying the stride between the beginning of adjacent rows. The other
formats do not. (Thus you cannot write a native-format BMP through the BMP
writer, both because it is in BGR order and because it may have padding
at the end of the line.)
HDR expects linear float data. Since the format is always 32-bit rgb(e)
data, alpha (if provided) is discarded, and for monochrome data it is
replicated across all three channels.
CREDITS:
PNG/BMP/TGA
Sean Barrett
HDR
Baldur Karlsson
TGA monochrome:
Jean-Sebastien Guay
misc enhancements:
Tim Kelsey
bugfixes:
github:Chribba
*/
#ifndef INCLUDE_STB_IMAGE_WRITE_H
@ -60,9 +84,10 @@ USAGE:
extern "C" {
#endif
extern int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
extern int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
#ifdef __cplusplus
}
@ -76,7 +101,30 @@ extern int stbi_write_tga(char const *filename, int w, int h, int comp, const vo
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && defined(STBIW_REALLOC)
// ok
#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC)
// ok
#else
#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC."
#endif
#ifndef STBIW_MALLOC
#define STBIW_MALLOC(sz) malloc(sz)
#define STBIW_REALLOC(p,sz) realloc(p,sz)
#define STBIW_FREE(p) free(p)
#endif
#ifndef STBIW_MEMMOVE
#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
#endif
#ifndef STBIW_ASSERT
#include <assert.h>
#define STBIW_ASSERT(x) assert(x)
#endif
typedef unsigned int stbiw_uint32;
typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
@ -95,7 +143,7 @@ static void writefv(FILE *f, const char *fmt, va_list v)
b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24);
fwrite(b,4,1,f); break; }
default:
assert(0);
STBIW_ASSERT(0);
return;
}
}
@ -108,7 +156,7 @@ static void write3(FILE *f, unsigned char a, unsigned char b, unsigned char c)
fwrite(arr, 3, 1, f);
}
static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad)
static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono)
{
unsigned char bg[3] = { 255, 0, 255}, px[3];
stbiw_uint32 zero = 0;
@ -117,7 +165,7 @@ static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp,
if (y <= 0)
return;
if (vdir < 0)
if (vdir < 0)
j_end = -1, j = y-1;
else
j_end = y, j = 0;
@ -128,8 +176,12 @@ static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp,
if (write_alpha < 0)
fwrite(&d[comp-1], 1, 1, f);
switch (comp) {
case 1:
case 2: fwrite(d, 1, 1, f);
case 1: fwrite(d, 1, 1, f);
break;
case 2: if (expand_mono)
write3(f, d[0],d[0],d[0]); // monochrome bmp
else
fwrite(d, 1, 1, f); // monochrome TGA
break;
case 4:
if (!write_alpha) {
@ -151,7 +203,7 @@ static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp,
}
}
static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, void *data, int alpha, int pad, const char *fmt, ...)
static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...)
{
FILE *f;
if (y < 0 || x < 0) return 0;
@ -161,7 +213,7 @@ static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, in
va_start(v, fmt);
writefv(f, fmt, v);
va_end(v);
write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad);
write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad,expand_mono);
fclose(f);
}
return f != NULL;
@ -170,7 +222,7 @@ static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, in
int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
{
int pad = (-x*3) & 3;
return outfile(filename,-1,-1,x,y,comp,(void *) data,0,pad,
return outfile(filename,-1,-1,x,y,comp,1,(void *) data,0,pad,
"11 4 22 4" "4 44 22 444444",
'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
@ -181,10 +233,159 @@ int stbi_write_tga(char const *filename, int x, int y, int comp, const void *dat
int has_alpha = (comp == 2 || comp == 4);
int colorbytes = has_alpha ? comp-1 : comp;
int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3
return outfile(filename, -1,-1, x, y, comp, (void *) data, has_alpha, 0,
return outfile(filename, -1,-1, x, y, comp, 0, (void *) data, has_alpha, 0,
"111 221 2222 11", 0,0,format, 0,0,0, 0,0,x,y, (colorbytes+has_alpha)*8, has_alpha*8);
}
// *************************************************************************************************
// Radiance RGBE HDR writer
// by Baldur Karlsson
#define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
{
int exponent;
float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
if (maxcomp < 1e-32) {
rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
} else {
float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
rgbe[0] = (unsigned char)(linear[0] * normalize);
rgbe[1] = (unsigned char)(linear[1] * normalize);
rgbe[2] = (unsigned char)(linear[2] * normalize);
rgbe[3] = (unsigned char)(exponent + 128);
}
}
void stbiw__write_run_data(FILE *f, int length, unsigned char databyte)
{
unsigned char lengthbyte = (unsigned char) (length+128);
STBIW_ASSERT(length+128 <= 255);
fwrite(&lengthbyte, 1, 1, f);
fwrite(&databyte, 1, 1, f);
}
void stbiw__write_dump_data(FILE *f, int length, unsigned char *data)
{
unsigned char lengthbyte = (unsigned char )(length & 0xff);
STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
fwrite(&lengthbyte, 1, 1, f);
fwrite(data, length, 1, f);
}
void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scratch, const float *scanline)
{
unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
unsigned char rgbe[4];
float linear[3];
int x;
scanlineheader[2] = (width&0xff00)>>8;
scanlineheader[3] = (width&0x00ff);
/* skip RLE for images too small or large */
if (width < 8 || width >= 32768) {
for (x=0; x < width; x++) {
switch (comp) {
case 4: /* fallthrough */
case 3: linear[2] = scanline[x*comp + 2];
linear[1] = scanline[x*comp + 1];
linear[0] = scanline[x*comp + 0];
break;
case 2: /* fallthrough */
case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0];
break;
}
stbiw__linear_to_rgbe(rgbe, linear);
fwrite(rgbe, 4, 1, f);
}
} else {
int c,r;
/* encode into scratch buffer */
for (x=0; x < width; x++) {
switch(comp) {
case 4: /* fallthrough */
case 3: linear[2] = scanline[x*comp + 2];
linear[1] = scanline[x*comp + 1];
linear[0] = scanline[x*comp + 0];
break;
case 2: /* fallthrough */
case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0];
break;
}
stbiw__linear_to_rgbe(rgbe, linear);
scratch[x + width*0] = rgbe[0];
scratch[x + width*1] = rgbe[1];
scratch[x + width*2] = rgbe[2];
scratch[x + width*3] = rgbe[3];
}
fwrite(scanlineheader, 4, 1, f);
/* RLE each component separately */
for (c=0; c < 4; c++) {
unsigned char *comp = &scratch[width*c];
x = 0;
while (x < width) {
// find first run
r = x;
while (r+2 < width) {
if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
break;
++r;
}
if (r+2 >= width)
r = width;
// dump up to first run
while (x < r) {
int len = r-x;
if (len > 128) len = 128;
stbiw__write_dump_data(f, len, &comp[x]);
x += len;
}
// if there's a run, output it
if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd
// find next byte after run
while (r < width && comp[r] == comp[x])
++r;
// output run up to r
while (x < r) {
int len = r-x;
if (len > 127) len = 127;
stbiw__write_run_data(f, len, comp[x]);
x += len;
}
}
}
}
}
}
int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
{
int i;
FILE *f;
if (y <= 0 || x <= 0 || data == NULL) return 0;
f = fopen(filename, "wb");
if (f) {
/* Each component is stored separately. Allocate scratch space for full output scanline. */
unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
fprintf(f, "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n" );
fprintf(f, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n" , y, x);
for(i=0; i < y; i++)
stbiw__write_hdr_scanline(f, x, comp, scratch, data + comp*i*x);
STBIW_FREE(scratch);
fclose(f);
}
return f != NULL;
}
/////////////////////////////////////////////////////////
// PNG
// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
#define stbiw__sbraw(a) ((int *) (a) - 2)
#define stbiw__sbm(a) stbiw__sbraw(a)[0]
@ -196,13 +397,13 @@ int stbi_write_tga(char const *filename, int x, int y, int comp, const void *dat
#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
#define stbiw__sbfree(a) ((a) ? free(stbiw__sbraw(a)),0 : 0)
#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
{
int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
void *p = realloc(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2);
assert(p);
void *p = STBIW_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2);
STBIW_ASSERT(p);
if (p) {
if (!*arr) ((int *) p)[1] = 0;
*arr = (void *) ((int *) p + 2);
@ -287,7 +488,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
i=0;
while (i < data_len-3) {
// hash next 3 bytes of data to be compressed
// hash next 3 bytes of data to be compressed
int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
unsigned char *bestloc = 0;
unsigned char **hlist = hash_table[h];
@ -300,7 +501,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
}
// when hash table entry is too long, delete half the entries
if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
memcpy(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
stbiw__sbn(hash_table[h]) = quality;
}
stbiw__sbpush(hash_table[h],data+i);
@ -323,7 +524,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
if (bestloc) {
int d = (int) (data+i - bestloc); // distance back
assert(d <= 32767 && best <= 258);
STBIW_ASSERT(d <= 32767 && best <= 258);
for (j=0; best > lengthc[j+1]-1; ++j);
stbiw__zlib_huff(j+257);
if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
@ -364,7 +565,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
}
*out_len = stbiw__sbn(out);
// make returned pointer freeable
memmove(stbiw__sbraw(out), out, *out_len);
STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
return (unsigned char *) stbiw__sbraw(out);
}
@ -411,8 +612,8 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in
if (stride_bytes == 0)
stride_bytes = x * n;
filt = (unsigned char *) malloc((x*n+1) * y); if (!filt) return 0;
line_buffer = (signed char *) malloc(x * n); if (!line_buffer) { free(filt); return 0; }
filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
for (j=0; j < y; ++j) {
static int mapping[] = { 0,1,2,3,4 };
static int firstmap[] = { 0,1,0,5,6 };
@ -451,20 +652,20 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in
}
// when we get here, best contains the filter type, and line_buffer contains the data
filt[j*(x*n+1)] = (unsigned char) best;
memcpy(filt+j*(x*n+1)+1, line_buffer, x*n);
STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
}
free(line_buffer);
STBIW_FREE(line_buffer);
zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory
free(filt);
STBIW_FREE(filt);
if (!zlib) return 0;
// each tag requires 12 bytes of overhead
out = (unsigned char *) malloc(8 + 12+13 + 12+zlen + 12);
out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
if (!out) return 0;
*out_len = 8 + 12+13 + 12+zlen + 12;
o=out;
memcpy(o,sig,8); o+= 8;
STBIW_MEMMOVE(o,sig,8); o+= 8;
stbiw__wp32(o, 13); // header length
stbiw__wptag(o, "IHDR");
stbiw__wp32(o, x);
@ -478,14 +679,16 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in
stbiw__wp32(o, zlen);
stbiw__wptag(o, "IDAT");
memcpy(o, zlib, zlen); o += zlen; free(zlib);
STBIW_MEMMOVE(o, zlib, zlen);
o += zlen;
STBIW_FREE(zlib);
stbiw__wpcrc(&o, zlen);
stbiw__wp32(o,0);
stbiw__wptag(o, "IEND");
stbiw__wpcrc(&o,0);
assert(o == out + *out_len);
STBIW_ASSERT(o == out + *out_len);
return out;
}
@ -497,16 +700,22 @@ int stbi_write_png(char const *filename, int x, int y, int comp, const void *dat
unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
if (!png) return 0;
f = fopen(filename, "wb");
if (!f) { free(png); return 0; }
if (!f) { STBIW_FREE(png); return 0; }
fwrite(png, 1, len, f);
fclose(f);
free(png);
STBIW_FREE(png);
return 1;
}
#endif // STB_IMAGE_WRITE_IMPLEMENTATION
/* Revision history
0.98 (2015-04-08)
added STBIW_MALLOC, STBIW_ASSERT etc
0.97 (2015-01-18)
fixed HDR asserts, rewrote HDR rle logic
0.96 (2015-01-17)
add HDR output
fix monochrome BMP
0.95 (2014-08-17)
add monochrome TGA output
0.94 (2014-05-31)

560
src/stb_rect_pack.h Normal file
View File

@ -0,0 +1,560 @@
// stb_rect_pack.h - v0.06 - public domain - rectangle packing
// Sean Barrett 2014
//
// Useful for e.g. packing rectangular textures into an atlas.
// Does not do rotation.
//
// Not necessarily the awesomest packing method, but better than
// the totally naive one in stb_truetype (which is primarily what
// this is meant to replace).
//
// Has only had a few tests run, may have issues.
//
// More docs to come.
//
// No memory allocations; uses qsort() and assert() from stdlib.
// Can override those by defining STBRP_SORT and STBRP_ASSERT.
//
// This library currently uses the Skyline Bottom-Left algorithm.
//
// Please note: better rectangle packers are welcome! Please
// implement them to the same API, but with a different init
// function.
//
// Credits
//
// Library
// Sean Barrett
// Minor features
// Martins Mozeiko
// Bugfixes / warning fixes
// [your name could be here]
//
// Version history:
//
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
// 0.05: added STBRP_ASSERT to allow replacing assert
// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
// 0.01: initial release
//////////////////////////////////////////////////////////////////////////////
//
// INCLUDE SECTION
//
#ifndef STB_INCLUDE_STB_RECT_PACK_H
#define STB_INCLUDE_STB_RECT_PACK_H
#define STB_RECT_PACK_VERSION 1
#ifdef STBRP_STATIC
#define STBRP_DEF static
#else
#define STBRP_DEF extern
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct stbrp_context stbrp_context;
typedef struct stbrp_node stbrp_node;
typedef struct stbrp_rect stbrp_rect;
#ifdef STBRP_LARGE_RECTS
typedef int stbrp_coord;
#else
typedef unsigned short stbrp_coord;
#endif
STBRP_DEF void stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
// Assign packed locations to rectangles. The rectangles are of type
// 'stbrp_rect' defined below, stored in the array 'rects', and there
// are 'num_rects' many of them.
//
// Rectangles which are successfully packed have the 'was_packed' flag
// set to a non-zero value and 'x' and 'y' store the minimum location
// on each axis (i.e. bottom-left in cartesian coordinates, top-left
// if you imagine y increasing downwards). Rectangles which do not fit
// have the 'was_packed' flag set to 0.
//
// You should not try to access the 'rects' array from another thread
// while this function is running, as the function temporarily reorders
// the array while it executes.
//
// To pack into another rectangle, you need to call stbrp_init_target
// again. To continue packing into the same rectangle, you can call
// this function again. Calling this multiple times with multiple rect
// arrays will probably produce worse packing results than calling it
// a single time with the full rectangle array, but the option is
// available.
struct stbrp_rect
{
// reserved for your use:
int id;
// input:
stbrp_coord w, h;
// output:
stbrp_coord x, y;
int was_packed; // non-zero if valid packing
}; // 16 bytes, nominally
STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
// Initialize a rectangle packer to:
// pack a rectangle that is 'width' by 'height' in dimensions
// using temporary storage provided by the array 'nodes', which is 'num_nodes' long
//
// You must call this function every time you start packing into a new target.
//
// There is no "shutdown" function. The 'nodes' memory must stay valid for
// the following stbrp_pack_rects() call (or calls), but can be freed after
// the call (or calls) finish.
//
// Note: to guarantee best results, either:
// 1. make sure 'num_nodes' >= 'width'
// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
//
// If you don't do either of the above things, widths will be quantized to multiples
// of small integers to guarantee the algorithm doesn't run out of temporary storage.
//
// If you do #2, then the non-quantized algorithm will be used, but the algorithm
// may run out of temporary storage and be unable to pack some rectangles.
STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
// Optionally call this function after init but before doing any packing to
// change the handling of the out-of-temp-memory scenario, described above.
// If you call init again, this will be reset to the default (false).
STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
// Optionally select which packing heuristic the library should use. Different
// heuristics will produce better/worse results for different data sets.
// If you call init again, this will be reset to the default.
enum
{
STBRP_HEURISTIC_Skyline_default=0,
STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
STBRP_HEURISTIC_Skyline_BF_sortHeight,
};
//////////////////////////////////////////////////////////////////////////////
//
// the details of the following structures don't matter to you, but they must
// be visible so you can handle the memory allocations for them
struct stbrp_node
{
stbrp_coord x,y;
stbrp_node *next;
};
struct stbrp_context
{
int width;
int height;
int align;
int init_mode;
int heuristic;
int num_nodes;
stbrp_node *active_head;
stbrp_node *free_head;
stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
};
#ifdef __cplusplus
}
#endif
#endif
//////////////////////////////////////////////////////////////////////////////
//
// IMPLEMENTATION SECTION
//
#ifdef STB_RECT_PACK_IMPLEMENTATION
#ifndef STBRP_SORT
#include <stdlib.h>
#define STBRP_SORT qsort
#endif
#ifndef STBRP_ASSERT
#include <assert.h>
#define STBRP_ASSERT assert
#endif
enum
{
STBRP__INIT_skyline = 1,
};
STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
{
switch (context->init_mode) {
case STBRP__INIT_skyline:
STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
context->heuristic = heuristic;
break;
default:
STBRP_ASSERT(0);
}
}
STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
{
if (allow_out_of_mem)
// if it's ok to run out of memory, then don't bother aligning them;
// this gives better packing, but may fail due to OOM (even though
// the rectangles easily fit). @TODO a smarter approach would be to only
// quantize once we've hit OOM, then we could get rid of this parameter.
context->align = 1;
else {
// if it's not ok to run out of memory, then quantize the widths
// so that num_nodes is always enough nodes.
//
// I.e. num_nodes * align >= width
// align >= width / num_nodes
// align = ceil(width/num_nodes)
context->align = (context->width + context->num_nodes-1) / context->num_nodes;
}
}
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
{
int i;
#ifndef STBRP_LARGE_RECTS
STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
#endif
for (i=0; i < num_nodes-1; ++i)
nodes[i].next = &nodes[i+1];
nodes[i].next = NULL;
context->init_mode = STBRP__INIT_skyline;
context->heuristic = STBRP_HEURISTIC_Skyline_default;
context->free_head = &nodes[0];
context->active_head = &context->extra[0];
context->width = width;
context->height = height;
context->num_nodes = num_nodes;
stbrp_setup_allow_out_of_mem(context, 0);
// node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
context->extra[0].x = 0;
context->extra[0].y = 0;
context->extra[0].next = &context->extra[1];
context->extra[1].x = (stbrp_coord) width;
#ifdef STBRP_LARGE_RECTS
context->extra[1].y = (1<<30);
#else
context->extra[1].y = 65535;
#endif
context->extra[1].next = NULL;
}
// find minimum y position if it starts at x1
static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
{
stbrp_node *node = first;
int x1 = x0 + width;
int min_y, visited_width, waste_area;
STBRP_ASSERT(first->x <= x0);
#if 0
// skip in case we're past the node
while (node->next->x <= x0)
++node;
#else
STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
#endif
STBRP_ASSERT(node->x <= x0);
min_y = 0;
waste_area = 0;
visited_width = 0;
while (node->x < x1) {
if (node->y > min_y) {
// raise min_y higher.
// we've accounted for all waste up to min_y,
// but we'll now add more waste for everything we've visted
waste_area += visited_width * (node->y - min_y);
min_y = node->y;
// the first time through, visited_width might be reduced
if (node->x < x0)
visited_width += node->next->x - x0;
else
visited_width += node->next->x - node->x;
} else {
// add waste area
int under_width = node->next->x - node->x;
if (under_width + visited_width > width)
under_width = width - visited_width;
waste_area += under_width * (min_y - node->y);
visited_width += under_width;
}
node = node->next;
}
*pwaste = waste_area;
return min_y;
}
typedef struct
{
int x,y;
stbrp_node **prev_link;
} stbrp__findresult;
static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
{
int best_waste = (1<<30), best_x, best_y = (1 << 30);
stbrp__findresult fr;
stbrp_node **prev, *node, *tail, **best = NULL;
// align to multiple of c->align
width = (width + c->align - 1);
width -= width % c->align;
STBRP_ASSERT(width % c->align == 0);
node = c->active_head;
prev = &c->active_head;
while (node->x + width <= c->width) {
int y,waste;
y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
// bottom left
if (y < best_y) {
best_y = y;
best = prev;
}
} else {
// best-fit
if (y + height <= c->height) {
// can only use it if it first vertically
if (y < best_y || (y == best_y && waste < best_waste)) {
best_y = y;
best_waste = waste;
best = prev;
}
}
}
prev = &node->next;
node = node->next;
}
best_x = (best == NULL) ? 0 : (*best)->x;
// if doing best-fit (BF), we also have to try aligning right edge to each node position
//
// e.g, if fitting
//
// ____________________
// |____________________|
//
// into
//
// | |
// | ____________|
// |____________|
//
// then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
//
// This makes BF take about 2x the time
if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
tail = c->active_head;
node = c->active_head;
prev = &c->active_head;
// find first node that's admissible
while (tail->x < width)
tail = tail->next;
while (tail) {
int xpos = tail->x - width;
int y,waste;
STBRP_ASSERT(xpos >= 0);
// find the left position that matches this
while (node->next->x <= xpos) {
prev = &node->next;
node = node->next;
}
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
if (y + height < c->height) {
if (y <= best_y) {
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
best_x = xpos;
STBRP_ASSERT(y <= best_y);
best_y = y;
best_waste = waste;
best = prev;
}
}
}
tail = tail->next;
}
}
fr.prev_link = best;
fr.x = best_x;
fr.y = best_y;
return fr;
}
static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
{
// find best position according to heuristic
stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
stbrp_node *node, *cur;
// bail if:
// 1. it failed
// 2. the best node doesn't fit (we don't always check this)
// 3. we're out of memory
if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
res.prev_link = NULL;
return res;
}
// on success, create new node
node = context->free_head;
node->x = (stbrp_coord) res.x;
node->y = (stbrp_coord) (res.y + height);
context->free_head = node->next;
// insert the new node into the right starting point, and
// let 'cur' point to the remaining nodes needing to be
// stiched back in
cur = *res.prev_link;
if (cur->x < res.x) {
// preserve the existing one, so start testing with the next one
stbrp_node *next = cur->next;
cur->next = node;
cur = next;
} else {
*res.prev_link = node;
}
// from here, traverse cur and free the nodes, until we get to one
// that shouldn't be freed
while (cur->next && cur->next->x <= res.x + width) {
stbrp_node *next = cur->next;
// move the current node to the free list
cur->next = context->free_head;
context->free_head = cur;
cur = next;
}
// stitch the list back in
node->next = cur;
if (cur->x < res.x + width)
cur->x = (stbrp_coord) (res.x + width);
#ifdef _DEBUG
cur = context->active_head;
while (cur->x < context->width) {
STBRP_ASSERT(cur->x < cur->next->x);
cur = cur->next;
}
STBRP_ASSERT(cur->next == NULL);
{
stbrp_node *L1 = NULL, *L2 = NULL;
int count=0;
cur = context->active_head;
while (cur) {
L1 = cur;
cur = cur->next;
++count;
}
cur = context->free_head;
while (cur) {
L2 = cur;
cur = cur->next;
++count;
}
STBRP_ASSERT(count == context->num_nodes+2);
}
#endif
return res;
}
static int rect_height_compare(const void *a, const void *b)
{
stbrp_rect *p = (stbrp_rect *) a;
stbrp_rect *q = (stbrp_rect *) b;
if (p->h > q->h)
return -1;
if (p->h < q->h)
return 1;
return (p->w > q->w) ? -1 : (p->w < q->w);
}
static int rect_width_compare(const void *a, const void *b)
{
stbrp_rect *p = (stbrp_rect *) a;
stbrp_rect *q = (stbrp_rect *) b;
if (p->w > q->w)
return -1;
if (p->w < q->w)
return 1;
return (p->h > q->h) ? -1 : (p->h < q->h);
}
static int rect_original_order(const void *a, const void *b)
{
stbrp_rect *p = (stbrp_rect *) a;
stbrp_rect *q = (stbrp_rect *) b;
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
}
#ifdef STBRP_LARGE_RECTS
#define STBRP__MAXVAL 0xffffffff
#else
#define STBRP__MAXVAL 0xffff
#endif
STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
{
int i;
// we use the 'was_packed' field internally to allow sorting/unsorting
for (i=0; i < num_rects; ++i) {
rects[i].was_packed = i;
#ifndef STBRP_LARGE_RECTS
STBRP_ASSERT(rects[i].w <= 0xffff && rects[i].h <= 0xffff);
#endif
}
// sort according to heuristic
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
for (i=0; i < num_rects; ++i) {
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
if (fr.prev_link) {
rects[i].x = (stbrp_coord) fr.x;
rects[i].y = (stbrp_coord) fr.y;
} else {
rects[i].x = rects[i].y = STBRP__MAXVAL;
}
}
// unsort
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
// set was_packed flags
for (i=0; i < num_rects; ++i)
rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
}
#endif

2632
src/stb_truetype.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,3 @@
#include "stb_vorbis.h"
#ifndef STB_VORBIS_HEADER_ONLY
@ -180,7 +179,7 @@
#define NULL 0
#endif
#ifndef _MSC_VER
#if !defined(_MSC_VER) && !(defined(__MINGW32__) && defined(__forceinline))
#if __GNUC__
#define __forceinline inline
#else
@ -3562,7 +3561,7 @@ static int start_decoder(vorb *f)
g->sorted_order[j] = (uint8) p[j].y;
// precompute the neighbors
for (j=2; j < g->values; ++j) {
int low = 0,hi = 0;
int low,hi;
neighbors(g->Xlist, j, &low,&hi);
g->neighbors[j][0] = low;
g->neighbors[j][1] = hi;
@ -5024,6 +5023,7 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in
#endif // STB_VORBIS_NO_PULLDATA_API
/* Version history
1.05 - 2015/04/19 - don't define __forceinline if it's redundant
1.04 - 2014/08/27 - fix missing const-correct case in API
1.03 - 2014/08/07 - Warning fixes
1.02 - 2014/07/09 - Declare qsort compare function _cdecl on windows

View File

@ -1,4 +1,4 @@
// Ogg Vorbis audio decoder - v1.04 - public domain
// Ogg Vorbis audio decoder - v1.05 - public domain
// http://nothings.org/stb_vorbis/
//
// Written by Sean Barrett in 2007, last updated in 2014
@ -24,12 +24,13 @@
// Casey Muratori John Bolton Gargaj
// Laurent Gomila Marc LeBlanc Ronny Chevalier
// Bernhard Wodo Evan Balster "alxprd"@github
// Tom Beaumont Ingo Leitgeb
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot
// (If you reported a bug but do not appear in this list, it is because
// someone else reported the bug before you. There were too many of you to
// list them all because I was lax about updating for a long time, sorry.)
//
// Partial history:
// 1.05 - 2015/04/19 - don't define __forceinline if it's redundant
// 1.04 - 2014/08/27 - fix missing const-correct case in API
// 1.03 - 2014/08/07 - warning fixes
// 1.02 - 2014/07/09 - declare qsort comparison as explicitly _cdecl in Windows
@ -58,6 +59,12 @@
#include <stdio.h>
#endif
// NOTE: Added to work with raylib on Android
#if defined(PLATFORM_ANDROID)
#include "utils.h" // Android fopen function map
#endif
// RaySan: Added for Linux
#ifdef __linux
#include <alloca.h>
#endif

View File

@ -30,15 +30,20 @@
#include <stdarg.h> // Used for functions with variable number of parameters (FormatText())
#include <stdio.h> // Standard input / output lib
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
#include "utils.h" // Required for function GetExtendion()
#include "utils.h" // Required for function GetExtension()
// Following libs are used on LoadTTF()
#define STB_TRUETYPE_IMPLEMENTATION
#define STB_RECT_PACK_IMPLEMENTATION
#include "stb_rect_pack.h"
#include "stb_truetype.h"
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
#define FONT_FIRST_CHAR 32
#define MAX_FONTCHARS 128
#define MAX_FORMATTEXT_LENGTH 50
#define MAX_FORMATTEXT_LENGTH 64
#define BIT_CHECK(a,b) ((a) & (1<<(b)))
@ -64,6 +69,7 @@ static SpriteFont defaultFont; // Default font provided by raylib
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 SpriteFont LoadRBMF(const char *fileName); // Load a rBMF font file (raylib BitMap Font)
static SpriteFont LoadTTF(const char *fileName, int fontSize); // Generate a sprite font image from TTF data (font size required)
extern void LoadDefaultFont(void);
extern void UnloadDefaultFont(void);
@ -73,16 +79,15 @@ extern void UnloadDefaultFont(void);
//----------------------------------------------------------------------------------
extern void LoadDefaultFont(void)
{
defaultFont.numChars = 96; // We know our default font has 94 chars
// NOTE: Using UTF8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement
// http://www.utf8-chartable.de/unicode-utf8-table.pl
Image image;
image.width = 128; // We know our default font image is 128 pixels width
image.height = 64; // We know our default font image is 64 pixels height
defaultFont.numChars = 224; // Number of chars included in our default font
// Default font is directly defined here (data generated from a sprite font image)
// This way, we reconstruct SpriteFont without creating large global variables
// This data is automatically allocated to Stack and automatically deallocated at the end of this function
int defaultFontData[256] = {
int defaultFontData[512] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00200020, 0x0001b000, 0x00000000, 0x00000000, 0x8ef92520, 0x00020a00, 0x7dbe8000, 0x1f7df45f,
0x4a2bf2a0, 0x0852091e, 0x41224000, 0x10041450, 0x2e292020, 0x08220812, 0x41222000, 0x10041450, 0x10f92020, 0x3efa084c, 0x7d22103c, 0x107df7de,
0xe8a12020, 0x08220832, 0x05220800, 0x10450410, 0xa4a3f000, 0x08520832, 0x05220400, 0x10450410, 0xe2f92020, 0x0002085e, 0x7d3e0281, 0x107df41f,
@ -98,42 +103,78 @@ extern void LoadDefaultFont(void)
0x04000404, 0x4100203c, 0x00000000, 0x00000800, 0xf7df7df0, 0x514bef85, 0xbefbefbe, 0x04513bef, 0x14414500, 0x494a2885, 0xa28a28aa, 0x04510820,
0xf44145f0, 0x474a289d, 0xa28a28aa, 0x04510be0, 0x14414510, 0x494a2884, 0xa28a28aa, 0x02910a00, 0xf7df7df0, 0xd14a2f85, 0xbefbe8aa, 0x011f7be0,
0x00000000, 0x00400804, 0x20080000, 0x00000000, 0x00000000, 0x00600f84, 0x20080000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0xac000000, 0x00000f01, 0x00000000, 0x00000000, 0x24000000, 0x00000901, 0x00000000, 0x00000000, 0x24000000, 0x00000901, 0x00000000, 0x00000000,
0x24fa28a2, 0x00000901, 0x00000000, 0x00000000, 0x2242252a, 0x00000952, 0x00000000, 0x00000000, 0x2422222a, 0x00000929, 0x00000000, 0x00000000,
0x2412252a, 0x00000901, 0x00000000, 0x00000000, 0x24fbe8be, 0x00000901, 0x00000000, 0x00000000, 0xac020000, 0x00000f01, 0x00000000, 0x00000000,
0x0003e000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0xac000000, 0x00000f01, 0x00000000, 0x00000000, 0x24000000, 0x00000901, 0x00000000, 0x06000000, 0x24000000, 0x00000901, 0x00000000, 0x09108000,
0x24fa28a2, 0x00000901, 0x00000000, 0x013e0000, 0x2242252a, 0x00000952, 0x00000000, 0x038a8000, 0x2422222a, 0x00000929, 0x00000000, 0x010a8000,
0x2412252a, 0x00000901, 0x00000000, 0x010a8000, 0x24fbe8be, 0x00000901, 0x00000000, 0x0ebe8000, 0xac020000, 0x00000f01, 0x00000000, 0x00048000,
0x0003e000, 0x00000000, 0x00000000, 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000038, 0x8443b80e, 0x00203a03,
0x02bea080, 0xf0000020, 0xc452208a, 0x04202b02, 0xf8029122, 0x07f0003b, 0xe44b388e, 0x02203a02, 0x081e8a1c, 0x0411e92a, 0xf4420be0, 0x01248202,
0xe8140414, 0x05d104ba, 0xe7c3b880, 0x00893a0a, 0x283c0e1c, 0x04500902, 0xc4400080, 0x00448002, 0xe8208422, 0x04500002, 0x80400000, 0x05200002,
0x083e8e00, 0x04100002, 0x804003e0, 0x07000042, 0xf8008400, 0x07f00003, 0x80400000, 0x04000022, 0x00000000, 0x00000000, 0x80400000, 0x04000002,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00800702, 0x1848a0c2, 0x84010000, 0x02920921, 0x01042642, 0x00005121, 0x42023f7f, 0x00291002,
0xefc01422, 0x7efdfbf7, 0xefdfa109, 0x03bbbbf7, 0x28440f12, 0x42850a14, 0x20408109, 0x01111010, 0x28440408, 0x42850a14, 0x2040817f, 0x01111010,
0xefc78204, 0x7efdfbf7, 0xe7cf8109, 0x011111f3, 0x2850a932, 0x42850a14, 0x2040a109, 0x01111010, 0x2850b840, 0x42850a14, 0xefdfbf79, 0x03bbbbf7,
0x001fa020, 0x00000000, 0x00001000, 0x00000000, 0x00002070, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x08022800, 0x00012283, 0x02430802, 0x01010001, 0x8404147c, 0x20000144, 0x80048404, 0x00823f08, 0xdfbf4284, 0x7e03f7ef, 0x142850a1, 0x0000210a,
0x50a14684, 0x528a1428, 0x142850a1, 0x03efa17a, 0x50a14a9e, 0x52521428, 0x142850a1, 0x02081f4a, 0x50a15284, 0x4a221428, 0xf42850a1, 0x03efa14b,
0x50a16284, 0x4a521428, 0x042850a1, 0x0228a17a, 0xdfbf427c, 0x7e8bf7ef, 0xf7efdfbf, 0x03efbd0b, 0x00000000, 0x04000000, 0x00000000, 0x00000008,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00200508, 0x00840400, 0x11458122, 0x00014210,
0x00514294, 0x51420800, 0x20a22a94, 0x0050a508, 0x00200000, 0x00000000, 0x00050000, 0x08000000, 0xfefbefbe, 0xfbefbefb, 0xfbeb9114, 0x00fbefbe,
0x20820820, 0x8a28a20a, 0x8a289114, 0x3e8a28a2, 0xfefbefbe, 0xfbefbe0b, 0x8a289114, 0x008a28a2, 0x228a28a2, 0x08208208, 0x8a289114, 0x088a28a2,
0xfefbefbe, 0xfbefbefb, 0xfa2f9114, 0x00fbefbe, 0x00000000, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000020, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00210100, 0x00000004, 0x00000000, 0x00000000, 0x14508200, 0x00001402, 0x00000000, 0x00000000,
0x00000010, 0x00000020, 0x00000000, 0x00000000, 0xa28a28be, 0x00002228, 0x00000000, 0x00000000, 0xa28a28aa, 0x000022e8, 0x00000000, 0x00000000,
0xa28a28aa, 0x000022a8, 0x00000000, 0x00000000, 0xa28a28aa, 0x000022e8, 0x00000000, 0x00000000, 0xbefbefbe, 0x00003e2f, 0x00000000, 0x00000000,
0x00000004, 0x00002028, 0x00000000, 0x00000000, 0x80000000, 0x00003e0f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000 };
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
int charsHeight = 10;
int charsDivisor = 1; // Every char is separated from the consecutive by a 1 pixel divisor, horizontally and vertically
int charsWidth[96] = { 3, 1, 4, 6, 5, 7, 6, 2, 3, 3, 5, 5, 2, 4, 1, 7, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 3, 4, 3, 6,
7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 5, 6, 5, 7, 6, 6, 6, 6, 6, 6, 7, 6, 7, 7, 6, 6, 6, 2, 7, 2, 3, 5,
2, 5, 5, 5, 5, 5, 4, 5, 5, 1, 2, 5, 2, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 3, 1, 3, 4, 4 };
int charsWidth[224] = { 3, 1, 4, 6, 5, 7, 6, 2, 3, 3, 5, 5, 2, 4, 1, 7, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 3, 4, 3, 6,
7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 5, 6, 5, 7, 6, 6, 6, 6, 6, 6, 7, 6, 7, 7, 6, 6, 6, 2, 7, 2, 3, 5,
2, 5, 5, 5, 5, 5, 4, 5, 5, 1, 2, 5, 2, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 3, 1, 3, 4, 4,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 5, 5, 5, 7, 1, 5, 3, 7, 3, 5, 4, 1, 7, 4, 3, 5, 3, 3, 2, 5, 6, 1, 2, 2, 3, 5, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 3, 3, 3, 3, 7, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 6, 6, 6, 4, 6,
5, 5, 5, 5, 5, 5, 9, 5, 5, 5, 5, 5, 2, 2, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 5 };
// Re-construct image from defaultFontData and generate OpenGL texture
//----------------------------------------------------------------------
image.pixels = (Color *)malloc(image.width * image.height * sizeof(Color));
int imWidth = 128;
int imHeight = 128;
Color *imagePixels = (Color *)malloc(imWidth*imHeight*sizeof(Color));
for (int i = 0; i < image.width * image.height; i++) image.pixels[i] = BLANK; // Initialize array
for (int i = 0; i < imWidth*imHeight; i++) imagePixels[i] = BLANK; // Initialize array
int counter = 0; // Font data elements counter
// Fill imgData with defaultFontData (convert from bit to pixel!)
for (int i = 0; i < image.width * image.height; i += 32)
for (int i = 0; i < imWidth*imHeight; i += 32)
{
for (int j = 31; j >= 0; j--)
{
if (BIT_CHECK(defaultFontData[counter], j)) image.pixels[i+j] = WHITE;
if (BIT_CHECK(defaultFontData[counter], j)) imagePixels[i+j] = WHITE;
}
counter++;
if (counter > 256) counter = 0; // Security check...
if (counter > 512) counter = 0; // Security check...
}
//FILE *myimage = fopen("default_font.raw", "wb");
//fwrite(image.pixels, 1, 128*128*4, myimage);
//fclose(myimage);
Image image = LoadImageFromData(imagePixels, imWidth, imHeight, UNCOMPRESSED_GRAY_ALPHA);
free(imagePixels);
defaultFont.texture = LoadTextureFromImage(image, false); // Convert loaded image to OpenGL texture
UnloadImage(image);
@ -172,7 +213,7 @@ extern void LoadDefaultFont(void)
extern void UnloadDefaultFont(void)
{
rlDeleteTextures(defaultFont.texture.id);
UnloadTexture(defaultFont.texture);
free(defaultFont.charSet);
}
@ -189,18 +230,21 @@ SpriteFont LoadSpriteFont(const char *fileName)
// Check file extension
if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName);
else if (strcmp(GetExtension(fileName),"ttf") == 0) spriteFont = LoadTTF(fileName, 20);
else
{
Image image = LoadImage(fileName);
// At this point we have a pixel array with all the data...
// At this point we have a data array...
Color *imagePixels = GetPixelData(image);
#if defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
ConvertToPOT(&image, MAGENTA);
#endif
// 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(image.pixels, image.width, image.height, &spriteFont.charSet);
int numChars = ParseImageData(imagePixels, image.width, image.height, &spriteFont.charSet);
TraceLog(INFO, "[%s] SpriteFont data parsed correctly", fileName);
TraceLog(INFO, "[%s] SpriteFont num chars detected: %i", fileName, numChars);
@ -208,7 +252,8 @@ SpriteFont LoadSpriteFont(const char *fileName)
spriteFont.numChars = numChars;
spriteFont.texture = LoadTextureFromImage(image, false); // Convert loaded image to OpenGL texture
free(imagePixels);
UnloadImage(image);
}
@ -218,7 +263,7 @@ SpriteFont LoadSpriteFont(const char *fileName)
// Unload SpriteFont from GPU memory
void UnloadSpriteFont(SpriteFont spriteFont)
{
rlDeleteTextures(spriteFont.texture.id);
UnloadTexture(spriteFont.texture);
free(spriteFont.charSet);
}
@ -244,41 +289,37 @@ void DrawText(const char *text, int posX, int posY, int fontSize, Color color)
void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, int fontSize, int spacing, Color tint)
{
int length = strlen(text);
int positionX = (int)position.x;
int offsetX = 0;
float scaleFactor;
unsigned char letter;
Character c;
if (fontSize <= spriteFont.charSet[0].h) scaleFactor = 1.0f;
else scaleFactor = (float)fontSize / spriteFont.charSet[0].h;
//if (fontSize <= spriteFont.charSet[0].h) scaleFactor = 1.0f;
//else scaleFactor = (float)fontSize / spriteFont.charSet[0].h;
scaleFactor = (float)fontSize/spriteFont.charSet[0].h;
rlEnableTexture(spriteFont.texture.id);
rlBegin(RL_QUADS);
for(int i = 0; i < length; i++)
for(int i = 0; i < length; i++)
{
if ((unsigned char)text[i] == 0xc2)
{
c = spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR];
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
rlTexCoord2f((float)c.x / spriteFont.texture.width, (float)c.y / spriteFont.texture.height);
rlVertex2f(positionX, position.y);
rlTexCoord2f((float)c.x / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height);
rlVertex2f(positionX, position.y + (c.h) * scaleFactor);
rlTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height);
rlVertex2f(positionX + (c.w) * scaleFactor, position.y + (c.h) * scaleFactor);
rlTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)c.y / spriteFont.texture.height);
rlVertex2f(positionX + (c.w) * scaleFactor, position.y);
positionX += ((spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR].w) * scaleFactor + spacing);
letter = (unsigned char)text[i + 1];
c = spriteFont.charSet[letter - FONT_FIRST_CHAR];
i++;
}
rlEnd();
else if ((unsigned char)text[i] == 0xc3)
{
letter = (unsigned char)text[i + 1];
c = spriteFont.charSet[letter - FONT_FIRST_CHAR + 64];
i++;
}
else c = spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR];
rlDisableTexture();
DrawTexturePro(spriteFont.texture, (Rectangle){ c.x, c.y, c.w, c.h }, (Rectangle){ position.x + offsetX, position.y, c.w*scaleFactor, c.h*scaleFactor} , (Vector2){ 0, 0 }, 0.0f, tint);
offsetX += (c.w*scaleFactor + spacing);
}
}
// Formatting of text with variables to 'embed'
@ -465,7 +506,6 @@ static SpriteFont LoadRBMF(const char *fileName)
} rbmfInfoHeader;
SpriteFont spriteFont;
Image image;
rbmfInfoHeader rbmfHeader;
unsigned int *rbmfFileData = NULL;
@ -487,9 +527,6 @@ static SpriteFont LoadRBMF(const char *fileName)
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));
@ -502,22 +539,26 @@ static SpriteFont LoadRBMF(const char *fileName)
// Re-construct image from rbmfFileData
//-----------------------------------------
image.pixels = (Color *)malloc(image.width * image.height * sizeof(Color));
Color *imagePixels = (Color *)malloc(rbmfHeader.imgWidth*rbmfHeader.imgHeight*sizeof(Color));
for (int i = 0; i < image.width * image.height; i++) image.pixels[i] = BLANK; // Initialize array
for (int i = 0; i < rbmfHeader.imgWidth*rbmfHeader.imgHeight; i++) imagePixels[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 i = 0; i < rbmfHeader.imgWidth*rbmfHeader.imgHeight; i += 32)
{
for (int j = 31; j >= 0; j--)
{
if (BIT_CHECK(rbmfFileData[counter], j)) image.pixels[i+j] = WHITE;
if (BIT_CHECK(rbmfFileData[counter], j)) imagePixels[i+j] = WHITE;
}
counter++;
}
Image image = LoadImageFromData(imagePixels, rbmfHeader.imgWidth, rbmfHeader.imgHeight, UNCOMPRESSED_GRAY_ALPHA);
free(imagePixels);
TraceLog(INFO, "[%s] Image reconstructed correctly, now converting it to texture", fileName);
@ -557,7 +598,7 @@ static SpriteFont LoadRBMF(const char *fileName)
TraceLog(INFO, "[%s] rBMF file loaded correctly as SpriteFont", fileName);
}
fclose(rbmfFile);
free(rbmfFileData); // Now we can free loaded data from RAM memory
@ -567,11 +608,105 @@ static SpriteFont LoadRBMF(const char *fileName)
}
// Generate a sprite font from TTF data (font size required)
static SpriteFont GenerateFromTTF(const char *fileName, int fontSize)
static SpriteFont LoadTTF(const char *fileName, int fontSize)
{
SpriteFont font;
// TODO: Load TTF and generate bitmap font and chars data
Image image;
image.width = 512;
image.height = 512;
//image.pixels = (Color *)malloc(image.width*image.height*sizeof(Color));
unsigned char *ttfBuffer = (unsigned char *)malloc(1 << 25);
// TODO: Load TTF and generate bitmap font and chars data -> REVIEW!
stbtt_packedchar chardata[128]; // Num characters: 128 (?) -> REVIEW!
unsigned char *tempBitmap = (unsigned char *)malloc(image.width*image.height*sizeof(unsigned char)); // One channel bitmap returned!
// REFERENCE
/*
typedef struct
{
unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
float xoff,yoff,xadvance;
float xoff2,yoff2;
} stbtt_packedchar;
*/
stbtt_pack_context pc;
FILE *ttfFile = fopen(fileName, "rb");
fread(ttfBuffer, 1, 1<<25, ttfFile);
stbtt_PackBegin(&pc, tempBitmap, image.width, image.height, 0, 1, NULL);
//stbtt_PackSetOversampling(&pc, 1, 1);
//stbtt_PackFontRange(&pc, ttfBuffer, 0, fontSize, 32, 95, chardata[0]+32);
stbtt_PackSetOversampling(&pc, 2, 2); // Better results
stbtt_PackFontRange(&pc, ttfBuffer, 0, fontSize, 32, 95, chardata + 32);
//stbtt_PackSetOversampling(&pc, 3, 1);
//stbtt_PackFontRange(&pc, ttfBuffer, 0, fontSize, 32, 95, chardata[2]+32);
stbtt_PackEnd(&pc);
free(ttfBuffer);
// Now we have image data in tempBitmap and chardata filled...
/*
for (int i = 0; i < 512*512; i++)
{
image.pixels[i].r = tempBitmap[i];
image.pixels[i].g = tempBitmap[i];
image.pixels[i].b = tempBitmap[i];
image.pixels[i].a = 255;
}
*/
free(tempBitmap);
// REFERENCE EXAMPLE
/*
//To draw, provide *text, posX, posY
//stbtt_aligned_quad letter;
//stbtt_GetPackedQuad(chardata[0], BITMAP_W, BITMAP_H, *text++, &posX, &posY, &letter, font ? 0 : integer_align);
void print(float x, float y, int fontNum, char *text)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, font_tex);
glBegin(GL_QUADS);
while (*text) {
stbtt_aligned_quad q;
stbtt_GetPackedQuad(chardata[fontNum], BITMAP_W, BITMAP_H, *text++, &x, &y, &q, fontNum ? 0 : integer_align);
drawBoxTC(q.x0,q.y0,q.x1,q.y1, q.s0,q.t0,q.s1,q.t1);
}
glEnd();
}
print(100,160, 0, "This is a test");
*/
font.numChars = 95;
font.charSet = (Character *)malloc(font.numChars*sizeof(Character));
font.texture = LoadTextureFromImage(image, false);
//stbtt_aligned_quad letter;
//int x = 0, y = 0;
for (int i = 0; i < font.numChars; i++)
{
font.charSet[i].value = i + 32;
//stbtt_GetPackedQuad(chardata[0], 512, 512, i, &x, &y, &letter, 0);
font.charSet[i].x = chardata[i + 32].x0;
font.charSet[i].y = chardata[i + 32].y0;
font.charSet[i].w = chardata[i + 32].x1 - chardata[i + 32].x0;
font.charSet[i].h = chardata[i + 32].y1 - chardata[i + 32].y0;
}
UnloadImage(image);
return font;
}

File diff suppressed because it is too large Load Diff

View File

@ -79,7 +79,7 @@ unsigned char *DecompressData(const unsigned char *data, unsigned long compSize,
pUncomp = (mz_uint8 *)malloc((size_t)uncompSize);
// Check correct memory allocation
if (!pUncomp)
if (pUncomp == NULL)
{
TraceLog(WARNING, "Out of memory while decompressing data");
}
@ -235,18 +235,18 @@ void TraceLog(int msgType, const char *text, ...)
}
// Initialize asset manager from android app
void InitAssetManager(AAssetManager *manager)
void InitAssetManager(AAssetManager *manager)
{
assetManager = manager;
}
// Replacement for fopen
FILE *android_fopen(const char *fileName, const char *mode)
FILE *android_fopen(const char *fileName, const char *mode)
{
if (mode[0] == 'w') return NULL;
AAsset *asset = AAssetManager_open(assetManager, fileName, 0);
if(!asset) return NULL;
return funopen(asset, android_read, android_write, android_seek, android_close);
@ -292,24 +292,24 @@ int GetNextPOT(int num)
// Module specific Functions Definition
//----------------------------------------------------------------------------------
#if defined(PLATFORM_ANDROID)
static int android_read(void *cookie, char *buf, int size)
static int android_read(void *cookie, char *buf, int size)
{
return AAsset_read((AAsset *)cookie, buf, size);
}
static int android_write(void *cookie, const char *buf, int size)
static int android_write(void *cookie, const char *buf, int size)
{
TraceLog(ERROR, "Can't provide write access to the APK");
return EACCES;
}
static fpos_t android_seek(void *cookie, fpos_t offset, int whence)
static fpos_t android_seek(void *cookie, fpos_t offset, int whence)
{
return AAsset_seek((AAsset *)cookie, offset, whence);
}
static int android_close(void *cookie)
static int android_close(void *cookie)
{
AAsset_close((AAsset *)cookie);
return 0;

View File

@ -2,7 +2,7 @@
#
# raylib - Advance Game
#
# makefile to compile advance game
# makefile to compile advance game for desktop platforms, Raspberry Pi and HTML5 (emscripten)
#
# Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
#
@ -23,49 +23,133 @@
#
#**************************************************************************************************
# define raylib platform if not defined (by default, compile for RPI)
# Other possible platform: PLATFORM_DESKTOP
PLATFORM ?= PLATFORM_RPI
# define raylib platform to compile for
# possible platforms: PLATFORM_DESKTOP PLATFORM_RPI PLATFORM_WEB
# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop()
PLATFORM ?= PLATFORM_DESKTOP
# determine PLATFORM_OS in case PLATFORM_DESKTOP selected
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
# No uname.exe on MinGW!, but OS=Windows_NT on Windows! ifeq ($(UNAME),Msys) -> Windows
ifeq ($(OS),Windows_NT)
PLATFORM_OS=WINDOWS
LIBPATH=win32
else
UNAMEOS:=$(shell uname)
ifeq ($(UNAMEOS),Linux)
PLATFORM_OS=LINUX
LIBPATH=linux
else
ifeq ($(UNAMEOS),Darwin)
PLATFORM_OS=OSX
LIBPATH=osx
endif
endif
endif
endif
# define compiler: gcc for C program, define as g++ for C++
CC = gcc
ifeq ($(PLATFORM),PLATFORM_WEB)
# define emscripten compiler
CC = emcc
else
ifeq ($(PLATFORM_OS),OSX)
# define llvm compiler for mac
CC = clang
else
# define default gcc compiler
CC = gcc
endif
endif
# define compiler flags:
# -O2 defines optimization level
# -Wall turns on most, but not all, compiler warnings
# -std=c99 use standard C from 1999 revision
CFLAGS = -O2 -Wall -std=c99
ifeq ($(PLATFORM),PLATFORM_RPI)
CFLAGS = -O2 -Wall -std=gnu99 -fgnu89-inline
else
CFLAGS = -O2 -Wall -std=c99
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 -s ASSERTIONS=1 --preload-file resources
#-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing
#-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
endif
#CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes
# define any directories containing required header files
ifeq ($(PLATFORM),PLATFORM_RPI)
INCLUDES = -I. -I./screens -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
else
INCLUDES = -I. -I./screens -I../../src
INCLUDES = -I. -I../../src
# external libraries headers
# GLFW3
INCLUDES += -I../../external/glfw3/include
# GLEW
INCLUDES += -I../../external/glew/include
# OpenAL Soft
INCLUDES += -I../../external/openal_soft/include
endif
# define library paths containing required libs
LFLAGS = -L. -L../../src -L/opt/vc/lib
ifeq ($(PLATFORM),PLATFORM_RPI)
LFLAGS = -L. -L../../src -L/opt/vc/lib
else
LFLAGS = -L. -L../../src
# external libraries to link with
# GLFW3
LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
ifneq ($(PLATFORM_OS),OSX)
# OpenAL Soft
LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
# GLEW
LFLAGS += -L../../external/glew/lib/$(LIBPATH)
endif
endif
# define any libraries to link into executable
# if you want to link libraries (libname.so or libname.a), use the -lname
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),LINUX)
# libraries for Debian GNU/Linux desktop compiling
# requires the following packages:
# libopenal-dev libglew-dev libegl1-mesa-dev
LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lm -pthread
else
ifeq ($(PLATFORM_OS),OSX)
# libraries for OS X 10.9 desktop compiling
# requires the following packages:
# libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
LIBS = -lraylib -lglfw -framework OpenGL -framework OpenAl -framework Cocoa
else
# libraries for Windows desktop compiling
# NOTE: GLFW3 and OpenAL Soft libraries should be installed
LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32
endif
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
# libraries for Raspberry Pi compiling
# NOTE: OpenAL Soft library should be installed (libopenal1 package)
LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal
else
# libraries for Windows desktop compiling
# NOTE: GLFW3 and OpenAL Soft libraries should be installed
LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
LIBS = ../../src/libraylib.bc
endif
# define additional parameters and flags for windows
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),WINDOWS)
# resources file contains windows exe icon
# -Wl,--subsystem,windows hides the console window
WINFLAGS = ../../src/resources -Wl,--subsystem,windows
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
EXT = .html
endif
# define all screen object files required
SCREENS = \
screens/screen_logo.o \
@ -80,7 +164,7 @@ default: advance_game
# compile template - advance_game
advance_game: advance_game.c $(SCREENS)
$(CC) -o $@ $< $(SCREENS) $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
$(CC) -o $@$(EXT) $< $(SCREENS) $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
# compile screen LOGO
screens/screen_logo.o: screens/screen_logo.c
@ -104,11 +188,24 @@ screens/screen_ending.o: screens/screen_ending.c
# clean everything
clean:
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),OSX)
find . -type f -perm +ugo+x -delete
rm -f *.o
else
ifeq ($(PLATFORM_OS),LINUX)
find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f
else
del *.o *.exe
endif
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
rm -f screens/*.o
# find . -executable -delete
else
del screens/*.o *.exe
find . -type f -executable -delete
rm -f *.o
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
del *.o *.html *.js
endif
@echo Cleaning done

View File

@ -2,7 +2,7 @@
#
# raylib - Basic Game
#
# makefile to compile basic game
# makefile to compile basic game for desktop platforms, Raspberry Pi and HTML5 (emscripten)
#
# Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
#
@ -23,18 +23,60 @@
#
#**************************************************************************************************
# define raylib platform (by default, compile for RPI)
# Other possible platform: PLATFORM_DESKTOP
PLATFORM ?= PLATFORM_RPI
# define raylib platform to compile for
# possible platforms: PLATFORM_DESKTOP PLATFORM_RPI PLATFORM_WEB
# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop()
PLATFORM ?= PLATFORM_DESKTOP
# determine PLATFORM_OS in case PLATFORM_DESKTOP selected
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
# No uname.exe on MinGW!, but OS=Windows_NT on Windows! ifeq ($(UNAME),Msys) -> Windows
ifeq ($(OS),Windows_NT)
PLATFORM_OS=WINDOWS
LIBPATH=win32
else
UNAMEOS:=$(shell uname)
ifeq ($(UNAMEOS),Linux)
PLATFORM_OS=LINUX
LIBPATH=linux
else
ifeq ($(UNAMEOS),Darwin)
PLATFORM_OS=OSX
LIBPATH=osx
endif
endif
endif
endif
# define compiler: gcc for C program, define as g++ for C++
CC = gcc
ifeq ($(PLATFORM),PLATFORM_WEB)
# define emscripten compiler
CC = emcc
else
ifeq ($(PLATFORM_OS),OSX)
# define llvm compiler for mac
CC = clang
else
# define default gcc compiler
CC = gcc
endif
endif
# define compiler flags:
# -O2 defines optimization level
# -Wall turns on most, but not all, compiler warnings
# -std=c99 use standard C from 1999 revision
CFLAGS = -O2 -Wall -std=c99
ifeq ($(PLATFORM),PLATFORM_RPI)
CFLAGS = -O2 -Wall -std=gnu99 -fgnu89-inline
else
CFLAGS = -O2 -Wall -std=c99
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 -s ASSERTIONS=1 --preload-file resources
#-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing
#-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
endif
#CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes
# define any directories containing required header files
@ -42,45 +84,100 @@ ifeq ($(PLATFORM),PLATFORM_RPI)
INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
else
INCLUDES = -I. -I../../src
# external libraries headers
# GLFW3
INCLUDES += -I../../external/glfw3/include
# GLEW
INCLUDES += -I../../external/glew/include
# OpenAL Soft
INCLUDES += -I../../external/openal_soft/include
endif
# define library paths containing required libs
LFLAGS = -L. -L../../src -L/opt/vc/lib
ifeq ($(PLATFORM),PLATFORM_RPI)
LFLAGS = -L. -L../../src -L/opt/vc/lib
else
LFLAGS = -L. -L../../src
# external libraries to link with
# GLFW3
LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
ifneq ($(PLATFORM_OS),OSX)
# OpenAL Soft
LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
# GLEW
LFLAGS += -L../../external/glew/lib/$(LIBPATH)
endif
endif
# define any libraries to link into executable
# if you want to link libraries (libname.so or libname.a), use the -lname
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),LINUX)
# libraries for Debian GNU/Linux desktop compiling
# requires the following packages:
# libopenal-dev libglew-dev libegl1-mesa-dev
LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lm -pthread
else
ifeq ($(PLATFORM_OS),OSX)
# libraries for OS X 10.9 desktop compiling
# requires the following packages:
# libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
LIBS = -lraylib -lglfw -framework OpenGL -framework OpenAl -framework Cocoa
else
# libraries for Windows desktop compiling
# NOTE: GLFW3 and OpenAL Soft libraries should be installed
LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32
endif
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
# libraries for Raspberry Pi compiling
# NOTE: OpenAL Soft library should be installed (libopenal1 package)
LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal
else
# libraries for Windows desktop compiling
# NOTE: GLFW3 and OpenAL Soft libraries should be installed
LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
LIBS = ../../src/libraylib.bc
endif
# define additional parameters and flags for windows
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),WINDOWS)
# resources file contains windows exe icon
# -Wl,--subsystem,windows hides the console window
WINFLAGS = ../../src/resources -Wl,--subsystem,windows
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
EXT = .html
endif
# typing 'make' will invoke the first target entry in the file,
# in this case, the 'default' target entry is basic_game
default: basic_game
# compile template - basic_game
basic_game: basic_game.c
$(CC) -o $@ $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
# clean everything
clean:
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),OSX)
find . -type f -perm +ugo+x -delete
rm -f *.o
else
ifeq ($(PLATFORM_OS),LINUX)
find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f
else
del *.o *.exe
endif
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
find . -type f -executable -delete
rm -f *.o
# find . -executable -delete
else
del *.o *.exe
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
del *.o *.html *.js
endif
@echo Cleaning done

View File

@ -2,7 +2,7 @@
#
# raylib - Basic Test
#
# makefile to compile basic test
# makefile to compile basic test for desktop platforms, Raspberry Pi and HTML5 (emscripten)
#
# Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
#
@ -23,18 +23,60 @@
#
#**************************************************************************************************
# define raylib platform if not defined (by default, compile for RPI)
# Other possible platform: PLATFORM_DESKTOP
PLATFORM ?= PLATFORM_RPI
# define raylib platform to compile for
# possible platforms: PLATFORM_DESKTOP PLATFORM_RPI PLATFORM_WEB
# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop()
PLATFORM ?= PLATFORM_DESKTOP
# determine PLATFORM_OS in case PLATFORM_DESKTOP selected
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
# No uname.exe on MinGW!, but OS=Windows_NT on Windows! ifeq ($(UNAME),Msys) -> Windows
ifeq ($(OS),Windows_NT)
PLATFORM_OS=WINDOWS
LIBPATH=win32
else
UNAMEOS:=$(shell uname)
ifeq ($(UNAMEOS),Linux)
PLATFORM_OS=LINUX
LIBPATH=linux
else
ifeq ($(UNAMEOS),Darwin)
PLATFORM_OS=OSX
LIBPATH=osx
endif
endif
endif
endif
# define compiler: gcc for C program, define as g++ for C++
CC = gcc
ifeq ($(PLATFORM),PLATFORM_WEB)
# define emscripten compiler
CC = emcc
else
ifeq ($(PLATFORM_OS),OSX)
# define llvm compiler for mac
CC = clang
else
# define default gcc compiler
CC = gcc
endif
endif
# define compiler flags:
# -O2 defines optimization level
# -Wall turns on most, but not all, compiler warnings
# -std=c99 use standard C from 1999 revision
CFLAGS = -O2 -Wall -std=c99
ifeq ($(PLATFORM),PLATFORM_RPI)
CFLAGS = -O2 -Wall -std=gnu99 -fgnu89-inline
else
CFLAGS = -O2 -Wall -std=c99
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 -s ASSERTIONS=1 --preload-file resources
#-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing
#-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
endif
#CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes
# define any directories containing required header files
@ -42,45 +84,100 @@ ifeq ($(PLATFORM),PLATFORM_RPI)
INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
else
INCLUDES = -I. -I../../src
# external libraries headers
# GLFW3
INCLUDES += -I../../external/glfw3/include
# GLEW
INCLUDES += -I../../external/glew/include
# OpenAL Soft
INCLUDES += -I../../external/openal_soft/include
endif
# define library paths containing required libs
LFLAGS = -L. -L../../src -L/opt/vc/lib
ifeq ($(PLATFORM),PLATFORM_RPI)
LFLAGS = -L. -L../../src -L/opt/vc/lib
else
LFLAGS = -L. -L../../src
# external libraries to link with
# GLFW3
LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
ifneq ($(PLATFORM_OS),OSX)
# OpenAL Soft
LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
# GLEW
LFLAGS += -L../../external/glew/lib/$(LIBPATH)
endif
endif
# define any libraries to link into executable
# if you want to link libraries (libname.so or libname.a), use the -lname
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),LINUX)
# libraries for Debian GNU/Linux desktop compiling
# requires the following packages:
# libopenal-dev libglew-dev libegl1-mesa-dev
LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lm -pthread
else
ifeq ($(PLATFORM_OS),OSX)
# libraries for OS X 10.9 desktop compiling
# requires the following packages:
# libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
LIBS = -lraylib -lglfw -framework OpenGL -framework OpenAl -framework Cocoa
else
# libraries for Windows desktop compiling
# NOTE: GLFW3 and OpenAL Soft libraries should be installed
LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32
endif
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
# libraries for Raspberry Pi compiling
# NOTE: OpenAL Soft library should be installed (libopenal1 package)
LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal
else
# libraries for Windows desktop compiling
# NOTE: GLFW3 and OpenAL Soft libraries should be installed
LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
LIBS = ../../src/libraylib.bc
endif
# define additional parameters and flags for windows
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),WINDOWS)
# resources file contains windows exe icon
# -Wl,--subsystem,windows hides the console window
WINFLAGS = ../../src/resources -Wl,--subsystem,windows
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
EXT = .html
endif
# typing 'make' will invoke the first target entry in the file,
# in this case, the 'default' target entry is basic_test
default: basic_test
# compile template - basic_test
basic_test: basic_test.c
$(CC) -o $@ $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
# clean everything
clean:
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),OSX)
find . -type f -perm +ugo+x -delete
rm -f *.o
else
ifeq ($(PLATFORM_OS),LINUX)
find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f
else
del *.o *.exe
endif
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
find . -type f -executable -delete
rm -f *.o
# find . -executable -delete
else
del *.o *.exe
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
del *.o *.html *.js
endif
@echo Cleaning done

View File

@ -2,7 +2,7 @@
#
# raylib - Simple Game
#
# makefile to compile simple game
# makefile to compile simple game for desktop platforms, Raspberry Pi and HTML5 (emscripten)
#
# Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
#
@ -23,12 +23,44 @@
#
#**************************************************************************************************
# define raylib platform (by default, compile for RPI)
# Other possible platform: PLATFORM_DESKTOP
PLATFORM ?= PLATFORM_RPI
# define raylib platform to compile for
# possible platforms: PLATFORM_DESKTOP PLATFORM_RPI PLATFORM_WEB
# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop()
PLATFORM ?= PLATFORM_DESKTOP
# determine PLATFORM_OS in case PLATFORM_DESKTOP selected
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
# No uname.exe on MinGW!, but OS=Windows_NT on Windows! ifeq ($(UNAME),Msys) -> Windows
ifeq ($(OS),Windows_NT)
PLATFORM_OS=WINDOWS
LIBPATH=win32
else
UNAMEOS:=$(shell uname)
ifeq ($(UNAMEOS),Linux)
PLATFORM_OS=LINUX
LIBPATH=linux
else
ifeq ($(UNAMEOS),Darwin)
PLATFORM_OS=OSX
LIBPATH=osx
endif
endif
endif
endif
# define compiler: gcc for C program, define as g++ for C++
CC = gcc
ifeq ($(PLATFORM),PLATFORM_WEB)
# define emscripten compiler
CC = emcc
else
ifeq ($(PLATFORM_OS),OSX)
# define llvm compiler for mac
CC = clang
else
# define default gcc compiler
CC = gcc
endif
endif
# define compiler flags:
# -O2 defines optimization level
@ -39,6 +71,12 @@ ifeq ($(PLATFORM),PLATFORM_RPI)
else
CFLAGS = -O2 -Wall -std=c99
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 -s ASSERTIONS=1 --preload-file resources
#-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing
#-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
endif
#CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes
# define any directories containing required header files
@ -46,37 +84,79 @@ ifeq ($(PLATFORM),PLATFORM_RPI)
INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
else
INCLUDES = -I. -I../../src
# external libraries headers
# GLFW3
INCLUDES += -I../../external/glfw3/include
# GLEW
INCLUDES += -I../../external/glew/include
# OpenAL Soft
INCLUDES += -I../../external/openal_soft/include
endif
# define library paths containing required libs
LFLAGS = -L. -L../../src -L/opt/vc/lib
ifeq ($(PLATFORM),PLATFORM_RPI)
LFLAGS = -L. -L../../src -L/opt/vc/lib
else
LFLAGS = -L. -L../../src
# external libraries to link with
# GLFW3
LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
ifneq ($(PLATFORM_OS),OSX)
# OpenAL Soft
LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
# GLEW
LFLAGS += -L../../external/glew/lib/$(LIBPATH)
endif
endif
# define any libraries to link into executable
# if you want to link libraries (libname.so or libname.a), use the -lname
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),LINUX)
# libraries for Debian GNU/Linux desktop compiling
# requires the following packages:
# libopenal-dev libglew-dev libegl1-mesa-dev
LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lm -pthread
else
ifeq ($(PLATFORM_OS),OSX)
# libraries for OS X 10.9 desktop compiling
# requires the following packages:
# libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
LIBS = -lraylib -lglfw -framework OpenGL -framework OpenAl -framework Cocoa
else
# libraries for Windows desktop compiling
# NOTE: GLFW3 and OpenAL Soft libraries should be installed
LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32
endif
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
# libraries for Raspberry Pi compiling
# NOTE: OpenAL Soft library should be installed (libopenal1 package)
LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal
else
# libraries for Windows desktop compiling
# NOTE: GLFW3 and OpenAL Soft libraries should be installed
LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
LIBS = ../../src/libraylib.bc
endif
# define additional parameters and flags for windows
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),WINDOWS)
# resources file contains windows exe icon
# -Wl,--subsystem,windows hides the console window
WINFLAGS = ../../src/resources -Wl,--subsystem,windows
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
EXT = .html
endif
# typing 'make' will invoke the first target entry in the file,
# in this case, the 'default' target entry is simple_game
default: simple_game
# compile template - simple_game
simple_game: simple_game.c screens.o
$(CC) -o $@ $< screens.o $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
$(CC) -o $@$(EXT) $< screens.o $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
# compile screens
screens.o: screens.c
@ -84,11 +164,24 @@ screens.o: screens.c
# clean everything
clean:
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),OSX)
find . -type f -perm +ugo+x -delete
rm -f *.o
else
ifeq ($(PLATFORM_OS),LINUX)
find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f
else
del *.o *.exe
endif
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
find . -type f -executable -delete
rm -f *.o
# find . -executable -delete
else
del *.o *.exe
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
del *.o *.html *.js
endif
@echo Cleaning done

Binary file not shown.

View File

@ -2,7 +2,7 @@
#
# raylib - Standard Game
#
# makefile to compile standard game
# makefile to compile standard game for desktop platforms, Raspberry Pi and HTML5 (emscripten)
#
# Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
#
@ -23,49 +23,133 @@
#
#**************************************************************************************************
# define raylib platform if not defined (by default, compile for RPI)
# Other possible platform: PLATFORM_DESKTOP
PLATFORM ?= PLATFORM_RPI
# define raylib platform to compile for
# possible platforms: PLATFORM_DESKTOP PLATFORM_RPI PLATFORM_WEB
# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop()
PLATFORM ?= PLATFORM_DESKTOP
# determine PLATFORM_OS in case PLATFORM_DESKTOP selected
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
# No uname.exe on MinGW!, but OS=Windows_NT on Windows! ifeq ($(UNAME),Msys) -> Windows
ifeq ($(OS),Windows_NT)
PLATFORM_OS=WINDOWS
LIBPATH=win32
else
UNAMEOS:=$(shell uname)
ifeq ($(UNAMEOS),Linux)
PLATFORM_OS=LINUX
LIBPATH=linux
else
ifeq ($(UNAMEOS),Darwin)
PLATFORM_OS=OSX
LIBPATH=osx
endif
endif
endif
endif
# define compiler: gcc for C program, define as g++ for C++
CC = gcc
ifeq ($(PLATFORM),PLATFORM_WEB)
# define emscripten compiler
CC = emcc
else
ifeq ($(PLATFORM_OS),OSX)
# define llvm compiler for mac
CC = clang
else
# define default gcc compiler
CC = gcc
endif
endif
# define compiler flags:
# -O2 defines optimization level
# -Wall turns on most, but not all, compiler warnings
# -std=c99 use standard C from 1999 revision
CFLAGS = -O2 -Wall -std=c99
ifeq ($(PLATFORM),PLATFORM_RPI)
CFLAGS = -O2 -Wall -std=gnu99 -fgnu89-inline
else
CFLAGS = -O2 -Wall -std=c99
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 -s ASSERTIONS=1 --preload-file resources
#-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing
#-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
endif
#CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes
# define any directories containing required header files
ifeq ($(PLATFORM),PLATFORM_RPI)
INCLUDES = -I. -I./screens -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
else
INCLUDES = -I. -I./screens -I../../src
INCLUDES = -I. -I../../src
# external libraries headers
# GLFW3
INCLUDES += -I../../external/glfw3/include
# GLEW
INCLUDES += -I../../external/glew/include
# OpenAL Soft
INCLUDES += -I../../external/openal_soft/include
endif
# define library paths containing required libs
LFLAGS = -L. -L../../src -L/opt/vc/lib
ifeq ($(PLATFORM),PLATFORM_RPI)
LFLAGS = -L. -L../../src -L/opt/vc/lib
else
LFLAGS = -L. -L../../src
# external libraries to link with
# GLFW3
LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
ifneq ($(PLATFORM_OS),OSX)
# OpenAL Soft
LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
# GLEW
LFLAGS += -L../../external/glew/lib/$(LIBPATH)
endif
endif
# define any libraries to link into executable
# if you want to link libraries (libname.so or libname.a), use the -lname
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),LINUX)
# libraries for Debian GNU/Linux desktop compiling
# requires the following packages:
# libopenal-dev libglew-dev libegl1-mesa-dev
LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lm -pthread
else
ifeq ($(PLATFORM_OS),OSX)
# libraries for OS X 10.9 desktop compiling
# requires the following packages:
# libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
LIBS = -lraylib -lglfw -framework OpenGL -framework OpenAl -framework Cocoa
else
# libraries for Windows desktop compiling
# NOTE: GLFW3 and OpenAL Soft libraries should be installed
LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32
endif
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
# libraries for Raspberry Pi compiling
# NOTE: OpenAL Soft library should be installed (libopenal1 package)
LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal
else
# libraries for Windows desktop compiling
# NOTE: GLFW3 and OpenAL Soft libraries should be installed
LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
LIBS = ../../src/libraylib.bc
endif
# define additional parameters and flags for windows
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),WINDOWS)
# resources file contains windows exe icon
# -Wl,--subsystem,windows hides the console window
WINFLAGS = ../../src/resources -Wl,--subsystem,windows
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
EXT = .html
endif
# define all screen object files required
SCREENS = \
screens/screen_logo.o \
@ -80,7 +164,7 @@ default: standard_game
# compile template - standard_game
standard_game: standard_game.c $(SCREENS)
$(CC) -o $@ $< $(SCREENS) $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
$(CC) -o $@$(EXT) $< $(SCREENS) $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
# compile screen LOGO
screens/screen_logo.o: screens/screen_logo.c
@ -104,11 +188,24 @@ screens/screen_ending.o: screens/screen_ending.c
# clean everything
clean:
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),OSX)
find . -type f -perm +ugo+x -delete
rm -f *.o
else
ifeq ($(PLATFORM_OS),LINUX)
find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f
else
del *.o *.exe
endif
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
rm -f screens/*.o
# find . -executable -delete
else
del screens/*.o *.exe
find . -type f -executable -delete
rm -f *.o
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
del *.o *.html *.js
endif
@echo Cleaning done