From 7c3628976808a20ce9bcac046c4b88bffd475241 Mon Sep 17 00:00:00 2001 From: Constantine Tarasenkov Date: Fri, 4 Sep 2015 15:38:14 +0300 Subject: Fix compiling on Linux --- src/gestures.c | 3 ++- src/makefile | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gestures.c b/src/gestures.c index 27e3830a..4cb61222 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -37,6 +37,7 @@ #if defined(_WIN32) //#include #elif defined(__linux) + #include // Declares storage size of ‘now’ #include // Used for clock functions #endif @@ -659,4 +660,4 @@ static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent return 1; } -#endif \ No newline at end of file +#endif diff --git a/src/makefile b/src/makefile index da57c2d2..a42bf060 100644 --- a/src/makefile +++ b/src/makefile @@ -73,7 +73,7 @@ endif ifeq ($(PLATFORM),PLATFORM_RPI) CFLAGS = -O1 -Wall -std=gnu99 -fgnu89-inline else - CFLAGS = -O1 -Wall -std=c99 + CFLAGS = -O1 -Wall -std=gnu99 endif #CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes -- cgit v1.2.3 From 6e9d3eb0f99c8ce00b769dbd03cc011216b97068 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 23 Jan 2016 12:37:42 +0100 Subject: Review comments --- src/raylib.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index bebf4bc5..49a320d4 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -7,10 +7,10 @@ * Features: * Library written in plain C code (C99) * Uses C# PascalCase/camelCase notation -* Hardware accelerated with OpenGL (1.1, 3.3+ or ES2) +* Hardware accelerated with OpenGL (1.1, 3.3 or ES2) * Unique OpenGL abstraction layer [rlgl] -* Powerful fonts module with SpriteFonts support -* Multiple textures support, including DDS and mipmaps generation +* Powerful fonts module with SpriteFonts support (including AngelCode fonts and TTF) +* Multiple textures support, including compressed formats and mipmaps generation * Basic 3d support for Shapes, Models, Heightmaps and Billboards * Powerful math module for Vector and Matrix operations [raymath] * Audio loading and playing with streaming support (WAV and OGG) @@ -18,20 +18,21 @@ * * Used external libs: * GLFW3 (www.glfw.org) for window/context management and input -* GLEW for OpenGL extensions loading (3.3+ and ES2) +* GLAD for OpenGL extensions loading (3.3 Core profile) * stb_image (Sean Barret) for images loading (JPEG, PNG, BMP, TGA, PSD, GIF, HDR, PIC) * stb_image_write (Sean Barret) for image writting (PNG) * stb_vorbis (Sean Barret) for ogg audio loading +* stb_truetype (Sean Barret) for ttf fonts loading * OpenAL Soft for audio device/context management * tinfl for data decompression (DEFLATE algorithm) * * Some design decisions: -* 32bit Colors - All defined color are always RGBA -* SpriteFonts - All loaded sprite-font images are converted to RGBA and POT textures +* 32bit Colors - All defined color are always RGBA (struct Color is 4 byte) * One custom default font is loaded automatically when InitWindow() -* If using OpenGL 3.3+ or ES2, one default shader is loaded automatically (internally defined) +* If using OpenGL 3.3 or ES2, several vertex buffers (VAO/VBO) are created to manage lines-triangles-quads +* If using OpenGL 3.3 or ES2, two default shaders are loaded automatically (internally defined) * -* -- LICENSE (raylib v1.2, September 2014) -- +* -- LICENSE -- * * raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software: -- cgit v1.2.3 From 08da91047e8a2c593c3bc40b31c4796ae6cbb26d Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 23 Jan 2016 13:22:13 +0100 Subject: Some code tweaks --- src/audio.c | 17 +++++------------ src/core.c | 2 ++ src/models.c | 2 +- src/raylib.h | 2 +- src/shapes.c | 4 ++-- 5 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/audio.c b/src/audio.c index 6313c9dc..e40fdd41 100644 --- a/src/audio.c +++ b/src/audio.c @@ -166,15 +166,8 @@ void CloseAudioDevice(void) // Load sound to memory Sound LoadSound(char *fileName) { - Sound sound; - Wave wave; - - // Init some default values for wave... - wave.data = NULL; - wave.dataSize = 0; - wave.sampleRate = 0; - wave.bitsPerSample = 0; - wave.channels = 0; + Sound sound = { 0 }; + Wave wave = { 0 }; // NOTE: The entire file is loaded to memory to play it all at once (no-streaming) @@ -236,7 +229,7 @@ Sound LoadSound(char *fileName) // Load sound from wave data Sound LoadSoundFromWave(Wave wave) { - Sound sound; + Sound sound = { 0 }; if (wave.data != NULL) { @@ -290,7 +283,7 @@ Sound LoadSoundFromWave(Wave wave) Sound LoadSoundFromRES(const char *rresName, int resId) { // NOTE: rresName could be directly a char array with all the data!!! --> TODO - Sound sound; + Sound sound = { 0 }; #if defined(AUDIO_STANDALONE) TraceLog(WARNING, "Sound loading from rRES resource file not supported on standalone mode"); @@ -791,7 +784,7 @@ static Wave LoadWAV(const char *fileName) WaveFormat waveFormat; WaveData waveData; - Wave wave; + Wave wave = { 0 }; FILE *wavFile; wavFile = fopen(fileName, "rb"); diff --git a/src/core.c b/src/core.c index 9b068300..7a5de04e 100644 --- a/src/core.c +++ b/src/core.c @@ -1230,7 +1230,9 @@ Vector2 GetTouchPosition(void) return position; } +#endif +#if defined(PLATFORM_ANDROID) // Detect if a button has been pressed once bool IsButtonPressed(int button) { diff --git a/src/models.c b/src/models.c index 80d9a13a..e90f455a 100644 --- a/src/models.c +++ b/src/models.c @@ -557,7 +557,7 @@ void DrawGizmo(Vector3 position) // Load a 3d model (from file) Model LoadModel(const char *fileName) { - Model model; + Model model = { 0 }; Mesh mesh = { 0 }; // NOTE: Initialize default data for model in case loading fails, maybe a cube? diff --git a/src/raylib.h b/src/raylib.h index 49a320d4..73200556 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -18,7 +18,7 @@ * * Used external libs: * GLFW3 (www.glfw.org) for window/context management and input -* GLAD for OpenGL extensions loading (3.3 Core profile) +* GLAD for OpenGL extensions loading (3.3 Core profile, only PLATFORM_DESKTOP) * stb_image (Sean Barret) for images loading (JPEG, PNG, BMP, TGA, PSD, GIF, HDR, PIC) * stb_image_write (Sean Barret) for image writting (PNG) * stb_vorbis (Sean Barret) for ogg audio loading diff --git a/src/shapes.c b/src/shapes.c index a4761536..3b4be071 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -397,8 +397,8 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec) int recCenterX = rec.x + rec.width/2; int recCenterY = rec.y + rec.height/2; - float dx = abs(center.x - recCenterX); - float dy = abs(center.y - recCenterY); + float dx = fabs(center.x - recCenterX); + float dy = fabs(center.y - recCenterY); if (dx > (rec.width/2 + radius)) { return false; } if (dy > (rec.height/2 + radius)) { return false; } -- cgit v1.2.3 From 41959eeae10d7d01fbd2abc19ccae4fc65aae031 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 24 Jan 2016 19:17:08 +0100 Subject: Added support for mouse gestures (need testing) Mouse input is interpreted as touches to allow mouse gestures detection... and get an unified inputs system for all platforms! --- src/core.c | 42 ++++++++++++++++++++++++++++++++++++------ src/raylib.h | 5 +++-- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/core.c b/src/core.c index 7a5de04e..811f082a 100644 --- a/src/core.c +++ b/src/core.c @@ -1197,23 +1197,31 @@ bool IsGamepadButtonUp(int gamepad, int button) } #endif -#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) // Returns touch position X int GetTouchX(void) { +#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) return (int)touchPosition.x; +#else // PLATFORM_DESKTOP, PLATFORM_RPI + return GetMouseX(); +#endif } // Returns touch position Y int GetTouchY(void) { +#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) return (int)touchPosition.y; +#else // PLATFORM_DESKTOP, PLATFORM_RPI + return GetMouseY(); +#endif } // Returns touch position XY // TODO: touch position should be scaled depending on display size and render size Vector2 GetTouchPosition(void) { +#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) Vector2 position = touchPosition; if ((screenWidth > displayWidth) || (screenHeight > displayHeight)) @@ -1227,10 +1235,12 @@ Vector2 GetTouchPosition(void) position.x = position.x*((float)renderWidth/(float)displayWidth) - renderOffsetX/2; position.y = position.y*((float)renderHeight/(float)displayHeight) - renderOffsetY/2; } +#else // PLATFORM_DESKTOP, PLATFORM_RPI + Vector2 position = GetMousePosition(); +#endif return position; } -#endif #if defined(PLATFORM_ANDROID) // Detect if a button has been pressed once @@ -1633,6 +1643,28 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods) { currentMouseState[button] = action; + + // TODO: Test mouse gestures + +#define ENABLE_MOUSE_GESTURES +#if defined(ENABLE_MOUSE_GESTURES) + // Process mouse events as touches to be able to use mouse-gestures + GestureEvent gestureEvent; + + // Register touch actions + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_DOWN; + else if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_MOVE; + else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_UP; + + // Register touch points count + gestureEvent.pointCount = 1; + + // Register touch points position, only one point registered + gestureEvent.position[0] = GetMousePosition(); + + // Gesture data is sent to gestures system for processing + ProcessGestureEvent(gestureEvent); +#endif } // GLFW3 Char Key Callback, runs on key pressed (get char value) @@ -1976,11 +2008,9 @@ static bool GetMouseButtonStatus(int button) // Poll (store) all input events static void PollInputEvents(void) { -#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) - - // TODO: Remove this requirement... + // NOTE: Gestures update must be called every frame to reset gestures correctly + // because ProcessGestureEvent() is just called on an event, not every frame UpdateGestures(); -#endif #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) // Mouse input polling diff --git a/src/raylib.h b/src/raylib.h index 73200556..41fa3f7d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -598,13 +598,15 @@ 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) || defined(PLATFORM_WEB) int GetTouchX(void); // Returns touch position X (relative to screen size) int GetTouchY(void); // Returns touch position Y (relative to screen size) Vector2 GetTouchPosition(void); // Returns touch position XY (relative to screen size) + +#if defined(PLATFORM_ANDROID) bool IsButtonPressed(int button); // Detect if an android physic button has been pressed bool IsButtonDown(int button); // Detect if an android physic button is being pressed bool IsButtonReleased(int button); // Detect if an android physic button has been released +#endif //------------------------------------------------------------------------------------ // Gestures and Touch Handling Functions (Module: gestures) @@ -621,7 +623,6 @@ Vector2 GetGestureDragVector(void); // Get gesture drag vect int GetGestureHoldDuration(void); // Get gesture hold time in frames float GetGesturePinchDelta(void); // Get gesture pinch delta float GetGesturePinchAngle(void); // Get gesture pinch angle -#endif //------------------------------------------------------------------------------------ // Camera System Functions (Module: camera) -- cgit v1.2.3 From 3113a20390a1e4d81e9f832e7aa1d022afdb56d1 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 25 Jan 2016 11:12:31 +0100 Subject: Added bounding box calculation --- src/models.c | 29 ++++++++++++++++++----------- src/raylib.h | 2 ++ src/raymath.h | 26 ++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/models.c b/src/models.c index e90f455a..2d78963e 100644 --- a/src/models.c +++ b/src/models.c @@ -1275,6 +1275,20 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec rlDisableTexture(); } +// Draw a bounding box with wires +void DrawBoundingBox(BoundingBox box) +{ + Vector3 size; + + size.x = fabsf(box.max.x - box.min.x); + size.y = fabsf(box.max.y - box.min.y); + size.z = fabsf(box.max.z - box.min.z); + + Vector3 center = { box.min.x + size.x/2.0f, box.min.y + size.y/2.0f, box.min.z + size.z/2.0f }; + + DrawCubeWires(center, size.x, size.y, size.z, GREEN); +} + // Detect collision between two spheres bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB) { @@ -1401,10 +1415,8 @@ bool CheckCollisionRayBox(Ray ray, Vector3 minBBox, Vector3 maxBBox) return collision; } -// TODO: Useful function to check collision area? -//BoundingBox GetCollisionArea(BoundingBox box1, BoundingBox box2) - // Calculate mesh bounding box limits +// NOTE: minVertex and maxVertex should be transformed by model transform matrix (position, scale, rotate) BoundingBox CalculateBoundingBox(Mesh mesh) { // Get min and max vertex to construct bounds (AABB) @@ -1413,15 +1425,10 @@ BoundingBox CalculateBoundingBox(Mesh mesh) for (int i = 1; i < mesh.vertexCount; i++) { - // TODO: Compare min and max with previous vertex - //minVertex = Vector3.Min(minVertex, mesh.vertices[i]); - //maxVertex = Vector3.Max(maxVertex, mesh.vertices[i]); + minVertex = VectorMin(minVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); + maxVertex = VectorMax(maxVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); } - - // NOTE: For OBB, transform mesh by model transform matrix - //minVertex = VectorTransform(meshMin, mesh.transform); - //maxVertex = VectorTransform(meshMax, mesh.transform); - + // Create the bounding box BoundingBox box; box.min = minVertex; diff --git a/src/raylib.h b/src/raylib.h index 41fa3f7d..097c8865 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -765,10 +765,12 @@ void DrawModel(Model model, Vector3 position, float scale, Color tint); 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 DrawModelWiresEx(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters +void DrawBoundingBox(BoundingBox box); // Draw bounding box (wires) 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 +BoundingBox CalculateBoundingBox(Mesh mesh); // Calculate mesh bounding box limits bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB); // Detect collision between two spheres bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, Vector3 maxBBox2); // Detect collision between two boxes bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSphere, float radiusSphere); // Detect collision between box and sphere diff --git a/src/raymath.h b/src/raymath.h index f5448504..46fab356 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -126,6 +126,8 @@ RMDEF Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount); // Calculate lin RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal); // Calculate reflected vector to normal RMDEF void VectorTransform(Vector3 *v, Matrix mat); // Transforms a Vector3 by a given Matrix RMDEF Vector3 VectorZero(void); // Return a Vector3 init to zero +RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2); // Return min value for each pair of components +RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2); // Return max value for each pair of components //------------------------------------------------------------------------------------ // Functions Declaration to work with Matrix @@ -361,6 +363,30 @@ RMDEF Vector3 VectorZero(void) return zero; } +// Return min value for each pair of components +RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2) +{ + Vector3 result; + + result.x = fminf(vec1.x, vec2.x); + result.y = fminf(vec1.y, vec2.y); + result.z = fminf(vec1.z, vec2.z); + + return result; +} + +// Return max value for each pair of components +RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2) +{ + Vector3 result; + + result.x = fmaxf(vec1.x, vec2.x); + result.y = fmaxf(vec1.y, vec2.y); + result.z = fmaxf(vec1.z, vec2.z); + + return result; +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Matrix math //---------------------------------------------------------------------------------- -- cgit v1.2.3 From d0ff78e7f41be9884e786026ddd22ed53fc0943f Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 25 Jan 2016 13:39:23 +0100 Subject: Move Light struct to example --- examples/resources/shaders/phong.vs | 2 ++ examples/shaders_basic_lighting.c | 19 +++++++++++++++++++ src/core.c | 6 ++++++ src/rlgl.h | 3 --- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/examples/resources/shaders/phong.vs b/examples/resources/shaders/phong.vs index ee6d34bf..52cc2227 100644 --- a/examples/resources/shaders/phong.vs +++ b/examples/resources/shaders/phong.vs @@ -7,7 +7,9 @@ in vec3 vertexNormal; // Projection and model data uniform mat4 mvpMatrix; + uniform mat4 modelMatrix; +//uniform mat4 viewMatrix; // Not used // Attributes to fragment shader out vec2 fragTexCoord; diff --git a/examples/shaders_basic_lighting.c b/examples/shaders_basic_lighting.c index ba779b94..649eab74 100644 --- a/examples/shaders_basic_lighting.c +++ b/examples/shaders_basic_lighting.c @@ -14,6 +14,17 @@ #define SHININESS_SPEED 1.0f #define LIGHT_SPEED 0.25f +// Light type +typedef struct Light { + Vector3 position; + Vector3 direction; + float intensity; + float specIntensity; + Color diffuse; + Color ambient; + Color specular; +} Light; + int main() { // Initialization @@ -48,6 +59,10 @@ int main() int cameraLoc = GetShaderLocation(shader, "cameraPos"); int lightLoc = GetShaderLocation(shader, "lightPos"); + // Model and View matrix locations (required for lighting) + int modelLoc = GetShaderLocation(shader, "modelMatrix"); + //int viewLoc = GetShaderLocation(shader, "viewMatrix"); // Not used + // Light and material definitions Light light; Material matBlinn; @@ -82,6 +97,10 @@ int main() //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera position + // NOTE: Model transform can be set in model.transform or directly with params at draw... WATCH OUT! + SetShaderValueMatrix(shader, modelLoc, model.transform); // Send model matrix to shader + //SetShaderValueMatrix(shader, viewLoc, GetCameraMatrix(camera)); // Not used + // Glossiness input control if(IsKeyDown(KEY_UP)) matBlinn.glossiness += SHININESS_SPEED; else if(IsKeyDown(KEY_DOWN)) diff --git a/src/core.c b/src/core.c index 811f082a..df380552 100644 --- a/src/core.c +++ b/src/core.c @@ -938,6 +938,12 @@ Vector2 WorldToScreen(Vector3 position, Camera camera) return screenPosition; } +// Get transform matrix for camera +Matrix GetCameraMatrix(Camera camera) +{ + return MatrixLookAt(camera.position, camera.target, camera.up); +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions //---------------------------------------------------------------------------------- diff --git a/src/rlgl.h b/src/rlgl.h index 76cae987..64581db8 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -167,9 +167,6 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; // Uniforms int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) - - int modelLoc; // Model transformation matrix uniform location point (vertex shader) - int viewLoc; // View transformation matrix uniform location point (vertex shader) int tintColorLoc; // Color uniform location point (fragment shader) int mapDiffuseLoc; // Diffuse map texture uniform location point (fragment shader) -- cgit v1.2.3 From 99f99bea470ace9577950db8976aa092a678635d Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 25 Jan 2016 13:54:09 +0100 Subject: Simplified shader matrix uniforms --- src/raylib.h | 42 +++++++++++++++++++++--------------------- src/rlgl.c | 25 ++++++++++++++----------- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index 097c8865..48aeda54 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -358,12 +358,31 @@ typedef struct Shader { int mapSpecularLoc; // Specular map texture uniform location point (fragment shader) } Shader; +// Material type +// TODO: Redesign material-shaders-textures system +typedef struct Material { + //Shader shader; + + //Texture2D texDiffuse; // Diffuse texture + //Texture2D texNormal; // Normal texture + //Texture2D texSpecular; // Specular texture + + Color colDiffuse; + Color colAmbient; + Color colSpecular; + + float glossiness; + float normalDepth; +} Material; + // 3d Model type +// TODO: Replace shader/testure by material typedef struct Model { Mesh mesh; Matrix transform; Texture2D texture; // Only for OpenGL 1.1, on newer versions this should be in the shader Shader shader; + //Material material; } Model; // Ray type (useful for raycast) @@ -387,26 +406,6 @@ typedef struct Wave { short channels; } Wave; -// Light type -typedef struct Light { - Vector3 position; - Vector3 direction; - float intensity; - float specIntensity; - Color diffuse; - Color ambient; - Color specular; -} Light; - -// Material type -typedef struct Material { - Color diffuse; - Color ambient; - Color specular; - float glossiness; - float normalDepth; -} Material; - // Texture formats // NOTE: Support depends on OpenGL version and platform typedef enum { @@ -535,11 +534,12 @@ void BeginDrawing(void); // Setup drawing can void BeginDrawingEx(int blendMode, Shader shader, Matrix transform); // Setup drawing canvas with extended parameters void EndDrawing(void); // End canvas drawing and Swap Buffers (Double Buffering) -void Begin3dMode(Camera cam); // Initializes 3D mode for drawing (Camera setup) +void Begin3dMode(Camera camera); // Initializes 3D mode for drawing (Camera setup) void End3dMode(void); // Ends 3D mode and returns to default 2D orthographic mode Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position Vector2 WorldToScreen(Vector3 position, Camera camera); // Returns the screen space position from a 3d world space position +Matrix GetCameraMatrix(Camera camera); // Returns camera transform matrix (view matrix) void SetTargetFPS(int fps); // Set target FPS (maximum) float GetFPS(void); // Returns current FPS diff --git a/src/rlgl.c b/src/rlgl.c index ec909385..49300054 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1477,8 +1477,8 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r // NOTE: Drawing in OpenGL 3.3+, matrices are passed to shader // TODO: Reduce number of matrices passed to shaders, use only matMVP - glUniformMatrix4fv(model.shader.modelLoc, 1, false, MatrixToFloat(matModel)); - glUniformMatrix4fv(model.shader.viewLoc, 1, false, MatrixToFloat(matView)); + //glUniformMatrix4fv(model.material.shader.modelLoc, 1, false, MatrixToFloat(matModel)); + //glUniformMatrix4fv(model.material.shader.viewLoc, 1, false, MatrixToFloat(matView)); glUniformMatrix4fv(model.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); @@ -2201,9 +2201,6 @@ Shader LoadShader(char *vsFileName, char *fsFileName) // Get handles to GLSL uniform locations (vertex shader) shader.mvpLoc = glGetUniformLocation(shader.id, "mvpMatrix"); - - shader.modelLoc = glGetUniformLocation(shader.id, "modelMatrix"); - shader.viewLoc = glGetUniformLocation(shader.id, "viewMatrix"); // Get handles to GLSL uniform locations (fragment shader) shader.tintColorLoc = glGetUniformLocation(shader.id, "fragTintColor"); @@ -2503,6 +2500,18 @@ void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size) #endif } +// Set shader uniform value (matrix 4x4) +void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glUseProgram(shader.id); + + glUniformMatrix4fv(uniformLoc, 1, false, MatrixToFloat(mat)); + + glUseProgram(0); +#endif +} + // Default diffuse shader map texture assignment void SetShaderMapDiffuse(Shader *shader, Texture2D texture) { @@ -2741,9 +2750,6 @@ static Shader LoadDefaultShader(void) // Get handles to GLSL uniform locations (vertex shader) shader.mvpLoc = glGetUniformLocation(shader.id, "mvpMatrix"); - - shader.modelLoc = glGetUniformLocation(shader.id, "modelMatrix"); - shader.viewLoc = glGetUniformLocation(shader.id, "viewMatrix"); // Get handles to GLSL uniform locations (fragment shader) shader.tintColorLoc = -1; @@ -2822,9 +2828,6 @@ static Shader LoadSimpleShader(void) // Get handles to GLSL uniform locations (vertex shader) shader.mvpLoc = glGetUniformLocation(shader.id, "mvpMatrix"); - - shader.modelLoc = glGetUniformLocation(shader.id, "modelMatrix"); - shader.viewLoc = glGetUniformLocation(shader.id, "viewMatrix"); // Get handles to GLSL uniform locations (fragment shader) shader.tintColorLoc = glGetUniformLocation(shader.id, "fragTintColor"); -- cgit v1.2.3 From c21ca3ca1a3c68459cf75fc27bc73430228e3f0b Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 26 Jan 2016 20:26:46 +0100 Subject: Updated screenshots --- examples/core_3d_camera_free.png | Bin 25106 -> 25167 bytes examples/textures_formats_loading.png | Bin 79031 -> 125797 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/examples/core_3d_camera_free.png b/examples/core_3d_camera_free.png index afb5a7c5..17920620 100644 Binary files a/examples/core_3d_camera_free.png and b/examples/core_3d_camera_free.png differ diff --git a/examples/textures_formats_loading.png b/examples/textures_formats_loading.png index 4cdb2f13..6778080f 100644 Binary files a/examples/textures_formats_loading.png and b/examples/textures_formats_loading.png differ -- cgit v1.2.3 From ac475f46b9609235a9db4f3057271f609c39db7b Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 28 Jan 2016 10:03:37 +0100 Subject: Added touch points id to gestures Required by ProcessGestureEvent() --- src/camera.c | 2 +- src/core.c | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/camera.c b/src/camera.c index 4768b176..1e7ac2ff 100644 --- a/src/camera.c +++ b/src/camera.c @@ -2,7 +2,7 @@ * * raylib Camera System - Camera Modes Setup and Control Functions * -* Copyright (c) 2015 Marc Palau and Ramon Santamaria +* Copyright (c) 2015 Marc Palau and Ramon Santamaria (@raysan5) * * 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. diff --git a/src/core.c b/src/core.c index df380552..8b36e1ea 100644 --- a/src/core.c +++ b/src/core.c @@ -1916,6 +1916,10 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) // Register touch points count gestureEvent.pointCount = AMotionEvent_getPointerCount(event); + // Register touch points id DESKTOP + gestureEvent.pointerId[0] = AMotionEvent_getPointerId(event, 0); + gestureEvent.pointerId[1] = AMotionEvent_getPointerId(event, 1); + // Register touch points position // NOTE: Only two points registered gestureEvent.position[0] = (Vector2){ AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0) }; @@ -2474,6 +2478,10 @@ static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent // Register touch points count gestureEvent.pointCount = touchEvent->numTouches; + // Register touch points id WEB + gestureEvent.pointerId[0] = touchEvent->touches[0].identifier; + gestureEvent.pointerId[1] = touchEvent->touches[1].identifier; + // Register touch points position // NOTE: Only two points registered // TODO: Touch data should be scaled accordingly! -- cgit v1.2.3 From 5d6475c93b5b23837220124d5dabd1c39ab9a80a Mon Sep 17 00:00:00 2001 From: Constantine Tarasenkov Date: Fri, 29 Jan 2016 03:22:51 +0300 Subject: Fix raylib compiling on Linux --- src/makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/makefile b/src/makefile index 70fbca7c..1996907d 100644 --- a/src/makefile +++ b/src/makefile @@ -91,7 +91,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 camera.o gestures.o stb_vorbis.o +OBJS = core.o rlgl.o glad.o shapes.o text.o textures.o models.o audio.o utils.o camera.o gestures.o stb_vorbis.o # typing 'make' will invoke the first target entry in the file, # in this case, the 'default' target entry is raylib @@ -114,9 +114,9 @@ core.o: core.c rlgl.o: rlgl.c $(CC) -c rlgl.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) -# compile raymath module -raymath.o: raymath.c - $(CC) -c raymath.c $(CFLAGS) $(INCLUDES) +# compile glad module +raymath.o: glad.c + $(CC) -c glad.c $(CFLAGS) $(INCLUDES) # compile shapes module shapes.o: shapes.c -- cgit v1.2.3 From db5493b783fbdfd95813bc0c9ab253e3fd421e02 Mon Sep 17 00:00:00 2001 From: Constantine Tarasenkov Date: Fri, 29 Jan 2016 03:47:43 +0300 Subject: Fix shader versions --- examples/resources/shaders/shapes_base.vs | 2 +- examples/resources/shaders/shapes_grayscale.fs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/resources/shaders/shapes_base.vs b/examples/resources/shaders/shapes_base.vs index 1fd686be..ad272dc1 100644 --- a/examples/resources/shaders/shapes_base.vs +++ b/examples/resources/shaders/shapes_base.vs @@ -1,4 +1,4 @@ -#version 110 +#version 330 attribute vec3 vertexPosition; attribute vec2 vertexTexCoord; diff --git a/examples/resources/shaders/shapes_grayscale.fs b/examples/resources/shaders/shapes_grayscale.fs index 23ba9153..0698e1bf 100644 --- a/examples/resources/shaders/shapes_grayscale.fs +++ b/examples/resources/shaders/shapes_grayscale.fs @@ -1,4 +1,4 @@ -#version 110 +#version 330 uniform sampler2D texture0; varying vec2 fragTexCoord; -- cgit v1.2.3 From e6ad166ae34a35ee2a2f53359146ae58d1376dd6 Mon Sep 17 00:00:00 2001 From: Constantine Tarasenkov Date: Fri, 29 Jan 2016 08:02:53 +0300 Subject: --- src/makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/makefile b/src/makefile index 1996907d..4f65c440 100644 --- a/src/makefile +++ b/src/makefile @@ -115,7 +115,7 @@ rlgl.o: rlgl.c $(CC) -c rlgl.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) # compile glad module -raymath.o: glad.c +glad.o: glad.c $(CC) -c glad.c $(CFLAGS) $(INCLUDES) # compile shapes module -- cgit v1.2.3 From 13925f7bd4ad6b71f03a24024057819eb1032e05 Mon Sep 17 00:00:00 2001 From: Constantine Tarasenkov Date: Fri, 29 Jan 2016 09:09:18 +0300 Subject: Add functions to disable and enable cursor --- src/core.c | 18 ++++++++++++++++++ src/raylib.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/src/core.c b/src/core.c index 8b36e1ea..cf6fcf33 100644 --- a/src/core.c +++ b/src/core.c @@ -1097,6 +1097,24 @@ void ShowCursor() cursorHidden = false; } +// Disable mouse cursor +void DisableCursor() +{ +#if defined(PLATFORM_DESKTOP) + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); +#endif + cursorHidden = true; +} + +// Enable mouse cursor +void EnableCursor() +{ +#if defined(PLATFORM_DESKTOP) + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); +#endif + cursorHidden = false; +} + // Check if mouse cursor is hidden bool IsCursorHidden() { diff --git a/src/raylib.h b/src/raylib.h index 48aeda54..6c1a8999 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -586,6 +586,8 @@ int GetMouseWheelMove(void); // Returns mouse wheel m void ShowCursor(void); // Shows cursor void HideCursor(void); // Hides cursor +void EnableCursor(void); // Enables cursor +void DisableCursor(void); // Disables cursor bool IsCursorHidden(void); // Returns true if cursor is not visible #endif -- cgit v1.2.3 From 708e8c558cb843b5e4b071bc2b99102533bafaea Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 29 Jan 2016 07:26:06 -0800 Subject: Added a bunch of sample games Those games have been developed by students and ported to a common base template. Some of them still require some review to be consistent with each other (formatting, variables naming, code structure...) --- games/samples/arkanoid.c | 349 ++++++++++++++++ games/samples/asteroids.c | 596 ++++++++++++++++++++++++++ games/samples/asteroids_survival.c | 395 ++++++++++++++++++ games/samples/floppy.c | 246 +++++++++++ games/samples/gold_fever.c | 293 +++++++++++++ games/samples/gorilas.c | 571 +++++++++++++++++++++++++ games/samples/missile_commander.c | 539 ++++++++++++++++++++++++ games/samples/pang.c | 692 ++++++++++++++++++++++++++++++ games/samples/snake.c | 293 +++++++++++++ games/samples/space_invaders.c | 407 ++++++++++++++++++ games/samples/tetris.c | 835 +++++++++++++++++++++++++++++++++++++ 11 files changed, 5216 insertions(+) create mode 100644 games/samples/arkanoid.c create mode 100644 games/samples/asteroids.c create mode 100644 games/samples/asteroids_survival.c create mode 100644 games/samples/floppy.c create mode 100644 games/samples/gold_fever.c create mode 100644 games/samples/gorilas.c create mode 100644 games/samples/missile_commander.c create mode 100644 games/samples/pang.c create mode 100644 games/samples/snake.c create mode 100644 games/samples/space_invaders.c create mode 100644 games/samples/tetris.c diff --git a/games/samples/arkanoid.c b/games/samples/arkanoid.c new file mode 100644 index 00000000..f10f9383 --- /dev/null +++ b/games/samples/arkanoid.c @@ -0,0 +1,349 @@ +/******************************************************************************************* +* +* raylib - sample game: arkanoid +* +* Sample game Marc Palau and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include +#include +#include +#include + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- + +#define PLAYER_MAX_LIFE 5 +#define LINES_OF_BRICKS 5 +#define BRICKS_PER_LINE 20 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum GameScreen { LOGO, TITLE, GAMEPLAY, ENDING } GameScreen; + +typedef struct Player { + Vector2 position; + Vector2 size; + int life; +} Player; + +typedef struct Ball { + Vector2 position; + Vector2 speed; + int radius; + bool active; +} Ball; + +typedef struct Brick { + Vector2 position; + bool active; +} Brick; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter; +static bool gameOver; +static bool pause; + +static Player player; +static Ball ball; +static Brick brick[LINES_OF_BRICKS][BRICKS_PER_LINE]; +static Vector2 brickSize; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +// Additional module functions +static void UpdateBall(void); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: arkanoid"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + brickSize = (Vector2){ GetScreenWidth()/BRICKS_PER_LINE, 40 }; + + // Initialize player + player.position = (Vector2){ screenWidth/2, screenHeight*7/8 }; + player.size = (Vector2){ screenWidth/10, 20 }; + player.life = PLAYER_MAX_LIFE; + + // Initialize ball + ball.position = (Vector2){ screenWidth/2, screenHeight*7/8 - 30 }; + ball.speed = (Vector2){ 0, 0 }; + ball.radius = 7; + ball.active = false; + + // Initialize bricks + int initialDownPosition = 50; + + for (int i = 0; i < LINES_OF_BRICKS; i++) + { + for (int j = 0; j < BRICKS_PER_LINE; j++) + { + brick[i][j].position = (Vector2){ j*brickSize.x + brickSize.x/2, i*brickSize.y + initialDownPosition }; + brick[i][j].active = true; + } + } +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + // Player movement + if (IsKeyDown(KEY_LEFT)) player.position.x -= 5; + if ((player.position.x - player.size.x/2) <= 0) player.position.x = player.size.x/2; + if (IsKeyDown(KEY_RIGHT)) player.position.x += 5; + if ((player.position.x + player.size.x/2) >= screenWidth) player.position.x = screenWidth - player.size.x/2; + + // Launch ball + if (!ball.active) + { + if (IsKeyPressed(KEY_SPACE)) + { + ball.active = true; + ball.speed = (Vector2){ 0, -5 }; + } + } + + UpdateBall(); + + // Game over logic + if (player.life <= 0) gameOver = true; + else + { + gameOver = true; + + for (int i = 0; i < LINES_OF_BRICKS; i++) + { + for (int j = 0; j < BRICKS_PER_LINE; j++) + { + if (brick[i][j].active) gameOver = false; + } + } + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } + + +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // Draw player bar + DrawRectangle(player.position.x - player.size.x/2, player.position.y - player.size.y/2, player.size.x, player.size.y, BLACK); + + // Draw player lives + for (int i = 0; i < player.life; i++) DrawRectangle(20 + 40*i, screenHeight - 30, 35, 10, LIGHTGRAY); + + // Draw ball + DrawCircleV(ball.position, ball.radius, MAROON); + + // Draw bricks + for (int i = 0; i < LINES_OF_BRICKS; i++) + { + for (int j = 0; j < BRICKS_PER_LINE; j++) + { + if (brick[i][j].active) + { + if ((i + j) % 2 == 0) DrawRectangle(brick[i][j].position.x - brickSize.x/2, brick[i][j].position.y - brickSize.y/2, brickSize.x, brickSize.y, GRAY); + else DrawRectangle(brick[i][j].position.x - brickSize.x/2, brick[i][j].position.y - brickSize.y/2, brickSize.x, brickSize.y, DARKGRAY); + } + } + } + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} + +//-------------------------------------------------------------------------------------- +// Additional module functions +//-------------------------------------------------------------------------------------- +static void UpdateBall() +{ + // Update position + if (ball.active) + { + ball.position.x += ball.speed.x; + ball.position.y += ball.speed.y; + } + else + { + ball.position = (Vector2){ player.position.x, screenHeight*7/8 - 30 }; + } + + // Bounce in x + if (((ball.position.x + ball.radius) >= screenWidth) || ((ball.position.x - ball.radius) <= 0)) ball.speed.x *= -1; + + // Bounce in y + if ((ball.position.y - ball.radius) <= 0) ball.speed.y *= -1; + + // Ball reaches bottom of the screen + if ((ball.position.y + ball.radius) >= screenHeight) + { + ball.speed = (Vector2){ 0, 0 }; + ball.active = false; + + player.life--; + } + + // Collision logic: ball vs player + if (CheckCollisionCircleRec(ball.position, ball.radius, + (Rectangle){ player.position.x - player.size.x/2, player.position.y - player.size.y/2, player.size.x, player.size.y})) + { + if (ball.speed.y > 0) + { + ball.speed.y *= -1; + ball.speed.x = (ball.position.x - player.position.x)/(player.size.x/2)*5; + } + } + + // Collision logic: ball vs bricks + for (int i = 0; i < LINES_OF_BRICKS; i++) + { + for (int j = 0; j < BRICKS_PER_LINE; j++) + { + if (brick[i][j].active) + { + // Hit below + if (((ball.position.y - ball.radius) <= (brick[i][j].position.y + brickSize.y/2)) && + ((ball.position.y - ball.radius) > (brick[i][j].position.y + brickSize.y/2 + ball.speed.y)) && + ((fabs(ball.position.x - brick[i][j].position.x)) < (brickSize.x/2 + ball.radius*2/3)) && (ball.speed.y < 0)) + { + brick[i][j].active = false; + ball.speed.y *= -1; + } + // Hit above + else if (((ball.position.y + ball.radius) >= (brick[i][j].position.y - brickSize.y/2)) && + ((ball.position.y + ball.radius) < (brick[i][j].position.y - brickSize.y/2 + ball.speed.y)) && + ((fabs(ball.position.x - brick[i][j].position.x)) < (brickSize.x/2 + ball.radius*2/3)) && (ball.speed.y > 0)) + { + brick[i][j].active = false; + ball.speed.y *= -1; + } + // Hit left + else if (((ball.position.x + ball.radius) >= (brick[i][j].position.x - brickSize.x/2)) && + ((ball.position.x + ball.radius) < (brick[i][j].position.x - brickSize.x/2 + ball.speed.x)) && + ((fabs(ball.position.y - brick[i][j].position.y)) < (brickSize.y/2 + ball.radius*2/3)) && (ball.speed.x > 0)) + { + brick[i][j].active = false; + ball.speed.x *= -1; + } + // Hit right + else if (((ball.position.x - ball.radius) <= (brick[i][j].position.x + brickSize.x/2)) && + ((ball.position.x - ball.radius) > (brick[i][j].position.x + brickSize.x/2 + ball.speed.x)) && + ((fabs(ball.position.y - brick[i][j].position.y)) < (brickSize.y/2 + ball.radius*2/3)) && (ball.speed.x < 0)) + { + brick[i][j].active = false; + ball.speed.x *= -1; + } + } + } + } +} \ No newline at end of file diff --git a/games/samples/asteroids.c b/games/samples/asteroids.c new file mode 100644 index 00000000..676b0154 --- /dev/null +++ b/games/samples/asteroids.c @@ -0,0 +1,596 @@ +/******************************************************************************************* +* +* raylib - sample game: asteroids +* +* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define MAX_SPEED 6 +#define METEORS_SPEED 2 +#define NUM_SHOOTS 10 +#define NUM_BIG_METEORS 4 +#define NUM_MEDIUM_METEORS 8 +#define NUM_SMALL_METEORS 16 +#define SHIP_BASE_SIZE 20.0f + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- + +typedef struct Player { + Vector2 position; + Vector2 speed; + float acceleration; + float rotation; + Vector3 collider; + Color color; +} Player; + +typedef struct Shoot { + Vector2 position; + Vector2 speed; + float radius; + float rotation; + int lifeSpawn; + bool active; + Color color; +} Shoot; + +typedef struct BigMeteor { + Vector2 position; + Vector2 speed; + float radius; + bool active; + Color color; +} BigMeteor; + +typedef struct MediumMeteor { + Vector2 position; + Vector2 speed; + float radius; + bool active; + Color color; +} MediumMeteor; + +typedef struct SmallMeteor { + Vector2 position; + Vector2 speed; + float radius; + bool active; + Color color; +} SmallMeteor; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter; +static bool gameOver; +static bool pause; +static bool victory; + +// NOTE: Defined triangle is isosceles with common angles of 70 degrees. +static float shipHeight; + +static Player player; +static Shoot shoot[NUM_SHOOTS]; +static BigMeteor bigMeteor[NUM_BIG_METEORS]; +static MediumMeteor mediumMeteor[NUM_MEDIUM_METEORS]; +static SmallMeteor smallMeteor[NUM_SMALL_METEORS]; + +static int countMediumMeteors; +static int countSmallMeteors; +static int meteorsDestroyed; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +static void InitShoot(Shoot shoot); +static void DrawSpaceship(Vector2 position, float rotation, Color color); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: asteroids"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + int posx, posy; + int velx, vely; + bool correctRange = false; + victory = false; + pause = false; + + shipHeight = (SHIP_BASE_SIZE/2)/tanf(20*DEG2RAD); + + // Initialization player + player.position = (Vector2){screenWidth/2, screenHeight/2 - shipHeight/2}; + player.speed = (Vector2){0, 0}; + player.acceleration = 0; + player.rotation = 0; + player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12}; + player.color = LIGHTGRAY; + + meteorsDestroyed = 0; + + //InitShoot(&shoot); + + // Initialization shoot + for (int i = 0; i < NUM_SHOOTS; i++) + { + shoot[i].position = (Vector2){0, 0}; + shoot[i].speed = (Vector2){0, 0}; + shoot[i].radius = 2; + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + shoot[i].color = WHITE; + } + + for (int i = 0; i < NUM_BIG_METEORS; i++) + { + posx = GetRandomValue(0, screenWidth); + + while(!correctRange) + { + if (posx > screenWidth/2 - 150 && posx < screenWidth/2 + 150) posx = GetRandomValue(0, screenWidth); + else correctRange = true; + } + + correctRange = false; + + posy = GetRandomValue(0, screenHeight); + + while(!correctRange) + { + if (posy > screenHeight/2 - 150 && posy < screenHeight/2 + 150) posy = GetRandomValue(0, screenHeight); + else correctRange = true; + } + + bigMeteor[i].position = (Vector2){posx, posy}; + + correctRange = false; + velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + + while(!correctRange) + { + if (velx == 0 && vely == 0) + { + velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + } + else correctRange = true; + } + + bigMeteor[i].speed = (Vector2){velx, vely}; + bigMeteor[i].radius = 40; + bigMeteor[i].active = true; + bigMeteor[i].color = BLUE; + } + + for (int i = 0; i < NUM_MEDIUM_METEORS; i++) + { + mediumMeteor[i].position = (Vector2){-100, -100}; + mediumMeteor[i].speed = (Vector2){0,0}; + mediumMeteor[i].radius = 20; + mediumMeteor[i].active = false; + mediumMeteor[i].color = BLUE; + } + + for (int i = 0; i < NUM_SMALL_METEORS; i++) + { + smallMeteor[i].position = (Vector2){-100, -100}; + smallMeteor[i].speed = (Vector2){0,0}; + smallMeteor[i].radius = 10; + smallMeteor[i].active = false; + smallMeteor[i].color = BLUE; + } + + countMediumMeteors = 0; + countSmallMeteors = 0; +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + // Player logic + + // Rotation + if (IsKeyDown(KEY_LEFT)) player.rotation -= 5; + if (IsKeyDown(KEY_RIGHT)) player.rotation += 5; + + // Speed + player.speed.x = sin(player.rotation*DEG2RAD)*MAX_SPEED; + player.speed.y = cos(player.rotation*DEG2RAD)*MAX_SPEED; + + // Controller + if (IsKeyDown(KEY_UP)) + { + if (player.acceleration < 1) player.acceleration += 0.04f; + } + else + { + if (player.acceleration > 0) player.acceleration -= 0.02f; + else if (player.acceleration < 0) player.acceleration = 0; + } + if (IsKeyDown(KEY_DOWN)) + { + if (player.acceleration > 0) player.acceleration -= 0.04f; + else if (player.acceleration < 0) player.acceleration = 0; + } + + // Movement + player.position.x += (player.speed.x*player.acceleration); + player.position.y -= (player.speed.y*player.acceleration); + + // Wall behaviour for player + if (player.position.x > screenWidth + shipHeight) player.position.x = -(shipHeight); + else if (player.position.x < -(shipHeight)) player.position.x = screenWidth + shipHeight; + if (player.position.y > (screenHeight + shipHeight)) player.position.y = -(shipHeight); + else if (player.position.y < -(shipHeight)) player.position.y = screenHeight + shipHeight; + + // Activation of shoot + if (IsKeyPressed(KEY_SPACE)) + { + for (int i = 0; i < NUM_SHOOTS; i++) + { + if (!shoot[i].active) + { + shoot[i].position = (Vector2){ player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight) }; + shoot[i].active = true; + shoot[i].speed.x = 1.5*sin(player.rotation*DEG2RAD)*MAX_SPEED; + shoot[i].speed.y = 1.5*cos(player.rotation*DEG2RAD)*MAX_SPEED; + shoot[i].rotation = player.rotation; + break; + } + } + } + + // Shoot life timer + for (int i = 0; i < NUM_SHOOTS; i++) + { + if (shoot[i].active) shoot[i].lifeSpawn++; + } + + // Shot logic + for (int i = 0; i < NUM_SHOOTS; i++) + { + if (shoot[i].active) + { + // Movement + shoot[i].position.x += shoot[i].speed.x; + shoot[i].position.y -= shoot[i].speed.y; + + // Wall behaviour for shoot + if (shoot[i].position.x > screenWidth + shoot[i].radius) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + } + else if (shoot[i].position.x < 0 - shoot[i].radius) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + } + if (shoot[i].position.y > screenHeight + shoot[i].radius) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + } + else if (shoot[i].position.y < 0 - shoot[i].radius) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + } + + // Life of shoot + if (shoot[i].lifeSpawn >= 60) + { + shoot[i].position = (Vector2){0, 0}; + shoot[i].speed = (Vector2){0, 0}; + shoot[i].lifeSpawn = 0; + shoot[i].active = false; + } + } + } + + // Collision Player to meteors + player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12}; + + for (int a = 0; a < NUM_BIG_METEORS; a++) + { + if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, bigMeteor[a].position, bigMeteor[a].radius) && bigMeteor[a].active) gameOver = true; + } + + for (int a = 0; a < NUM_MEDIUM_METEORS; a++) + { + if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, mediumMeteor[a].position, mediumMeteor[a].radius) && mediumMeteor[a].active) gameOver = true; + } + + for (int a = 0; a < NUM_SMALL_METEORS; a++) + { + if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, smallMeteor[a].position, smallMeteor[a].radius) && smallMeteor[a].active) gameOver = true; + } + + // Meteor logic + for (int i = 0; i < NUM_BIG_METEORS; i++) + { + if (bigMeteor[i].active) + { + // movement + bigMeteor[i].position.x += bigMeteor[i].speed.x; + bigMeteor[i].position.y += bigMeteor[i].speed.y; + + // wall behaviour + if (bigMeteor[i].position.x > screenWidth + bigMeteor[i].radius) bigMeteor[i].position.x = -(bigMeteor[i].radius); + else if (bigMeteor[i].position.x < 0 - bigMeteor[i].radius) bigMeteor[i].position.x = screenWidth + bigMeteor[i].radius; + if (bigMeteor[i].position.y > screenHeight + bigMeteor[i].radius) bigMeteor[i].position.y = -(bigMeteor[i].radius); + else if (bigMeteor[i].position.y < 0 - bigMeteor[i].radius) bigMeteor[i].position.y = screenHeight + bigMeteor[i].radius; + } + } + + for (int i = 0; i < NUM_MEDIUM_METEORS; i++) + { + if (mediumMeteor[i].active) + { + // movement + mediumMeteor[i].position.x += mediumMeteor[i].speed.x; + mediumMeteor[i].position.y += mediumMeteor[i].speed.y; + + // wall behaviour + if (mediumMeteor[i].position.x > screenWidth + mediumMeteor[i].radius) mediumMeteor[i].position.x = -(mediumMeteor[i].radius); + else if (mediumMeteor[i].position.x < 0 - mediumMeteor[i].radius) mediumMeteor[i].position.x = screenWidth + mediumMeteor[i].radius; + if (mediumMeteor[i].position.y > screenHeight + mediumMeteor[i].radius) mediumMeteor[i].position.y = -(mediumMeteor[i].radius); + else if (mediumMeteor[i].position.y < 0 - mediumMeteor[i].radius) mediumMeteor[i].position.y = screenHeight + mediumMeteor[i].radius; + } + } + + for (int i = 0; i < NUM_SMALL_METEORS; i++) + { + if (smallMeteor[i].active) + { + // movement + smallMeteor[i].position.x += smallMeteor[i].speed.x; + smallMeteor[i].position.y += smallMeteor[i].speed.y; + + // wall behaviour + if (smallMeteor[i].position.x > screenWidth + smallMeteor[i].radius) smallMeteor[i].position.x = -(smallMeteor[i].radius); + else if (smallMeteor[i].position.x < 0 - smallMeteor[i].radius) smallMeteor[i].position.x = screenWidth + smallMeteor[i].radius; + if (smallMeteor[i].position.y > screenHeight + smallMeteor[i].radius) smallMeteor[i].position.y = -(smallMeteor[i].radius); + else if (smallMeteor[i].position.y < 0 - smallMeteor[i].radius) smallMeteor[i].position.y = screenHeight + smallMeteor[i].radius; + } + } + + // Collision behaviour + for (int i = 0; i < NUM_SHOOTS; i++) + { + if ((shoot[i].active)) + { + for (int a = 0; a < NUM_BIG_METEORS; a++) + { + if (bigMeteor[a].active && CheckCollisionCircles(shoot[i].position, shoot[i].radius, bigMeteor[a].position, bigMeteor[a].radius)) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + bigMeteor[a].active = false; + meteorsDestroyed++; + for (int j = 0; j < 2; j ++) + { + if (countMediumMeteors%2 == 0) + { + mediumMeteor[countMediumMeteors].position = (Vector2){bigMeteor[a].position.x, bigMeteor[a].position.y}; + mediumMeteor[countMediumMeteors].speed = (Vector2){cos(shoot[i].rotation*DEG2RAD)*METEORS_SPEED*-1, sin(shoot[i].rotation*DEG2RAD)*METEORS_SPEED*-1}; + } + else + { + mediumMeteor[countMediumMeteors].position = (Vector2){bigMeteor[a].position.x, bigMeteor[a].position.y}; + mediumMeteor[countMediumMeteors].speed = (Vector2){cos(shoot[i].rotation*DEG2RAD)*METEORS_SPEED, sin(shoot[i].rotation*DEG2RAD)*METEORS_SPEED}; + } + + mediumMeteor[countMediumMeteors].active = true; + countMediumMeteors ++; + } + //bigMeteor[a].position = (Vector2){-100, -100}; + bigMeteor[a].color = RED; + a = NUM_BIG_METEORS; + } + } + } + if ((shoot[i].active)) + { + for (int b = 0; b < NUM_MEDIUM_METEORS; b++) + { + if (mediumMeteor[b].active && CheckCollisionCircles(shoot[i].position, shoot[i].radius, mediumMeteor[b].position, mediumMeteor[b].radius)) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + mediumMeteor[b].active = false; + meteorsDestroyed++; + for (int j = 0; j < 2; j ++) + { + if (countSmallMeteors%2 == 0) + { + smallMeteor[countSmallMeteors].position = (Vector2){mediumMeteor[b].position.x, mediumMeteor[b].position.y}; + smallMeteor[countSmallMeteors].speed = (Vector2){cos(shoot[i].rotation*DEG2RAD)*METEORS_SPEED*-1, sin(shoot[i].rotation*DEG2RAD)*METEORS_SPEED*-1}; + } + else + { + smallMeteor[countSmallMeteors].position = (Vector2){mediumMeteor[b].position.x, mediumMeteor[b].position.y}; + smallMeteor[countSmallMeteors].speed = (Vector2){cos(shoot[i].rotation*DEG2RAD)*METEORS_SPEED, sin(shoot[i].rotation*DEG2RAD)*METEORS_SPEED}; + } + + smallMeteor[countSmallMeteors].active = true; + countSmallMeteors ++; + } + //mediumMeteor[b].position = (Vector2){-100, -100}; + mediumMeteor[b].color = GREEN; + b = NUM_MEDIUM_METEORS; + } + } + } + if ((shoot[i].active)) + { + for (int c = 0; c < NUM_SMALL_METEORS; c++) + { + if (smallMeteor[c].active && CheckCollisionCircles(shoot[i].position, shoot[i].radius, smallMeteor[c].position, smallMeteor[c].radius)) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + smallMeteor[c].active = false; + meteorsDestroyed++; + smallMeteor[c].color = YELLOW; + // smallMeteor[c].position = (Vector2){-100, -100}; + c = NUM_SMALL_METEORS; + } + } + } + } + } + + if (meteorsDestroyed == NUM_BIG_METEORS + NUM_MEDIUM_METEORS + NUM_SMALL_METEORS) victory = true; + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(DARKGRAY); + + if (!gameOver) + { + // Draw spaceship + Vector2 v1 = { player.position.x + sinf(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cosf(player.rotation*DEG2RAD)*(shipHeight) }; + Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2) }; + Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2) }; + DrawTriangleLines(v1, v2, v3, player.color); + + // Draw meteors + for (int i = 0; i < NUM_BIG_METEORS; i++) + { + if (bigMeteor[i].active) DrawCircleV(bigMeteor[i].position, bigMeteor[i].radius, bigMeteor[i].color); + else DrawCircleV(bigMeteor[i].position, bigMeteor[i].radius, Fade(bigMeteor[i].color, 0.25f)); + } + + for (int i = 0; i < NUM_MEDIUM_METEORS; i++) + { + if (mediumMeteor[i].active) DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, mediumMeteor[i].color); + else DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, Fade(mediumMeteor[i].color, 0.25f)); + } + + for (int i = 0; i < NUM_SMALL_METEORS; i++) + { + if (smallMeteor[i].active) DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, smallMeteor[i].color); + else DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, Fade(smallMeteor[i].color, 0.25f)); + } + + // Draw shoot + for (int i = 0; i < NUM_SHOOTS; i++) + { + if (shoot[i].active) DrawCircleV(shoot[i].position, shoot[i].radius, shoot[i].color); + } + + if (victory) DrawText("VICTORY", screenWidth/2 - MeasureText("VICTORY", 20)/2, screenHeight/2, 20, LIGHTGRAY); + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} \ No newline at end of file diff --git a/games/samples/asteroids_survival.c b/games/samples/asteroids_survival.c new file mode 100644 index 00000000..e2be9366 --- /dev/null +++ b/games/samples/asteroids_survival.c @@ -0,0 +1,395 @@ +/******************************************************************************************* +* +* raylib - sample game: asteroids survival +* +* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define MAX_SPEED 6 +#define METEORS_SPEED 2 +#define NUM_SHOOTS 10 +#define NUM_BIG_METEORS 4 +#define NUM_MEDIUM_METEORS 8 +#define NUM_SMALL_METEORS 16 +#define SHIP_BASE_SIZE 20.0f + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- + +typedef struct Player { + Vector2 position; + Vector2 speed; + float acceleration; + float rotation; + Vector3 collider; + Color color; +} Player; + +typedef struct MediumMeteor { + Vector2 position; + Vector2 speed; + float radius; + bool active; + Color color; +} MediumMeteor; + +typedef struct SmallMeteor { + Vector2 position; + Vector2 speed; + float radius; + bool active; + Color color; +} SmallMeteor; + + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter; +static bool gameOver; +static bool pause; + +// NOTE: Defined triangle is isosceles with common angles of 70 degrees. +static float shipHeight; + +static Player player; +static MediumMeteor mediumMeteor[NUM_MEDIUM_METEORS]; +static SmallMeteor smallMeteor[NUM_SMALL_METEORS]; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +static void DrawSpaceship(Vector2 position, float rotation, Color color); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: asteroids survival"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + int posx, posy; + int velx, vely; + bool correctRange = false; + + pause = false; + + framesCounter = 0; + + shipHeight = (SHIP_BASE_SIZE/2)/tanf(20*DEG2RAD); + + // Initialization player + player.position = (Vector2){screenWidth/2, screenHeight/2 - shipHeight/2}; + player.speed = (Vector2){0, 0}; + player.acceleration = 0; + player.rotation = 0; + player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12}; + player.color = LIGHTGRAY; + + for (int i = 0; i < NUM_MEDIUM_METEORS; i++) + { + posx = GetRandomValue(0, screenWidth); + + while(!correctRange) + { + if (posx > screenWidth/2 - 150 && posx < screenWidth/2 + 150) posx = GetRandomValue(0, screenWidth); + else correctRange = true; + } + + correctRange = false; + + posy = GetRandomValue(0, screenHeight); + + while(!correctRange) + { + if (posy > screenHeight/2 - 150 && posy < screenHeight/2 + 150) posy = GetRandomValue(0, screenHeight); + else correctRange = true; + } + + correctRange = false; + velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + + while(!correctRange) + { + if (velx == 0 && vely == 0) + { + velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + } + else correctRange = true; + } + mediumMeteor[i].position = (Vector2){posx, posy}; + mediumMeteor[i].speed = (Vector2){velx, vely}; + mediumMeteor[i].radius = 20; + mediumMeteor[i].active = true; + mediumMeteor[i].color = GREEN; + } + + for (int i = 0; i < NUM_SMALL_METEORS; i++) + { + posx = GetRandomValue(0, screenWidth); + + while(!correctRange) + { + if (posx > screenWidth/2 - 150 && posx < screenWidth/2 + 150) posx = GetRandomValue(0, screenWidth); + else correctRange = true; + } + + correctRange = false; + + posy = GetRandomValue(0, screenHeight); + + while(!correctRange) + { + if (posy > screenHeight/2 - 150 && posy < screenHeight/2 + 150) posy = GetRandomValue(0, screenHeight); + else correctRange = true; + } + + correctRange = false; + velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + + while(!correctRange) + { + if (velx == 0 && vely == 0) + { + velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + } + else correctRange = true; + } + smallMeteor[i].position = (Vector2){posx, posy}; + smallMeteor[i].speed = (Vector2){velx, vely}; + smallMeteor[i].radius = 10; + smallMeteor[i].active = true; + smallMeteor[i].color = YELLOW; + } +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + framesCounter++; + + // Player logic + + // Rotation + if (IsKeyDown(KEY_LEFT)) player.rotation -= 5; + if (IsKeyDown(KEY_RIGHT)) player.rotation += 5; + + // Speed + player.speed.x = sin(player.rotation*DEG2RAD)*MAX_SPEED; + player.speed.y = cos(player.rotation*DEG2RAD)*MAX_SPEED; + + // Controller + if (IsKeyDown(KEY_UP)) + { + if (player.acceleration < 1) player.acceleration += 0.04f; + } + else + { + if (player.acceleration > 0) player.acceleration -= 0.02f; + else if (player.acceleration < 0) player.acceleration = 0; + } + if (IsKeyDown(KEY_DOWN)) + { + if (player.acceleration > 0) player.acceleration -= 0.04f; + else if (player.acceleration < 0) player.acceleration = 0; + } + + // Movement + player.position.x += (player.speed.x*player.acceleration); + player.position.y -= (player.speed.y*player.acceleration); + + // Wall behaviour for player + if (player.position.x > screenWidth + shipHeight) player.position.x = -(shipHeight); + else if (player.position.x < -(shipHeight)) player.position.x = screenWidth + shipHeight; + if (player.position.y > (screenHeight + shipHeight)) player.position.y = -(shipHeight); + else if (player.position.y < -(shipHeight)) player.position.y = screenHeight + shipHeight; + + // Collision Player to meteors + player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12}; + + for (int a = 0; a < NUM_MEDIUM_METEORS; a++) + { + if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, mediumMeteor[a].position, mediumMeteor[a].radius) && mediumMeteor[a].active) gameOver = true; + } + + for (int a = 0; a < NUM_SMALL_METEORS; a++) + { + if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, smallMeteor[a].position, smallMeteor[a].radius) && smallMeteor[a].active) gameOver = true; + } + + // Meteor logic + + for (int i = 0; i < NUM_MEDIUM_METEORS; i++) + { + if (mediumMeteor[i].active) + { + // movement + mediumMeteor[i].position.x += mediumMeteor[i].speed.x; + mediumMeteor[i].position.y += mediumMeteor[i].speed.y; + + // wall behaviour + if (mediumMeteor[i].position.x > screenWidth + mediumMeteor[i].radius) mediumMeteor[i].position.x = -(mediumMeteor[i].radius); + else if (mediumMeteor[i].position.x < 0 - mediumMeteor[i].radius) mediumMeteor[i].position.x = screenWidth + mediumMeteor[i].radius; + if (mediumMeteor[i].position.y > screenHeight + mediumMeteor[i].radius) mediumMeteor[i].position.y = -(mediumMeteor[i].radius); + else if (mediumMeteor[i].position.y < 0 - mediumMeteor[i].radius) mediumMeteor[i].position.y = screenHeight + mediumMeteor[i].radius; + } + } + + for (int i = 0; i < NUM_SMALL_METEORS; i++) + { + if (smallMeteor[i].active) + { + // movement + smallMeteor[i].position.x += smallMeteor[i].speed.x; + smallMeteor[i].position.y += smallMeteor[i].speed.y; + + // wall behaviour + if (smallMeteor[i].position.x > screenWidth + smallMeteor[i].radius) smallMeteor[i].position.x = -(smallMeteor[i].radius); + else if (smallMeteor[i].position.x < 0 - smallMeteor[i].radius) smallMeteor[i].position.x = screenWidth + smallMeteor[i].radius; + if (smallMeteor[i].position.y > screenHeight + smallMeteor[i].radius) smallMeteor[i].position.y = -(smallMeteor[i].radius); + else if (smallMeteor[i].position.y < 0 - smallMeteor[i].radius) smallMeteor[i].position.y = screenHeight + smallMeteor[i].radius; + } + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(DARKGRAY); + + if (!gameOver) + { + // Draw spaceship + Vector2 v1 = { player.position.x + sinf(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cosf(player.rotation*DEG2RAD)*(shipHeight) }; + Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2) }; + Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2) }; + + DrawTriangleLines(v1, v2, v3, player.color); + + // Draw meteor + for (int i = 0;i < NUM_MEDIUM_METEORS; i++) + { + if (mediumMeteor[i].active) DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, mediumMeteor[i].color); + else DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, Fade(mediumMeteor[i].color, 0.25f)); + } + + for (int i = 0;i < NUM_SMALL_METEORS; i++) + { + if (smallMeteor[i].active) DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, smallMeteor[i].color); + else DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, Fade(smallMeteor[i].color, 0.25f)); + } + + DrawText(FormatText("SURVIVAL TIME: %.02f", (float)framesCounter/60), 10, 10, 20, WHITE); + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} \ No newline at end of file diff --git a/games/samples/floppy.c b/games/samples/floppy.c new file mode 100644 index 00000000..d66f5bbe --- /dev/null +++ b/games/samples/floppy.c @@ -0,0 +1,246 @@ +/******************************************************************************************* +* +* raylib - sample game: floppy +* +* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define MAX_TUBES 100 +#define FLOPPY_RADIUS 24 +#define TUBES_WIDTH 80 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct Floppy { + Vector2 position; + int radius; + Color color; +} Floppy; + +typedef struct Tubes { + Rectangle rec; + Color color; + bool active; +} Tubes; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter; +static bool gameOver; +static bool pause; +static int score; +static int hiScore = 0; + +static Floppy floppy; +static Tubes tubes[MAX_TUBES*2]; +static Vector2 tubesPos[MAX_TUBES]; +static int tubesSpeedX; +static bool superfx; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: floppy"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + floppy.radius = FLOPPY_RADIUS; + floppy.position = (Vector2){80, screenHeight/2 - floppy.radius}; + tubesSpeedX = 2; + + for (int i = 0; i < MAX_TUBES; i++) + { + tubesPos[i].x = 400 + 280*i; + tubesPos[i].y = -GetRandomValue(0, 120); + } + + for (int i = 0; i < MAX_TUBES*2; i += 2) + { + tubes[i].rec.x = tubesPos[i/2].x; + tubes[i].rec.y = tubesPos[i/2].y; + tubes[i].rec.width = TUBES_WIDTH; + tubes[i].rec.height = 255; + + tubes[i+1].rec.x = tubesPos[i/2].x; + tubes[i+1].rec.y = 600 + tubesPos[i/2].y - 255; + tubes[i+1].rec.width = TUBES_WIDTH; + tubes[i+1].rec.height = 255; + + tubes[i/2].active = true; + } + + score = 0; + + gameOver = false; + superfx = false; + pause = false; +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + for (int i = 0; i < MAX_TUBES; i++) tubesPos[i].x -= tubesSpeedX; + + for (int i = 0; i < MAX_TUBES*2; i += 2) + { + tubes[i].rec.x = tubesPos[i/2].x; + tubes[i+1].rec.x = tubesPos[i/2].x; + } + + if (IsKeyDown(KEY_SPACE) && !gameOver) floppy.position.y -= 3; + else floppy.position.y += 1; + + // Check Collisions + for (int i = 0; i < MAX_TUBES*2; i++) + { + if (CheckCollisionCircleRec(floppy.position, floppy.radius, tubes[i].rec)) + { + gameOver = true; + pause = false; + } + else if ((tubesPos[i/2].x < floppy.position.x) && tubes[i/2].active && !gameOver) + { + score += 100; + tubes[i/2].active = false; + + superfx = true; + + if (score > hiScore) hiScore = score; + } + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + DrawCircle(floppy.position.x, floppy.position.y, floppy.radius, BLUE); + + // Draw tubes + for (int i = 0; i < MAX_TUBES; i++) + { + DrawRectangle(tubes[i*2].rec.x, tubes[i*2].rec.y, tubes[i*2].rec.width, tubes[i*2].rec.height, RED); + DrawRectangle(tubes[i*2 + 1].rec.x, tubes[i*2 + 1].rec.y, tubes[i*2 + 1].rec.width, tubes[i*2 + 1].rec.height, RED); + } + + // Draw flashing fx (one frame only) + if (superfx) + { + DrawRectangle(0, 0, screenWidth, screenHeight, GOLD); + superfx = false; + } + + DrawText(FormatText("%04i", score), 20, 20, 40, PINK); + DrawText(FormatText("HI-SCORE: %04i", hiScore), 20, 70, 20, VIOLET); + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} \ No newline at end of file diff --git a/games/samples/gold_fever.c b/games/samples/gold_fever.c new file mode 100644 index 00000000..d4c0d99f --- /dev/null +++ b/games/samples/gold_fever.c @@ -0,0 +1,293 @@ +/******************************************************************************************* +* +* raylib - sample game: gold fever +* +* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct Player { + Vector2 position; + int radius; + Vector2 speed; + Color color; +} Player; + +typedef struct Enemy { + Vector2 position; + int radius; + int radiusBounds; + Vector2 speed; + bool moveRight; + Color colorBounds; + Color color; +} Enemy; + +typedef struct Points { + Vector2 position; + int radius; + int value; + bool active; + Color color; +} Points; + +typedef struct Exit { + Rectangle rec; + bool active; + bool save; + Color color; +} Exit; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter; +static bool gameOver; +static bool pause; +static int score; +static int hiScore = 0; + +static Player player; +static Enemy enemy; +static Points points; +static Exit exit; +static bool follow; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + + InitWindow(screenWidth, screenHeight, "sample game: gold fever"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + pause = false; + score = 0; + + player.position = (Vector2){50, 50}; + player.radius = 20; + player.speed = (Vector2){5, 5}; + player.color = DARKGRAY; + + enemy.position = (Vector2){screenWidth - 50, screenHeight/2}; + enemy.radius = 20; + enemy.radiusBounds = 150; + enemy.speed = (Vector2){3, 3}; + enemy.moveRight = true; + enemy.color = MAROON; + enemy.colorBounds = RED; + follow = false; + + points.radius = 10; + points.position = (Vector2){GetRandomValue(points.radius, screenWidth - points.radius), GetRandomValue(points.radius, screenHeight - points.radius)}; + points.value = 100; + points.active = true; + points.color = GOLD; + + exit.rec.width = 50; + exit.rec.height = 50; + exit.rec.x = GetRandomValue(0, screenWidth - exit.rec.width); + exit.rec.y = GetRandomValue(0, screenHeight - exit.rec.height); + exit.active = false; + exit.save = false; + exit.color = PINK; +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + //Control player + if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x; + if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x; + if (IsKeyDown(KEY_UP)) player.position.y -= player.speed.y; + if (IsKeyDown(KEY_DOWN)) player.position.y += player.speed.y; + + //wall behaviour player + if (player.position.x - player.radius <= 0) player.position.x = player.radius; + if (player.position.x + player.radius >= screenWidth) player.position.x = screenWidth - player.radius; + if (player.position.y - player.radius <= 0) player.position.y = player.radius; + if (player.position.y + player.radius >= screenHeight) player.position.y = screenHeight - player.radius; + + //IA Enemy + if ( (follow || CheckCollisionCircles(player.position, player.radius, enemy.position, enemy.radiusBounds)) && !exit.save) + { + if (player.position.x > enemy.position.x) enemy.position.x += enemy.speed.x; + if (player.position.x < enemy.position.x) enemy.position.x -= enemy.speed.x; + + if (player.position.y > enemy.position.y) enemy.position.y += enemy.speed.y; + if (player.position.y < enemy.position.y) enemy.position.y -= enemy.speed.y; + } + else + { + if (enemy.moveRight) enemy.position.x += enemy.speed.x; + else enemy.position.x -= enemy.speed.x; + } + + //wall behaviour enemy + if (enemy.position.x - enemy.radius <= 0) enemy.moveRight = true; + if (enemy.position.x + enemy.radius >= screenWidth) enemy.moveRight = false; + + if (enemy.position.x - enemy.radius <= 0) enemy.position.x = enemy.radius; + if (enemy.position.x + enemy.radius >= screenWidth) enemy.position.x = screenWidth - enemy.radius; + if (enemy.position.y - enemy.radius <= 0) enemy.position.y = enemy.radius; + if (enemy.position.y + enemy.radius >= screenHeight) enemy.position.y = screenHeight - enemy.radius; + + //Collisions + if (CheckCollisionCircles(player.position, player.radius, points.position, points.radius) && points.active) + { + follow = true; + points.active = false; + exit.active = true; + } + + if (CheckCollisionCircles(player.position, player.radius, enemy.position, enemy.radius) && !exit.save) + { + gameOver = true; + + if (hiScore < score) hiScore = score; + } + + if (CheckCollisionCircleRec(player.position, player.radius, exit.rec)) + { + follow = false; + + if (!points.active) + { + score += points.value; + points.active = true; + enemy.speed.x += 0.5; + enemy.speed.y += 0.5; + points.position = (Vector2){GetRandomValue(points.radius, screenWidth - points.radius), GetRandomValue(points.radius, screenHeight - points.radius)}; + } + + exit.save = true; + } + else exit.save = false; + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + if (follow) ClearBackground(RED); + + DrawCircleLines(enemy.position.x, enemy.position.y, enemy.radiusBounds, enemy.colorBounds); + DrawCircleV(enemy.position, enemy.radius, enemy.color); + + DrawCircleV(player.position, player.radius, player.color); + DrawCircleV(points.position, points.radius, points.color); + + if (exit.active) DrawRectangleRec(exit.rec, exit.color); + + DrawText(FormatText("SCORE: %04i", score), 10, 10, 20, GRAY); + DrawText(FormatText("HI-SCORE: %04i", hiScore), 300, 10, 20, GRAY); + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} \ No newline at end of file diff --git a/games/samples/gorilas.c b/games/samples/gorilas.c new file mode 100644 index 00000000..86fd3f5b --- /dev/null +++ b/games/samples/gorilas.c @@ -0,0 +1,571 @@ +/******************************************************************************************* +* +* raylib - sample game: gorilas +* +* Sample game Marc Palau and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include +#include +#include +#include + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define MAX_BUILDINGS 15 +#define MAX_EXPLOSIONS 200 +#define MAX_PLAYERS 2 + +#define BUILDING_RELATIVE_ERROR 30 // Building size random range % +#define BUILDING_MIN_RELATIVE_HEIGHT 20 // Minimum height in % of the screenHeight +#define BUILDING_MAX_RELATIVE_HEIGHT 60 // Maximum height in % of the screenHeight +#define BUILDING_MIN_GRAYSCALE_COLOR 120 // Minimum gray color for the buildings +#define BUILDING_MAX_GRAYSCALE_COLOR 200 // Maximum gray color for the buildings + +#define MIN_PLAYER_POSITION 5 // Minimum x position % +#define MAX_PLAYER_POSITION 20 // Maximum x position % + +#define GRAVITY 9.81f +#define DELTA_FPS 60 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct Player { + Vector2 position; + Vector2 size; + + Vector2 aimingPoint; + int aimingAngle; + int aimingPower; + + Vector2 previousPoint; + int previousAngle; + int previousPower; + + Vector2 impactPoint; + + bool isLeftTeam; // This player belongs to the left or to the right team + bool isPlayer; // If is a player or an AI + bool isAlive; +} Player; + +typedef struct Building { + Rectangle rectangle; + Color color; +} Building; + +typedef struct Explosion { + Vector2 position; + int radius; + bool active; +} Explosion; + +typedef struct Ball { + Vector2 position; + Vector2 speed; + int radius; + bool active; +} Ball; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static bool gameOver = false; +static bool pause = false; + +static Player player[MAX_PLAYERS]; +static Building building[MAX_BUILDINGS]; +static Explosion explosion[MAX_EXPLOSIONS]; +static Ball ball; + +static int playerTurn = 0; +static bool ballOnAir = false; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +// Additional module functions +static void InitBuildings(void); +static void InitPlayers(void); +static bool UpdatePlayer(int playerTurn); +static bool UpdateBall(int playerTurn); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: gorilas"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + // Init shoot + ball.radius = 10; + ballOnAir = false; + ball.active = false; + + InitBuildings(); + InitPlayers(); + + // Init explosions + for (int i = 0; i < MAX_EXPLOSIONS; i++) + { + explosion[i].position = (Vector2){ 0.0f, 0.0f }; + explosion[i].radius = 30; + explosion[i].active = false; + } +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + if (!ballOnAir) ballOnAir = UpdatePlayer(playerTurn); // If we are aiming + else + { + if (UpdateBall(playerTurn)) // If collision + { + // Game over logic + bool leftTeamAlive = false; + bool rightTeamAlive = false; + + for (int i = 0; i < MAX_PLAYERS; i++) + { + if (player[i].isAlive) + { + if (player[i].isLeftTeam) leftTeamAlive = true; + if (!player[i].isLeftTeam) rightTeamAlive = true; + } + } + + if (leftTeamAlive && rightTeamAlive) + { + ballOnAir = false; + ball.active = false; + + playerTurn++; + + if (playerTurn == MAX_PLAYERS) playerTurn = 0; + } + else + { + gameOver = true; + + // if (leftTeamAlive) left team wins + // if (rightTeamAlive) right team wins + } + } + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // Draw buildings + for (int i = 0; i < MAX_BUILDINGS; i++) DrawRectangleRec(building[i].rectangle, building[i].color); + + // Draw explosions + for (int i = 0; i < MAX_EXPLOSIONS; i++) + { + if (explosion[i].active) DrawCircle(explosion[i].position.x, explosion[i].position.y, explosion[i].radius, RAYWHITE); + } + + // Draw players + for (int i = 0; i < MAX_PLAYERS; i++) + { + if (player[i].isAlive) + { + if (player[i].isLeftTeam) DrawRectangle(player[i].position.x - player[i].size.x/2, player[i].position.y - player[i].size.y/2, + player[i].size.x, player[i].size.y, BLUE); + else DrawRectangle(player[i].position.x - player[i].size.x/2, player[i].position.y - player[i].size.y/2, + player[i].size.x, player[i].size.y, RED); + } + } + + // Draw ball + if (ball.active) DrawCircle(ball.position.x, ball.position.y, ball.radius, MAROON); + + // Draw the angle and the power of the aim, and the previous ones + if (!ballOnAir) + { + // Draw shot information + /* + if (player[playerTurn].isLeftTeam) + { + DrawText(FormatText("Previous Point %i, %i", (int)player[playerTurn].previousPoint.x, (int)player[playerTurn].previousPoint.y), 20, 20, 20, DARKBLUE); + DrawText(FormatText("Previous Angle %i", player[playerTurn].previousAngle), 20, 50, 20, DARKBLUE); + DrawText(FormatText("Previous Power %i", player[playerTurn].previousPower), 20, 80, 20, DARKBLUE); + DrawText(FormatText("Aiming Point %i, %i", (int)player[playerTurn].aimingPoint.x, (int)player[playerTurn].aimingPoint.y), 20, 110, 20, DARKBLUE); + DrawText(FormatText("Aiming Angle %i", player[playerTurn].aimingAngle), 20, 140, 20, DARKBLUE); + DrawText(FormatText("Aiming Power %i", player[playerTurn].aimingPower), 20, 170, 20, DARKBLUE); + } + else + { + DrawText(FormatText("Previous Point %i, %i", (int)player[playerTurn].previousPoint.x, (int)player[playerTurn].previousPoint.y), screenWidth*3/4, 20, 20, DARKBLUE); + DrawText(FormatText("Previous Angle %i", player[playerTurn].previousAngle), screenWidth*3/4, 50, 20, DARKBLUE); + DrawText(FormatText("Previous Power %i", player[playerTurn].previousPower), screenWidth*3/4, 80, 20, DARKBLUE); + DrawText(FormatText("Aiming Point %i, %i", (int)player[playerTurn].aimingPoint.x, (int)player[playerTurn].aimingPoint.y), screenWidth*3/4, 110, 20, DARKBLUE); + DrawText(FormatText("Aiming Angle %i", player[playerTurn].aimingAngle), screenWidth*3/4, 140, 20, DARKBLUE); + DrawText(FormatText("Aiming Power %i", player[playerTurn].aimingPower), screenWidth*3/4, 170, 20, DARKBLUE); + } + */ + + // Draw aim + if (player[playerTurn].isLeftTeam) + { + // Previous aiming + DrawTriangle((Vector2){ player[playerTurn].position.x - player[playerTurn].size.x/4, player[playerTurn].position.y - player[playerTurn].size.y/4 }, + (Vector2){ player[playerTurn].position.x + player[playerTurn].size.x/4, player[playerTurn].position.y + player[playerTurn].size.y/4 }, + player[playerTurn].previousPoint, GRAY); + + // Actual aiming + DrawTriangle((Vector2){ player[playerTurn].position.x - player[playerTurn].size.x/4, player[playerTurn].position.y - player[playerTurn].size.y/4 }, + (Vector2){ player[playerTurn].position.x + player[playerTurn].size.x/4, player[playerTurn].position.y + player[playerTurn].size.y/4 }, + player[playerTurn].aimingPoint, DARKBLUE); + } + else + { + // Previous aiming + DrawTriangle((Vector2){ player[playerTurn].position.x - player[playerTurn].size.x/4, player[playerTurn].position.y + player[playerTurn].size.y/4 }, + (Vector2){ player[playerTurn].position.x + player[playerTurn].size.x/4, player[playerTurn].position.y - player[playerTurn].size.y/4 }, + player[playerTurn].previousPoint, GRAY); + + // Actual aiming + DrawTriangle((Vector2){ player[playerTurn].position.x - player[playerTurn].size.x/4, player[playerTurn].position.y + player[playerTurn].size.y/4 }, + (Vector2){ player[playerTurn].position.x + player[playerTurn].size.x/4, player[playerTurn].position.y - player[playerTurn].size.y/4 }, + player[playerTurn].aimingPoint, MAROON); + } + } + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} + +//-------------------------------------------------------------------------------------- +// Additional module functions +//-------------------------------------------------------------------------------------- +static void InitBuildings(void) +{ + // Horizontal generation + int currentWidth = 0; + + // We make sure the absolute error randomly generated for each building, has as a minimum value the screenWidth. + // This way all the screen will be filled with buildings. Each building will have a different, random width. + + float relativeWidth = 100/(100 - BUILDING_RELATIVE_ERROR); + float buildingWidthMean = (screenWidth*relativeWidth/MAX_BUILDINGS) + 1; // We add one to make sure we will cover the whole screen. + + // Vertical generation + int currentHeighth = 0; + int grayLevel; + + // Creation + for (int i = 0; i < MAX_BUILDINGS; i++) + { + // Horizontal + building[i].rectangle.x = currentWidth; + building[i].rectangle.width = GetRandomValue(buildingWidthMean*(100 - BUILDING_RELATIVE_ERROR/2)/100 + 1, buildingWidthMean*(100 + BUILDING_RELATIVE_ERROR)/100); + + currentWidth += building[i].rectangle.width; + + // Vertical + currentHeighth = GetRandomValue(BUILDING_MIN_RELATIVE_HEIGHT, BUILDING_MAX_RELATIVE_HEIGHT); + building[i].rectangle.y = screenHeight - (screenHeight*currentHeighth/100); + building[i].rectangle.height = screenHeight*currentHeighth/100 + 1; + + // Color + grayLevel = GetRandomValue(BUILDING_MIN_GRAYSCALE_COLOR, BUILDING_MAX_GRAYSCALE_COLOR); + building[i].color = (Color){ grayLevel, grayLevel, grayLevel, 255 }; + } +} + +static void InitPlayers(void) +{ + for (int i = 0; i < MAX_PLAYERS; i++) + { + player[i].isAlive = true; + + // Decide the team of this player + if (i % 2 == 0) player[i].isLeftTeam = true; + else player[i].isLeftTeam = false; + + // Now there is no AI + player[i].isPlayer = true; + + // Set size, by default by now + player[i].size = (Vector2){ 40, 40 }; + + // Set position + if (player[i].isLeftTeam) player[i].position.x = GetRandomValue(screenWidth*MIN_PLAYER_POSITION/100, screenWidth*MAX_PLAYER_POSITION/100); + else player[i].position.x = screenWidth - GetRandomValue(screenWidth*MIN_PLAYER_POSITION/100, screenWidth*MAX_PLAYER_POSITION/100); + + for (int j = 0; j < MAX_BUILDINGS; j++) + { + if (building[j].rectangle.x > player[i].position.x) + { + // Set the player in the center of the building + player[i].position.x = building[j-1].rectangle.x + building[j-1].rectangle.width/2; + // Set the player at the top of the building + player[i].position.y = building[j-1].rectangle.y - player[i].size.y/2; + break; + } + } + + // Set statistics to 0 + player[i].aimingPoint = player[i].position; + player[i].previousAngle = 0; + player[i].previousPower = 0; + player[i].previousPoint = player[i].position; + player[i].aimingAngle = 0; + player[i].aimingPower = 0; + + player[i].impactPoint = (Vector2){ -100, -100 }; + } +} + +static bool UpdatePlayer(int playerTurn) +{ + // If we are aiming at the firing quadrant, we calculate the angle + if (GetMousePosition().y <= player[playerTurn].position.y) + { + // Left team + if (player[playerTurn].isLeftTeam && GetMousePosition().x >= player[playerTurn].position.x) + { + // Distance (calculating the fire power) + player[playerTurn].aimingPower = sqrt(pow(player[playerTurn].position.x - GetMousePosition().x, 2) + pow(player[playerTurn].position.y - GetMousePosition().y, 2)); + // Calculates the angle via arcsin + player[playerTurn].aimingAngle = asin((player[playerTurn].position.y - GetMousePosition().y)/player[playerTurn].aimingPower)*RAD2DEG; + // Point of the screen we are aiming at + player[playerTurn].aimingPoint = GetMousePosition(); + + // Ball fired + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + player[playerTurn].previousPoint = player[playerTurn].aimingPoint; + player[playerTurn].previousPower = player[playerTurn].aimingPower; + player[playerTurn].previousAngle = player[playerTurn].aimingAngle; + ball.position = player[playerTurn].position; + + return true; + } + } + // Right team + else if (!player[playerTurn].isLeftTeam && GetMousePosition().x <= player[playerTurn].position.x) + { + // Distance (calculating the fire power) + player[playerTurn].aimingPower = sqrt(pow(player[playerTurn].position.x - GetMousePosition().x, 2) + pow(player[playerTurn].position.y - GetMousePosition().y, 2)); + // Calculates the angle via arcsin + player[playerTurn].aimingAngle = asin((player[playerTurn].position.y - GetMousePosition().y)/player[playerTurn].aimingPower)*RAD2DEG; + // Point of the screen we are aiming at + player[playerTurn].aimingPoint = GetMousePosition(); + + // Ball fired + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + player[playerTurn].previousPoint = player[playerTurn].aimingPoint; + player[playerTurn].previousPower = player[playerTurn].aimingPower; + player[playerTurn].previousAngle = player[playerTurn].aimingAngle; + ball.position = player[playerTurn].position; + + return true; + } + } + else + { + player[playerTurn].aimingPoint = player[playerTurn].position; + player[playerTurn].aimingPower = 0; + player[playerTurn].aimingAngle = 0; + } + } + else + { + player[playerTurn].aimingPoint = player[playerTurn].position; + player[playerTurn].aimingPower = 0; + player[playerTurn].aimingAngle = 0; + } + + return false; +} + +static bool UpdateBall(int playerTurn) +{ + static int explosionNumber = 0; + + // Activate ball + if (!ball.active) + { + if (player[playerTurn].isLeftTeam) + { + ball.speed.x = cos(player[playerTurn].previousAngle*DEG2RAD)*player[playerTurn].previousPower*3/DELTA_FPS; + ball.speed.y = -sin(player[playerTurn].previousAngle*DEG2RAD)*player[playerTurn].previousPower*3/DELTA_FPS; + ball.active = true; + } + else + { + ball.speed.x = -cos(player[playerTurn].previousAngle*DEG2RAD)*player[playerTurn].previousPower*3/DELTA_FPS; + ball.speed.y = -sin(player[playerTurn].previousAngle*DEG2RAD)*player[playerTurn].previousPower*3/DELTA_FPS; + ball.active = true; + } + } + + ball.position.x += ball.speed.x; + ball.position.y += ball.speed.y; + ball.speed.y += GRAVITY/DELTA_FPS; + + // Collision + if (ball.position.x + ball.radius < 0) return true; + else if (ball.position.x - ball.radius > screenWidth) return true; + else + { + // Player collision + for (int i = 0; i < MAX_PLAYERS; i++) + { + if (CheckCollisionCircleRec(ball.position, ball.radius, (Rectangle){ player[i].position.x - player[i].size.x/2, player[i].position.y - player[i].size.y/2, + player[i].size.x, player[i].size.y })) + { + // We can't hit ourselves + if (i == playerTurn) return false; + else + { + // We set the impact point + player[playerTurn].impactPoint.x = ball.position.x; + player[playerTurn].impactPoint.y = ball.position.y + ball.radius; + + // We destroy the player + player[i].isAlive = false; + return true; + } + } + } + + // Building collision + // NOTE: We only check building collision if we are not inside an explosion + for (int i = 0; i < MAX_BUILDINGS; i++) + { + if (CheckCollisionCircles(ball.position, ball.radius, explosion[i].position, explosion[i].radius - ball.radius)) + { + return false; + } + } + + for (int i = 0; i < MAX_BUILDINGS; i++) + { + if (CheckCollisionCircleRec(ball.position, ball.radius, building[i].rectangle)) + { + // We set the impact point + player[playerTurn].impactPoint.x = ball.position.x; + player[playerTurn].impactPoint.y = ball.position.y + ball.radius; + + // We create an explosion + explosion[explosionNumber].position = player[playerTurn].impactPoint; + explosion[explosionNumber].active = true; + explosionNumber++; + + return true; + } + } + } + + return false; +} \ No newline at end of file diff --git a/games/samples/missile_commander.c b/games/samples/missile_commander.c new file mode 100644 index 00000000..6317c41a --- /dev/null +++ b/games/samples/missile_commander.c @@ -0,0 +1,539 @@ +/******************************************************************************************* +* +* raylib - sample game: missile commander +* +* Sample game Marc Palau and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include +#include +#include +#include + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define MAX_MISSILES 100 +#define MAX_INTERCEPTORS 30 +#define MAX_EXPLOSIONS 100 +#define LAUNCHERS_AMOUNT 3 // Not a variable, should not be changed +#define BUILDINGS_AMOUNT 6 // Not a variable, should not be changed + +#define LAUNCHER_SIZE 80 +#define BUILDING_SIZE 60 +#define EXPLOSION_RADIUS 40 + +#define MISSILE_SPEED 1 +#define MISSILE_LAUNCH_FRAMES 80 +#define INTERCEPTOR_SPEED 10 +#define EXPLOSION_INCREASE_TIME 90 // In frames +#define EXPLOSION_TOTAL_TIME 210 // In frames + +#define EXPLOSION_COLOR (Color){ 125, 125, 125, 125 } + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct Missile { + Vector2 origin; + Vector2 position; + Vector2 objective; + Vector2 speed; + + bool active; +} Missile; + +typedef struct Interceptor { + Vector2 origin; + Vector2 position; + Vector2 objective; + Vector2 speed; + + bool active; +} Interceptor; + +typedef struct Explosion { + Vector2 position; + float radiusMultiplier; + int frame; + bool active; +} Explosion; + +typedef struct Launcher { + Vector2 position; + bool active; +} Launcher; + +typedef struct Building { + Vector2 position; + bool active; +} Building; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter = 0; +static bool gameOver = false; +static bool pause = false; +static int score = 0; + +static Missile missile[MAX_MISSILES]; +static Interceptor interceptor[MAX_INTERCEPTORS]; +static Explosion explosion[MAX_EXPLOSIONS]; +static Launcher launcher[LAUNCHERS_AMOUNT]; +static Building building[BUILDINGS_AMOUNT]; +static int explosionIndex = 0; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +// Additional module functions +static void UpdateOutgoingFire(); +static void UpdateIncomingFire(); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: missile commander"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//-------------------------------------------------------------------------------------- +// Game Module Functions Definition +//-------------------------------------------------------------------------------------- + +// Initialize game variables +void InitGame(void) +{ + // Initialize missiles + for (int i = 0; i < MAX_MISSILES; i++) + { + missile[i].origin = (Vector2){ 0, 0 }; + missile[i].speed = (Vector2){ 0, 0 }; + missile[i].position = (Vector2){ 0, 0 }; + + missile[i].active = false; + } + + // Initialize interceptors + for (int i = 0; i < MAX_INTERCEPTORS; i++) + { + interceptor[i].origin = (Vector2){ 0, 0 }; + interceptor[i].speed = (Vector2){ 0, 0 }; + interceptor[i].position = (Vector2){ 0, 0 }; + + interceptor[i].active = false; + } + + // Initialize explosions + for (int i = 0; i < MAX_EXPLOSIONS; i++) + { + explosion[i].position = (Vector2){ 0, 0 }; + explosion[i].frame = 0; + explosion[i].active = false; + } + + // Initialize buildings and launchers + int sparcing = screenWidth/(LAUNCHERS_AMOUNT + BUILDINGS_AMOUNT + 1); + + // Buildings and launchers placing + launcher[0].position = (Vector2){ 1*sparcing, screenHeight - LAUNCHER_SIZE/2 }; + building[0].position = (Vector2){ 2*sparcing, screenHeight - BUILDING_SIZE/2 }; + building[1].position = (Vector2){ 3*sparcing, screenHeight - BUILDING_SIZE/2 }; + building[2].position = (Vector2){ 4*sparcing, screenHeight - BUILDING_SIZE/2 }; + launcher[1].position = (Vector2){ 5*sparcing, screenHeight - LAUNCHER_SIZE/2 }; + building[3].position = (Vector2){ 6*sparcing, screenHeight - BUILDING_SIZE/2 }; + building[4].position = (Vector2){ 7*sparcing, screenHeight - BUILDING_SIZE/2 }; + building[5].position = (Vector2){ 8*sparcing, screenHeight - BUILDING_SIZE/2 }; + launcher[2].position = (Vector2){ 9*sparcing, screenHeight - LAUNCHER_SIZE/2 }; + + // Buildings and launchers activation + for (int i = 0; i < LAUNCHERS_AMOUNT; i++) launcher[i].active = true; + for (int i = 0; i < BUILDINGS_AMOUNT; i++) building[i].active = true; + + // Initialize game variables + score = 0; +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + framesCounter++; + + static + float distance; + + // Interceptors update + for (int i = 0; i < MAX_INTERCEPTORS; i++) + { + if (interceptor[i].active) + { + // Update position + interceptor[i].position.x += interceptor[i].speed.x; + interceptor[i].position.y += interceptor[i].speed.y; + + // Distance to objective + distance = sqrt( pow(interceptor[i].position.x - interceptor[i].objective.x, 2) + + pow(interceptor[i].position.y - interceptor[i].objective.y, 2)); + + if (distance < INTERCEPTOR_SPEED) + { + // Interceptor dissapears + interceptor[i].active = false; + + // Explosion + explosion[explosionIndex].position = interceptor[i].position; + explosion[explosionIndex].active = true; + explosion[explosionIndex].frame = 0; + explosionIndex++; + if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0; + + break; + } + } + } + + // Missiles update + for (int i = 0; i < MAX_MISSILES; i++) + { + if (missile[i].active) + { + // Update position + missile[i].position.x += missile[i].speed.x; + missile[i].position.y += missile[i].speed.y; + + // Collision and missile out of bounds + if (missile[i].position.y > screenHeight) missile[i].active = false; + else + { + // CHeck collision with launchers + for (int j = 0; j < LAUNCHERS_AMOUNT; j++) + { + if (launcher[j].active) + { + if (CheckCollisionPointRec(missile[i].position, (Rectangle){ launcher[j].position.x - LAUNCHER_SIZE/2, launcher[j].position.y - LAUNCHER_SIZE/2, + LAUNCHER_SIZE, LAUNCHER_SIZE })) + { + // Missile dissapears + missile[i].active = false; + + // Explosion and destroy building + launcher[j].active = false; + + explosion[explosionIndex].position = missile[i].position; + explosion[explosionIndex].active = true; + explosion[explosionIndex].frame = 0; + explosionIndex++; + if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0; + + break; + } + } + } + + // CHeck collision with buildings + for (int j = 0; j < BUILDINGS_AMOUNT; j++) + { + if (building[j].active) + { + if (CheckCollisionPointRec(missile[i].position, (Rectangle){ building[j].position.x - BUILDING_SIZE/2, building[j].position.y - BUILDING_SIZE/2, + BUILDING_SIZE, BUILDING_SIZE })) + { + // Missile dissapears + missile[i].active = false; + + // Explosion and destroy building + building[j].active = false; + + explosion[explosionIndex].position = missile[i].position; + explosion[explosionIndex].active = true; + explosion[explosionIndex].frame = 0; + explosionIndex++; + if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0; + + break; + } + } + } + + // CHeck collision with explosions + for (int j = 0; j < MAX_EXPLOSIONS; j++) + { + if (explosion[j].active) + { + if (CheckCollisionPointCircle(missile[i].position, explosion[j].position, EXPLOSION_RADIUS*explosion[j].radiusMultiplier)) + { + // Missile dissapears and we earn 100 points + missile[i].active = false; + score += 100; + + explosion[explosionIndex].position = missile[i].position; + explosion[explosionIndex].active = true; + explosion[explosionIndex].frame = 0; + explosionIndex++; + if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0; + + break; + } + } + } + } + } + } + + // Explosions update + for (int i = 0; i < MAX_EXPLOSIONS; i++) + { + if (explosion[i].active) + { + explosion[i].frame++; + + if (explosion[i].frame <= EXPLOSION_INCREASE_TIME) explosion[i].radiusMultiplier = explosion[i].frame/(float)EXPLOSION_INCREASE_TIME; + else if (explosion[i].frame <= EXPLOSION_TOTAL_TIME) explosion[i].radiusMultiplier = 1 - (explosion[i].frame - (float)EXPLOSION_INCREASE_TIME)/(float)EXPLOSION_TOTAL_TIME; + else + { + explosion[i].frame = 0; + explosion[i].active = false; + } + } + } + + // Fire logic + UpdateOutgoingFire(); + UpdateIncomingFire(); + + // Game over logic + int checker = 0; + + for (int i = 0; i < LAUNCHERS_AMOUNT; i++) + { + if (!launcher[i].active) checker++; + if (checker == LAUNCHERS_AMOUNT) gameOver = true; + } + + checker = 0; + for (int i = 0; i < BUILDINGS_AMOUNT; i++) + { + if (!building[i].active) checker++; + if (checker == BUILDINGS_AMOUNT) gameOver = true; + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // Draw missiles + for (int i = 0; i < MAX_MISSILES; i++) + { + if (missile[i].active) + { + DrawLine(missile[i].origin.x, missile[i].origin.y, missile[i].position.x, missile[i].position.y, RED); + + if (framesCounter % 16 < 8) DrawCircle(missile[i].position.x, missile[i].position.y, 3, YELLOW); + } + } + + // Draw interceptors + for (int i = 0; i < MAX_INTERCEPTORS; i++) + { + if (interceptor[i].active) + { + DrawLine(interceptor[i].origin.x, interceptor[i].origin.y, interceptor[i].position.x, interceptor[i].position.y, GREEN); + + if (framesCounter % 16 < 8) DrawCircle(interceptor[i].position.x, interceptor[i].position.y, 3, BLUE); + } + } + + // Draw explosions + for (int i = 0; i < MAX_EXPLOSIONS; i++) + { + if (explosion[i].active) DrawCircle(explosion[i].position.x, explosion[i].position.y, EXPLOSION_RADIUS*explosion[i].radiusMultiplier, EXPLOSION_COLOR); + } + + // Draw buildings and launchers + for (int i = 0; i < LAUNCHERS_AMOUNT; i++) + { + if (launcher[i].active) DrawRectangle(launcher[i].position.x - LAUNCHER_SIZE/2, launcher[i].position.y - LAUNCHER_SIZE/2, LAUNCHER_SIZE, LAUNCHER_SIZE, GRAY); + } + + for (int i = 0; i < BUILDINGS_AMOUNT; i++) + { + if (building[i].active) DrawRectangle(building[i].position.x - BUILDING_SIZE/2, building[i].position.y - BUILDING_SIZE/2, BUILDING_SIZE, BUILDING_SIZE, LIGHTGRAY); + } + + // Draw score + DrawText(FormatText("SCORE %4i", score), 20, 20, 40, LIGHTGRAY); + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} + +//-------------------------------------------------------------------------------------- +// Additional module functions +//-------------------------------------------------------------------------------------- +static void UpdateOutgoingFire() +{ + static int interceptorNumber = 0; + int launcherShooting = 0; + + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) launcherShooting = 1; + if (IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) launcherShooting = 2; + if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) launcherShooting = 3; + + if (launcherShooting > 0 && launcher[launcherShooting - 1].active) + { + float module; + float sideX; + float sideY; + + // Activate the interceptor + interceptor[interceptorNumber].active = true; + + // Assign start position + interceptor[interceptorNumber].origin = launcher[launcherShooting - 1].position; + interceptor[interceptorNumber].position = interceptor[interceptorNumber].origin; + interceptor[interceptorNumber].objective = GetMousePosition(); + + // Calculate speed + module = sqrt( pow(interceptor[interceptorNumber].objective.x - interceptor[interceptorNumber].origin.x, 2) + + pow(interceptor[interceptorNumber].objective.y - interceptor[interceptorNumber].origin.y, 2)); + + sideX = (interceptor[interceptorNumber].objective.x - interceptor[interceptorNumber].origin.x)*INTERCEPTOR_SPEED/module; + sideY = (interceptor[interceptorNumber].objective.y - interceptor[interceptorNumber].origin.y)*INTERCEPTOR_SPEED/module; + + interceptor[interceptorNumber].speed = (Vector2){ sideX, sideY }; + + // Update + interceptorNumber++; + if (interceptorNumber == MAX_INTERCEPTORS) interceptorNumber = 0; + } +} + +static void UpdateIncomingFire() +{ + static int missileIndex = 0; + + // Launch missile + if (framesCounter % MISSILE_LAUNCH_FRAMES == 0) + { + float module; + float sideX; + float sideY; + + // Activate the missile + missile[missileIndex].active = true; + + // Assign start position + missile[missileIndex].origin = (Vector2){ GetRandomValue(20, screenWidth - 20), -10 }; + missile[missileIndex].position = missile[missileIndex].origin; + missile[missileIndex].objective = (Vector2){ GetRandomValue(20, screenWidth - 20), screenHeight + 10 }; + + // Calculate speed + module = sqrt( pow(missile[missileIndex].objective.x - missile[missileIndex].origin.x, 2) + + pow(missile[missileIndex].objective.y - missile[missileIndex].origin.y, 2)); + + sideX = (missile[missileIndex].objective.x - missile[missileIndex].origin.x)*MISSILE_SPEED/module; + sideY = (missile[missileIndex].objective.y - missile[missileIndex].origin.y)*MISSILE_SPEED/module; + + missile[missileIndex].speed = (Vector2){ sideX, sideY }; + + // Update + missileIndex++; + if (missileIndex == MAX_MISSILES) missileIndex = 0; + } +} \ No newline at end of file diff --git a/games/samples/pang.c b/games/samples/pang.c new file mode 100644 index 00000000..e7b2bb86 --- /dev/null +++ b/games/samples/pang.c @@ -0,0 +1,692 @@ +/******************************************************************************************* +* +* raylib - sample game: pang +* +* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define MAX_SPEED 5 +#define METEORS_SPEED 2 +#define NUM_SHOOTS 1 +#define NUM_BIG_METEORS 2 +#define NUM_MEDIUM_METEORS 4 +#define NUM_SMALL_METEORS 8 +#define SHIP_BASE_SIZE 20.0f + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- + +typedef struct Player { + Vector2 position; + Vector2 speed; + float rotation; + Vector3 collider; + Color color; +} Player; + +typedef struct Shoot { + Vector2 position; + Vector2 speed; + float radius; + float rotation; + int lifeSpawn; + bool active; + Color color; +} Shoot; + +typedef struct BigMeteor { + Vector2 position; + Vector2 speed; + float radius; + int points; + bool active; + Color color; +} BigMeteor; + +typedef struct MediumMeteor { + Vector2 position; + Vector2 speed; + float radius; + int points; + bool active; + Color color; +} MediumMeteor; + +typedef struct SmallMeteor { + Vector2 position; + Vector2 speed; + float radius; + int points; + bool active; + Color color; +} SmallMeteor; + +typedef struct Points { + char letter; + Vector2 position; + int value; + Color color; + float alpha; +} Points; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter; +static bool gameOver; +static bool pause; +static int score; + +static Player player; +static Shoot shoot[NUM_SHOOTS]; +static BigMeteor bigMeteor[NUM_BIG_METEORS]; +static MediumMeteor mediumMeteor[NUM_MEDIUM_METEORS]; +static SmallMeteor smallMeteor[NUM_SMALL_METEORS]; +static Points points[5]; + +// NOTE: Defined triangle is isosceles with common angles of 70 degrees. +static float shipHeight; +static float gravity; + +static int countMediumMeteors; +static int countSmallMeteors; +static int meteorsDestroyed; +static Vector2 linePosition; + +static bool victory; +static bool lose; +static bool awake; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +static void InitShoot(Shoot shoot); +static void DrawSpaceship(Vector2 position, float rotation, Color color); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + InitWindow(screenWidth, screenHeight, "sample game: pang"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +static void InitGame(void) +{ + int posx, posy; + int velx = 0; + int vely = 0; + + framesCounter = 0; + gameOver = false; + pause = false; + score = 0; + + victory = false; + lose = false; + awake = true; + gravity = 0.25f; + + linePosition = (Vector2){ 0.0f , 0.0f }; + shipHeight = (SHIP_BASE_SIZE/2)/tanf(20*DEG2RAD); + + // Initialization player + player.position = (Vector2){ screenWidth/2, screenHeight }; + player.speed = (Vector2){ MAX_SPEED, MAX_SPEED }; + player.rotation = 0; + player.collider = (Vector3){ player.position.x, player.position.y - shipHeight/2.0f, 12.0f }; + player.color = LIGHTGRAY; + + meteorsDestroyed = 0; + + // Initialize shoots + for (int i = 0; i < NUM_SHOOTS; i++) + { + shoot[i].position = (Vector2){ 0, 0 }; + shoot[i].speed = (Vector2){ 0, 0 }; + shoot[i].radius = 2; + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + shoot[i].color = WHITE; + } + + // Initialize big meteors + for (int i = 0; i < NUM_BIG_METEORS; i++) + { + bigMeteor[i].radius = 40.0f; + posx = GetRandomValue(0 + bigMeteor[i].radius, screenWidth - bigMeteor[i].radius); + posy = GetRandomValue(0 + bigMeteor[i].radius, screenHeight/2); + + bigMeteor[i].position = (Vector2){ posx, posy }; + + while ((velx == 0) || (vely == 0)) + { + velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + } + + bigMeteor[i].speed = (Vector2){ velx, vely }; + bigMeteor[i].points = 200; + bigMeteor[i].active = true; + bigMeteor[i].color = BLUE; + } + + // Initialize medium meteors + for (int i = 0; i < NUM_MEDIUM_METEORS; i++) + { + mediumMeteor[i].position = (Vector2){-100, -100}; + mediumMeteor[i].speed = (Vector2){0,0}; + mediumMeteor[i].radius = 20.0f; + mediumMeteor[i].points = 100; + mediumMeteor[i].active = false; + mediumMeteor[i].color = BLUE; + } + + // Initialize small meteors + for (int i = 0; i < NUM_SMALL_METEORS; i++) + { + smallMeteor[i].position = (Vector2){ -100, -100 }; + smallMeteor[i].speed = (Vector2){ 0, 0 }; + smallMeteor[i].radius = 10.0f; + smallMeteor[i].points = 50; + smallMeteor[i].active = false; + smallMeteor[i].color = BLUE; + } + + // Initialize animated points + for (int i = 0; i < 5; i++) + { + points[i].position = (Vector2){ 0, 0 }; + points[i].value = 0; + points[i].alpha = 0.0f; + } + + countMediumMeteors = 0; + countSmallMeteors = 0; +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + if (awake) + { + // Player logic + if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x; + if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x; + + // Wall behaviour for player + if (player.position.x + SHIP_BASE_SIZE/2 > screenWidth) player.position.x = screenWidth - SHIP_BASE_SIZE/2; + else if (player.position.x - SHIP_BASE_SIZE/2 < 0) player.position.x = 0 + SHIP_BASE_SIZE/2; + + // Activation of shoot + if (IsKeyPressed(KEY_SPACE)) + { + for (int i = 0; i < NUM_SHOOTS; i++) + { + if (!shoot[i].active) + { + shoot[i].position = (Vector2){ player.position.x, player.position.y - shipHeight }; + linePosition = (Vector2){ player.position.x, player.position.y}; + shoot[i].active = true; + shoot[i].speed.y = MAX_SPEED; + break; + } + } + } + + // Shoot life timer + for (int i = 0; i < NUM_SHOOTS; i++) + { + if (shoot[i].active) shoot[i].lifeSpawn++; + } + + // Shot logic + for (int i = 0; i < NUM_SHOOTS; i++) + { + if (shoot[i].active) + { + // Movement + shoot[i].position.y -= shoot[i].speed.y; + + // Wall behaviour for shoot + if (shoot[i].position.x > screenWidth + shoot[i].radius) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + } + else if (shoot[i].position.x < 0 - shoot[i].radius) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + } + + if (shoot[i].position.y > screenHeight + shoot[i].radius) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + } + else if (shoot[i].position.y < 0 - shoot[i].radius) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + } + + // Life of shoot + if (shoot[i].lifeSpawn >= 120) + { + shoot[i].position = (Vector2){0, 0}; + shoot[i].speed = (Vector2){0, 0}; + shoot[i].lifeSpawn = 0; + shoot[i].active = false; + } + } + } + + // Player collision with meteors + player.collider = (Vector3){player.position.x, player.position.y - shipHeight/2, 12}; + + for (int i = 0; i < NUM_BIG_METEORS; i++) + { + if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, bigMeteor[i].position, bigMeteor[i].radius) && bigMeteor[i].active) + { + gameOver = true; + } + } + + for (int i = 0; i < NUM_MEDIUM_METEORS; i++) + { + if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, mediumMeteor[i].position, mediumMeteor[i].radius) && mediumMeteor[i].active) + { + gameOver = true; + } + } + + for (int i = 0; i < NUM_SMALL_METEORS; i++) + { + if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, smallMeteor[i].position, smallMeteor[i].radius) && smallMeteor[i].active) + { + gameOver = true; + } + } + + // Meteor logic + for (int i = 0; i < NUM_BIG_METEORS; i++) + { + if (bigMeteor[i].active) + { + // movement + bigMeteor[i].position.x += bigMeteor[i].speed.x; + bigMeteor[i].position.y += bigMeteor[i].speed.y; + + // wall behaviour + if (((bigMeteor[i].position.x + bigMeteor[i].radius) >= screenWidth) || ((bigMeteor[i].position.x - bigMeteor[i].radius) <= 0)) bigMeteor[i].speed.x *= -1; + if ((bigMeteor[i].position.y - bigMeteor[i].radius) <= 0) bigMeteor[i].speed.y *= -1.5; + + if ((bigMeteor[i].position.y + bigMeteor[i].radius) >= screenHeight) + { + bigMeteor[i].speed.y *= -1; + bigMeteor[i].position.y = screenHeight - bigMeteor[i].radius; + } + + bigMeteor[i].speed.y += gravity; + } + } + + for (int i = 0; i < NUM_MEDIUM_METEORS; i++) + { + if (mediumMeteor[i].active) + { + // Movement logic + mediumMeteor[i].position.x += mediumMeteor[i].speed.x; + mediumMeteor[i].position.y += mediumMeteor[i].speed.y; + + // Wall behaviour + if (mediumMeteor[i].position.x + mediumMeteor[i].radius >= screenWidth || mediumMeteor[i].position.x - mediumMeteor[i].radius <= 0) mediumMeteor[i].speed.x *= -1; + if (mediumMeteor[i].position.y - mediumMeteor[i].radius <= 0) mediumMeteor[i].speed.y *= -1; + if (mediumMeteor[i].position.y + mediumMeteor[i].radius >= screenHeight) + { + mediumMeteor[i].speed.y *= -1; + mediumMeteor[i].position.y = screenHeight - mediumMeteor[i].radius; + } + + mediumMeteor[i].speed.y += gravity + 0.12f; + } + } + + for (int i = 0; i < NUM_SMALL_METEORS; i++) + { + if (smallMeteor[i].active) + { + // movement + smallMeteor[i].position.x += smallMeteor[i].speed.x; + smallMeteor[i].position.y += smallMeteor[i].speed.y; + + // wall behaviour + if (smallMeteor[i].position.x + smallMeteor[i].radius >= screenWidth || smallMeteor[i].position.x - smallMeteor[i].radius <= 0) smallMeteor[i].speed.x *= -1; + if (smallMeteor[i].position.y - smallMeteor[i].radius <= 0) smallMeteor[i].speed.y *= -1; + if (smallMeteor[i].position.y + smallMeteor[i].radius >= screenHeight) + { + smallMeteor[i].speed.y *= -1; + smallMeteor[i].position.y = screenHeight - smallMeteor[i].radius; + } + + smallMeteor[i].speed.y += gravity + 0.25f; + } + } + + // Collision behaviour + for (int i = 0; i < NUM_SHOOTS; i++) + { + if ((shoot[i].active)) + { + for (int a = 0; a < NUM_BIG_METEORS; a++) + { + if (bigMeteor[a].active && (bigMeteor[a].position.x - bigMeteor[a].radius <= linePosition.x && bigMeteor[a].position.x + bigMeteor[a].radius >= linePosition.x) + && (bigMeteor[a].position.y + bigMeteor[a].radius >= shoot[i].position.y)) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + bigMeteor[a].active = false; + meteorsDestroyed++; + score += bigMeteor[a].points; + + for (int z = 0; z < 5; z++) + { + if (points[z].alpha == 0.0f) + { + points[z].position = bigMeteor[a].position; + points[z].value = bigMeteor[a].points; + points[z].color = RED; + points[z].alpha = 1.0f; + z = 5; + } + } + + for (int j = 0; j < 2; j ++) + { + if ((countMediumMeteors%2) == 0) + { + mediumMeteor[countMediumMeteors].position = (Vector2){bigMeteor[a].position.x, bigMeteor[a].position.y}; + mediumMeteor[countMediumMeteors].speed = (Vector2){METEORS_SPEED*-1, METEORS_SPEED}; + } + else + { + mediumMeteor[countMediumMeteors].position = (Vector2){bigMeteor[a].position.x, bigMeteor[a].position.y}; + mediumMeteor[countMediumMeteors].speed = (Vector2){METEORS_SPEED, METEORS_SPEED}; + } + + mediumMeteor[countMediumMeteors].active = true; + countMediumMeteors ++; + } + + bigMeteor[a].color = RED; + a = NUM_BIG_METEORS; + } + } + } + + if ((shoot[i].active)) + { + for (int b = 0; b < NUM_MEDIUM_METEORS; b++) + { + if (mediumMeteor[b].active && (mediumMeteor[b].position.x - mediumMeteor[b].radius <= linePosition.x && mediumMeteor[b].position.x + mediumMeteor[b].radius >= linePosition.x) + && (mediumMeteor[b].position.y + mediumMeteor[b].radius >= shoot[i].position.y)) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + mediumMeteor[b].active = false; + meteorsDestroyed++; + score += mediumMeteor[b].points; + + for (int z = 0; z < 5; z++) + { + if (points[z].alpha == 0.0f) + { + points[z].position = mediumMeteor[b].position; + points[z].value = mediumMeteor[b].points; + points[z].color = GREEN; + points[z].alpha = 1.0f; + z = 5; + } + } + + for (int j = 0; j < 2; j ++) + { + if (countSmallMeteors%2 == 0) + { + smallMeteor[countSmallMeteors].position = (Vector2){mediumMeteor[b].position.x, mediumMeteor[b].position.y}; + smallMeteor[countSmallMeteors].speed = (Vector2){METEORS_SPEED*-1, METEORS_SPEED*-1}; + } + else + { + smallMeteor[countSmallMeteors].position = (Vector2){mediumMeteor[b].position.x, mediumMeteor[b].position.y}; + smallMeteor[countSmallMeteors].speed = (Vector2){METEORS_SPEED, METEORS_SPEED*-1}; + } + + smallMeteor[countSmallMeteors].active = true; + countSmallMeteors ++; + } + mediumMeteor[b].color = GREEN; + b = NUM_MEDIUM_METEORS; + } + } + } + + if ((shoot[i].active)) + { + for (int c = 0; c < NUM_SMALL_METEORS; c++) + { + if (smallMeteor[c].active && (smallMeteor[c].position.x - smallMeteor[c].radius <= linePosition.x && smallMeteor[c].position.x + smallMeteor[c].radius >= linePosition.x) + && (smallMeteor[c].position.y + smallMeteor[c].radius >= shoot[i].position.y)) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + smallMeteor[c].active = false; + meteorsDestroyed++; + smallMeteor[c].color = YELLOW; + score += smallMeteor[c].points; + + for (int z = 0; z < 5; z++) + { + if (points[z].alpha == 0.0f) + { + points[z].position = smallMeteor[c].position; + points[z].value = smallMeteor[c].points; + points[z].color = YELLOW; + points[z].alpha = 1.0f; + z = 5; + } + } + + c = NUM_SMALL_METEORS; + } + } + } + } + + for (int z = 0; z < 5; z++) + { + if (points[z].alpha > 0.0f) + { + points[z].position.y -= 2; + points[z].alpha -= 0.02f; + } + + if (points[z].alpha < 0.0f) points[z].alpha = 0.0f; + } + + if (meteorsDestroyed == (NUM_BIG_METEORS + NUM_MEDIUM_METEORS + NUM_SMALL_METEORS)) victory = true; + } + else + { + framesCounter++; + if (framesCounter%180 == 0) awake = false; + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(DARKGRAY); + + if (!gameOver) + { + // Draw player + Vector2 v1 = { player.position.x + sinf(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cosf(player.rotation*DEG2RAD)*(shipHeight) }; + Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2) }; + Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2) }; + DrawTriangleLines(v1, v2, v3, player.color); + + // Draw meteor + for (int i = 0;i < NUM_BIG_METEORS; i++) + { + if (bigMeteor[i].active) DrawCircleV(bigMeteor[i].position, bigMeteor[i].radius, bigMeteor[i].color); + else + { + DrawCircleV(bigMeteor[i].position, bigMeteor[i].radius, Fade(bigMeteor[i].color, 0.25f)); + //DrawText(FormatText("%i", bigMeteor[i].points), bigMeteor[i].position.x - MeasureText("200", 20)/2, bigMeteor[i].position.y - 10, 20, Fade(WHITE, 0.25f)); + } + } + + for (int i = 0;i < NUM_MEDIUM_METEORS; i++) + { + if (mediumMeteor[i].active) DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, mediumMeteor[i].color); + else + { + DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, Fade(mediumMeteor[i].color, 0.25f)); + //DrawText(FormatText("%i", mediumMeteor[i].points), mediumMeteor[i].position.x - MeasureText("100", 20)/2, mediumMeteor[i].position.y - 10, 20, Fade(WHITE, 0.25f)); + } + } + + for (int i = 0;i < NUM_SMALL_METEORS; i++) + { + if (smallMeteor[i].active) DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, smallMeteor[i].color); + else + { + DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, Fade(smallMeteor[i].color, 0.25f)); + //DrawText(FormatText("%i", smallMeteor[i].points), smallMeteor[i].position.x - MeasureText("50", 10)/2, smallMeteor[i].position.y - 5, 10, Fade(WHITE, 0.25f)); + } + } + + // Draw shoot + + for (int i = 0; i < NUM_SHOOTS; i++) + { + if (shoot[i].active) DrawLine(linePosition.x, linePosition.y, shoot[i].position.x, shoot[i].position.y, RED); + } + + for (int z = 0; z < 5; z++) + { + if (points[z].alpha > 0.0f) + { + DrawText(FormatText("+%i", points[z].value), points[z].position.x, points[z].position.y, 20, Fade(points[z].color, points[z].alpha)); + } + } + + // Draw Text + DrawText(FormatText("SCORE: %i", score), 10, 10, 20, LIGHTGRAY); + + if (victory) DrawText("VICTORY", screenWidth/2 - MeasureText("VICTORY", 40)/2, screenHeight/2 - 40, 40, LIGHTGRAY); + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, LIGHTGRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, LIGHTGRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} \ No newline at end of file diff --git a/games/samples/snake.c b/games/samples/snake.c new file mode 100644 index 00000000..ac2f6132 --- /dev/null +++ b/games/samples/snake.c @@ -0,0 +1,293 @@ +/******************************************************************************************* +* +* raylib - sample game: snake +* +* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define SNAKE_LENGTH 256 +#define SQUARE_SIZE 31 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct Snake { + Vector2 position; + Vector2 size; + Vector2 speed; + Color color; +} Snake; + +typedef struct Food { + Vector2 position; + Vector2 size; + bool active; + Color color; +} Food; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter; +static bool gameOver; +static bool pause; + +static Food fruit; +static Snake snake[SNAKE_LENGTH]; +static Vector2 snakePosition[SNAKE_LENGTH]; +static bool allowMove; +static Vector2 offset; +static int counterTail; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: snake"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + framesCounter = 0; + gameOver = false; + pause = false; + + counterTail = 1; + allowMove = false; + + offset.x = screenWidth%SQUARE_SIZE; + offset.y = screenHeight%SQUARE_SIZE; + + for (int i = 0; i < SNAKE_LENGTH; i++) + { + snake[i].position = (Vector2){ offset.x/2, offset.y/2 }; + snake[i].size = (Vector2){ SQUARE_SIZE, SQUARE_SIZE }; + snake[i].speed = (Vector2){ SQUARE_SIZE, 0 }; + + if (i == 0) snake[i].color = DARKBLUE; + else snake[i].color = BLUE; + } + + for (int i = 0; i < SNAKE_LENGTH; i++) + { + snakePosition[i] = (Vector2){ 0.0f, 0.0f }; + } + + fruit.size = (Vector2){ SQUARE_SIZE, SQUARE_SIZE }; + fruit.color = SKYBLUE; + fruit.active = false; +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + // control + if (IsKeyPressed(KEY_RIGHT) && (snake[0].speed.x == 0) && allowMove) + { + snake[0].speed = (Vector2){ SQUARE_SIZE, 0 }; + allowMove = false; + } + if (IsKeyPressed(KEY_LEFT) && (snake[0].speed.x == 0) && allowMove) + { + snake[0].speed = (Vector2){ -SQUARE_SIZE, 0 }; + allowMove = false; + } + if (IsKeyPressed(KEY_UP) && (snake[0].speed.y == 0) && allowMove) + { + snake[0].speed = (Vector2){ 0, -SQUARE_SIZE }; + allowMove = false; + } + if (IsKeyPressed(KEY_DOWN) && (snake[0].speed.y == 0) && allowMove) + { + snake[0].speed = (Vector2){ 0, SQUARE_SIZE }; + allowMove = false; + } + + // movement + for (int i = 0; i < counterTail; i++) snakePosition[i] = snake[i].position; + + if ((framesCounter%5) == 0) + { + for (int i = 0; i < counterTail; i++) + { + if (i == 0) + { + snake[0].position.x += snake[0].speed.x; + snake[0].position.y += snake[0].speed.y; + allowMove = true; + } + else snake[i].position = snakePosition[i-1]; + } + } + + // wall behaviour + if (((snake[0].position.x) > (screenWidth - offset.x)) || + ((snake[0].position.y) > (screenHeight - offset.y)) || + (snake[0].position.x < 0) || (snake[0].position.y < 0)) + { + gameOver = true; + } + + // collision with yourself + for (int i = 1; i < counterTail; i++) + { + if ((snake[0].position.x == snake[i].position.x) && (snake[0].position.y == snake[i].position.y)) gameOver = true; + } + + // TODO: review logic: fruit.position calculation + if (!fruit.active) + { + fruit.active = true; + fruit.position = (Vector2){ GetRandomValue(0, (screenWidth/SQUARE_SIZE) - 1)*SQUARE_SIZE + offset.x/2, GetRandomValue(0, (screenHeight/SQUARE_SIZE) - 1)*SQUARE_SIZE + offset.y/2 }; + + for (int i = 0; i < counterTail; i++) + { + while ((fruit.position.x == snake[i].position.x) && (fruit.position.y == snake[i].position.y)) + { + fruit.position = (Vector2){ GetRandomValue(0, (screenWidth/SQUARE_SIZE) - 1)*SQUARE_SIZE, GetRandomValue(0, (screenHeight/SQUARE_SIZE) - 1)*SQUARE_SIZE }; + i = 0; + } + } + } + + // collision + if (CheckCollisionRecs((Rectangle){(int)snake[0].position.x, (int)snake[0].position.y, (int)snake[0].size.x, (int)snake[0].size.y}, + (Rectangle){(int)fruit.position.x, (int)fruit.position.y, (int)fruit.size.x, (int)fruit.size.y})) + { + snake[counterTail].position = snakePosition[counterTail - 1]; + counterTail += 1; + fruit.active = false; + } + + framesCounter++; + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // Draw grid lines + for (int i = 0; i < screenWidth/SQUARE_SIZE + 1; i++) + { + DrawLineV((Vector2){SQUARE_SIZE*i + offset.x/2, offset.y/2}, (Vector2){SQUARE_SIZE*i + offset.x/2, screenHeight - offset.y/2}, LIGHTGRAY); + } + + for (int i = 0; i < screenHeight/SQUARE_SIZE + 1; i++) + { + DrawLineV((Vector2){offset.x/2, SQUARE_SIZE*i + offset.y/2}, (Vector2){screenWidth - offset.x/2, SQUARE_SIZE*i + offset.y/2}, LIGHTGRAY); + } + + // Draw snake + for (int i = 0; i < counterTail; i++) DrawRectangleV(snake[i].position, snake[i].size, snake[i].color); + + // Draw fruit to pick + DrawRectangleV(fruit.position, fruit.size, fruit.color); + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} \ No newline at end of file diff --git a/games/samples/space_invaders.c b/games/samples/space_invaders.c new file mode 100644 index 00000000..9f380628 --- /dev/null +++ b/games/samples/space_invaders.c @@ -0,0 +1,407 @@ +/******************************************************************************************* +* +* raylib - sample game: space invaders +* +* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define NUM_SHOOTS 50 +#define NUM_MAX_ENEMIES 50 +#define FIRST_WAVE 10 +#define SECOND_WAVE 20 +#define THIRD_WAVE 50 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum { FIRST = 0, SECOND, THIRD } enemyWave; + +typedef struct Player{ + Rectangle rec; + Vector2 speed; + Color color; +} Player; + +typedef struct Enemy{ + Rectangle rec; + Vector2 speed; + bool active; + Color color; +} Enemy; + +typedef struct Shoot{ + Rectangle rec; + Vector2 speed; + bool active; + Color color; +} Shoot; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter; +static bool gameOver; +static bool pause; +static int score; +static bool victory; + +static Player player; +static Enemy enemy[NUM_MAX_ENEMIES]; +static Shoot shoot[NUM_SHOOTS]; +static enemyWave wave; + +static int shootRate; +static float alpha; + +static int activeEnemies; +static int enemiesKill; +static bool smooth; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: space invaders"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + // Initialize game variables + shootRate = 0; + pause = false; + gameOver = false; + victory = false; + smooth = false; + wave = FIRST; + activeEnemies = FIRST_WAVE; + enemiesKill = 0; + score = 0; + alpha = 0; + + // Initialize player + player.rec.x = 20; + player.rec.y = 50; + player.rec.width = 10; + player.rec.height = 10; + player.speed.x = 5; + player.speed.y = 5; + player.color = BLACK; + + // Initialize enemies + for (int i = 0; i < NUM_MAX_ENEMIES; i++) + { + enemy[i].rec.width = 10; + enemy[i].rec.height = 10; + enemy[i].rec.x = GetRandomValue(screenWidth, screenWidth + 1000); + enemy[i].rec.y = GetRandomValue(0, screenHeight - enemy[i].rec.height); + enemy[i].speed.x = 5; + enemy[i].speed.y = 5; + enemy[i].active = true; + enemy[i].color = DARKGRAY; + } + + // Initialize shoots + for (int i = 0; i < NUM_SHOOTS; i++) + { + shoot[i].rec.x = player.rec.x; + shoot[i].rec.y = player.rec.y + player.rec.height/4; + shoot[i].rec.width = 10; + shoot[i].rec.height = 5; + shoot[i].speed.x = 7; + shoot[i].speed.y = 0; + shoot[i].active = false; + shoot[i].color = WHITE; + } +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + switch (wave) + { + case FIRST: + { + if (!smooth) + { + alpha += 0.02f; + + if (alpha >= 1.0f) smooth = true; + } + + if (smooth) alpha -= 0.02f; + + if (enemiesKill == activeEnemies) + { + enemiesKill = 0; + + for (int i = 0; i < activeEnemies; i++) + { + if (!enemy[i].active) enemy[i].active = true; + } + + activeEnemies = SECOND_WAVE; + wave = SECOND; + smooth = false; + alpha = 0.0f; + } + } break; + case SECOND: + { + if (!smooth) + { + alpha += 0.02f; + + if (alpha >= 1.0f) smooth = true; + } + + if (smooth) alpha -= 0.02f; + + if (enemiesKill == activeEnemies) + { + enemiesKill = 0; + + for (int i = 0; i < activeEnemies; i++) + { + if (!enemy[i].active) enemy[i].active = true; + } + + activeEnemies = THIRD_WAVE; + wave = THIRD; + smooth = false; + alpha = 0.0f; + } + } break; + case THIRD: + { + if (!smooth) + { + alpha += 0.02f; + + if (alpha >= 1.0f) smooth = true; + } + + if (smooth) alpha -= 0.02f; + + if (enemiesKill == activeEnemies) victory = true; + + } break; + default: break; + } + + // Player movement + if (IsKeyDown(KEY_RIGHT)) player.rec.x += player.speed.x; + if (IsKeyDown(KEY_LEFT)) player.rec.x -= player.speed.x; + if (IsKeyDown(KEY_UP)) player.rec.y -= player.speed.y; + if (IsKeyDown(KEY_DOWN)) player.rec.y += player.speed.y; + + // Player collision with enemy + for (int i = 0; i < activeEnemies; i++) + { + if (CheckCollisionRecs(player.rec, enemy[i].rec)) gameOver = true; + } + + // Enemy behaviour + for (int i = 0; i < activeEnemies; i++) + { + if (enemy[i].active) + { + enemy[i].rec.x -= enemy[i].speed.x; + + if (enemy[i].rec.x < 0) + { + enemy[i].rec.x = GetRandomValue(screenWidth, screenWidth + 1000); + enemy[i].rec.y = GetRandomValue(0, screenHeight - enemy[i].rec.height); + } + } + } + + // Wall behaviour + if (player.rec.x <= 0) player.rec.x = 0; + if (player.rec.x + player.rec.width >= screenWidth) player.rec.x = screenWidth - player.rec.width; + if (player.rec.y <= 0) player.rec.y = 0; + if (player.rec.y + player.rec.height >= screenHeight) player.rec.y = screenHeight - player.rec.height; + + //Shoot initialization + if (IsKeyDown(KEY_SPACE)) + { + shootRate += 5; + + for (int i = 0; i < NUM_SHOOTS; i++) + { + if (!shoot[i].active && shootRate%20 == 0) + { + shoot[i].rec.x = player.rec.x; + shoot[i].rec.y = player.rec.y + player.rec.height/4; + shoot[i].active = true; + break; + } + } + } + + // Shoot logic + for (int i = 0; i < NUM_SHOOTS; i++) + { + if (shoot[i].active) + { + // Movement + shoot[i].rec.x += shoot[i].speed.x; + + // Collision with enemy + for (int j = 0; j < activeEnemies; j++) + { + if (enemy[j].active) + { + if (CheckCollisionRecs(shoot[i].rec, enemy[j].rec)) + { + shoot[i].active = false; + enemy[j].active = false; + enemy[j].rec.x = GetRandomValue(screenWidth, screenWidth + 1000); + enemy[j].rec.y = GetRandomValue(0, screenHeight - enemy[j].rec.height); + shootRate = 0; + enemiesKill++; + score += 100; + } + + if (shoot[i].rec.x + shoot[i].rec.width >= screenWidth) + { + shoot[i].active = false; + shootRate = 0; + } + } + } + } + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(LIGHTGRAY); + + if (!gameOver) + { + DrawRectangleRec(player.rec, player.color); + + if (wave == FIRST) DrawText("FIRST WAVE", screenWidth/2 - MeasureText("FIRST WAVE", 40)/2, screenHeight/2 - 40, 40, Fade(BLACK, alpha)); + else if (wave == SECOND) DrawText("SECOND WAVE", screenWidth/2 - MeasureText("SECOND WAVE", 40)/2, screenHeight/2 - 40, 40, Fade(BLACK, alpha)); + else if (wave == THIRD) DrawText("THIRD WAVE", screenWidth/2 - MeasureText("THIRD WAVE", 40)/2, screenHeight/2 - 40, 40, Fade(BLACK, alpha)); + + for (int i = 0; i < activeEnemies; i++) + { + if (enemy[i].active) DrawRectangleRec(enemy[i].rec, enemy[i].color); + } + + for (int i = 0; i < NUM_SHOOTS; i++) + { + if (shoot[i].active) DrawRectangleRec(shoot[i].rec, shoot[i].color); + } + + DrawText(FormatText("%04i", score), 20, 20, 40, DARKGRAY); + + if (victory) DrawText("YOU WIN", screenWidth/2 - MeasureText("YOU WIN", 40)/2, screenHeight/2 - 40, 40, BLACK); + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} \ No newline at end of file diff --git a/games/samples/tetris.c b/games/samples/tetris.c new file mode 100644 index 00000000..8d550f3d --- /dev/null +++ b/games/samples/tetris.c @@ -0,0 +1,835 @@ +/******************************************************************************************* +* +* raylib - sample game: tetris +* +* Sample game Marc Palau and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include +#include +#include +#include + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define SQUARE_SIZE 30 + +#define GRID_HORIZONTAL_SIZE 12 +#define GRID_VERTICAL_SIZE 20 + +#define LATERAL_SPEED 10 +#define TURNING_SPEED 12 +#define FAST_FALL_AWAIT_COUNTER 30 + +#define FADING_TIME 33 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum GridSquare { EMPTY, MOVING, FULL, BLOCK, FADING } GridSquare; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 620; + +static bool gameOver = false; +static bool pause = false; + +// Matrices +static GridSquare grid [GRID_HORIZONTAL_SIZE][GRID_VERTICAL_SIZE]; +static GridSquare piece [4][4]; +static GridSquare incomingPiece [4][4]; + +// Theese variables keep track of the active piece position +static int piecePositionX = 0; +static int piecePositionY = 0; + +// Game parameters +static Color fadingColor; +//static int fallingSpeed; // In frames + +static bool beginPlay = true; // This var is only true at the begining of the game, used for the first matrix creations +static bool pieceActive = false; +static bool detection = false; +static bool lineToDelete = false; + +// Statistics +static int level = 1; +static int lines = 0; + +// Counters +static int gravityMovementCounter = 0; +static int lateralMovementCounter = 0; +static int turnMovementCounter = 0; +static int fastFallMovementCounter = 0; + +static int fadeLineCounter = 0; + +// Based on level +static int gravitySpeed = 30; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +// Additional module functions +static bool Createpiece(); +static void GetRandompiece(); +static void ResolveFallingMovement(); +static bool ResolveLateralMovement(); +static bool ResolveTurnMovement(); +static void CheckDetection(); +static void CheckCompletition(); +static void DeleteCompleteLines(); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: tetris"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//-------------------------------------------------------------------------------------- +// Game Module Functions Definition +//-------------------------------------------------------------------------------------- + +// Initialize game variables +void InitGame(void) +{ + // Initialize game statistics + level = 1; + lines = 0; + + fadingColor = GRAY; + + piecePositionX = 0; + piecePositionY = 0; + + pause = false; + + beginPlay = true; + pieceActive = false; + detection = false; + lineToDelete = false; + + // Counters + gravityMovementCounter = 0; + lateralMovementCounter = 0; + turnMovementCounter = 0; + fastFallMovementCounter = 0; + + fadeLineCounter = 0; + gravitySpeed = 30; + + // Initialize grid matrices + for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++) + { + for (int j = 0; j < GRID_VERTICAL_SIZE; j++) + { + if ((j == GRID_VERTICAL_SIZE - 1) || (i == 0) || (i == GRID_HORIZONTAL_SIZE - 1)) grid[i][j] = BLOCK; + else grid[i][j] = EMPTY; + } + } + + // Initialize incoming piece matrices + for (int i = 0; i < 4; i++) + { + for (int j = 0; j< 4; j++) + { + incomingPiece[i][j] = EMPTY; + } + } +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + if (!lineToDelete) + { + if (!pieceActive) + { + // Get another piece + pieceActive = Createpiece(); + + // We leave a little time before starting the fast falling down + fastFallMovementCounter = 0; + } + else // Piece falling + { + // Counters update + fastFallMovementCounter++; + gravityMovementCounter++; + lateralMovementCounter++; + turnMovementCounter++; + + // We make sure to move if we've pressed the key this frame + if (IsKeyPressed(KEY_LEFT) || IsKeyPressed(KEY_RIGHT)) lateralMovementCounter = LATERAL_SPEED; + if (IsKeyPressed(KEY_UP)) turnMovementCounter = TURNING_SPEED; + + // Fall down + if (IsKeyDown(KEY_DOWN) && (fastFallMovementCounter >= FAST_FALL_AWAIT_COUNTER)) + { + // We make sure the piece is going to fall this frame + gravityMovementCounter += gravitySpeed; + } + + if (gravityMovementCounter >= gravitySpeed) + { + // Basic falling movement + CheckDetection(&detection); + + // Check if the piece has collided with another piece or with the boundings + ResolveFallingMovement(&detection, &pieceActive); + + // Check if we fullfilled a line and if so, erase the line and pull down the the lines above + CheckCompletition(&lineToDelete); + + gravityMovementCounter = 0; + } + + // Move laterally at player's will + if (lateralMovementCounter >= LATERAL_SPEED) + { + // Update the lateral movement and if success, reset the lateral counter + if (!ResolveLateralMovement()) lateralMovementCounter = 0; + } + + // Turn the piece at player's will + if (turnMovementCounter >= TURNING_SPEED) + { + // Update the turning movement and reset the turning counter + if (ResolveTurnMovement()) turnMovementCounter = 0; + } + } + + // Game over logic + for (int j = 0; j < 2; j++) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if (grid[i][j] == FULL) + { + gameOver = true; + } + } + } + } + else + { + // Animation when deleting lines + fadeLineCounter++; + + if (fadeLineCounter%8 < 4) fadingColor = MAROON; + else fadingColor = GRAY; + + if (fadeLineCounter >= FADING_TIME) + { + DeleteCompleteLines(); + fadeLineCounter = 0; + lineToDelete = false; + } + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // Draw gameplay area + Vector2 offset; + offset.x = screenWidth/2 - (GRID_HORIZONTAL_SIZE*SQUARE_SIZE/2); + offset.y = screenHeight/2 - ((GRID_VERTICAL_SIZE - 1)*SQUARE_SIZE/2) + SQUARE_SIZE*2; + + offset.y -= 60; // NOTE: Harcoded position! + + int controller = offset.x; + + for (int j = 0; j < GRID_VERTICAL_SIZE; j++) + { + for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++) + { + // Draw each square of the grid + if (grid[i][j] == EMPTY) + { + DrawLine(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, LIGHTGRAY ); + DrawLine(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, LIGHTGRAY ); + DrawLine(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY ); + DrawLine(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY ); + offset.x += SQUARE_SIZE; + } + else if (grid[i][j] == FULL) + { + DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, GRAY); + offset.x += SQUARE_SIZE; + } + else if (grid[i][j] == MOVING) + { + DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, DARKGRAY); + offset.x += SQUARE_SIZE; + } + else if (grid[i][j] == BLOCK) + { + DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, LIGHTGRAY); + offset.x += SQUARE_SIZE; + } + else if (grid[i][j] == FADING) + { + DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, fadingColor); + offset.x += SQUARE_SIZE; + } + } + + offset.x = controller; + offset.y += SQUARE_SIZE; + } + + // Draw incoming piece + //offset.x = screenWidth/2 - (4*SQUARE_SIZE/2); + //offset.y = (screenHeight/2 - ((GRID_VERTICAL_SIZE - 1)*SQUARE_SIZE/2)) - (3*SQUARE_SIZE); + + // NOTE: Harcoded positions for the demo! + offset.x = 850; + offset.y = 75; + + int controler = offset.x; + + for (int j = 0; j < 4; j++) + { + for (int i = 0; i < 4; i++) + { + if (incomingPiece[i][j] == EMPTY) + { + DrawLine(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, LIGHTGRAY ); + DrawLine(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, LIGHTGRAY ); + DrawLine(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY ); + DrawLine(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY ); + offset.x += SQUARE_SIZE; + } + else if (incomingPiece[i][j] == MOVING) + { + DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, GRAY); + offset.x += SQUARE_SIZE; + } + } + + offset.x = controler; + offset.y += SQUARE_SIZE; + } + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} + +//-------------------------------------------------------------------------------------- +// Additional module functions +//-------------------------------------------------------------------------------------- +static bool Createpiece() +{ + piecePositionX = (int)((GRID_HORIZONTAL_SIZE - 4)/2); + piecePositionY = 0; + + // If the game is starting and you are going to create the first piece, we create an extra one + if (beginPlay) + { + GetRandompiece(); + beginPlay = false; + } + + // We assign the incoming piece to the actual piece + for (int i = 0; i < 4; i++) + { + for (int j = 0; j< 4; j++) + { + piece[i][j] = incomingPiece[i][j]; + } + } + + // We assign a random piece to the incoming one + GetRandompiece(); + + // Assign the piece to the grid + for (int i = piecePositionX; i < piecePositionX + 4; i++) + { + for (int j = 0; j < 4; j++) + { + if (piece[i - (int)piecePositionX][j] == MOVING) grid[i][j] = MOVING; + } + } + + return true; +} + +static void GetRandompiece() +{ + srand(time(NULL)); + int random = rand() % 7; + + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 4; j++) + { + incomingPiece[i][j] = EMPTY; + } + } + + switch(random) + { + case 0: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //Cube + case 1: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //L + case 2: { incomingPiece[1][2] = MOVING; incomingPiece[2][0] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; } break; //L inversa + case 3: { incomingPiece[0][1] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //Recta + case 4: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][1] = MOVING; } break; //Creu tallada + case 5: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[3][2] = MOVING; } break; //S + case 6: { incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //S inversa + } +} + +static void ResolveFallingMovement(bool *detection, bool *pieceActive) +{ + // If we finished moving this piece, we stop it + if (*detection) + { + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if (grid[i][j] == MOVING) + { + grid[i][j] = FULL; + *detection = false; + *pieceActive = false; + } + } + } + } + // We move down the piece + else + { + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if (grid[i][j] == MOVING) + { + grid[i][j+1] = MOVING; + grid[i][j] = EMPTY; + } + } + } + piecePositionY++; + } +} + +static bool ResolveLateralMovement() +{ + bool collision = false; + + // Move left + if (IsKeyDown(KEY_LEFT)) + { + // Check if is possible to move to left + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if (grid[i][j] == MOVING) + { + // Check if we are touching the left wall or we have a full square at the left + if ((i-1 == 0) || (grid[i-1][j] == FULL)) collision = true; + } + } + } + // If able, move left + if (!collision) + { + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) // We check the matrix from left to right + { + // Move everything to the left + if (grid[i][j] == MOVING) + { + grid[i-1][j] = MOVING; + grid[i][j] = EMPTY; + } + } + } + + piecePositionX--; + } + } + + // Move right + else if (IsKeyDown(KEY_RIGHT)) + { + // Check if is possible to move to right + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if (grid[i][j] == MOVING) + { + // Check if we are touching the right wall or we have a full square at the right + if ((i+1 == GRID_HORIZONTAL_SIZE - 1) || (grid[i+1][j] == FULL)) + { + collision = true; + + } + } + } + } + // If able move right + if (!collision) + { + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = GRID_HORIZONTAL_SIZE - 1; i >= 1; i--) // We check the matrix from right to left + { + // Move everything to the right + if (grid[i][j] == MOVING) + { + grid[i+1][j] = MOVING; + grid[i][j] = EMPTY; + } + } + } + + piecePositionX++; + } + } + + return collision; +} + +static bool ResolveTurnMovement() +{ + // Input for turning the piece + if (IsKeyDown(KEY_UP)) + { + int aux; + bool checker = false; + + // Check all turning possibilities + if ((grid[piecePositionX + 3][piecePositionY] == MOVING) && + (grid[piecePositionX][piecePositionY] != EMPTY) && + (grid[piecePositionX][piecePositionY] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX + 3][piecePositionY + 3] == MOVING) && + (grid[piecePositionX + 3][piecePositionY] != EMPTY) && + (grid[piecePositionX + 3][piecePositionY] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX][piecePositionY + 3] == MOVING) && + (grid[piecePositionX + 3][piecePositionY + 3] != EMPTY) && + (grid[piecePositionX + 3][piecePositionY + 3] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX][piecePositionY] == MOVING) && + (grid[piecePositionX][piecePositionY + 3] != EMPTY) && + (grid[piecePositionX][piecePositionY + 3] != MOVING)) + { + checker = true; + } + + + if ((grid[piecePositionX + 1][piecePositionY] == MOVING) && + (grid[piecePositionX][piecePositionY + 2] != EMPTY) && + (grid[piecePositionX][piecePositionY + 2] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX + 3][piecePositionY + 1] == MOVING) && + (grid[piecePositionX + 1][piecePositionY] != EMPTY) && + (grid[piecePositionX + 1][piecePositionY] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX + 2][piecePositionY + 3] == MOVING) && + (grid[piecePositionX + 3][piecePositionY + 1] != EMPTY) && + (grid[piecePositionX + 3][piecePositionY + 1] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX][piecePositionY + 2] == MOVING) && + (grid[piecePositionX + 2][piecePositionY + 3] != EMPTY) && + (grid[piecePositionX + 2][piecePositionY + 3] != MOVING)) + { + checker = true; + } + + + if ((grid[piecePositionX + 2][piecePositionY] == MOVING) && + (grid[piecePositionX][piecePositionY + 1] != EMPTY) && + (grid[piecePositionX][piecePositionY + 1] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX + 3][piecePositionY + 2] == MOVING) && + (grid[piecePositionX + 2][piecePositionY] != EMPTY) && + (grid[piecePositionX + 2][piecePositionY] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX + 1][piecePositionY + 3] == MOVING) && + (grid[piecePositionX + 3][piecePositionY + 2] != EMPTY) && + (grid[piecePositionX + 3][piecePositionY + 2] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX][piecePositionY + 1] == MOVING) && + (grid[piecePositionX + 1][piecePositionY + 3] != EMPTY) && + (grid[piecePositionX + 1][piecePositionY + 3] != MOVING)) + { + checker = true; + } + + if ((grid[piecePositionX + 1][piecePositionY + 1] == MOVING) && + (grid[piecePositionX + 1][piecePositionY + 2] != EMPTY) && + (grid[piecePositionX + 1][piecePositionY + 2] != MOVING)) + { + checker = true; + } + + if ((grid[piecePositionX + 2][piecePositionY + 1] == MOVING) && + (grid[piecePositionX + 1][piecePositionY + 1] != EMPTY) && + (grid[piecePositionX + 1][piecePositionY + 1] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX + 2][piecePositionY + 2] == MOVING) && + (grid[piecePositionX + 2][piecePositionY + 1] != EMPTY) && + (grid[piecePositionX + 2][piecePositionY + 1] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX + 1][piecePositionY + 2] == MOVING) && + (grid[piecePositionX + 2][piecePositionY + 2] != EMPTY) && + (grid[piecePositionX + 2][piecePositionY + 2] != MOVING)) + { + checker = true; + } + + if (!checker) + { + aux = piece[0][0]; + piece[0][0] = piece[3][0]; + piece[3][0] = piece[3][3]; + piece[3][3] = piece[0][3]; + piece[0][3] = aux; + + aux = piece[1][0]; + piece[1][0] = piece[3][1]; + piece[3][1] = piece[2][3]; + piece[2][3] = piece[0][2]; + piece[0][2] = aux; + + aux = piece[2][0]; + piece[2][0] = piece[3][2]; + piece[3][2] = piece[1][3]; + piece[1][3] = piece[0][1]; + piece[0][1] = aux; + + aux = piece[1][1]; + piece[1][1] = piece[2][1]; + piece[2][1] = piece[2][2]; + piece[2][2] = piece[1][2]; + piece[1][2] = aux; + } + + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if (grid[i][j] == MOVING) + { + grid[i][j] = EMPTY; + } + } + } + + for (int i = piecePositionX; i < piecePositionX + 4; i++) + { + for (int j = piecePositionY; j < piecePositionY + 4; j++) + { + if (piece[i - piecePositionX][j - piecePositionY] == MOVING) + { + grid[i][j] = MOVING; + } + } + } + return true; + } + + return false; +} + +static void CheckDetection(bool *detection) +{ + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if ((grid[i][j] == MOVING) && ((grid[i][j+1] == FULL) || (grid[i][j+1] == BLOCK))) *detection = true; + } + } +} + +static void CheckCompletition(bool *lineToDelete) +{ + int calculator; + + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + calculator = 0; + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + // Count each square of the line + if (grid[i][j] == FULL) + { + calculator++; + } + + // Check if we completed the whole line + if (calculator == GRID_HORIZONTAL_SIZE - 2) + { + *lineToDelete = true; + calculator = 0; + // points++; + + // Mark the completed line + for (int z = 1; z < GRID_HORIZONTAL_SIZE - 1; z++) + { + grid[z][j] = FADING; + } + } + } + } +} + +static void DeleteCompleteLines() +{ + // erase the completed line + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + while (grid[1][j] == FADING) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + grid[i][j] = EMPTY; + } + for (int j2 = j-1; j2 >= 0; j2--) + { + for (int i2 = 1; i2 < GRID_HORIZONTAL_SIZE - 1; i2++) + { + if (grid[i2][j2] == FULL) + { + grid[i2][j2+1] = FULL; + grid[i2][j2] = EMPTY; + } + else if (grid[i2][j2] == FADING) + { + grid[i2][j2+1] = FADING; + grid[i2][j2] = EMPTY; + } + } + } + } + } +} \ No newline at end of file -- cgit v1.2.3 From e484d58d9c9cc9a081675e2ceef4d55a276ce43c Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 31 Jan 2016 15:31:51 +0100 Subject: Uploaded gamejam game sources --- games/light_my_ritual/light_my_ritual.c | 271 +++++++ games/light_my_ritual/makefile | 203 +++++ games/light_my_ritual/resources/audio/ambient.ogg | Bin 0 -> 1274574 bytes .../light_my_ritual/resources/audio/light_off.wav | Bin 0 -> 9291 bytes games/light_my_ritual/resources/audio/light_on.wav | Bin 0 -> 2335 bytes games/light_my_ritual/resources/audio/ritual.ogg | Bin 0 -> 2592921 bytes games/light_my_ritual/resources/audio/start.wav | Bin 0 -> 14079 bytes games/light_my_ritual/resources/font_arcadian.png | Bin 0 -> 97566 bytes games/light_my_ritual/resources/lights_map.png | Bin 0 -> 430 bytes .../resources/textures/back_title.png | Bin 0 -> 182900 bytes .../resources/textures/background.png | Bin 0 -> 1231218 bytes games/light_my_ritual/resources/textures/book.png | Bin 0 -> 4402 bytes .../resources/textures/circle_level_i_off.png | Bin 0 -> 15448 bytes .../resources/textures/circle_level_i_on.png | Bin 0 -> 51443 bytes .../resources/textures/circle_level_ii_off.png | Bin 0 -> 27962 bytes .../resources/textures/circle_level_ii_on.png | Bin 0 -> 106608 bytes .../resources/textures/circle_level_iii_off.png | Bin 0 -> 37564 bytes .../resources/textures/circle_level_iii_on.png | Bin 0 -> 160307 bytes games/light_my_ritual/resources/textures/enemy.png | Bin 0 -> 2812 bytes .../resources/textures/foreground_level_i.png | Bin 0 -> 28111 bytes .../resources/textures/foreground_level_ii.png | Bin 0 -> 36121 bytes .../resources/textures/foreground_level_iii.png | Bin 0 -> 42136 bytes games/light_my_ritual/resources/textures/light.png | Bin 0 -> 2275 bytes .../resources/textures/light_glow.png | Bin 0 -> 8661 bytes .../resources/textures/light_ray.png | Bin 0 -> 8780 bytes .../resources/textures/msg_ritual.png | Bin 0 -> 114012 bytes .../light_my_ritual/resources/textures/player.png | Bin 0 -> 2899 bytes .../resources/textures/time_over.png | Bin 0 -> 115874 bytes games/light_my_ritual/resources/textures/title.png | Bin 0 -> 213549 bytes games/light_my_ritual/screens/screen_gameplay.c | 842 +++++++++++++++++++++ games/light_my_ritual/screens/screen_logo_raylib.c | 214 ++++++ games/light_my_ritual/screens/screen_title.c | 105 +++ games/light_my_ritual/screens/screens.h | 78 ++ 33 files changed, 1713 insertions(+) create mode 100644 games/light_my_ritual/light_my_ritual.c create mode 100644 games/light_my_ritual/makefile create mode 100644 games/light_my_ritual/resources/audio/ambient.ogg create mode 100644 games/light_my_ritual/resources/audio/light_off.wav create mode 100644 games/light_my_ritual/resources/audio/light_on.wav create mode 100644 games/light_my_ritual/resources/audio/ritual.ogg create mode 100644 games/light_my_ritual/resources/audio/start.wav create mode 100644 games/light_my_ritual/resources/font_arcadian.png create mode 100644 games/light_my_ritual/resources/lights_map.png create mode 100644 games/light_my_ritual/resources/textures/back_title.png create mode 100644 games/light_my_ritual/resources/textures/background.png create mode 100644 games/light_my_ritual/resources/textures/book.png create mode 100644 games/light_my_ritual/resources/textures/circle_level_i_off.png create mode 100644 games/light_my_ritual/resources/textures/circle_level_i_on.png create mode 100644 games/light_my_ritual/resources/textures/circle_level_ii_off.png create mode 100644 games/light_my_ritual/resources/textures/circle_level_ii_on.png create mode 100644 games/light_my_ritual/resources/textures/circle_level_iii_off.png create mode 100644 games/light_my_ritual/resources/textures/circle_level_iii_on.png create mode 100644 games/light_my_ritual/resources/textures/enemy.png create mode 100644 games/light_my_ritual/resources/textures/foreground_level_i.png create mode 100644 games/light_my_ritual/resources/textures/foreground_level_ii.png create mode 100644 games/light_my_ritual/resources/textures/foreground_level_iii.png create mode 100644 games/light_my_ritual/resources/textures/light.png create mode 100644 games/light_my_ritual/resources/textures/light_glow.png create mode 100644 games/light_my_ritual/resources/textures/light_ray.png create mode 100644 games/light_my_ritual/resources/textures/msg_ritual.png create mode 100644 games/light_my_ritual/resources/textures/player.png create mode 100644 games/light_my_ritual/resources/textures/time_over.png create mode 100644 games/light_my_ritual/resources/textures/title.png create mode 100644 games/light_my_ritual/screens/screen_gameplay.c create mode 100644 games/light_my_ritual/screens/screen_logo_raylib.c create mode 100644 games/light_my_ritual/screens/screen_title.c create mode 100644 games/light_my_ritual/screens/screens.h diff --git a/games/light_my_ritual/light_my_ritual.c b/games/light_my_ritual/light_my_ritual.c new file mode 100644 index 00000000..0f1dc47e --- /dev/null +++ b/games/light_my_ritual/light_my_ritual.c @@ -0,0 +1,271 @@ +/******************************************************************************************* +* +* GLOBAL GAME JAM 2016 - LIGHT MY RITUAL! +* +* Preparing a ritual session is not that easy. +* You must light all the candles before the astral alignment finishes... +* but dark creatures move in the shadows to put out all your lights! +* Be fast! Be smart! Light my ritual! +* +* This game has been created using raylib (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (Ray San - raysan@raysanweb.com) +* +********************************************************************************************/ + +#include "raylib.h" +#include "screens/screens.h" // NOTE: Defines global variable: currentScreen + +#include + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- +const int screenWidth = 1280; +const int screenHeight = 720; + +// 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; + +//---------------------------------------------------------------------------------- +// Local Functions Declaration +//---------------------------------------------------------------------------------- +void TransitionToScreen(int screen); +void ChangeToScreen(int screen); // No transition effect +void UpdateTransition(void); +void DrawTransition(void); + +void UpdateDrawFrame(void); // Update and Draw one frame + +//---------------------------------------------------------------------------------- +// Main entry point +//---------------------------------------------------------------------------------- +int main(void) +{ + // Initialization + //--------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "GGJ16 - LIGHT MY RITUAL!"); + + // Global data loading (assets that must be available in all screens, i.e. fonts) + InitAudioDevice(); + + Image image = LoadImage("resources/lights_map.png"); // Load image in CPU memory (RAM) + + lightsMap = GetImageData(image); // Get image pixels data as an array of Color + lightsMapWidth = image.width; + lightsMapHeight = image.height; + + UnloadImage(image); // Unload image from CPU memory (RAM) + + //PlayMusicStream("resources/audio/come_play_with_me.ogg"); + + font = LoadSpriteFont("resources/font_arcadian.png"); + //doors = LoadTexture("resources/textures/doors.png"); + //sndDoor = LoadSound("resources/audio/door.ogg"); + + // Setup and Init first screen + currentScreen = LOGO_RL; + //InitTitleScreen(); + //InitGameplayScreen(); + rlInitLogoScreen(); + +#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 + { + UpdateDrawFrame(); + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + switch (currentScreen) + { + case LOGO_RL: rlUnloadLogoScreen(); break; + case TITLE: UnloadTitleScreen(); break; + case GAMEPLAY: UnloadGameplayScreen(); break; + default: break; + } + + // Unload all global loaded data (i.e. fonts) here! + UnloadSpriteFont(font); + //UnloadSound(sndDoor); + + free(lightsMap); + + CloseAudioDevice(); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +void TransitionToScreen(int screen) +{ + onTransition = true; + transFromScreen = currentScreen; + transToScreen = screen; +} + +void ChangeToScreen(int screen) +{ + switch (currentScreen) + { + case LOGO_RL: rlUnloadLogoScreen(); break; + case TITLE: UnloadTitleScreen(); break; + case GAMEPLAY: UnloadGameplayScreen(); break; + default: break; + } + + switch (screen) + { + case LOGO_RL: rlInitLogoScreen(); break; + case TITLE: InitTitleScreen(); break; + case GAMEPLAY: InitGameplayScreen(); break; + default: break; + } + + currentScreen = screen; +} + +void UpdateTransition(void) +{ + if (!transFadeOut) + { + transAlpha += 0.05f; + + if (transAlpha >= 1.0) + { + transAlpha = 1.0; + + switch (transFromScreen) + { + case LOGO_RL: rlUnloadLogoScreen(); break; + case TITLE: UnloadTitleScreen(); break; + case GAMEPLAY: UnloadGameplayScreen(); break; + default: break; + } + + switch (transToScreen) + { + case LOGO_RL: + { + rlInitLogoScreen(); + currentScreen = LOGO_RL; + } break; + case TITLE: + { + InitTitleScreen(); + currentScreen = TITLE; + } break; + case GAMEPLAY: + { + InitGameplayScreen(); + currentScreen = GAMEPLAY; + } break; + default: break; + } + + transFadeOut = true; + } + } + else // Transition fade out logic + { + transAlpha -= 0.05f; + + if (transAlpha <= 0) + { + transAlpha = 0; + transFadeOut = false; + onTransition = false; + transFromScreen = -1; + transToScreen = -1; + } + } +} + +void DrawTransition(void) +{ + DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(BLACK, transAlpha)); +} + +// Update and draw game frame +void UpdateDrawFrame(void) +{ + // Update + //---------------------------------------------------------------------------------- + if (!onTransition) + { + switch(currentScreen) + { + case LOGO_RL: + { + rlUpdateLogoScreen(); + + if (rlFinishLogoScreen()) TransitionToScreen(TITLE); + + } break; + case TITLE: + { + UpdateTitleScreen(); + + if (FinishTitleScreen() == 1) TransitionToScreen(GAMEPLAY); + + } break; + case GAMEPLAY: + { + UpdateGameplayScreen(); + + if (FinishGameplayScreen() == 1) ChangeToScreen(LOGO_RL); + else if (FinishGameplayScreen() == 2) TransitionToScreen(TITLE); + + } break; + default: break; + } + } + else + { + // Update transition (fade-in, fade-out) + UpdateTransition(); + } + + UpdateMusicStream(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + switch(currentScreen) + { + case LOGO_RL: rlDrawLogoScreen(); break; + case TITLE: DrawTitleScreen(); break; + case GAMEPLAY: DrawGameplayScreen(); break; + default: break; + } + + if (onTransition) DrawTransition(); + + //DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- +} + diff --git a/games/light_my_ritual/makefile b/games/light_my_ritual/makefile new file mode 100644 index 00000000..b7e1bb58 --- /dev/null +++ b/games/light_my_ritual/makefile @@ -0,0 +1,203 @@ +#************************************************************************************************** +# +# raylib - Advance Game +# +# makefile to compile advance game +# +# 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 if not defined (by default, compile for RPI) +# Other possible platform: PLATFORM_DESKTOP +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 = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources -s ALLOW_MEMORY_GROWTH=1 + #-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 + +# 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. -IC:/raylib/raylib/src -IC:/raylib/raylib/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. -LC:/raylib/raylib/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 = C:/raylib/raylib/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 = C:/raylib/raylib/src/resources -Wl,--subsystem,windows +endif + +ifeq ($(PLATFORM),PLATFORM_WEB) + EXT = .html +endif + +# define all screen object files required +SCREENS = \ + screens/screen_logo_raylib.o \ + screens/screen_title.o \ + screens/screen_gameplay.o \ + +# typing 'make' will invoke the first target entry in the file, +# in this case, the 'default' target entry is advance_game +default: light_my_ritual + +# compile template - advance_game +light_my_ritual: light_my_ritual.c $(SCREENS) + $(CC) -o $@$(EXT) $< $(SCREENS) $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + +# compile screen LOGO raylib +screens/screen_logo_raylib.o: screens/screen_logo_raylib.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen TITLE +screens/screen_title.o: screens/screen_title.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen ENDING +screens/screen_gameplay.o: screens/screen_gameplay.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) diff --git a/games/light_my_ritual/resources/audio/ambient.ogg b/games/light_my_ritual/resources/audio/ambient.ogg new file mode 100644 index 00000000..5828c516 Binary files /dev/null and b/games/light_my_ritual/resources/audio/ambient.ogg differ diff --git a/games/light_my_ritual/resources/audio/light_off.wav b/games/light_my_ritual/resources/audio/light_off.wav new file mode 100644 index 00000000..d2203e72 Binary files /dev/null and b/games/light_my_ritual/resources/audio/light_off.wav differ diff --git a/games/light_my_ritual/resources/audio/light_on.wav b/games/light_my_ritual/resources/audio/light_on.wav new file mode 100644 index 00000000..38b7ca58 Binary files /dev/null and b/games/light_my_ritual/resources/audio/light_on.wav differ diff --git a/games/light_my_ritual/resources/audio/ritual.ogg b/games/light_my_ritual/resources/audio/ritual.ogg new file mode 100644 index 00000000..4674ff7b Binary files /dev/null and b/games/light_my_ritual/resources/audio/ritual.ogg differ diff --git a/games/light_my_ritual/resources/audio/start.wav b/games/light_my_ritual/resources/audio/start.wav new file mode 100644 index 00000000..66ce7ac1 Binary files /dev/null and b/games/light_my_ritual/resources/audio/start.wav differ diff --git a/games/light_my_ritual/resources/font_arcadian.png b/games/light_my_ritual/resources/font_arcadian.png new file mode 100644 index 00000000..5c3df51a Binary files /dev/null and b/games/light_my_ritual/resources/font_arcadian.png differ diff --git a/games/light_my_ritual/resources/lights_map.png b/games/light_my_ritual/resources/lights_map.png new file mode 100644 index 00000000..362094cd Binary files /dev/null and b/games/light_my_ritual/resources/lights_map.png differ diff --git a/games/light_my_ritual/resources/textures/back_title.png b/games/light_my_ritual/resources/textures/back_title.png new file mode 100644 index 00000000..54921247 Binary files /dev/null and b/games/light_my_ritual/resources/textures/back_title.png differ diff --git a/games/light_my_ritual/resources/textures/background.png b/games/light_my_ritual/resources/textures/background.png new file mode 100644 index 00000000..367bdd30 Binary files /dev/null and b/games/light_my_ritual/resources/textures/background.png differ diff --git a/games/light_my_ritual/resources/textures/book.png b/games/light_my_ritual/resources/textures/book.png new file mode 100644 index 00000000..c0bfbdb3 Binary files /dev/null and b/games/light_my_ritual/resources/textures/book.png differ diff --git a/games/light_my_ritual/resources/textures/circle_level_i_off.png b/games/light_my_ritual/resources/textures/circle_level_i_off.png new file mode 100644 index 00000000..7961af7d Binary files /dev/null and b/games/light_my_ritual/resources/textures/circle_level_i_off.png differ diff --git a/games/light_my_ritual/resources/textures/circle_level_i_on.png b/games/light_my_ritual/resources/textures/circle_level_i_on.png new file mode 100644 index 00000000..1f217734 Binary files /dev/null and b/games/light_my_ritual/resources/textures/circle_level_i_on.png differ diff --git a/games/light_my_ritual/resources/textures/circle_level_ii_off.png b/games/light_my_ritual/resources/textures/circle_level_ii_off.png new file mode 100644 index 00000000..642adc3b Binary files /dev/null and b/games/light_my_ritual/resources/textures/circle_level_ii_off.png differ diff --git a/games/light_my_ritual/resources/textures/circle_level_ii_on.png b/games/light_my_ritual/resources/textures/circle_level_ii_on.png new file mode 100644 index 00000000..93b71b3a Binary files /dev/null and b/games/light_my_ritual/resources/textures/circle_level_ii_on.png differ diff --git a/games/light_my_ritual/resources/textures/circle_level_iii_off.png b/games/light_my_ritual/resources/textures/circle_level_iii_off.png new file mode 100644 index 00000000..daf50be9 Binary files /dev/null and b/games/light_my_ritual/resources/textures/circle_level_iii_off.png differ diff --git a/games/light_my_ritual/resources/textures/circle_level_iii_on.png b/games/light_my_ritual/resources/textures/circle_level_iii_on.png new file mode 100644 index 00000000..e2256e95 Binary files /dev/null and b/games/light_my_ritual/resources/textures/circle_level_iii_on.png differ diff --git a/games/light_my_ritual/resources/textures/enemy.png b/games/light_my_ritual/resources/textures/enemy.png new file mode 100644 index 00000000..dc0a911d Binary files /dev/null and b/games/light_my_ritual/resources/textures/enemy.png differ diff --git a/games/light_my_ritual/resources/textures/foreground_level_i.png b/games/light_my_ritual/resources/textures/foreground_level_i.png new file mode 100644 index 00000000..32b96740 Binary files /dev/null and b/games/light_my_ritual/resources/textures/foreground_level_i.png differ diff --git a/games/light_my_ritual/resources/textures/foreground_level_ii.png b/games/light_my_ritual/resources/textures/foreground_level_ii.png new file mode 100644 index 00000000..44f26003 Binary files /dev/null and b/games/light_my_ritual/resources/textures/foreground_level_ii.png differ diff --git a/games/light_my_ritual/resources/textures/foreground_level_iii.png b/games/light_my_ritual/resources/textures/foreground_level_iii.png new file mode 100644 index 00000000..0fc039d7 Binary files /dev/null and b/games/light_my_ritual/resources/textures/foreground_level_iii.png differ diff --git a/games/light_my_ritual/resources/textures/light.png b/games/light_my_ritual/resources/textures/light.png new file mode 100644 index 00000000..5d08326f Binary files /dev/null and b/games/light_my_ritual/resources/textures/light.png differ diff --git a/games/light_my_ritual/resources/textures/light_glow.png b/games/light_my_ritual/resources/textures/light_glow.png new file mode 100644 index 00000000..d31356c6 Binary files /dev/null and b/games/light_my_ritual/resources/textures/light_glow.png differ diff --git a/games/light_my_ritual/resources/textures/light_ray.png b/games/light_my_ritual/resources/textures/light_ray.png new file mode 100644 index 00000000..f9f877fa Binary files /dev/null and b/games/light_my_ritual/resources/textures/light_ray.png differ diff --git a/games/light_my_ritual/resources/textures/msg_ritual.png b/games/light_my_ritual/resources/textures/msg_ritual.png new file mode 100644 index 00000000..73f14d48 Binary files /dev/null and b/games/light_my_ritual/resources/textures/msg_ritual.png differ diff --git a/games/light_my_ritual/resources/textures/player.png b/games/light_my_ritual/resources/textures/player.png new file mode 100644 index 00000000..d6849478 Binary files /dev/null and b/games/light_my_ritual/resources/textures/player.png differ diff --git a/games/light_my_ritual/resources/textures/time_over.png b/games/light_my_ritual/resources/textures/time_over.png new file mode 100644 index 00000000..9f7935be Binary files /dev/null and b/games/light_my_ritual/resources/textures/time_over.png differ diff --git a/games/light_my_ritual/resources/textures/title.png b/games/light_my_ritual/resources/textures/title.png new file mode 100644 index 00000000..55eb593d Binary files /dev/null and b/games/light_my_ritual/resources/textures/title.png differ diff --git a/games/light_my_ritual/screens/screen_gameplay.c b/games/light_my_ritual/screens/screen_gameplay.c new file mode 100644 index 00000000..b91d2545 --- /dev/null +++ b/games/light_my_ritual/screens/screen_gameplay.c @@ -0,0 +1,842 @@ +/********************************************************************************************** +* +* raylib - Advance Game template +* +* Gameplay 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 + +#define MAX_LIGHTS_I 8 +#define MAX_LIGHTS_II 12 +#define MAX_LIGHTS_III 20 + +#define MAX_ENEMIES 8 + +#define MAX_PLAYER_ENERGY 40.0f +#define ENERGY_REFILL_RATIO 0.2f + +#define GAMEPAD_SENSITIVITY 4.0f // More sensitivity, more speed :P + +#define LIGHT_ANIM_FRAMES 7 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct Player { + Vector2 position; + Vector2 speed; + int radius; + Color color; + float lightEnergy; +} Player; + +typedef struct Enemy { + Vector2 position; + Vector2 targetPos; // light target position + int targetNum; // light target number + float speed; // scalar value + int radius; + int active; + int awakeFramesDelay; + int framesCounter; + Color color; +} Enemy; + +typedef struct Light { + Vector2 position; + int radius; + int requiredEnergy; + bool active; + Color color; + + int framesCounter; + int currentFrame; + Rectangle frameRec; +} Light; + +typedef enum { LEVEL_I, LEVEL_II, LEVEL_III, LEVEL_FINISHED } LightedLevel; + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Gameplay screen global variables +static int framesCounter; +static int finishScreen; + +//static Texture2D background; + +static bool pause; + +static Player player; + +static Light lightsI[MAX_LIGHTS_I]; +static Light lightsII[MAX_LIGHTS_II]; +static Light lightsIII[MAX_LIGHTS_III]; + +static Enemy enemies[MAX_ENEMIES]; + +static int ritualLevel; +static int previousLightedLevel; +static int currentLightedLevel; + +static Vector2 lighterPosition; + +static int maxLightEnergy; +static int currentLightEnergy; + +static float ritualTime; +static bool startRitual; +static float alphaRitual; + +static bool timeOver; +static int nextStarsAlignment; + +static Texture2D background; +static Texture2D foregroundI; +static Texture2D foregroundII; +static Texture2D foregroundIII; +static Texture2D texPlayer; +static Texture2D texEnemy; +static Texture2D texLight; +static Texture2D lightGlow; +static Texture2D lightRay; +static Texture2D book; +static Texture2D texRitual; +static Texture2D texTimeOver; +static Texture2D circleIoff, circleIIoff, circleIIIoff; +static Texture2D circleIon, circleIIon, circleIIIon; + +static Rectangle lightOff, lightOn; + +static Sound fxLightOn, fxLightOff; + +// Debug variables +static bool enemiesStopped; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static bool ColorEqual(Color col1, Color col2); // Check if two colors are equal +static Vector2 Vector2Subtract(Vector2 v1, Vector2 v2); +static void Vector2Normalize(Vector2 *v); +static void EnemyReset(Enemy *enemy); + +//---------------------------------------------------------------------------------- +// Gameplay Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Gameplay Screen Initialization logic +void InitGameplayScreen(void) +{ + framesCounter = 0; + finishScreen = 0; + pause = false; + + // Textures loading + background = LoadTexture("resources/textures/background.png"); + foregroundI = LoadTexture("resources/textures/foreground_level_i.png"); + foregroundII = LoadTexture("resources/textures/foreground_level_ii.png"); + foregroundIII = LoadTexture("resources/textures/foreground_level_iii.png"); + texPlayer = LoadTexture("resources/textures/player.png"); + texEnemy = LoadTexture("resources/textures/enemy.png"); + texLight = LoadTexture("resources/textures/light.png"); + lightGlow = LoadTexture("resources/textures/light_glow.png"); + lightRay = LoadTexture("resources/textures/light_ray.png"); + book = LoadTexture("resources/textures/book.png"); + texRitual = LoadTexture("resources/textures/msg_ritual.png"); + texTimeOver = LoadTexture("resources/textures/time_over.png"); + + circleIoff = LoadTexture("resources/textures/circle_level_i_off.png"); + circleIIoff = LoadTexture("resources/textures/circle_level_ii_off.png"); + circleIIIoff = LoadTexture("resources/textures/circle_level_iii_off.png"); + circleIon = LoadTexture("resources/textures/circle_level_i_on.png"); + circleIIon = LoadTexture("resources/textures/circle_level_ii_on.png"); + circleIIIon = LoadTexture("resources/textures/circle_level_iii_on.png"); + + lightOff = (Rectangle){ 0, 0, 64, 64 }; + lightOn = (Rectangle){ 64, 0, 64, 64 }; + + fxLightOn = LoadSound("resources/audio/light_on.wav"); + fxLightOff = LoadSound("resources/audio/light_off.wav"); + + // Initialize player + player.position = (Vector2){ GetScreenWidth()/2, GetScreenHeight()/2 - 40 }; + player.radius = 20; + player.speed = (Vector2){5, 5}; + player.color = WHITE; + + // Initialize lights positions based on lights map image data + int kI = 0, kII = 0, kIII = 0; + for (int y = 0; y < lightsMapHeight; y++) + { + for (int x = 0; x < lightsMapWidth; x++) + { + if (ColorEqual(lightsMap[y*lightsMapWidth + x], (Color){ 255, 0, 0, 255 })) + { + // Store light position I + lightsI[kI].position.x = (float)x*10; + lightsI[kI].position.y = (float)y*10; + kI++; + + //printf("Light %02i position: %i, %i\n", kI, (int)lightsI[kI - 1].position.x, (int)lightsI[kI - 1].position.y); + } + else if (ColorEqual(lightsMap[y*lightsMapWidth + x], (Color){ 0, 255, 0, 255 })) + { + // Store light position II + lightsII[kII].position.x = (float)x*10; + lightsII[kII].position.y = (float)y*10; + kII++; + } + else if (ColorEqual(lightsMap[y*lightsMapWidth + x], (Color){ 0, 0, 255, 255 })) + { + // Store light position III + lightsIII[kIII].position.x = (float)x*10; + lightsIII[kIII].position.y = (float)y*10; + kIII++; + } + } + } + + // Initialize lights I + for (int i = 0; i < MAX_LIGHTS_I; i++) + { + lightsI[i].radius = 12; + lightsI[i].requiredEnergy = GetRandomValue(3, 9); + lightsI[i].active = false; + lightsI[i].color = GOLD; + + lightsI[i].framesCounter = 0; + lightsI[i].currentFrame = 0; + lightsI[i].frameRec = (Rectangle){ 0, 0, 64, 64 }; + } + + // Initialize lights II + for (int i = 0; i < MAX_LIGHTS_II; i++) + { + lightsII[i].radius = 8; + lightsII[i].requiredEnergy = GetRandomValue(3, 8); + lightsII[i].active = false; + lightsII[i].color = GOLD; + + lightsII[i].framesCounter = 0; + lightsII[i].currentFrame = 0; + lightsII[i].frameRec = (Rectangle){ 0, 0, 64, 64 }; + } + + // Initialize lights III + for (int i = 0; i < MAX_LIGHTS_III; i++) + { + lightsIII[i].radius = 8; + lightsIII[i].requiredEnergy = GetRandomValue(4, 10); + lightsIII[i].active = false; + lightsIII[i].color = GOLD; + + lightsIII[i].framesCounter = 0; + lightsIII[i].currentFrame = 0; + lightsIII[i].frameRec = (Rectangle){ 0, 0, 64, 64 }; + } + + // Initialize ritual level + ritualLevel = 0; + currentLightedLevel = LEVEL_I; + lighterPosition = (Vector2){ GetScreenWidth()/2, GetScreenHeight()/2 }; + + // Initialize enemies + for (int i = 0; i < MAX_ENEMIES; i++) EnemyReset(&enemies[i]); + + // Initialize max light energy (depends on lights randomness) + maxLightEnergy = 0; + + for (int i = 0; i < MAX_LIGHTS_I; i++) maxLightEnergy += lightsI[i].requiredEnergy; + for (int i = 0; i < MAX_LIGHTS_II; i++) maxLightEnergy += lightsII[i].requiredEnergy; + for (int i = 0; i < MAX_LIGHTS_III; i++) maxLightEnergy += lightsIII[i].requiredEnergy; + + //printf("Max light energy: %i\n", maxLightEnergy); + + // Initialize ritual variables + ritualTime = 0.0f; + startRitual = false;; + alphaRitual = 0.0f; + + timeOver = false; + nextStarsAlignment = GetRandomValue(500, 1000); + + enemiesStopped = false; + + PlayMusicStream("resources/audio/ritual.ogg"); +} + +// Gameplay Screen Update logic +void UpdateGameplayScreen(void) +{ + if (IsKeyPressed('P')) pause = !pause; + + if (!pause && (currentLightedLevel != LEVEL_FINISHED) && !timeOver) + { + framesCounter++; // Time starts counting to awake enemies + + // Player movement logic + if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x; + else if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x; + + if (IsKeyDown(KEY_UP)) player.position.y -= player.speed.y; + else if (IsKeyDown(KEY_DOWN)) player.position.y += player.speed.y; + + // Debug key to stop enemies + if (IsKeyPressed(KEY_S)) enemiesStopped = !enemiesStopped; + + /* + if (IsGamepadAvailable(GAMEPAD_PLAYER1)) + { + Vector2 movement = GetGamepadMovement(GAMEPAD_PLAYER1); + + player.position.x += movement.x*GAMEPAD_SENSITIVITY; + player.position.y += movement.y*GAMEPAD_SENSITIVITY; + } + */ + + // Player light energy filling logic + if (CheckCollisionCircles(player.position, player.radius, lighterPosition, 50)) + { + player.lightEnergy += ENERGY_REFILL_RATIO; + player.color = (Color){ 255, 255, 100, 255 }; + } + else player.color = WHITE; + + if (player.lightEnergy > MAX_PLAYER_ENERGY) player.lightEnergy = MAX_PLAYER_ENERGY; + + // Player vs lights collision detection (depends on lighted level) + if (currentLightedLevel == LEVEL_I) + { + for (int i = 0; i < MAX_LIGHTS_I; i++) + { + // Check player vs lightI collision + if (CheckCollisionCircles(player.position, player.radius, lightsI[i].position, lightsI[i].radius)) + { + if (!lightsI[i].active && (player.lightEnergy >= lightsI[i].requiredEnergy)) + { + lightsI[i].active = true; + lightsI[i].currentFrame = 1; + player.lightEnergy -= lightsI[i].requiredEnergy; + + PlaySound(fxLightOn); + } + } + } + } + else if (currentLightedLevel == LEVEL_II) + { + for (int i = 0; i < MAX_LIGHTS_II; i++) + { + if (CheckCollisionCircles(player.position, player.radius, lightsII[i].position, lightsII[i].radius)) + { + if (!lightsII[i].active && (player.lightEnergy >= lightsII[i].requiredEnergy)) + { + lightsII[i].active = true; + player.lightEnergy -= lightsII[i].requiredEnergy; + + PlaySound(fxLightOn); + } + } + } + } + else if (currentLightedLevel == LEVEL_III) + { + for (int i = 0; i < MAX_LIGHTS_III; i++) + { + if (CheckCollisionCircles(player.position, player.radius, lightsIII[i].position, lightsIII[i].radius)) + { + if (!lightsIII[i].active && (player.lightEnergy >= lightsIII[i].requiredEnergy)) + { + lightsIII[i].active = true; + player.lightEnergy -= lightsIII[i].requiredEnergy; + + PlaySound(fxLightOn); + } + } + } + } + + // Lights animation (it doesn't depend on currentLightedLevel) + for (int i = 0; i < MAX_LIGHTS_I; i++) + { + // Light animation + if (lightsI[i].active) + { + lightsI[i].framesCounter++; + + if (lightsI[i].framesCounter > 10) + { + lightsI[i].currentFrame++; + + if (lightsI[i].currentFrame > LIGHT_ANIM_FRAMES - 1) lightsI[i].currentFrame = 1; + + lightsI[i].framesCounter = 0; + } + } + + lightsI[i].frameRec.x = lightsI[i].currentFrame*texLight.width/LIGHT_ANIM_FRAMES; + } + + for (int i = 0; i < MAX_LIGHTS_II; i++) + { + // Light animation + if (lightsII[i].active) + { + lightsII[i].framesCounter++; + + if (lightsII[i].framesCounter > 10) + { + lightsII[i].currentFrame++; + + if (lightsII[i].currentFrame > LIGHT_ANIM_FRAMES - 1) lightsII[i].currentFrame = 1; + + lightsII[i].framesCounter = 0; + } + } + + lightsII[i].frameRec.x = lightsII[i].currentFrame*texLight.width/LIGHT_ANIM_FRAMES; + } + + for (int i = 0; i < MAX_LIGHTS_III; i++) + { + // Light animation + if (lightsIII[i].active) + { + lightsIII[i].framesCounter++; + + if (lightsIII[i].framesCounter > 10) + { + lightsIII[i].currentFrame++; + + if (lightsIII[i].currentFrame > LIGHT_ANIM_FRAMES - 1) lightsIII[i].currentFrame = 1; + + lightsIII[i].framesCounter = 0; + } + } + + lightsIII[i].frameRec.x = lightsIII[i].currentFrame*texLight.width/LIGHT_ANIM_FRAMES; + } + + // Enemies logic + if (!enemiesStopped) + { + for (int i = 0; i < MAX_ENEMIES; i++) + { + if (!enemies[i].active) enemies[i].framesCounter++; + + if (enemies[i].framesCounter > enemies[i].awakeFramesDelay) enemies[i].active = true; + + if (enemies[i].active) + { + // Move to the target + Vector2 dir = Vector2Subtract(enemies[i].targetPos, enemies[i].position); + Vector2Normalize(&dir); + + enemies[i].position.x += dir.x*enemies[i].speed; + enemies[i].position.y += dir.y*enemies[i].speed; + + if (currentLightedLevel == LEVEL_I) + { + if (CheckCollisionCircles(enemies[i].position, enemies[i].radius, enemies[i].targetPos, lightsI[enemies[i].targetNum].radius)) + { + lightsI[enemies[i].targetNum].active = false; + lightsI[enemies[i].targetNum].framesCounter = 0; + lightsI[enemies[i].targetNum].currentFrame = 0; + lightsI[enemies[i].targetNum].frameRec = (Rectangle){ 0, 0, 64, 64 }; + + EnemyReset(&enemies[i]); + + PlaySound(fxLightOff); + } + } + else if (currentLightedLevel == LEVEL_II) + { + if (CheckCollisionCircles(enemies[i].position, enemies[i].radius, enemies[i].targetPos, lightsII[enemies[i].targetNum].radius)) + { + lightsII[enemies[i].targetNum].active = false; + lightsII[enemies[i].targetNum].framesCounter = 0; + lightsII[enemies[i].targetNum].currentFrame = 0; + lightsII[enemies[i].targetNum].frameRec = (Rectangle){ 0, 0, 64, 64 }; + + EnemyReset(&enemies[i]); + + PlaySound(fxLightOff); + } + } + else if (currentLightedLevel == LEVEL_III) + { + if (CheckCollisionCircles(enemies[i].position, enemies[i].radius, enemies[i].targetPos, lightsIII[enemies[i].targetNum].radius)) + { + lightsIII[enemies[i].targetNum].active = false; + lightsIII[enemies[i].targetNum].framesCounter = 0; + lightsIII[enemies[i].targetNum].currentFrame = 0; + lightsIII[enemies[i].targetNum].frameRec = (Rectangle){ 0, 0, 64, 64 }; + + EnemyReset(&enemies[i]); + + PlaySound(fxLightOff); + } + } + } + } + } + + // Check current light energy (for right bar) + currentLightEnergy = 0; + + for (int i = 0; i < MAX_LIGHTS_I; i++) if (lightsI[i].active) currentLightEnergy += lightsI[i].requiredEnergy; + for (int i = 0; i < MAX_LIGHTS_II; i++) if (lightsII[i].active) currentLightEnergy += lightsII[i].requiredEnergy; + for (int i = 0; i < MAX_LIGHTS_III; i++) if (lightsIII[i].active) currentLightEnergy += lightsIII[i].requiredEnergy; + + // Check current lighted level + // Check ending conditions: all lights off, ritual level reached + previousLightedLevel = currentLightedLevel; + + currentLightedLevel = LEVEL_I; + + bool lightedLevel = true; + for (int i = 0; i < MAX_LIGHTS_I; i++) if (!lightsI[i].active) lightedLevel = false; + if (lightedLevel) currentLightedLevel = LEVEL_II; + + for (int i = 0; i < MAX_LIGHTS_II; i++) if (!lightsII[i].active) lightedLevel = false; + if (lightedLevel) currentLightedLevel = LEVEL_III; + + for (int i = 0; i < MAX_LIGHTS_III; i++) if (!lightsIII[i].active) lightedLevel = false; + if (lightedLevel) + { + currentLightedLevel = LEVEL_FINISHED; + + for (int i = 0; i < MAX_ENEMIES; i++) enemies[i].active = false; + } + + if (currentLightedLevel != previousLightedLevel) for (int i = 0; i < MAX_ENEMIES; i++) EnemyReset(&enemies[i]); + + ritualTime = (float)framesCounter/60; + + // Check game over condition (time run out) + if ((99.0f - ritualTime) <= 0.0f) + { + ritualTime = 99.0f; + timeOver = true; + } + } + + if (startRitual) + { + alphaRitual += 0.02f; + + SetMusicVolume(1.0f - alphaRitual); + + if (alphaRitual > 1.0f) finishScreen = 1; + } +} + +// Gameplay Screen Draw logic +void DrawGameplayScreen(void) +{ + DrawTexture(background, 0, 0, WHITE); + + // DrawText("STARS ARE ALIGNED! NO TIME TO LOOSE! LIGHT MY RITUAL!", + + // Draw foreground and circles + if ((currentLightedLevel == LEVEL_FINISHED) || (currentLightedLevel == LEVEL_III)) DrawTexture(foregroundIII, 0, 0, WHITE); + else if (currentLightedLevel == LEVEL_II) DrawTexture(foregroundII, 0, 0, WHITE); + else if (currentLightedLevel == LEVEL_I) DrawTexture(foregroundI, 0, 0, WHITE); + + // Draw lighted circles (depends on current lighted level) + switch (currentLightedLevel) + { + case LEVEL_FINISHED: + { + DrawTexture(circleIIIon, GetScreenWidth()/2 - circleIIIon.width/2, GetScreenHeight()/2 - circleIIIon.height/2, WHITE); + DrawTexture(circleIIon, GetScreenWidth()/2 - circleIIon.width/2, GetScreenHeight()/2 - circleIIon.height/2, WHITE); + DrawTexture(circleIon, GetScreenWidth()/2 - circleIon.width/2, GetScreenHeight()/2 - circleIon.height/2, WHITE); + } break; + case LEVEL_III: + { + DrawTexture(circleIIIoff, GetScreenWidth()/2 - circleIIIoff.width/2, GetScreenHeight()/2 - circleIIIoff.height/2, WHITE); + DrawTexture(circleIIon, GetScreenWidth()/2 - circleIIon.width/2, GetScreenHeight()/2 - circleIIon.height/2, WHITE); + DrawTexture(circleIon, GetScreenWidth()/2 - circleIon.width/2, GetScreenHeight()/2 - circleIon.height/2, WHITE); + } break; + case LEVEL_II: + { + DrawTexture(circleIIoff, GetScreenWidth()/2 - circleIIoff.width/2, GetScreenHeight()/2 - circleIIoff.height/2, WHITE); + DrawTexture(circleIon, GetScreenWidth()/2 - circleIon.width/2, GetScreenHeight()/2 - circleIon.height/2, WHITE); + } break; + case LEVEL_I: + { + DrawTexture(circleIoff, GetScreenWidth()/2 - circleIoff.width/2, GetScreenHeight()/2 - circleIoff.height/2, WHITE); + } break; + default: break; + } + + // Draw lights (depends on current lighted level) + switch (currentLightedLevel) + { + case LEVEL_FINISHED: + case LEVEL_III: + { + for (int i = 0; i < MAX_LIGHTS_III; i++) + { + //if (lightsIII[i].active) DrawCircleV(lightsIII[i].position, lightsIII[i].radius, GOLD); + //else DrawCircleLines(lightsIII[i].position.x, lightsIII[i].position.y, lightsIII[i].radius, GRAY); + + if (lightsIII[i].active) + { + DrawTextureRec(texLight, lightsIII[i].frameRec, (Vector2){ lightsIII[i].position.x - 32, lightsIII[i].position.y - 32 }, WHITE); + DrawTexture(lightGlow, lightsIII[i].position.x - lightGlow.width/2, lightsIII[i].position.y - lightGlow.height/2, Fade(WHITE, 0.3f)); + DrawText(FormatText("%02i", lightsIII[i].requiredEnergy), lightsIII[i].position.x - 10, lightsIII[i].position.y + 14, 20, GRAY); + } + else + { + DrawTextureRec(texLight, lightsIII[i].frameRec, (Vector2){ lightsIII[i].position.x - 32, lightsIII[i].position.y - 32 }, WHITE); + DrawText(FormatText("%02i", lightsIII[i].requiredEnergy), lightsIII[i].position.x - 10, lightsIII[i].position.y + 14, 20, YELLOW); + } + } + } + case LEVEL_II: + { + for (int i = 0; i < MAX_LIGHTS_II; i++) + { + //if (lightsII[i].active) DrawCircleV(lightsII[i].position, lightsII[i].radius, GOLD); + //else DrawCircleLines(lightsI[i].position.x, lightsI[i].position.y, lightsI[i].radius, GRAY); + + if (lightsII[i].active) + { + DrawTextureRec(texLight, lightsII[i].frameRec, (Vector2){ lightsII[i].position.x - 32, lightsII[i].position.y - 32 }, WHITE); + DrawTexture(lightGlow, lightsII[i].position.x - lightGlow.width/2, lightsII[i].position.y - lightGlow.height/2, Fade(WHITE, 0.3f)); + DrawText(FormatText("%02i", lightsII[i].requiredEnergy), lightsII[i].position.x - 10, lightsII[i].position.y + 14, 20, GRAY); + } + else + { + DrawTextureRec(texLight, lightsII[i].frameRec, (Vector2){ lightsII[i].position.x - 32, lightsII[i].position.y - 32 }, WHITE); + DrawText(FormatText("%02i", lightsII[i].requiredEnergy), lightsII[i].position.x - 10, lightsII[i].position.y + 14, 20, YELLOW); + } + } + } + case LEVEL_I: + { + for (int i = 0; i < MAX_LIGHTS_I; i++) + { + //if (lightsI[i].active) DrawCircleV(lightsI[i].position, lightsI[i].radius, GOLD); + //else DrawCircleLines(lightsI[i].position.x, lightsI[i].position.y, lightsI[i].radius, GRAY); + + if (lightsI[i].active) + { + DrawTextureRec(texLight, lightsI[i].frameRec, (Vector2){ lightsI[i].position.x - 32, lightsI[i].position.y - 32 }, WHITE); + DrawTexture(lightGlow, lightsI[i].position.x - lightGlow.width/2, lightsI[i].position.y - lightGlow.height/2, Fade(WHITE, 0.3f)); + DrawText(FormatText("%02i", lightsI[i].requiredEnergy), lightsI[i].position.x - 10, lightsI[i].position.y + 14, 20, GRAY); + } + else + { + DrawTextureRec(texLight, lightsI[i].frameRec, (Vector2){ lightsI[i].position.x - 32, lightsI[i].position.y - 32 }, WHITE); + DrawText(FormatText("%02i", lightsI[i].requiredEnergy), lightsI[i].position.x - 10, lightsI[i].position.y + 14, 20, YELLOW); + } + } + } + default: break; + } + + // Draw main lighter + DrawTexture(book, GetScreenWidth()/2 - book.width/2, GetScreenHeight()/2, WHITE); + DrawTexture(lightRay, GetScreenWidth()/2 - lightRay.width/2, 0, Fade(WHITE, 0.5f)); + + // Draw player + //DrawCircleV(player.position, player.radius, player.color); + DrawTexture(texPlayer, player.position.x - 32, player.position.y - 32, player.color); + + if (currentLightedLevel != LEVEL_FINISHED) + { + // Draw enemies (depends on current lighted level) + for (int i = 0; i < MAX_ENEMIES; i++) + { + if (enemies[i].active) + { + //DrawCircleV(enemies[i].position, enemies[i].radius, enemies[i].color); + DrawTextureRec(texEnemy, (Rectangle){ 0, 0, 64, 64 }, (Vector2){ enemies[i].position.x - 32, enemies[i].position.y - 32 }, WHITE); + } + } + + // Draw time left for ritual + DrawTextEx(font, FormatText("%02.2f", (99.0f - ritualTime)), (Vector2){ 560, 20 }, font.size, 0, WHITE); + + // Draw light energy bar + DrawRectangle(20, 30, 400, 20, GRAY); + DrawRectangle(20, 30, (400*player.lightEnergy)/MAX_PLAYER_ENERGY, 20, GOLD); + DrawRectangleLines(20, 30, 400, 20, LIGHTGRAY); + DrawText(FormatText("%03.0f", player.lightEnergy), 430, 30, 20, WHITE); + + // Draw level lighted bar (for completion) + DrawRectangle(GetScreenWidth() - 40, 30, 20, 660, GRAY); + DrawRectangle(GetScreenWidth() - 40, 30 + 660 - 660*currentLightEnergy/maxLightEnergy, 20, 660*currentLightEnergy/maxLightEnergy, YELLOW); + DrawRectangleLines(GetScreenWidth() - 40, 30, 20, 660, LIGHTGRAY); + + // Show message: "You run out of light!!!" if player.lightEnergy <= 0 + if (player.lightEnergy < 2) + { + if ((framesCounter/20)%2) DrawTextEx(font, "YOU'RE RUNNING OUT OF LIGHT!", (Vector2){ 20, 60 }, font.size/2, 0, WHITE); + } + } + else if (!timeOver) // LEVEL_FINISHED + { + DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(BLACK, 0.4f)); + + // Wait some time before jumping to ending: raylib + DrawTexture(texRitual, GetScreenWidth()/2 - texRitual.width/2, 100, WHITE); + DrawTextEx(font, FormatText("BEST LIGHTING TIME: %02.2f", ritualTime), (Vector2){ 320, 340 }, 50, 0, WHITE); + DrawTextEx(font, "PRESS ENTER to START the RITUAL", (Vector2){ 160, 480 }, 60, 0, WHITE); + + if (IsKeyPressed(KEY_ENTER)) startRitual = true; + } + + if (timeOver) + { + DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(BLACK, 0.4f)); + + DrawTexture(texTimeOver, GetScreenWidth()/2 - texTimeOver.width/2, 140, WHITE); + DrawTextEx(font, FormatText("NEXT STARS ALIGNMENT IN %i YEARS", nextStarsAlignment), (Vector2){ 200, 360 }, 50, 0, WHITE); + DrawTextEx(font, "PRESS ENTER to GO HOME...", (Vector2){ 260, 480 }, 60, 0, WHITE); + + if (IsKeyPressed(KEY_ENTER)) finishScreen = 2; + } + + if (startRitual) DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(RAYWHITE, alphaRitual)); + + if (pause) DrawTextEx(font, "RITUAL PAUSED", (Vector2){ GetScreenWidth()/2 - MeasureText("RITUAL PAUSED", 40)/2, 110 }, 50, 0, WHITE); +} + +// Gameplay Screen Unload logic +void UnloadGameplayScreen(void) +{ + // Unload GAMEPLAY screen variables here! + UnloadTexture(background); + UnloadTexture(foregroundI); + UnloadTexture(foregroundII); + UnloadTexture(foregroundIII); + UnloadTexture(texPlayer); + UnloadTexture(texEnemy); + UnloadTexture(texLight); + UnloadTexture(lightGlow); + UnloadTexture(lightRay); + UnloadTexture(book); + UnloadTexture(texRitual); + UnloadTexture(texTimeOver); + + // Unload circles + UnloadTexture(circleIoff); + UnloadTexture(circleIIoff); + UnloadTexture(circleIIIoff); + UnloadTexture(circleIon); + UnloadTexture(circleIIon); + UnloadTexture(circleIIIon); + + // Unload sounds + UnloadSound(fxLightOn); + UnloadSound(fxLightOff); +} + +// Gameplay Screen should finish? +int FinishGameplayScreen(void) +{ + return finishScreen; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Check two colors if equal +static bool ColorEqual(Color col1, Color col2) +{ + return ((col1.r == col2.r) && (col1.g == col2.g) && (col1.b == col2.b) && (col1.a == col2.a)); +} + +// Substract two vectors +static Vector2 Vector2Subtract(Vector2 v1, Vector2 v2) +{ + Vector2 result; + + result.x = v1.x - v2.x; + result.y = v1.y - v2.y; + + return result; +} + +// Normalize provided vector +static void Vector2Normalize(Vector2 *v) +{ + float length, ilength; + + length = sqrt(v->x*v->x + v->y*v->y); + + if (length == 0) length = 1.0f; + + ilength = 1.0f/length; + + v->x *= ilength; + v->y *= ilength; +} + +// Reset enemy parameters +// NOTE: Depends on currentLightedLevel +static void EnemyReset(Enemy *enemy) +{ + enemy->active = false; + enemy->framesCounter = 0; + enemy->color = RED; + enemy->radius = 10; + + int side = GetRandomValue(0, 1); + + if (side) enemy->position = (Vector2){ GetRandomValue(50, 150), GetRandomValue(50, GetScreenHeight() - 50) }; + else enemy->position = (Vector2){ GetRandomValue(GetScreenWidth() - 150, GetScreenWidth() - 50), GetRandomValue(50, GetScreenHeight() - 50) }; + + // TODO: Choose only active lights + // TODO: if currentLightedLevel has no active lights, choose light from a lower level! + + if (currentLightedLevel == LEVEL_I) + { + enemy->targetNum = GetRandomValue(0, MAX_LIGHTS_I - 1); // LEVEL_I + enemy->targetPos = lightsI[enemy->targetNum].position; + enemy->speed = (float)GetRandomValue(15, 20)/10.0f; + enemy->awakeFramesDelay = GetRandomValue(90, 400); + } + else if (currentLightedLevel == LEVEL_II) + { + enemy->targetNum = GetRandomValue(0, MAX_LIGHTS_II - 1); // LEVEL_II + enemy->targetPos = lightsII[enemy->targetNum].position; + enemy->speed = (float)GetRandomValue(10, 20)/10.0f; + enemy->awakeFramesDelay = GetRandomValue(240, 800); + } + else if (currentLightedLevel == LEVEL_III) + { + enemy->targetNum = GetRandomValue(0, MAX_LIGHTS_III - 1); // LEVEL_III + enemy->targetPos = lightsIII[enemy->targetNum].position; + enemy->speed = (float)GetRandomValue(8, 18)/10.0f; + enemy->awakeFramesDelay = GetRandomValue(180, 1200); + } +} \ No newline at end of file diff --git a/games/light_my_ritual/screens/screen_logo_raylib.c b/games/light_my_ritual/screens/screen_logo_raylib.c new file mode 100644 index 00000000..40157b10 --- /dev/null +++ b/games/light_my_ritual/screens/screen_logo_raylib.c @@ -0,0 +1,214 @@ +/********************************************************************************************** +* +* raylib - Advance 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" + +#define LOGO_RECS_SIDE 16 + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Logo screen global variables +static int framesCounter; +static int finishScreen; + +static int logoPositionX; +static int logoPositionY; + +static int lettersCount; + +static int topSideRecWidth; +static int leftSideRecHeight; + +static int bottomSideRecWidth; +static int rightSideRecHeight; + +static char raylib[8]; // raylib text array, max 8 letters +static int state; // Tracking animation states (State Machine) +static float alpha = 1.0f; // Useful for fading + +//---------------------------------------------------------------------------------- +// Logo Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Logo Screen Initialization logic +void rlInitLogoScreen(void) +{ + // Initialize LOGO screen variables here! + finishScreen = 0; + framesCounter = 0; + lettersCount = 0; + + logoPositionX = GetScreenWidth()/2 - 128; + logoPositionY = GetScreenHeight()/2 - 128; + + topSideRecWidth = LOGO_RECS_SIDE; + leftSideRecHeight = LOGO_RECS_SIDE; + bottomSideRecWidth = LOGO_RECS_SIDE; + rightSideRecHeight = LOGO_RECS_SIDE; + + for (int i = 0; i < 8; i++) raylib[i] = '\0'; + + state = 0; + alpha = 1.0f; + + PlayMusicStream("resources/audio/ambient.ogg"); + SetMusicVolume(1.0f); +} + +// Logo Screen Update logic +void rlUpdateLogoScreen(void) +{ + // Update LOGO screen variables here! + if (state == 0) // State 0: Small box blinking + { + framesCounter++; + + if (framesCounter == 80) + { + state = 1; + framesCounter = 0; // Reset counter... will be used later... + } + } + else if (state == 1) // State 1: Top and left bars growing + { + topSideRecWidth += 8; + leftSideRecHeight += 8; + + if (topSideRecWidth == 256) state = 2; + } + else if (state == 2) // State 2: Bottom and right bars growing + { + bottomSideRecWidth += 8; + rightSideRecHeight += 8; + + if (bottomSideRecWidth == 256) state = 3; + } + else if (state == 3) // State 3: Letters appearing (one by one) + { + framesCounter++; + + if (framesCounter/10) // Every 12 frames, one more letter! + { + lettersCount++; + framesCounter = 0; + } + + switch (lettersCount) + { + 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; + } + + // When all letters have appeared... + if (lettersCount >= 10) + { + state = 4; + framesCounter = 0; + } + } + else if (state == 4) + { + framesCounter++; + + if (framesCounter > 100) + { + alpha -= 0.02f; + + if (alpha <= 0.0f) + { + alpha = 0.0f; + finishScreen = 1; + } + } + } +} + +// Logo Screen Draw logic +void rlDrawLogoScreen(void) +{ + if (state == 0) + { + if ((framesCounter/10)%2) DrawRectangle(logoPositionX, logoPositionY, 16, 16, BLACK); + } + else if (state == 1) + { + DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK); + DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK); + } + else if (state == 2) + { + DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK); + DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK); + + DrawRectangle(logoPositionX + 240, logoPositionY, 16, rightSideRecHeight, BLACK); + DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, BLACK); + } + else if (state == 3) + { + DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha)); + DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha)); + + DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha)); + DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha)); + + DrawRectangle(GetScreenWidth()/2 - 112, GetScreenHeight()/2 - 112, 224, 224, Fade(RAYWHITE, alpha)); + + DrawText(raylib, GetScreenWidth()/2 - 44, GetScreenHeight()/2 + 48, 50, Fade(BLACK, alpha)); + } + else if (state == 4) + { + DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha)); + DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha)); + + DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha)); + DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha)); + + DrawRectangle(GetScreenWidth()/2 - 112, GetScreenHeight()/2 - 112, 224, 224, Fade(RAYWHITE, alpha)); + + DrawText(raylib, GetScreenWidth()/2 - 44, GetScreenHeight()/2 + 48, 50, Fade(BLACK, alpha)); + + if (framesCounter > 20) DrawText("powered by", logoPositionX, logoPositionY - 27, 20, Fade(DARKGRAY, alpha)); + } +} + +// Logo Screen Unload logic +void rlUnloadLogoScreen(void) +{ + // TODO: Unload LOGO screen variables here! +} + +// Logo Screen should finish? +int rlFinishLogoScreen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/light_my_ritual/screens/screen_title.c b/games/light_my_ritual/screens/screen_title.c new file mode 100644 index 00000000..c1ecaf12 --- /dev/null +++ b/games/light_my_ritual/screens/screen_title.c @@ -0,0 +1,105 @@ +/********************************************************************************************** +* +* raylib - Advance Game template +* +* Title 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) +//---------------------------------------------------------------------------------- + +// Title screen global variables +static int framesCounter; +static int finishScreen; + +static Texture2D background; +static Texture2D title; +static float titleAlpha = 0.0f; + +static Sound fxStart; + +//---------------------------------------------------------------------------------- +// Title Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Title Screen Initialization logic +void InitTitleScreen(void) +{ + // Initialize TITLE screen variables here! + framesCounter = 0; + finishScreen = 0; + + background = LoadTexture("resources/textures/back_title.png"); + title = LoadTexture("resources/textures/title.png"); + + fxStart = LoadSound("resources/audio/start.wav"); +} + +// Title Screen Update logic +void UpdateTitleScreen(void) +{ + // Update TITLE screen variables here! + framesCounter++; + + titleAlpha += 0.005f; + + if (titleAlpha >= 1.0f) titleAlpha = 1.0f; + + // Press enter to change to ATTIC screen + if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + { + PlaySound(fxStart); + finishScreen = 1; + } +} + +// Title Screen Draw logic +void DrawTitleScreen(void) +{ + DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), (Color){ 26, 26, 26, 255 }); + + DrawTexture(background, GetScreenWidth()/2 - background.width/2, 0, WHITE); + DrawTexture(title, GetScreenWidth()/2 - title.width/2, 30, Fade(WHITE, titleAlpha)); + + DrawText("(c) Developed by Ramon Santamaria (@raysan5)", 20, GetScreenHeight() - 40, 20, LIGHTGRAY); + + if ((framesCounter > 180) && ((framesCounter/40)%2)) DrawTextEx(font, "PRESS ENTER to START LIGHTING", (Vector2){ 230, 450 }, font.size, -2, WHITE); +} + +// Title Screen Unload logic +void UnloadTitleScreen(void) +{ + // Unload TITLE screen variables here! + UnloadTexture(background); + UnloadTexture(title); + + UnloadSound(fxStart); +} + +// Title Screen should finish? +int FinishTitleScreen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/light_my_ritual/screens/screens.h b/games/light_my_ritual/screens/screens.h new file mode 100644 index 00000000..8fee5274 --- /dev/null +++ b/games/light_my_ritual/screens/screens.h @@ -0,0 +1,78 @@ +/********************************************************************************************** +* +* raylib - Advance 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_RL = 0, TITLE, GAMEPLAY } GameScreen; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +GameScreen currentScreen; +SpriteFont font; + +Color *lightsMap; +int lightsMapWidth, lightsMapHeight; + +#ifdef __cplusplus +extern "C" { // Prevents name mangling of functions +#endif + +//---------------------------------------------------------------------------------- +// raylib Logo Screen Functions Declaration +//---------------------------------------------------------------------------------- +void rlInitLogoScreen(void); +void rlUpdateLogoScreen(void); +void rlDrawLogoScreen(void); +void rlUnloadLogoScreen(void); +int rlFinishLogoScreen(void); + +//---------------------------------------------------------------------------------- +// Title Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitTitleScreen(void); +void UpdateTitleScreen(void); +void DrawTitleScreen(void); +void UnloadTitleScreen(void); +int FinishTitleScreen(void); + +//---------------------------------------------------------------------------------- +// Gameplay Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitGameplayScreen(void); +void UpdateGameplayScreen(void); +void DrawGameplayScreen(void); +void UnloadGameplayScreen(void); +int FinishGameplayScreen(void); + +#ifdef __cplusplus +} +#endif + +#endif // SCREENS_H \ No newline at end of file -- cgit v1.2.3 From 728e1715cc52fb25081f3ce17cb5b3f72f7eb218 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 2 Feb 2016 16:43:42 +0100 Subject: Redesigned gestures system... ...and improved mouse gestures support Some testing still required... --- src/core.c | 29 +++++- src/gestures.c | 300 +++++++++++++++++++++++++++++---------------------------- src/raylib.h | 23 +++-- 3 files changed, 189 insertions(+), 163 deletions(-) diff --git a/src/core.c b/src/core.c index cf6fcf33..1c9e16ae 100644 --- a/src/core.c +++ b/src/core.c @@ -253,6 +253,7 @@ static void InitGamepad(void); // Init raw gamepad inpu static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods); // GLFW3 Mouse Button Callback, runs on mouse button pressed +static void MouseCursorPosCallback(GLFWwindow *window, double x, double y); // GLFW3 Cursor Position Callback, runs on mouse move static void CharCallback(GLFWwindow *window, unsigned int key); // GLFW3 Char Key Callback, runs on key pressed (get char value) 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 @@ -1415,6 +1416,7 @@ static void InitDisplay(int width, int height) glfwSetCursorEnterCallback(window, CursorEnterCallback); glfwSetKeyCallback(window, KeyCallback); glfwSetMouseButtonCallback(window, MouseButtonCallback); + glfwSetCursorPosCallback(window, MouseCursorPosCallback); // Track mouse position changes glfwSetCharCallback(window, CharCallback); glfwSetScrollCallback(window, ScrollCallback); glfwSetWindowIconifyCallback(window, WindowIconifyCallback); @@ -1677,7 +1679,7 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int // Register touch actions if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_DOWN; - else if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_MOVE; + //else if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_MOVE; else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_UP; // Register touch points count @@ -1685,7 +1687,28 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int // Register touch points position, only one point registered gestureEvent.position[0] = GetMousePosition(); + + // Gesture data is sent to gestures system for processing + ProcessGestureEvent(gestureEvent); +#endif +} + +// GLFW3 Cursor Position Callback, runs on mouse move +static void MouseCursorPosCallback(GLFWwindow *window, double x, double y) +{ +#define ENABLE_MOUSE_GESTURES +#if defined(ENABLE_MOUSE_GESTURES) + // Process mouse events as touches to be able to use mouse-gestures + GestureEvent gestureEvent; + + gestureEvent.touchAction = TOUCH_MOVE; + + // Register touch points count + gestureEvent.pointCount = 1; + // Register touch points position, only one point registered + gestureEvent.position[0] = (Vector2){ (float)x, (float)y }; + // Gesture data is sent to gestures system for processing ProcessGestureEvent(gestureEvent); #endif @@ -1934,7 +1957,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) // Register touch points count gestureEvent.pointCount = AMotionEvent_getPointerCount(event); - // Register touch points id DESKTOP + // Register touch points id gestureEvent.pointerId[0] = AMotionEvent_getPointerId(event, 0); gestureEvent.pointerId[1] = AMotionEvent_getPointerId(event, 1); @@ -2496,7 +2519,7 @@ static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent // Register touch points count gestureEvent.pointCount = touchEvent->numTouches; - // Register touch points id WEB + // Register touch points id gestureEvent.pointerId[0] = touchEvent->touches[0].identifier; gestureEvent.pointerId[1] = touchEvent->touches[1].identifier; diff --git a/src/gestures.c b/src/gestures.c index ea744555..59f2c5b7 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -46,7 +46,11 @@ // Defines and Macros //---------------------------------------------------------------------------------- #define FORCE_TO_SWIPE 20 -#define TAP_TIMEOUT 300 +#define FORCE_TO_DRAG 20 +#define FORCE_TO_PINCH 5 +#define TAP_TIMEOUT 300 // Time in milliseconds +#define PINCH_TIMEOUT 300 // Time in milliseconds +#define DOUBLETAP_RANGE 30 //#define MAX_TOUCH_POINTS 4 //---------------------------------------------------------------------------------- @@ -61,10 +65,6 @@ typedef enum { //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -static GestureType gestureType = TYPE_MOTIONLESS; -static double eventTime = 0; -//static int32_t touchId; // Not used... - // Tap gesture variables static Vector2 initialTapPosition = { 0, 0 }; @@ -78,6 +78,21 @@ static Vector2 endDragPosition = { 0, 0 }; static Vector2 lastDragPosition = { 0, 0 }; static Vector2 dragVector = { 0, 0 }; +// Albert&Ian +static Vector2 touchDownPosition = { 0, 0 }; +static Vector2 touchDownPosition2 = { 0, 0 }; +static Vector2 touchUpPosition = { 0, 0 }; +static Vector2 moveDownPosition = { 0, 0 }; +static Vector2 moveDownPosition2 = { 0, 0 }; + +static int numTap = 0; +static int numHold = 0; +static int numPinch = 0; +static int pointCount = 0; +static int touchId = -1; + +static double eventTime = 0; + static float magnitude = 0; // Distance traveled dragging static float angle = 0; // Angle direction of the drag static float intensity = 0; // How fast we did the drag (pixels per frame) @@ -95,7 +110,7 @@ static int previousGesture = GESTURE_NONE; static int currentGesture = GESTURE_NONE; // Enabled gestures flags, all gestures enabled by default -static unsigned int enabledGestures = 0b0000011111111111; +static unsigned int enabledGestures = 0b0000001111111111; //---------------------------------------------------------------------------------- // Module specific Functions Declaration @@ -105,6 +120,7 @@ static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, flo static float VectorDistance(Vector2 v1, Vector2 v2); static float VectorDotProduct(Vector2 v1, Vector2 v2); static double GetCurrentTime(); +static float Vector2Distance(); //---------------------------------------------------------------------------------- // Module Functions Definition @@ -119,173 +135,160 @@ void ProcessGestureEvent(GestureEvent event) previousGesture = currentGesture; - switch (gestureType) - { - case TYPE_MOTIONLESS: // Detect TAP, DOUBLE_TAP and HOLD events + pointCount = event.pointCount; + + // Albert&Ian + if (pointCount < 2) + { + touchId = event.pointerId[0]; + if (event.touchAction == TOUCH_DOWN) { - if (event.touchAction == TOUCH_DOWN) + numTap++; // Tap counter + + // Detect GESTURE_DOUBLE_TAP + if ((currentGesture == GESTURE_NONE) && (numTap >= 2) && ((GetCurrentTime() - eventTime) < TAP_TIMEOUT) && (GetMagnitude(touchDownPosition, event.position[0]) < DOUBLETAP_RANGE)) { - if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]); - 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; - } + currentGesture = GESTURE_DOUBLETAP; + numTap = 0; } - else if (event.touchAction == TOUCH_UP) + else // Detect GESTURE_TAP { - 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(); + numTap = 1; + currentGesture = GESTURE_TAP; } - // Begin dragging - else if (event.touchAction == TOUCH_MOVE) + + touchDownPosition = event.position[0]; + + touchUpPosition = touchDownPosition; + eventTime = GetCurrentTime(); + } + else if (event.touchAction == TOUCH_UP) + { + if (currentGesture = GESTURE_DRAG) { - if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]); - else - { - // Set the drag starting position - initialDragPosition = initialTapPosition; - endDragPosition = initialDragPosition; - - // Initialize drag - draggingTimeCounter = 0; - gestureType = TYPE_DRAG; - currentGesture = GESTURE_NONE; - } + touchUpPosition = event.position[0]; } - } break; - case TYPE_DRAG: // Detect DRAG and SWIPE events - { - // end of the drag - if (event.touchAction == TOUCH_UP) + + // Calculate for swipe + magnitude = GetMagnitude(touchDownPosition, touchUpPosition); + intensity = magnitude / (float)draggingTimeCounter; + + // Detect GESTURE_SWIPE + if ((intensity > FORCE_TO_SWIPE) && (touchId == 0)) + { + angle = CalculateAngle(touchDownPosition, touchUpPosition, magnitude); + if ((angle < 30) || (angle > 330)) currentGesture = GESTURE_SWIPE_RIGHT; // Right + else if ((angle > 30) && (angle < 120)) currentGesture = GESTURE_SWIPE_UP; // Up + else if ((angle > 120) && (angle < 210)) currentGesture = GESTURE_SWIPE_LEFT; // Left + else if ((angle > 210) && (angle < 300)) currentGesture = GESTURE_SWIPE_DOWN; // Down + else currentGesture = GESTURE_NONE; + } + else { - // 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; + currentGesture = GESTURE_NONE; } - // Update while we are dragging - else if (event.touchAction == TOUCH_MOVE) + + draggingTimeCounter = 0; + } + else if (event.touchAction == TOUCH_MOVE) + { + if (GetMagnitude(moveDownPosition, event.position[0]) > 5) eventTime = GetCurrentTime(); + moveDownPosition = event.position[0]; + + if (currentGesture == GESTURE_HOLD) { - if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]); - else - { - lastDragPosition = endDragPosition; - endDragPosition = event.position[0]; - - //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; - - // Check if drag movement is less than minimum to keep it as hold state or switch to drag state - if(magnitude > FORCE_TO_SWIPE) - { - currentGesture = GESTURE_DRAG; - draggingTimeCounter++; - } - else currentGesture = GESTURE_HOLD; - } + if (numHold == 1) touchDownPosition = event.position[0]; + + numHold = 2; + + magnitude = GetMagnitude(touchDownPosition, moveDownPosition); + + // Detect GESTURE_DRAG + if (magnitude >= FORCE_TO_DRAG) currentGesture = GESTURE_DRAG; } - } break; - case TYPE_DUAL_INPUT: + + draggingTimeCounter++; + } + } + else + { + // two fingers + + if (event.touchAction == TOUCH_DOWN) + { + touchDownPosition = event.position[0]; + touchDownPosition2 = event.position[1]; + + currentGesture = GESTURE_HOLD; + } + else if (event.touchAction == TOUCH_MOVE) { - if (event.touchAction == TOUCH_UP) + magnitude = GetMagnitude(moveDownPosition, moveDownPosition2); + + touchDownPosition = moveDownPosition; + touchDownPosition2 = moveDownPosition2; + + moveDownPosition = event.position[0]; + moveDownPosition2 = event.position[1]; + + if ( (GetMagnitude(touchDownPosition, moveDownPosition) > FORCE_TO_PINCH) || (GetMagnitude(touchDownPosition2, moveDownPosition2) > FORCE_TO_PINCH)) { - if (event.pointCount == 1) - { - // Set the drag starting position - initialTapPosition = event.position[0]; - } - gestureType = TYPE_MOTIONLESS; + if ((GetMagnitude(moveDownPosition, moveDownPosition2) - magnitude) < 0) currentGesture = GESTURE_PINCH_IN; + else currentGesture = GESTURE_PINCH_OUT; } - else if (event.touchAction == TOUCH_MOVE) + else { - // 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) - { - // Calculate distances - float initialDistance = VectorDistance(firstInitialPinchPosition, secondInitialPinchPosition); - float endDistance = VectorDistance(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 - if (VectorDotProduct(firstTouchVector, secondTouchVector) < -0.5) pinchDelta = initialDistance - endDistance; - else pinchDelta = 0; - - // 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; + currentGesture = GESTURE_HOLD; } - } break; + } + else if (event.touchAction == TOUCH_UP) + { + currentGesture = GESTURE_NONE; + } + } +} + +// Update gestures detected (must be called every frame) +void UpdateGestures(void) +{ + // NOTE: Gestures are processed through system callbacks on touch events + + // Detect GESTURE_HOLD + if (((currentGesture == GESTURE_TAP) || (currentGesture == GESTURE_DOUBLETAP)) && pointCount < 2) currentGesture = GESTURE_HOLD; + if ((GetCurrentTime() - eventTime) > TAP_TIMEOUT && (currentGesture == GESTURE_DRAG) && pointCount < 2) + { + currentGesture = GESTURE_HOLD; + numHold = 1; } + + // Detect GESTURE_NONE + if ((currentGesture == GESTURE_SWIPE_RIGHT) || (currentGesture == GESTURE_SWIPE_UP) || (currentGesture == GESTURE_SWIPE_LEFT) || (currentGesture == GESTURE_SWIPE_DOWN)) + { + currentGesture = GESTURE_NONE; + } +} + +// Calculate distance between two vectors +float Vector2Distance(Vector2 v1, Vector3 v2) +{ + float result; + + float dx = v2.x - v1.x; + float dy = v2.y - v1.y; + + result = sqrt(dx*dx + dy*dy); + + return result; } // Check if a gesture have been detected bool IsGestureDetected(void) { - if (currentGesture != GESTURE_NONE) return true; + if ((enabledGestures & currentGesture) != GESTURE_NONE) return true; else return false; } @@ -298,7 +301,7 @@ int GetGestureType(void) void SetGesturesEnabled(unsigned int gestureFlags) { - enabledGestures = enabledGestures | gestureFlags; + enabledGestures = gestureFlags; } // Get drag intensity (pixels per frame) @@ -440,6 +443,7 @@ static float VectorDotProduct(Vector2 v1, Vector2 v2) return result; } +// Time measure returned are milliseconds static double GetCurrentTime() { double time = 0; diff --git a/src/raylib.h b/src/raylib.h index 6c1a8999..a22c3f83 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -435,17 +435,17 @@ typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode; // Gestures type // NOTE: It could be used as flags to enable only some gestures typedef enum { - GESTURE_NONE = 1, - GESTURE_TAP = 2, - GESTURE_DOUBLETAP = 4, - GESTURE_HOLD = 8, - GESTURE_DRAG = 16, - GESTURE_SWIPE_RIGHT = 32, - GESTURE_SWIPE_LEFT = 64, - GESTURE_SWIPE_UP = 128, - GESTURE_SWIPE_DOWN = 256, - GESTURE_PINCH_IN = 512, - GESTURE_PINCH_OUT = 1024 + GESTURE_NONE = 0, + GESTURE_TAP = 1, + GESTURE_DOUBLETAP = 2, + GESTURE_HOLD = 4, + GESTURE_DRAG = 8, + GESTURE_SWIPE_RIGHT = 16, + GESTURE_SWIPE_LEFT = 32, + GESTURE_SWIPE_UP = 64, + GESTURE_SWIPE_DOWN = 128, + GESTURE_PINCH_IN = 256, + GESTURE_PINCH_OUT = 512 } Gestures; typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction; @@ -781,7 +781,6 @@ bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadi bool CheckCollisionRayBox(Ray ray, Vector3 minBBox, Vector3 maxBBox); // Detect collision between ray and box Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius); // Detect collision of player radius with cubicmap // NOTE: Return the normal vector of the impacted surface - //------------------------------------------------------------------------------------ // Shaders System Functions (Module: rlgl) // NOTE: This functions are useless when using OpenGL 1.1 -- cgit v1.2.3 From 65ecde1e75bd9e2738c8640e966328abeaa5658e Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 2 Feb 2016 17:59:13 +0100 Subject: Cleaned code a little bit --- src/gestures.c | 118 +++++++++------------------------------------------------ 1 file changed, 18 insertions(+), 100 deletions(-) diff --git a/src/gestures.c b/src/gestures.c index 59f2c5b7..8c690066 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -65,20 +65,11 @@ typedef enum { //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -// Tap gesture variables -static Vector2 initialTapPosition = { 0, 0 }; - -// Double Tap gesture variables -static bool doubleTapping = false; -static bool untap = false; // Check if recently done a tap // Drag gesture variables -static Vector2 initialDragPosition = { 0, 0 }; -static Vector2 endDragPosition = { 0, 0 }; -static Vector2 lastDragPosition = { 0, 0 }; static Vector2 dragVector = { 0, 0 }; -// Albert&Ian +// Touch gesture variables static Vector2 touchDownPosition = { 0, 0 }; static Vector2 touchDownPosition2 = { 0, 0 }; static Vector2 touchUpPosition = { 0, 0 }; @@ -87,7 +78,6 @@ static Vector2 moveDownPosition2 = { 0, 0 }; static int numTap = 0; static int numHold = 0; -static int numPinch = 0; static int pointCount = 0; static int touchId = -1; @@ -99,10 +89,6 @@ static float intensity = 0; // How fast we did the drag (pixels per static int draggingTimeCounter = 0; // Time that have passed while dragging // Pinch gesture variables -static Vector2 firstInitialPinchPosition = { 0, 0 }; -static Vector2 secondInitialPinchPosition = { 0, 0 }; -static Vector2 firstEndPinchPosition = { 0, 0 }; -static Vector2 secondEndPinchPosition = { 0, 0 }; static float pinchDelta = 0; // Pinch delta displacement // Detected gestures @@ -115,12 +101,9 @@ static unsigned int enabledGestures = 0b0000001111111111; //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- -static void InitPinchGesture(Vector2 posA, Vector2 posB); static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, float magnitude); -static float VectorDistance(Vector2 v1, Vector2 v2); -static float VectorDotProduct(Vector2 v1, Vector2 v2); +static float Vector2Distance(Vector2 v1, Vector2 v2); static double GetCurrentTime(); -static float Vector2Distance(); //---------------------------------------------------------------------------------- // Module Functions Definition @@ -135,18 +118,18 @@ void ProcessGestureEvent(GestureEvent event) previousGesture = currentGesture; - pointCount = event.pointCount; + pointCount = event.pointCount; // Required on UpdateGestures() - // Albert&Ian if (pointCount < 2) { touchId = event.pointerId[0]; + if (event.touchAction == TOUCH_DOWN) { numTap++; // Tap counter // Detect GESTURE_DOUBLE_TAP - if ((currentGesture == GESTURE_NONE) && (numTap >= 2) && ((GetCurrentTime() - eventTime) < TAP_TIMEOUT) && (GetMagnitude(touchDownPosition, event.position[0]) < DOUBLETAP_RANGE)) + if ((currentGesture == GESTURE_NONE) && (numTap >= 2) && ((GetCurrentTime() - eventTime) < TAP_TIMEOUT) && (Vector2Distance(touchDownPosition, event.position[0]) < DOUBLETAP_RANGE)) { currentGesture = GESTURE_DOUBLETAP; numTap = 0; @@ -164,19 +147,17 @@ void ProcessGestureEvent(GestureEvent event) } else if (event.touchAction == TOUCH_UP) { - if (currentGesture = GESTURE_DRAG) - { - touchUpPosition = event.position[0]; - } - + if (currentGesture == GESTURE_DRAG) touchUpPosition = event.position[0]; + // Calculate for swipe - magnitude = GetMagnitude(touchDownPosition, touchUpPosition); + magnitude = Vector2Distance(touchDownPosition, touchUpPosition); intensity = magnitude / (float)draggingTimeCounter; // Detect GESTURE_SWIPE if ((intensity > FORCE_TO_SWIPE) && (touchId == 0)) { angle = CalculateAngle(touchDownPosition, touchUpPosition, magnitude); + if ((angle < 30) || (angle > 330)) currentGesture = GESTURE_SWIPE_RIGHT; // Right else if ((angle > 30) && (angle < 120)) currentGesture = GESTURE_SWIPE_UP; // Up else if ((angle > 120) && (angle < 210)) currentGesture = GESTURE_SWIPE_LEFT; // Left @@ -196,7 +177,8 @@ void ProcessGestureEvent(GestureEvent event) } else if (event.touchAction == TOUCH_MOVE) { - if (GetMagnitude(moveDownPosition, event.position[0]) > 5) eventTime = GetCurrentTime(); + if (Vector2Distance(moveDownPosition, event.position[0]) > 5) eventTime = GetCurrentTime(); + moveDownPosition = event.position[0]; if (currentGesture == GESTURE_HOLD) @@ -205,7 +187,7 @@ void ProcessGestureEvent(GestureEvent event) numHold = 2; - magnitude = GetMagnitude(touchDownPosition, moveDownPosition); + magnitude = Vector2Distance(touchDownPosition, moveDownPosition); // Detect GESTURE_DRAG if (magnitude >= FORCE_TO_DRAG) currentGesture = GESTURE_DRAG; @@ -214,10 +196,8 @@ void ProcessGestureEvent(GestureEvent event) draggingTimeCounter++; } } - else + else // Two touch points { - // two fingers - if (event.touchAction == TOUCH_DOWN) { touchDownPosition = event.position[0]; @@ -227,7 +207,7 @@ void ProcessGestureEvent(GestureEvent event) } else if (event.touchAction == TOUCH_MOVE) { - magnitude = GetMagnitude(moveDownPosition, moveDownPosition2); + magnitude = Vector2Distance(moveDownPosition, moveDownPosition2); touchDownPosition = moveDownPosition; touchDownPosition2 = moveDownPosition2; @@ -235,9 +215,9 @@ void ProcessGestureEvent(GestureEvent event) moveDownPosition = event.position[0]; moveDownPosition2 = event.position[1]; - if ( (GetMagnitude(touchDownPosition, moveDownPosition) > FORCE_TO_PINCH) || (GetMagnitude(touchDownPosition2, moveDownPosition2) > FORCE_TO_PINCH)) + if ((Vector2Distance(touchDownPosition, moveDownPosition) > FORCE_TO_PINCH) || (Vector2Distance(touchDownPosition2, moveDownPosition2) > FORCE_TO_PINCH)) { - if ((GetMagnitude(moveDownPosition, moveDownPosition2) - magnitude) < 0) currentGesture = GESTURE_PINCH_IN; + if ((Vector2Distance(moveDownPosition, moveDownPosition2) - magnitude) < 0) currentGesture = GESTURE_PINCH_IN; else currentGesture = GESTURE_PINCH_OUT; } else @@ -259,6 +239,7 @@ void UpdateGestures(void) // Detect GESTURE_HOLD if (((currentGesture == GESTURE_TAP) || (currentGesture == GESTURE_DOUBLETAP)) && pointCount < 2) currentGesture = GESTURE_HOLD; + if ((GetCurrentTime() - eventTime) > TAP_TIMEOUT && (currentGesture == GESTURE_DRAG) && pointCount < 2) { currentGesture = GESTURE_HOLD; @@ -272,19 +253,6 @@ void UpdateGestures(void) } } -// Calculate distance between two vectors -float Vector2Distance(Vector2 v1, Vector3 v2) -{ - float result; - - float dx = v2.x - v1.x; - float dy = v2.y - v1.y; - - result = sqrt(dx*dx + dy*dy); - - return result; -} - // Check if a gesture have been detected bool IsGestureDetected(void) { @@ -342,20 +310,6 @@ float GetGesturePinchAngle(void) return 0; } -// Update gestures detected (must be called every frame) -void UpdateGestures(void) -{ - // NOTE: Gestures are processed through system callbacks on touch events - - // When screen is touched, in first frame GESTURE_TAP is called but in next frame touch event callback is not called (if touch position doesn't change), - // so we need to store previous frame gesture type manually in this update function to switch to HOLD if current gesture is - // GESTURE_TAP two frames in a row. Due to current gesture is set to HOLD, current gesture doesn't need to be reset to NONE every frame. - // It will be reset when UP is called. - if(currentGesture == GESTURE_TAP) previousGesture = currentGesture; - - if(previousGesture == GESTURE_TAP && currentGesture == GESTURE_TAP) currentGesture = GESTURE_HOLD; -} - //---------------------------------------------------------------------------------- // Module specific Functions Definition //---------------------------------------------------------------------------------- @@ -395,28 +349,7 @@ static float CalculateAngle(Vector2 initialPosition, Vector2 finalPosition, floa return angle; } -static void InitPinchGesture(Vector2 posA, Vector2 posB) -{ - initialDragPosition = (Vector2){ 0, 0 }; - endDragPosition = (Vector2){ 0, 0 }; - lastDragPosition = (Vector2){ 0, 0 }; - - // Initialize positions - firstInitialPinchPosition = posA; - secondInitialPinchPosition = posB; - - firstEndPinchPosition = firstInitialPinchPosition; - secondEndPinchPosition = secondInitialPinchPosition; - - // Resets - magnitude = 0; - angle = 0; - intensity = 0; - - gestureType = TYPE_DUAL_INPUT; -} - -static float VectorDistance(Vector2 v1, Vector2 v2) +static float Vector2Distance(Vector2 v1, Vector2 v2) { float result; @@ -428,21 +361,6 @@ static float VectorDistance(Vector2 v1, Vector2 v2) return result; } -static float VectorDotProduct(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; -} - // Time measure returned are milliseconds static double GetCurrentTime() { -- cgit v1.2.3 From df5c64d0beee06df8c87a43e5341b6b98f82839f Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 2 Feb 2016 18:41:01 +0100 Subject: Functions parameters reorganize: Axis and Angle sin(), cos() functions cached and replaced by float c99 versions sinf(), cos() --- src/models.c | 12 ++++++------ src/raylib.h | 4 ++-- src/raymath.h | 47 +++++++++++++++++++++++++---------------------- src/rlgl.c | 8 ++++---- src/rlgl.h | 2 +- 5 files changed, 38 insertions(+), 35 deletions(-) diff --git a/src/models.c b/src/models.c index 2d78963e..91cb5813 100644 --- a/src/models.c +++ b/src/models.c @@ -1149,14 +1149,14 @@ void DrawModel(Model model, Vector3 position, float scale, Color tint) Vector3 vScale = { scale, scale, scale }; Vector3 rotationAxis = { 0.0f, 0.0f, 0.0f }; - DrawModelEx(model, position, 0.0f, rotationAxis, vScale, tint); + DrawModelEx(model, position, rotationAxis, 0.0f, vScale, tint); } // Draw a model with extended parameters -void DrawModelEx(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color tint) +void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint) { // NOTE: Rotation must be provided in degrees, it's converted to radians inside rlglDrawModel() - rlglDrawModel(model, position, rotationAngle, rotationAxis, scale, tint, false); + rlglDrawModel(model, position, rotationAxis, rotationAngle, scale, tint, false); } // Draw a model wires (with texture if set) @@ -1165,14 +1165,14 @@ void DrawModelWires(Model model, Vector3 position, float scale, Color color) Vector3 vScale = { scale, scale, scale }; Vector3 rotationAxis = { 0.0f, 0.0f, 0.0f }; - rlglDrawModel(model, position, 0.0f, rotationAxis, vScale, color, true); + rlglDrawModel(model, position, rotationAxis, 0.0f, vScale, color, true); } // Draw a model wires (with texture if set) with extended parameters -void DrawModelWiresEx(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color tint) +void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint) { // NOTE: Rotation must be provided in degrees, it's converted to radians inside rlglDrawModel() - rlglDrawModel(model, position, rotationAngle, rotationAxis, scale, tint, true); + rlglDrawModel(model, position, rotationAxis, rotationAngle, scale, tint, true); } // Draw a billboard diff --git a/src/raylib.h b/src/raylib.h index a22c3f83..c306518d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -764,9 +764,9 @@ void UnloadModel(Model model); void SetModelTexture(Model *model, Texture2D texture); // Link a texture to a model void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) -void DrawModelEx(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color tint); // Draw a model with extended parameters +void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, 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 DrawModelWiresEx(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters +void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters void DrawBoundingBox(BoundingBox box); // Draw bounding box (wires) void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint); // Draw a billboard texture diff --git a/src/raymath.h b/src/raymath.h index 46fab356..35cee39f 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -141,7 +141,7 @@ RMDEF Matrix MatrixIdentity(void); // Returns identit RMDEF Matrix MatrixAdd(Matrix left, Matrix right); // Add two matrices RMDEF Matrix MatrixSubstract(Matrix left, Matrix right); // Substract two matrices (left - right) RMDEF Matrix MatrixTranslate(float x, float y, float z); // Returns translation matrix -RMDEF Matrix MatrixRotate(float angle, Vector3 axis); // Returns rotation matrix for an angle around an specified axis (angle in radians) +RMDEF Matrix MatrixRotate(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis (angle in radians) RMDEF Matrix MatrixRotateX(float angle); // Returns x-rotation matrix (angle in radians) RMDEF Matrix MatrixRotateY(float angle); // Returns y-rotation matrix (angle in radians) RMDEF Matrix MatrixRotateZ(float angle); // Returns z-rotation matrix (angle in radians) @@ -162,8 +162,8 @@ RMDEF Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2); // Calcula RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float slerp); // Calculates spherical linear interpolation between two quaternions RMDEF Quaternion QuaternionFromMatrix(Matrix matrix); // Returns a quaternion for a given rotation matrix RMDEF Matrix QuaternionToMatrix(Quaternion q); // Returns a matrix for a given quaternion -RMDEF Quaternion QuaternionFromAxisAngle(float angle, Vector3 axis); // Returns rotation quaternion for an angle and axis -RMDEF void QuaternionToAxisAngle(Quaternion q, float *outAngle, Vector3 *outAxis); // Returns the rotation angle and axis for a given quaternion +RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle); // Returns rotation quaternion for an angle and axis +RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle); // Returns the rotation angle and axis for a given quaternion RMDEF void QuaternionTransform(Quaternion *q, Matrix mat); // Transform a quaternion given a transformation matrix #ifdef __cplusplus @@ -587,7 +587,7 @@ RMDEF Matrix MatrixTranslate(float x, float y, float z) // Create rotation matrix from axis and angle // NOTE: Angle should be provided in radians -RMDEF Matrix MatrixRotate(float angle, Vector3 axis) +RMDEF Matrix MatrixRotate(Vector3 axis, float angle) { Matrix result; @@ -605,9 +605,9 @@ RMDEF Matrix MatrixRotate(float angle, Vector3 axis) z *= length; } - float s = sinf(angle); - float c = cosf(angle); - float t = 1.0f - c; + float sinres = sinf(angle); + float cosres = cosf(angle); + float t = 1.0f - cosres; // Cache some matrix values (speed optimization) float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3; @@ -615,9 +615,9 @@ RMDEF Matrix MatrixRotate(float angle, Vector3 axis) 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; + float b00 = x*x*t + cosres, b01 = y*x*t + z*sinres, b02 = z*x*t - y*sinres; + float b10 = x*y*t - z*sinres, b11 = y*y*t + cosres, b12 = z*y*t + x*sinres; + float b20 = x*z*t + y*sinres, b21 = y*z*t - x*sinres, b22 = z*z*t + cosres; // Perform rotation-specific matrix multiplication result.m0 = a00*b00 + a10*b01 + a20*b02; @@ -688,8 +688,8 @@ RMDEF Matrix MatrixRotateX(float angle) { Matrix result = MatrixIdentity(); - float cosres = (float)cos(angle); - float sinres = (float)sin(angle); + float cosres = cosf(angle); + float sinres = sinf(angle); result.m5 = cosres; result.m6 = -sinres; @@ -720,8 +720,8 @@ RMDEF Matrix MatrixRotateZ(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.m1 = -sinres; @@ -946,8 +946,8 @@ RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount) } else { - float ratioA = sin((1 - amount)*halfTheta)/sinHalfTheta; - float ratioB = sin(amount*halfTheta)/sinHalfTheta; + float ratioA = sinf((1 - amount)*halfTheta)/sinHalfTheta; + float ratioB = sinf(amount*halfTheta)/sinHalfTheta; result.x = (q1.x*ratioA + q2.x*ratioB); result.y = (q1.y*ratioA + q2.y*ratioB); @@ -1060,7 +1060,7 @@ RMDEF Matrix QuaternionToMatrix(Quaternion q) // Returns rotation quaternion for an angle and axis // NOTE: angle must be provided in radians -RMDEF Quaternion QuaternionFromAxisAngle(float angle, Vector3 axis) +RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle) { Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f }; @@ -1069,11 +1069,14 @@ RMDEF Quaternion QuaternionFromAxisAngle(float angle, Vector3 axis) angle *= 0.5f; VectorNormalize(&axis); + + float sinres = sinf(angle); + float cosres = cosf(angle); - 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); + result.x = axis.x*sinres; + result.y = axis.y*sinres; + result.z = axis.z*sinres; + result.w = cosres; QuaternionNormalize(&result); @@ -1081,7 +1084,7 @@ RMDEF Quaternion QuaternionFromAxisAngle(float angle, Vector3 axis) } // Returns the rotation angle and axis for a given quaternion -RMDEF void QuaternionToAxisAngle(Quaternion q, float *outAngle, Vector3 *outAxis) +RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle) { if (fabs(q.w) > 1.0f) QuaternionNormalize(&q); diff --git a/src/rlgl.c b/src/rlgl.c index 49300054..48e6ac1b 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -411,7 +411,7 @@ void rlRotatef(float angleDeg, float x, float y, float z) Vector3 axis = (Vector3){ x, y, z }; VectorNormalize(&axis); - matRotation = MatrixRotate(angleDeg*DEG2RAD, axis); + matRotation = MatrixRotate(axis, angleDeg*DEG2RAD); MatrixTranspose(&matRotation); @@ -1406,13 +1406,13 @@ void rlglDrawPostpro(void) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glBindFramebuffer(GL_FRAMEBUFFER, 0); - rlglDrawModel(postproQuad, (Vector3){0,0,0}, 0.0f, (Vector3){0,0,0}, (Vector3){1.0f, 1.0f, 1.0f}, (Color){ 255, 255, 255, 255 }, false); + rlglDrawModel(postproQuad, (Vector3){0,0,0}, (Vector3){0,0,0}, 0.0f, (Vector3){1.0f, 1.0f, 1.0f}, (Color){ 255, 255, 255, 255 }, false); #endif } // Draw a 3d model // NOTE: Model transform can come within model struct -void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color color, bool wires) +void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color color, bool wires) { #if defined (GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) // NOTE: glPolygonMode() not available on OpenGL ES @@ -1461,7 +1461,7 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r // Calculate transformation matrix from function parameters // Get transform matrix (rotation -> scale -> translation) - Matrix matRotation = MatrixRotate(rotationAngle*DEG2RAD, rotationAxis); + Matrix matRotation = MatrixRotate(rotationAxis, rotationAngle*DEG2RAD); Matrix matScale = MatrixScale(scale.x, scale.y, scale.z); Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z); Matrix matTransform = MatrixMultiply(MatrixMultiply(matRotation, matScale), matTranslation); diff --git a/src/rlgl.h b/src/rlgl.h index 64581db8..9e0aaaaa 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -262,7 +262,7 @@ void rlglInitPostpro(void); // Initialize postprocessing sys void rlglDrawPostpro(void); // Draw with postprocessing shader Model rlglLoadModel(Mesh mesh); // Upload vertex data into GPU and provided VAO/VBO ids -void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color color, bool wires); +void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color color, bool wires); Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates -- cgit v1.2.3 From 646f1c3f716dd817ff717d35480a744a8be46ead Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 3 Feb 2016 17:45:28 +0100 Subject: Some formating tweaks --- src/camera.c | 114 +++++++++++++++++++++++++++++------------------------------ src/camera.h | 4 +-- src/core.c | 15 ++++---- src/raylib.h | 4 +-- src/rlgl.c | 2 +- 5 files changed, 70 insertions(+), 69 deletions(-) diff --git a/src/camera.c b/src/camera.c index 1e7ac2ff..6539da5f 100644 --- a/src/camera.c +++ b/src/camera.c @@ -36,44 +36,44 @@ // Defines and Macros //---------------------------------------------------------------------------------- // CAMERA_GENERIC -#define CAMERA_SCROLL_SENSITIVITY 1.5 +#define CAMERA_SCROLL_SENSITIVITY 1.5f // 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 +#define FREE_CAMERA_MOUSE_SENSITIVITY 0.01f +#define FREE_CAMERA_DISTANCE_MIN_CLAMP 0.3f +#define FREE_CAMERA_DISTANCE_MAX_CLAMP 120.0f +#define FREE_CAMERA_MIN_CLAMP 85.0f +#define FREE_CAMERA_MAX_CLAMP -85.0f +#define FREE_CAMERA_SMOOTH_ZOOM_SENSITIVITY 0.05f +#define FREE_CAMERA_PANNING_DIVIDER 5.1f // ORBITAL_CAMERA -#define ORBITAL_CAMERA_SPEED 0.01 +#define ORBITAL_CAMERA_SPEED 0.01f // 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_MOUSE_SENSITIVITY 0.003f +#define FIRST_PERSON_FOCUS_DISTANCE 25.0f +#define FIRST_PERSON_MIN_CLAMP 85.0f +#define FIRST_PERSON_MAX_CLAMP -85.0f -#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_STEP_TRIGONOMETRIC_DIVIDER 5.0f +#define FIRST_PERSON_STEP_DIVIDER 30.0f +#define FIRST_PERSON_WAVING_DIVIDER 200.0f -#define FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION 0.85 +#define FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION 0.85f // 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 } +//#define THIRD_PERSON_MOUSE_SENSITIVITY 0.003f +#define THIRD_PERSON_DISTANCE_CLAMP 1.2f +#define THIRD_PERSON_MIN_CLAMP 5.0f +#define THIRD_PERSON_MAX_CLAMP -85.0f +#define THIRD_PERSON_OFFSET (Vector3){ 0.4f, 0.0f, 0.0f } // 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 +#define PLAYER_WIDTH 0.4f +#define PLAYER_HEIGHT 0.9f +#define PLAYER_DEPTH 0.4f +#define PLAYER_MOVEMENT_DIVIDER 20.0f //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -84,11 +84,11 @@ typedef enum { MOVE_FRONT = 0, MOVE_LEFT, MOVE_BACK, MOVE_RIGHT, MOVE_UP, MOVE_D //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -static Camera internalCamera = {{2, 0, 2}, {0, 0, 0}, {0, 1, 0}}; -static Vector2 cameraAngle = { 0, 0 }; +static Camera internalCamera = {{ 2.0f, 0.0f, 2.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; +static Vector2 cameraAngle = { 0.0f, 0.0f }; static float cameraTargetDistance = 5.0f; -static Vector2 cameraMousePosition = { 0, 0 }; -static Vector2 cameraMouseVariation = { 0, 0 }; +static Vector2 cameraMousePosition = { 0.0f, 0.0f }; +static Vector2 cameraMouseVariation = { 0.0f, 0.0f }; static float mouseSensitivity = 0.003f; static int cameraMoveControl[6] = { 'W', 'A', 'S', 'D', 'E', 'Q' }; static int cameraMoveCounter = 0; @@ -107,7 +107,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition); #if defined(CAMERA_STANDALONE) // NOTE: Camera controls depend on some raylib input functions // TODO: Set your own input functions (used in ProcessCamera()) -static Vector2 GetMousePosition() { return (Vector2){ 0, 0}; } +static Vector2 GetMousePosition() { return (Vector2){ 0.0f, 0.0f }; } static void SetMousePosition(Vector2 pos) {} static int IsMouseButtonDown(int button) { return 0;} static int GetMouseWheelMove() { return 0; } @@ -129,33 +129,33 @@ void SetCameraMode(int mode) if ((cameraMode == CAMERA_FIRST_PERSON) && (mode == CAMERA_FREE)) { cameraMode = CAMERA_THIRD_PERSON; - cameraTargetDistance = 5; - cameraAngle.y = -40 * DEG2RAD; + cameraTargetDistance = 5.0f; + 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; + cameraTargetDistance = 5.0f; + 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 }; + cameraTargetDistance = 10.0f; + cameraAngle.x = 45*DEG2RAD; + cameraAngle.y = -40*DEG2RAD; + internalCamera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; ProcessCamera(&internalCamera, &internalCamera.position); ShowCursor(); } else if ((cameraMode == CAMERA_CUSTOM) && (mode == CAMERA_ORBITAL)) { - cameraTargetDistance = 10; - cameraAngle.x = 225 * DEG2RAD; - cameraAngle.y = -40 * DEG2RAD; - internalCamera.target = (Vector3){ 0, 0, 0}; + cameraTargetDistance = 10.0f; + cameraAngle.x = 225*DEG2RAD; + cameraAngle.y = -40*DEG2RAD; + internalCamera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; ProcessCamera(&internalCamera, &internalCamera.position); } @@ -165,7 +165,7 @@ void SetCameraMode(int mode) // Update camera (player position is ignored) void UpdateCamera(Camera *camera) { - Vector3 position = { 0, 0, 0 }; + Vector3 position = { 0.0f, 0.0f, 0.0f }; // Process internal camera and player position (if required) if (cameraMode != CAMERA_CUSTOM) ProcessCamera(&internalCamera, &position); @@ -244,7 +244,7 @@ void SetCameraMoveControls(int frontKey, int backKey, int leftKey, int rightKey, // Set camera mouse sensitivity (1st person and 3rd person cameras) void SetCameraMouseSensitivity(float sensitivity) { - mouseSensitivity = (sensitivity/10000.0); + mouseSensitivity = (sensitivity/10000.0f); } //---------------------------------------------------------------------------------- @@ -376,12 +376,12 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) // Focus to center // TODO: Move this function out of the module? - if (IsKeyDown('Z')) camera->target = (Vector3){ 0, 0, 0 }; + if (IsKeyDown('Z')) camera->target = (Vector3){ 0.0f, 0.0f, 0.0f }; // 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; + if (cameraAngle.y <= 0.0f) 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; @@ -398,12 +398,12 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) if (cameraTargetDistance < THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = THIRD_PERSON_DISTANCE_CLAMP; // Focus to center - if (IsKeyDown('Z')) camera->target = (Vector3){ 0, 0, 0 }; + if (IsKeyDown('Z')) camera->target = (Vector3){ 0.0f, 0.0f, 0.0f }; // 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; + if (cameraAngle.y <= 0.0f) 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; @@ -412,7 +412,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) case CAMERA_FIRST_PERSON: case CAMERA_THIRD_PERSON: { - int isMoving = 0; + bool isMoving = false; // Keyboard inputs if (IsKeyDown(cameraMoveControl[MOVE_FRONT])) @@ -422,7 +422,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) if (!cameraUseGravity) camera->position.y += sin(cameraAngle.y)/PLAYER_MOVEMENT_DIVIDER; - isMoving = 1; + isMoving = true; } else if (IsKeyDown(cameraMoveControl[MOVE_BACK])) { @@ -431,7 +431,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) if (!cameraUseGravity) camera->position.y -= sin(cameraAngle.y)/PLAYER_MOVEMENT_DIVIDER; - isMoving = 1; + isMoving = true; } if (IsKeyDown(cameraMoveControl[MOVE_LEFT])) @@ -439,23 +439,23 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) playerPosition->x -= cos(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER; playerPosition->z += sin(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER; - isMoving = 1; + isMoving = true; } else if (IsKeyDown(cameraMoveControl[MOVE_RIGHT])) { playerPosition->x += cos(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER; playerPosition->z -= sin(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER; - isMoving = 1; + isMoving = true; } if (IsKeyDown(cameraMoveControl[MOVE_UP])) { - if (!cameraUseGravity) playerPosition->y += 1/PLAYER_MOVEMENT_DIVIDER; + if (!cameraUseGravity) playerPosition->y += 1.0f/PLAYER_MOVEMENT_DIVIDER; } else if (IsKeyDown(cameraMoveControl[MOVE_DOWN])) { - if (!cameraUseGravity) playerPosition->y -= 1/PLAYER_MOVEMENT_DIVIDER; + if (!cameraUseGravity) playerPosition->y -= 1.0f/PLAYER_MOVEMENT_DIVIDER; } if (cameraMode == CAMERA_THIRD_PERSON) @@ -482,7 +482,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) // 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; + if (cameraAngle.y <= 0.0f) 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; diff --git a/src/camera.h b/src/camera.h index ed85320a..9ad09c6f 100644 --- a/src/camera.h +++ b/src/camera.h @@ -28,8 +28,8 @@ #define PI 3.14159265358979323846 #endif -#define DEG2RAD (PI / 180.0f) -#define RAD2DEG (180.0f / PI) +#define DEG2RAD (PI/180.0f) +#define RAD2DEG (180.0f/PI) //---------------------------------------------------------------------------------- // Defines and Macros diff --git a/src/core.c b/src/core.c index 1c9e16ae..c872d43e 100644 --- a/src/core.c +++ b/src/core.c @@ -116,6 +116,7 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- +#define STORAGE_FILENAME "storage.data" //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -591,7 +592,7 @@ void Begin3dMode(Camera camera) // Setup perspective projection float aspect = (float)screenWidth/(float)screenHeight; - double top = 0.1f*tan(45.0f*PI/360.0f); + double top = 0.1*tan(45.0*PI/360.0); double right = top*aspect; // NOTE: zNear and zFar values are important when computing depth buffer values @@ -630,7 +631,7 @@ void SetTargetFPS(int fps) // Returns current FPS float GetFPS(void) { - return (float)(1/frameTime); + return (float)(1.0/frameTime); } // Returns time in seconds for one frame @@ -791,10 +792,10 @@ void StorageSaveValue(int position, int value) FILE *storageFile = NULL; // Try open existing file to append data - storageFile = fopen("storage.data", "rb+"); + storageFile = fopen(STORAGE_FILENAME, "rb+"); // If file doesn't exist, create a new storage data file - if (!storageFile) storageFile = fopen("storage.data", "wb"); + if (!storageFile) storageFile = fopen(STORAGE_FILENAME, "wb"); if (!storageFile) TraceLog(WARNING, "Storage data file could not be created"); else @@ -822,7 +823,7 @@ int StorageLoadValue(int position) int value = 0; // Try open existing file to append data - FILE *storageFile = fopen("storage.data", "rb"); + FILE *storageFile = fopen(STORAGE_FILENAME, "rb"); if (!storageFile) TraceLog(WARNING, "Storage data file could not be found"); else @@ -889,8 +890,8 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) MatrixInvert(&matProjView); // Calculate far and near points - Quaternion near = { deviceCoords.x, deviceCoords.y, 0, 1}; - Quaternion far = { deviceCoords.x, deviceCoords.y, 1, 1}; + Quaternion near = { deviceCoords.x, deviceCoords.y, 0.0f, 1.0f}; + Quaternion far = { deviceCoords.x, deviceCoords.y, 1.0f, 1.0f}; // Multiply points by unproject matrix QuaternionTransform(&near, matProjView); diff --git a/src/raylib.h b/src/raylib.h index c306518d..3d8100b3 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -81,8 +81,8 @@ #define PI 3.14159265358979323846 #endif -#define DEG2RAD (PI / 180.0f) -#define RAD2DEG (180.0f / PI) +#define DEG2RAD (PI/180.0f) +#define RAD2DEG (180.0f/PI) // raylib Config Flags #define FLAG_FULLSCREEN_MODE 1 diff --git a/src/rlgl.c b/src/rlgl.c index 48e6ac1b..6810cb4b 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1406,7 +1406,7 @@ void rlglDrawPostpro(void) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glBindFramebuffer(GL_FRAMEBUFFER, 0); - rlglDrawModel(postproQuad, (Vector3){0,0,0}, (Vector3){0,0,0}, 0.0f, (Vector3){1.0f, 1.0f, 1.0f}, (Color){ 255, 255, 255, 255 }, false); + rlglDrawModel(postproQuad, (Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, 0.0f, (Vector3){1.0f, 1.0f, 1.0f}, (Color){ 255, 255, 255, 255 }, false); #endif } -- cgit v1.2.3 From 4fae37bb88962816328a6b4e0f23bedb084b0604 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 7 Feb 2016 11:08:31 +0100 Subject: Removed floppy game, available as sample --- games/floppy/floppy.c | 213 ---------------------------------- games/floppy/resources/background.png | Bin 228930 -> 0 bytes games/floppy/resources/coin.wav | Bin 37396 -> 0 bytes games/floppy/resources/floppy.png | Bin 2030 -> 0 bytes games/floppy/resources/jump.wav | Bin 14540 -> 0 bytes games/floppy/resources/tubes.png | Bin 19623 -> 0 bytes 6 files changed, 213 deletions(-) delete mode 100644 games/floppy/floppy.c delete mode 100644 games/floppy/resources/background.png delete mode 100644 games/floppy/resources/coin.wav delete mode 100644 games/floppy/resources/floppy.png delete mode 100644 games/floppy/resources/jump.wav delete mode 100644 games/floppy/resources/tubes.png diff --git a/games/floppy/floppy.c b/games/floppy/floppy.c deleted file mode 100644 index 0c0cb5f2..00000000 --- a/games/floppy/floppy.c +++ /dev/null @@ -1,213 +0,0 @@ -/******************************************************************************************* -* -* raylib game - Floppy Bird -* -* This game has been created using raylib 1.1 (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" - -#define MAX_TUBES 100 - -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "Floppy Bird"); - - InitAudioDevice(); // Initialize audio device - - Sound coin = LoadSound("resources/coin.wav"); - Sound jump = LoadSound("resources/jump.wav"); - - Texture2D background = LoadTexture("resources/background.png"); - Texture2D tubes = LoadTexture("resources/tubes.png"); - Texture2D floppy = LoadTexture("resources/floppy.png"); - - Vector2 floppyPos = { 80, screenHeight/2 - floppy.height/2 }; - - Vector2 tubesPos[MAX_TUBES]; - int tubesSpeedX = 2; - - for (int i = 0; i < MAX_TUBES; i++) - { - tubesPos[i].x = 400 + 280*i; - tubesPos[i].y = -GetRandomValue(0, 120); - } - - Rectangle tubesRecs[MAX_TUBES*2]; - bool tubesActive[MAX_TUBES]; - - for (int i = 0; i < MAX_TUBES*2; i += 2) - { - tubesRecs[i].x = tubesPos[i/2].x; - tubesRecs[i].y = tubesPos[i/2].y; - tubesRecs[i].width = tubes.width; - tubesRecs[i].height = 255; - - tubesRecs[i+1].x = tubesPos[i/2].x; - tubesRecs[i+1].y = 600 + tubesPos[i/2].y - 255; - tubesRecs[i+1].width = tubes.width; - tubesRecs[i+1].height = 255; - - tubesActive[i/2] = true; - } - - int backScroll = 0; - - int score = 0; - int hiscore = 0; - - bool gameover = false; - bool superfx = false; - - SetTargetFPS(60); - //--------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - - // Background scroll logic - backScroll--; - if (backScroll <= -800) backScroll = 0; - - // Player movement logic - if (!gameover) - { - if (IsKeyDown(KEY_SPACE)) floppyPos.y -= 3; - else floppyPos.y += 1; - - if (IsKeyPressed(KEY_SPACE)) PlaySound(jump); - } - - // Tubes moving logic - for (int i = 0; i < MAX_TUBES; i++) tubesPos[i].x -= tubesSpeedX; - - for (int i = 0; i < MAX_TUBES*2; i += 2) - { - tubesRecs[i].x = tubesPos[i/2].x; - tubesRecs[i+1].x = tubesPos[i/2].x; - } - - // Check collisions player-tubes - for (int i = 0; i < MAX_TUBES*2; i++) - { - if (CheckCollisionCircleRec((Vector2){ floppyPos.x + floppy.width/2, floppyPos.y + floppy.height/2 }, floppy.width/2, tubesRecs[i])) - { - gameover = true; - } - else if ((tubesPos[i/2].x < floppyPos.x) && tubesActive[i/2] && !gameover) - { - score += 100; - tubesActive[i/2] = false; - PlaySound(coin); - - superfx = true; - - if (score > hiscore) hiscore = score; - } - } - - // Gameover logic for reset - if (gameover && IsKeyPressed(KEY_ENTER)) - { - for (int i = 0; i < MAX_TUBES; i++) - { - tubesPos[i].x = 400 + 280*i; - tubesPos[i].y = -GetRandomValue(0, 120); - } - - for (int i = 0; i < MAX_TUBES*2; i += 2) - { - tubesRecs[i].x = tubesPos[i/2].x; - tubesRecs[i].y = tubesPos[i/2].y; - - tubesRecs[i+1].x = tubesPos[i/2].x; - tubesRecs[i+1].y = 600 + tubesPos[i/2].y - 255; - - tubesActive[i/2] = true; - } - - floppyPos.x = 80; - floppyPos.y = screenHeight/2 - floppy.height/2; - - gameover = false; - score = 0; - } - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - // Draw scrolling background - DrawTexture(background, backScroll, 0, WHITE); - DrawTexture(background, screenWidth + backScroll, 0, WHITE); - - // Draw moving tubes - for (int i = 0; i < MAX_TUBES; i++) - { - if (tubesPos[i].x <= 800) DrawTextureEx(tubes, tubesPos[i], 0, 1.0, WHITE); - - // Draw collision recs - //DrawRectangleLines(tubesRecs[i*2].x, tubesRecs[i*2].y, tubesRecs[i*2].width, tubesRecs[i*2].height, RED); - //DrawRectangleLines(tubesRecs[i*2 + 1].x, tubesRecs[i*2 + 1].y, tubesRecs[i*2 + 1].width, tubesRecs[i*2 + 1].height, RED); - } - - // Draw scores - DrawText(FormatText("%04i", score), 20, 20, 40, PINK); - DrawText(FormatText("HI-SCORE: %04i", hiscore), 20, 70, 20, VIOLET); - - // Draw player or game over messages - if (!gameover) - { - DrawTextureEx(floppy, floppyPos, 0, 1.0, WHITE); - - // Draw collision circle - //DrawCircleLines(floppyPos.x + floppy.width/2, floppyPos.y + floppy.height/2, floppy.width/2, RED); - } - else - { - DrawText("GAME OVER", 100, 180, 100, MAROON); - DrawText("PRESS ENTER to RETRY!", 280, 280, 20, RED); - } - - // Draw screen light flash when passing through a tube - if (superfx) - { - DrawRectangle(0, 0, screenWidth, screenHeight, GOLD); - superfx = false; - } - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadTexture(background); // Texture unloading - UnloadTexture(tubes); // Texture unloading - UnloadTexture(floppy); // Texture unloading - - UnloadSound(coin); // Unload sound data - UnloadSound(jump); // Unload sound data - - CloseAudioDevice(); // Close audio device - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/games/floppy/resources/background.png b/games/floppy/resources/background.png deleted file mode 100644 index eab9d865..00000000 Binary files a/games/floppy/resources/background.png and /dev/null differ diff --git a/games/floppy/resources/coin.wav b/games/floppy/resources/coin.wav deleted file mode 100644 index d3b6e93c..00000000 Binary files a/games/floppy/resources/coin.wav and /dev/null differ diff --git a/games/floppy/resources/floppy.png b/games/floppy/resources/floppy.png deleted file mode 100644 index 7c851086..00000000 Binary files a/games/floppy/resources/floppy.png and /dev/null differ diff --git a/games/floppy/resources/jump.wav b/games/floppy/resources/jump.wav deleted file mode 100644 index 1f68d336..00000000 Binary files a/games/floppy/resources/jump.wav and /dev/null differ diff --git a/games/floppy/resources/tubes.png b/games/floppy/resources/tubes.png deleted file mode 100644 index a3ca8e7e..00000000 Binary files a/games/floppy/resources/tubes.png and /dev/null differ -- cgit v1.2.3 From 4a3509f06d60e2761aa048378fe979e11a5a1667 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 7 Feb 2016 11:09:12 +0100 Subject: Added game sources: Skully Escape This game was developed for King GameJam 2015 --- games/skully_escape/makefile | 254 ++++++++++++ games/skully_escape/monster.c | 54 +++ games/skully_escape/monster.h | 73 ++++ games/skully_escape/player.c | 281 +++++++++++++ games/skully_escape/player.h | 51 +++ .../resources/audio/come_play_with_me.ogg | Bin 0 -> 2310768 bytes games/skully_escape/resources/audio/door.ogg | Bin 0 -> 32434 bytes games/skully_escape/resources/audio/scream.ogg | Bin 0 -> 19696 bytes games/skully_escape/resources/textures/alagard.png | Bin 0 -> 36659 bytes .../resources/textures/background_aisle01.png | Bin 0 -> 670481 bytes .../resources/textures/background_aisle02.png | Bin 0 -> 507254 bytes .../resources/textures/background_armory.png | Bin 0 -> 252006 bytes .../resources/textures/background_attic.png | Bin 0 -> 286704 bytes .../resources/textures/background_bathroom.png | Bin 0 -> 254709 bytes .../resources/textures/background_kitchen.png | Bin 0 -> 310161 bytes .../resources/textures/background_livingroom.png | Bin 0 -> 319096 bytes games/skully_escape/resources/textures/doors.png | Bin 0 -> 82485 bytes .../resources/textures/monster_arc.png | Bin 0 -> 49342 bytes .../resources/textures/monster_blazon01.png | Bin 0 -> 47467 bytes .../resources/textures/monster_blazon02.png | Bin 0 -> 47085 bytes .../resources/textures/monster_blazon03.png | Bin 0 -> 52593 bytes .../resources/textures/monster_candle.png | Bin 0 -> 70445 bytes .../resources/textures/monster_chair_left.png | Bin 0 -> 42529 bytes .../resources/textures/monster_chair_right.png | Bin 0 -> 46303 bytes .../resources/textures/monster_closet.png | Bin 0 -> 93494 bytes .../resources/textures/monster_lamp_left.png | Bin 0 -> 80413 bytes .../resources/textures/monster_lamp_right.png | Bin 0 -> 148299 bytes .../resources/textures/monster_mirror.png | Bin 0 -> 67383 bytes .../resources/textures/monster_phone.png | Bin 0 -> 51545 bytes .../resources/textures/monster_picture.png | Bin 0 -> 96506 bytes .../resources/textures/monster_window.png | Bin 0 -> 175595 bytes games/skully_escape/resources/textures/skully.png | Bin 0 -> 138765 bytes .../resources/textures/skully_icon.png | Bin 0 -> 3165 bytes .../resources/textures/skully_logo.png | Bin 0 -> 19137 bytes games/skully_escape/resources/textures/title.png | Bin 0 -> 120338 bytes games/skully_escape/screens/screen_aisle01.c | 409 +++++++++++++++++++ games/skully_escape/screens/screen_aisle02.c | 444 +++++++++++++++++++++ games/skully_escape/screens/screen_armory.c | 404 +++++++++++++++++++ games/skully_escape/screens/screen_attic.c | 332 +++++++++++++++ games/skully_escape/screens/screen_bathroom.c | 383 ++++++++++++++++++ games/skully_escape/screens/screen_ending.c | 90 +++++ games/skully_escape/screens/screen_kitchen.c | 403 +++++++++++++++++++ games/skully_escape/screens/screen_livingroom.c | 403 +++++++++++++++++++ games/skully_escape/screens/screen_logo.c | 108 +++++ games/skully_escape/screens/screen_logo_raylib.c | 201 ++++++++++ games/skully_escape/screens/screen_title.c | 92 +++++ games/skully_escape/screens/screens.h | 164 ++++++++ games/skully_escape/skully_escape.c | 403 +++++++++++++++++++ 48 files changed, 4549 insertions(+) create mode 100644 games/skully_escape/makefile create mode 100644 games/skully_escape/monster.c create mode 100644 games/skully_escape/monster.h create mode 100644 games/skully_escape/player.c create mode 100644 games/skully_escape/player.h create mode 100644 games/skully_escape/resources/audio/come_play_with_me.ogg create mode 100644 games/skully_escape/resources/audio/door.ogg create mode 100644 games/skully_escape/resources/audio/scream.ogg create mode 100644 games/skully_escape/resources/textures/alagard.png create mode 100644 games/skully_escape/resources/textures/background_aisle01.png create mode 100644 games/skully_escape/resources/textures/background_aisle02.png create mode 100644 games/skully_escape/resources/textures/background_armory.png create mode 100644 games/skully_escape/resources/textures/background_attic.png create mode 100644 games/skully_escape/resources/textures/background_bathroom.png create mode 100644 games/skully_escape/resources/textures/background_kitchen.png create mode 100644 games/skully_escape/resources/textures/background_livingroom.png create mode 100644 games/skully_escape/resources/textures/doors.png create mode 100644 games/skully_escape/resources/textures/monster_arc.png create mode 100644 games/skully_escape/resources/textures/monster_blazon01.png create mode 100644 games/skully_escape/resources/textures/monster_blazon02.png create mode 100644 games/skully_escape/resources/textures/monster_blazon03.png create mode 100644 games/skully_escape/resources/textures/monster_candle.png create mode 100644 games/skully_escape/resources/textures/monster_chair_left.png create mode 100644 games/skully_escape/resources/textures/monster_chair_right.png create mode 100644 games/skully_escape/resources/textures/monster_closet.png create mode 100644 games/skully_escape/resources/textures/monster_lamp_left.png create mode 100644 games/skully_escape/resources/textures/monster_lamp_right.png create mode 100644 games/skully_escape/resources/textures/monster_mirror.png create mode 100644 games/skully_escape/resources/textures/monster_phone.png create mode 100644 games/skully_escape/resources/textures/monster_picture.png create mode 100644 games/skully_escape/resources/textures/monster_window.png create mode 100644 games/skully_escape/resources/textures/skully.png create mode 100644 games/skully_escape/resources/textures/skully_icon.png create mode 100644 games/skully_escape/resources/textures/skully_logo.png create mode 100644 games/skully_escape/resources/textures/title.png create mode 100644 games/skully_escape/screens/screen_aisle01.c create mode 100644 games/skully_escape/screens/screen_aisle02.c create mode 100644 games/skully_escape/screens/screen_armory.c create mode 100644 games/skully_escape/screens/screen_attic.c create mode 100644 games/skully_escape/screens/screen_bathroom.c create mode 100644 games/skully_escape/screens/screen_ending.c create mode 100644 games/skully_escape/screens/screen_kitchen.c create mode 100644 games/skully_escape/screens/screen_livingroom.c create mode 100644 games/skully_escape/screens/screen_logo.c create mode 100644 games/skully_escape/screens/screen_logo_raylib.c create mode 100644 games/skully_escape/screens/screen_title.c create mode 100644 games/skully_escape/screens/screens.h create mode 100644 games/skully_escape/skully_escape.c diff --git a/games/skully_escape/makefile b/games/skully_escape/makefile new file mode 100644 index 00000000..0a343037 --- /dev/null +++ b/games/skully_escape/makefile @@ -0,0 +1,254 @@ +#************************************************************************************************** +# +# raylib - Advance Game +# +# makefile to compile advance game +# +# 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 if not defined (by default, compile for RPI) +# Other possible platform: PLATFORM_DESKTOP +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 = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources -s ALLOW_MEMORY_GROWTH=1 + #-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 + +# 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. -IC:/raylib/raylib/src -IC:/raylib/raylib/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. -LC:/raylib/raylib/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 = C:/raylib/raylib/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 = C:/raylib/raylib/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_logo_raylib.o \ + screens/screen_title.o \ + screens/screen_attic.o \ + screens/screen_aisle01.o \ + screens/screen_aisle02.o \ + screens/screen_armory.o \ + screens/screen_livingroom.o \ + screens/screen_kitchen.o \ + screens/screen_bathroom.o \ + screens/screen_ending.o \ + player.o \ + monster.o \ + +# typing 'make' will invoke the first target entry in the file, +# in this case, the 'default' target entry is advance_game +default: skully_escape + +# compile template - advance_game +skully_escape: skully_escape.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 LOGO raylib +screens/screen_logo_raylib.o: screens/screen_logo_raylib.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen TITLE +screens/screen_title.o: screens/screen_title.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen ATTIC +screens/screen_attic.o: screens/screen_attic.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen AISLE01 +screens/screen_aisle01.o: screens/screen_aisle01.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen AISLE02 +screens/screen_aisle02.o: screens/screen_aisle02.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen BATHROOM +screens/screen_bathroom.o: screens/screen_bathroom.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen LIVINGROOM +screens/screen_livingroom.o: screens/screen_livingroom.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen KITCHEN +screens/screen_kitchen.o: screens/screen_kitchen.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen ARMORY +screens/screen_armory.o: screens/screen_armory.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen ENDING +screens/screen_ending.o: screens/screen_ending.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen LOGO +player.o: player.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen LOGO +monster.o: monster.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) diff --git a/games/skully_escape/monster.c b/games/skully_escape/monster.c new file mode 100644 index 00000000..643d0a73 --- /dev/null +++ b/games/skully_escape/monster.c @@ -0,0 +1,54 @@ +/*********************************************************************************** +* +* KING GAME JAM - GRAY TEAM +* +* +* +* +* This game has been created using raylib (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" +#include "monster.h" + +void UpdateMonster(Monster *monster) +{ + if (!monster->active) + { + if (CheckCollisionPointRec(GetMousePosition(), monster->bounds)) monster->selected = true; + else monster->selected = false; + } + else if (monster->spooky) + { + monster->framesCounter++; + monster->currentSeq = 0; + + if (monster->framesCounter > 7) + { + monster->currentFrame++; + monster->framesCounter = 0; + + if (monster->currentFrame > monster->numFrames - 1) monster->currentFrame = 1; + } + } + + monster->frameRec.x = monster->currentFrame*monster->texture.width/monster->numFrames; + monster->frameRec.y = monster->currentSeq*monster->texture.height; +} + +void DrawMonster(Monster monster, int scroll) +{ + Vector2 scrollPos = { monster.position.x - scroll, monster.position.y }; + + if (monster.selected) DrawTextureRec(monster.texture, monster.frameRec, scrollPos, RED); + else DrawTextureRec(monster.texture, monster.frameRec, scrollPos, WHITE); +} + +void UnloadMonster(Monster monster) +{ + UnloadTexture(monster.texture); +} \ No newline at end of file diff --git a/games/skully_escape/monster.h b/games/skully_escape/monster.h new file mode 100644 index 00000000..e7e01856 --- /dev/null +++ b/games/skully_escape/monster.h @@ -0,0 +1,73 @@ +/********************************************************************************************** +* +* raylib - Advance 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 MONSTER_H +#define MONSTER_H + +#define MONSTER_ANIM_FRAMES 7 +#define MONSTER_ANIM_SEQ 2 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//--------------------------------------------------------------------------------- +typedef struct Monster { + Vector2 position; + Texture2D texture; + Rectangle bounds; + Rectangle frameRec; + Color color; + int framesCounter; + int currentFrame; + int currentSeq; + int numFrames; + bool active; + bool selected; + bool spooky; +} Monster; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- + + + +#ifdef __cplusplus +extern "C" { // Prevents name mangling of functions +#endif + +//---------------------------------------------------------------------------------- +// Monster Functions Declaration +//---------------------------------------------------------------------------------- + +void UpdateMonster(Monster *monster); +void DrawMonster(Monster monster, int scroll); +void UnloadMonster(Monster monster); + + +#ifdef __cplusplus +} +#endif + +#endif // SCREENS_H \ No newline at end of file diff --git a/games/skully_escape/player.c b/games/skully_escape/player.c new file mode 100644 index 00000000..11006f65 --- /dev/null +++ b/games/skully_escape/player.c @@ -0,0 +1,281 @@ +/*********************************************************************************** +* +* KING GAME JAM - GRAY TEAM +* +* +* +* +* This game has been created using raylib (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" +#include "player.h" + +#define PLAYER_ANIM_FRAMES 4 +#define PLAYER_ANIM_SEQ 6 + +//---------------------------------------------------------------------------------- +// Module Variables Definition +//---------------------------------------------------------------------------------- + +// Player mouse moving variables +static bool movingAnim; +static int moveDirection; +static int nextMovePoint; + +// Mouse pointer variables +static Vector2 pointerPosition; +static bool pointerAnim; +static float pointerAlpha; + +static int framesCounter; +static bool outControl = false; + +static int animTimer = 0; + +static Texture2D texLife; + +static void DrawLifes(void); + +// player initialitaction definition +void InitPlayer(void) +{ + // NOTE: Some player variables are only initialized once + player.texture = LoadTexture("resources/textures/skully.png"); + player.position = (Vector2){ 350, 400 }; + player.numLifes = 4; + + ResetPlayer(); + + framesCounter = 0; + + texLife = LoadTexture("resources/textures/skully_icon.png"); +} + +// player update definition +void UpdatePlayer(void) +{ + if (!outControl) + { + if ((IsKeyDown(KEY_LEFT)) || (IsKeyDown(KEY_RIGHT))) + { + moveDirection = -1; + movingAnim = false; + } + + if ((IsKeyDown(KEY_RIGHT)) || (moveDirection == 0)) + { + player.currentSeq = WALK_RIGHT; + framesCounter++; + + if (framesCounter > 15) + { + player.currentFrame++; + framesCounter = 0; + + if (player.currentFrame > PLAYER_ANIM_FRAMES - 1) player.currentFrame = 0; + } + + player.position.x += 4; + } + else if ((IsKeyDown(KEY_LEFT)) || (moveDirection == 1)) + { + player.currentSeq = WALK_LEFT; + framesCounter++; + + if (framesCounter > 15) + { + player.currentFrame++; + framesCounter = 0; + + if (player.currentFrame > PLAYER_ANIM_FRAMES - 1) player.currentFrame = 0; + } + + player.position.x -= 4; + } + else player.currentFrame = 0; + } + else + { + framesCounter++; + animTimer++; + + if (framesCounter > 10) + { + player.currentFrame++; + framesCounter = 0; + + if (player.currentFrame > PLAYER_ANIM_FRAMES - 1) player.currentFrame = 0; + + // We can adjust animation playing time depending on sequence + switch (player.currentSeq) + { + case SCARE_RIGHT: + { + if (animTimer > 180) + { + animTimer = 0; + outControl = false; + player.currentSeq = WALK_LEFT; + } + } break; + case SCARE_LEFT: + { + if (animTimer > 240) + { + animTimer = 0; + outControl = false; + player.currentSeq = WALK_RIGHT; + } + } break; + case SEARCH: + case FIND_KEY: + { + if (animTimer > 240) + { + animTimer = 0; + outControl = false; + player.currentSeq = WALK_RIGHT; + } + } break; + } + } + } + + if (player.position.x < 30) player.position.x = 30; + else if (player.position.x > (GetScreenWidth() - 200)) player.position.x = GetScreenWidth() - 200; + + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + pointerPosition = GetMousePosition(); + pointerAnim = true; + pointerAlpha = 1.0f; + + nextMovePoint = (int)pointerPosition.x; + movingAnim = true; + } + + if (movingAnim) + { + if (nextMovePoint > (player.position.x + (player.frameRec.width/2) + 5)) moveDirection = 0; // Move Left + else if (nextMovePoint < (player.position.x + (player.frameRec.width/2) - 5)) moveDirection = 1; // Move Right + else + { + moveDirection = -1; + movingAnim = 0; + } + } + + player.frameRec.x = player.currentFrame*player.texture.width/PLAYER_ANIM_FRAMES; + player.frameRec.y = (player.currentSeq - 1)*player.texture.height/PLAYER_ANIM_SEQ; + + // Update player bounds + player.bounds = (Rectangle){ player.position.x + 50, player.position.y - 60, 100, 300 }; + + // Mouse pointer alpha animation + if (pointerAnim) + { + pointerAlpha -= 0.1f; + + if (pointerAlpha <= 0.0f) + { + pointerAlpha = 0.0f; + pointerAnim = false; + } + } +} +// +void DrawPlayer(void) +{ + DrawTextureRec(player.texture, player.frameRec, player.position, WHITE); + + // Draw mouse pointer on click + if (pointerAnim) DrawCircleV(pointerPosition, 20, Fade(RED, pointerAlpha)); + + DrawLifes(); +} + +void UnloadPlayer(void) +{ + UnloadTexture(player.texture); + UnloadTexture(texLife); +} + +void ResetPlayer(void) +{ + // Reset player variables + player.frameRec = (Rectangle){ 0, 0, player.texture.width/PLAYER_ANIM_FRAMES, player.texture.height/PLAYER_ANIM_SEQ }; + player.currentFrame = 0; + player.currentSeq = WALK_RIGHT; + + player.key = false; + player.dead = false; + + // Reset player position + if (player.position.x < 400) player.position.x = GetScreenWidth() - 350; + if (player.position.x > (GetScreenWidth() - 400)) player.position.x = 350; + + // Reset moving variables + movingAnim = false; + moveDirection = -1; + nextMovePoint = 0; + framesCounter = 0; + outControl = false; + animTimer = 0; + + // Reset pointer + pointerAlpha = 0.0f; + pointerAnim = false; +} + +void ScarePlayer(void) +{ + player.currentFrame = 0; + + if (moveDirection == 0) player.currentSeq = SCARE_RIGHT; + else if (moveDirection == 1) player.currentSeq = SCARE_LEFT; + else player.currentSeq = SCARE_RIGHT; + + player.numLifes--; + + if (player.numLifes <= 0) player.dead = true; + + outControl = true; +} + +void SearchKeyPlayer(void) +{ + moveDirection = -1; + movingAnim = 0; + + player.currentFrame = 0; + player.currentSeq = SEARCH; + + outControl = true; +} + +void FindKeyPlayer(void) +{ + player.currentFrame = 0; + player.currentSeq = FIND_KEY; + player.key = true; + + outControl = true; +} + +static void DrawLifes(void) +{ + if (player.numLifes != 0) + { + Vector2 position = { 20, GetScreenHeight() - texLife.height - 20 }; + + for(int i = 0; i < player.numLifes; i++) + { + DrawTexture(texLife, position.x + i*texLife.width, position.y, Fade(RAYWHITE, 0.7f)); + } + } +} \ No newline at end of file diff --git a/games/skully_escape/player.h b/games/skully_escape/player.h new file mode 100644 index 00000000..7d59bdde --- /dev/null +++ b/games/skully_escape/player.h @@ -0,0 +1,51 @@ +#ifndef PLAYER_H +#define PLAYER_H + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum { NONE, WALK_RIGHT, WALK_LEFT, SCARE_RIGHT, SCARE_LEFT, SEARCH, FIND_KEY } PlayerSequence; + +typedef struct Player { + Vector2 position; + Rectangle bounds; + Texture2D texture; + Color color; + + // Animation variables + Rectangle frameRec; + int currentFrame; + int currentSeq; + + bool key; + int numLifes; + bool dead; +} Player; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +Player player; + +#ifdef __cplusplus +extern "C" { // Prevents name mangling of functions +#endif + +//---------------------------------------------------------------------------------- +// Logo Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitPlayer(void); +void UpdatePlayer(void); +void DrawPlayer(void); +void UnloadPlayer(void); +void ResetPlayer(void); + +void ScarePlayer(void); +void SearchKeyPlayer(void); +void FindKeyPlayer(void); + +#ifdef __cplusplus +} +#endif + +#endif // SCREENS_H \ No newline at end of file diff --git a/games/skully_escape/resources/audio/come_play_with_me.ogg b/games/skully_escape/resources/audio/come_play_with_me.ogg new file mode 100644 index 00000000..425498b8 Binary files /dev/null and b/games/skully_escape/resources/audio/come_play_with_me.ogg differ diff --git a/games/skully_escape/resources/audio/door.ogg b/games/skully_escape/resources/audio/door.ogg new file mode 100644 index 00000000..a1d1cd1b Binary files /dev/null and b/games/skully_escape/resources/audio/door.ogg differ diff --git a/games/skully_escape/resources/audio/scream.ogg b/games/skully_escape/resources/audio/scream.ogg new file mode 100644 index 00000000..41524027 Binary files /dev/null and b/games/skully_escape/resources/audio/scream.ogg differ diff --git a/games/skully_escape/resources/textures/alagard.png b/games/skully_escape/resources/textures/alagard.png new file mode 100644 index 00000000..c5cc54dc Binary files /dev/null and b/games/skully_escape/resources/textures/alagard.png differ diff --git a/games/skully_escape/resources/textures/background_aisle01.png b/games/skully_escape/resources/textures/background_aisle01.png new file mode 100644 index 00000000..482056f8 Binary files /dev/null and b/games/skully_escape/resources/textures/background_aisle01.png differ diff --git a/games/skully_escape/resources/textures/background_aisle02.png b/games/skully_escape/resources/textures/background_aisle02.png new file mode 100644 index 00000000..fced627f Binary files /dev/null and b/games/skully_escape/resources/textures/background_aisle02.png differ diff --git a/games/skully_escape/resources/textures/background_armory.png b/games/skully_escape/resources/textures/background_armory.png new file mode 100644 index 00000000..1a93807f Binary files /dev/null and b/games/skully_escape/resources/textures/background_armory.png differ diff --git a/games/skully_escape/resources/textures/background_attic.png b/games/skully_escape/resources/textures/background_attic.png new file mode 100644 index 00000000..446e09a7 Binary files /dev/null and b/games/skully_escape/resources/textures/background_attic.png differ diff --git a/games/skully_escape/resources/textures/background_bathroom.png b/games/skully_escape/resources/textures/background_bathroom.png new file mode 100644 index 00000000..55061d1f Binary files /dev/null and b/games/skully_escape/resources/textures/background_bathroom.png differ diff --git a/games/skully_escape/resources/textures/background_kitchen.png b/games/skully_escape/resources/textures/background_kitchen.png new file mode 100644 index 00000000..5c74c74e Binary files /dev/null and b/games/skully_escape/resources/textures/background_kitchen.png differ diff --git a/games/skully_escape/resources/textures/background_livingroom.png b/games/skully_escape/resources/textures/background_livingroom.png new file mode 100644 index 00000000..f91a11f9 Binary files /dev/null and b/games/skully_escape/resources/textures/background_livingroom.png differ diff --git a/games/skully_escape/resources/textures/doors.png b/games/skully_escape/resources/textures/doors.png new file mode 100644 index 00000000..f5a75d05 Binary files /dev/null and b/games/skully_escape/resources/textures/doors.png differ diff --git a/games/skully_escape/resources/textures/monster_arc.png b/games/skully_escape/resources/textures/monster_arc.png new file mode 100644 index 00000000..ae3e346d Binary files /dev/null and b/games/skully_escape/resources/textures/monster_arc.png differ diff --git a/games/skully_escape/resources/textures/monster_blazon01.png b/games/skully_escape/resources/textures/monster_blazon01.png new file mode 100644 index 00000000..2d2a409c Binary files /dev/null and b/games/skully_escape/resources/textures/monster_blazon01.png differ diff --git a/games/skully_escape/resources/textures/monster_blazon02.png b/games/skully_escape/resources/textures/monster_blazon02.png new file mode 100644 index 00000000..8cea9361 Binary files /dev/null and b/games/skully_escape/resources/textures/monster_blazon02.png differ diff --git a/games/skully_escape/resources/textures/monster_blazon03.png b/games/skully_escape/resources/textures/monster_blazon03.png new file mode 100644 index 00000000..cc4665a1 Binary files /dev/null and b/games/skully_escape/resources/textures/monster_blazon03.png differ diff --git a/games/skully_escape/resources/textures/monster_candle.png b/games/skully_escape/resources/textures/monster_candle.png new file mode 100644 index 00000000..9feef00d Binary files /dev/null and b/games/skully_escape/resources/textures/monster_candle.png differ diff --git a/games/skully_escape/resources/textures/monster_chair_left.png b/games/skully_escape/resources/textures/monster_chair_left.png new file mode 100644 index 00000000..b3ac070f Binary files /dev/null and b/games/skully_escape/resources/textures/monster_chair_left.png differ diff --git a/games/skully_escape/resources/textures/monster_chair_right.png b/games/skully_escape/resources/textures/monster_chair_right.png new file mode 100644 index 00000000..d29cc021 Binary files /dev/null and b/games/skully_escape/resources/textures/monster_chair_right.png differ diff --git a/games/skully_escape/resources/textures/monster_closet.png b/games/skully_escape/resources/textures/monster_closet.png new file mode 100644 index 00000000..7c0c8f27 Binary files /dev/null and b/games/skully_escape/resources/textures/monster_closet.png differ diff --git a/games/skully_escape/resources/textures/monster_lamp_left.png b/games/skully_escape/resources/textures/monster_lamp_left.png new file mode 100644 index 00000000..3b31b77f Binary files /dev/null and b/games/skully_escape/resources/textures/monster_lamp_left.png differ diff --git a/games/skully_escape/resources/textures/monster_lamp_right.png b/games/skully_escape/resources/textures/monster_lamp_right.png new file mode 100644 index 00000000..26491866 Binary files /dev/null and b/games/skully_escape/resources/textures/monster_lamp_right.png differ diff --git a/games/skully_escape/resources/textures/monster_mirror.png b/games/skully_escape/resources/textures/monster_mirror.png new file mode 100644 index 00000000..2e994309 Binary files /dev/null and b/games/skully_escape/resources/textures/monster_mirror.png differ diff --git a/games/skully_escape/resources/textures/monster_phone.png b/games/skully_escape/resources/textures/monster_phone.png new file mode 100644 index 00000000..a4862ef7 Binary files /dev/null and b/games/skully_escape/resources/textures/monster_phone.png differ diff --git a/games/skully_escape/resources/textures/monster_picture.png b/games/skully_escape/resources/textures/monster_picture.png new file mode 100644 index 00000000..29549895 Binary files /dev/null and b/games/skully_escape/resources/textures/monster_picture.png differ diff --git a/games/skully_escape/resources/textures/monster_window.png b/games/skully_escape/resources/textures/monster_window.png new file mode 100644 index 00000000..47d70a79 Binary files /dev/null and b/games/skully_escape/resources/textures/monster_window.png differ diff --git a/games/skully_escape/resources/textures/skully.png b/games/skully_escape/resources/textures/skully.png new file mode 100644 index 00000000..9ce6cd58 Binary files /dev/null and b/games/skully_escape/resources/textures/skully.png differ diff --git a/games/skully_escape/resources/textures/skully_icon.png b/games/skully_escape/resources/textures/skully_icon.png new file mode 100644 index 00000000..91a0bc2a Binary files /dev/null and b/games/skully_escape/resources/textures/skully_icon.png differ diff --git a/games/skully_escape/resources/textures/skully_logo.png b/games/skully_escape/resources/textures/skully_logo.png new file mode 100644 index 00000000..93e8bfe2 Binary files /dev/null and b/games/skully_escape/resources/textures/skully_logo.png differ diff --git a/games/skully_escape/resources/textures/title.png b/games/skully_escape/resources/textures/title.png new file mode 100644 index 00000000..20e08c88 Binary files /dev/null and b/games/skully_escape/resources/textures/title.png differ diff --git a/games/skully_escape/screens/screen_aisle01.c b/games/skully_escape/screens/screen_aisle01.c new file mode 100644 index 00000000..17d25058 --- /dev/null +++ b/games/skully_escape/screens/screen_aisle01.c @@ -0,0 +1,409 @@ +/********************************************************************************************** +* +* raylib - Advance Game template +* +* Gameplay 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 "../player.h" +#include "../monster.h" + +#include + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Gameplay screen global variables +static int framesCounter; +static int finishScreen; + +static Texture2D background; + +// Declare doors +static Door doorRight; +static Door doorCenter; +static Door doorLeft; + +// Decalre monsters +static Monster lamp; +static Monster picture; + +static bool monsterHover = false; +static int monsterCheck = -1; // Identify checking monster + +static const char message[256] = "WHO IS THERE???\nANYBODY IN THE ROOM???"; +static int msgPosX = 100; + +static int msgState = 0; // 0-writting, 1-wait, 2-choose +static int lettersCounter = 0; +static char msgBuffer[256] = { '\0' }; +static int msgCounter = 0; + +static bool searching = false; + +static int scroll = 0; + +//---------------------------------------------------------------------------------- +// Gameplay Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Gameplay Screen Initialization logic +void InitAisle01Screen(void) +{ + ResetPlayer(); + + // Reset Screen variables + monsterHover = false; + monsterCheck = -1; + msgState = 0; + msgCounter = 0; + lettersCounter = 0; + for (int i = 0; i < 256; i++) msgBuffer[i] = '\0'; + + framesCounter = 0; + finishScreen = 0; + + background = LoadTexture("resources/textures/background_aisle01.png"); + + scroll = player.position.x - 200; + + // Initialize doors + doorLeft.position = (Vector2) { -30, 135 }; + doorLeft.facing = 0; + doorLeft.locked = true; + doorLeft.frameRec =(Rectangle) {((doors.width/3)*doorLeft.facing), doors.height/2, doors.width/3, doors.height/2}; + doorLeft.bound = (Rectangle) { doorLeft.position.x, doorLeft.position.y, doors.width/3, doors.height/2}; + doorLeft.selected = false; + + doorCenter.position = (Vector2) { 1115, 104 }; + doorCenter.facing = 1; + doorCenter.locked = true; + doorCenter.frameRec =(Rectangle) {((doors.width/3)*doorCenter.facing), doors.height/2, doors.width/3, doors.height/2}; + doorCenter.bound = (Rectangle) { doorCenter.position.x, doorCenter.position.y, doors.width/3, doors.height/2}; + doorCenter.selected = false; + + doorRight.position = (Vector2) { 1710, 140 }; + doorRight.facing = 2; + doorRight.locked = true; + doorRight.frameRec =(Rectangle) {((doors.width/3)*doorRight.facing), doors.height/2, doors.width/3, doors.height/2}; + doorRight.bound = (Rectangle) { doorRight.position.x, doorRight.position.y, doors.width/3, doors.height/2}; + + // Monster init: lamp + lamp.position = (Vector2){ 187, 256 }; + lamp.texture = LoadTexture("resources/textures/monster_lamp_left.png"); + lamp.currentFrame = 0; + lamp.framesCounter = 0; + lamp.numFrames = 4; + lamp.bounds = (Rectangle){ lamp.position.x + 20, lamp.position.y, 90, 380 }; + lamp.frameRec = (Rectangle) { 0, 0, lamp.texture.width/lamp.numFrames, lamp.texture.height }; + lamp.selected = false; + lamp.active = false; + lamp.spooky = true; + + // Monster init: arc + picture.position = (Vector2){ 637, 178 }; + picture.texture = LoadTexture("resources/textures/monster_picture.png"); + picture.currentFrame = 0; + picture.framesCounter = 0; + picture.numFrames = 4; + picture.bounds = (Rectangle){ picture.position.x + 44, picture.position.y, 174, 256 }; + picture.frameRec = (Rectangle) { 0, 0, picture.texture.width/picture.numFrames, picture.texture.height }; + picture.selected = false; + picture.active = false; + picture.spooky = false; +} + +// Gameplay Screen Update logic +void UpdateAisle01Screen(void) +{ + // Update doors bounds + doorLeft.bound.x = doorLeft.position.x - scroll; + doorCenter.bound.x = doorCenter.position.x - scroll; + doorRight.bound.x = doorRight.position.x - scroll; + + if (player.key) + { + // Door: left + if ((CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) || + (CheckCollisionRecs(player.bounds, doorLeft.bound))) doorLeft.selected = true; + else doorLeft.selected = false; + + if ((doorLeft.selected) && (CheckCollisionRecs(player.bounds, doorLeft.bound))) + { + if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) || (IsKeyPressed(KEY_SPACE))) + { + if (doorLeft.locked) + { + doorLeft.frameRec.y = 0; + doorLeft.locked = false; + PlaySound(sndDoor); + } + else finishScreen = 1; + } + } + + // Door: center + if ((CheckCollisionPointRec(GetMousePosition(), doorCenter.bound)) || + (CheckCollisionRecs(player.bounds, doorCenter.bound))) doorCenter.selected = true; + else doorCenter.selected = false; + + if ((doorCenter.selected) && (CheckCollisionRecs(player.bounds, doorCenter.bound))) + { + if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorCenter.bound)) || (IsKeyPressed(KEY_SPACE))) + { + if (doorCenter.locked) + { + doorCenter.frameRec.y = 0; + doorCenter.locked = false; + PlaySound(sndDoor); + } + else finishScreen = 2; + } + } + + // Door: right + if ((CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) || + (CheckCollisionRecs(player.bounds, doorRight.bound))) doorRight.selected = true; + else doorRight.selected = false; + + if ((doorRight.selected) && (CheckCollisionRecs(player.bounds, doorRight.bound))) + { + if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) || (IsKeyPressed(KEY_SPACE))) + { + if (doorRight.locked) + { + doorRight.frameRec.y = 0; + doorRight.locked = false; + PlaySound(sndDoor); + } + else finishScreen = 3; + } + } + } + + if (msgState > 2) + { + UpdatePlayer(); + + // Monsters logic + UpdateMonster(&lamp); + UpdateMonster(&picture); + } + + // Update monster bounds + lamp.bounds.x = lamp.position.x + 20 - scroll; + picture.bounds.x = picture.position.x + 44 - scroll; + + // Check player hover monsters to interact + if (((CheckCollisionRecs(player.bounds, lamp.bounds)) && !lamp.active) || + ((CheckCollisionRecs(player.bounds, picture.bounds)) && !picture.active)) monsterHover = true; + else monsterHover = false; + + // Monters logic: lamp + if ((CheckCollisionRecs(player.bounds, lamp.bounds)) && !lamp.active) + { + lamp.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), lamp.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 1; + } + } + else lamp.selected = false; + + // Monters logic: picture + if ((CheckCollisionRecs(player.bounds, picture.bounds)) && !picture.active) + { + picture.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), picture.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 2; + } + } + else picture.selected = false; + + if (searching) + { + framesCounter++; + + if (framesCounter > 180) + { + if (monsterCheck == 1) + { + if (lamp.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + lamp.active = true; + lamp.selected = false; + } + else if (monsterCheck == 2) + { + if (picture.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + picture.active = true; + picture.selected = false; + } + + searching = false; + framesCounter = 0; + } + } + + // Text animation + framesCounter++; + + if ((framesCounter%2) == 0) lettersCounter++; + + if (msgState == 0) + { + if (lettersCounter <= (int)strlen(message)) strncpy(msgBuffer, message, lettersCounter); + else + { + for (int i = 0; i < (int)strlen(msgBuffer); i++) msgBuffer[i] = '\0'; + + lettersCounter = 0; + msgState = 1; + } + + if (IsKeyPressed(KEY_ENTER)) msgState = 1; + } + else if (msgState == 1) + { + msgCounter++; + + if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + { + msgState = 2; + msgCounter = 0; + } + } + else if (msgState == 2) + { + msgCounter++; + + if (msgCounter > 180) msgState = 3; + } + else msgCounter++; + + if (player.position.x > 200) + { + scroll = player.position.x - 200; + + if (scroll > 620) scroll = 620; + } +} + +// Gameplay Screen Draw logic +void DrawAisle01Screen(void) +{ + DrawTexture(background, -scroll, 0, WHITE); + + // Draw monsters + DrawMonster(lamp, scroll); + DrawMonster(picture, scroll); + + // Draw door + Vector2 doorScrollPos = { doorCenter.position.x - scroll, doorCenter.position.y }; + if (doorCenter.selected) DrawTextureRec(doors, doorCenter.frameRec, doorScrollPos, GREEN); + else DrawTextureRec(doors, doorCenter.frameRec, doorScrollPos, WHITE); + + doorScrollPos = (Vector2){ doorLeft.position.x - scroll, doorLeft.position.y }; + if (doorLeft.selected) DrawTextureRec(doors, doorLeft.frameRec, doorScrollPos, GREEN); + else DrawTextureRec(doors, doorLeft.frameRec, doorScrollPos, WHITE); + + doorScrollPos = (Vector2){ doorRight.position.x - scroll, doorRight.position.y }; + if (doorRight.selected) DrawTextureRec(doors, doorRight.frameRec, doorScrollPos, GREEN); + else DrawTextureRec(doors, doorRight.frameRec, doorScrollPos, WHITE); + + // Draw messsages + if (msgState < 2) DrawRectangle(0, 40, GetScreenWidth(), 200, Fade(LIGHTGRAY, 0.5f)); + else if (msgState == 2) DrawRectangle(0, 80, GetScreenWidth(), 100, Fade(LIGHTGRAY, 0.5f)); + + if (msgState == 0) + { + DrawTextEx(font, msgBuffer, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE); + } + else if (msgState == 1) + { + DrawTextEx(font, message, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE); + + if ((msgCounter/30)%2) DrawText("PRESS ENTER or CLICK", GetScreenWidth() - 280, 200, 20, BLACK); + } + else if (msgState == 2) + { + if ((msgCounter/30)%2) + { + DrawTextEx(font, "CHOOSE WISELY!", (Vector2){ 300, 95 }, font.size*2, 2, WHITE); + + DrawRectangleRec(lamp.bounds, Fade(RED, 0.6f)); + DrawRectangleRec(picture.bounds, Fade(RED, 0.6f)); + } + } + else + { + if ((monsterHover) && ((msgCounter/30)%2)) + { + DrawRectangle(0, 0, GetScreenWidth(), 50, Fade(LIGHTGRAY, 0.5f)); + DrawText("PRESS SPACE or CLICK to INTERACT", 420, 15, 20, BLACK); + } + } + + DrawPlayer(); // NOTE: Also draws mouse pointer! +} + +// Gameplay Screen Unload logic +void UnloadAisle01Screen(void) +{ + // TODO: Unload GAMEPLAY screen variables here! + UnloadTexture(background); + + UnloadMonster(lamp); + UnloadMonster(picture); +} + +// Gameplay Screen should finish? +int FinishAisle01Screen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/skully_escape/screens/screen_aisle02.c b/games/skully_escape/screens/screen_aisle02.c new file mode 100644 index 00000000..6186a1fc --- /dev/null +++ b/games/skully_escape/screens/screen_aisle02.c @@ -0,0 +1,444 @@ +/********************************************************************************************** +* +* raylib - Advance Game template +* +* Gameplay 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 "../player.h" +#include "../monster.h" + +#include + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Gameplay screen global variables +static int framesCounter; +static int finishScreen; + +static Texture2D background; + +// Declare doors +static Door doorLeft; + +// Decalre monsters +static Monster lamp; +static Monster chair; +static Monster picture; +static Monster arc; + +static bool monsterHover = false; +static int monsterCheck = -1; // Identify checking monster + +static const char message[256] = "HAS LEGS BUT CAN NOT WALK...\nSEARCH FOR IT TO OPEN THE DOOR!"; +static int msgPosX = 100; + +static int msgState = 0; // 0-writting, 1-wait, 2-choose +static int lettersCounter = 0; +static char msgBuffer[256] = { '\0' }; +static int msgCounter = 0; + +static bool searching = false; + +static int scroll = 0; + +//---------------------------------------------------------------------------------- +// Gameplay Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Gameplay Screen Initialization logic +void InitAisle02Screen(void) +{ + ResetPlayer(); + + // Reset Screen variables + monsterHover = false; + monsterCheck = -1; + msgState = 0; + msgCounter = 0; + lettersCounter = 0; + for (int i = 0; i < 256; i++) msgBuffer[i] = '\0'; + + framesCounter = 0; + finishScreen = 0; + + background = LoadTexture("resources/textures/background_aisle02.png"); + + scroll = player.position.x - 200; + + // Initialize doors + doorLeft.position = (Vector2) { -10, 136 }; + doorLeft.facing = 0; + doorLeft.locked = true; + doorLeft.frameRec =(Rectangle) {((doors.width/3)*doorLeft.facing), doors.height/2, doors.width/3, doors.height/2}; + doorLeft.bound = (Rectangle) { doorLeft.position.x, doorLeft.position.y, doors.width/3, doors.height/2}; + doorLeft.selected = false; + + // Monster init: lamp + lamp.position = (Vector2){ 1520, 300 }; + lamp.texture = LoadTexture("resources/textures/monster_lamp_right.png"); + lamp.currentFrame = 0; + lamp.framesCounter = 0; + lamp.numFrames = 4; + lamp.bounds = (Rectangle){ lamp.position.x + 200, lamp.position.y, 90, 380 }; + lamp.frameRec = (Rectangle) { 0, 0, lamp.texture.width/lamp.numFrames, lamp.texture.height }; + lamp.selected = false; + lamp.active = false; + lamp.spooky = true; + + // Monster init: chair + chair.position = (Vector2){ 1400, 404 }; + chair.texture = LoadTexture("resources/textures/monster_chair_right.png"); + chair.currentFrame = 0; + chair.framesCounter = 0; + chair.numFrames = 4; + chair.bounds = (Rectangle){ chair.position.x + 50, chair.position.y + 30, 120, 190 }; + chair.frameRec = (Rectangle) { 0, 0, chair.texture.width/chair.numFrames, chair.texture.height }; + chair.selected = false; + chair.active = false; + chair.spooky = false; + + // Monster init: picture + picture.position = (Vector2){ 837, 162 }; + picture.texture = LoadTexture("resources/textures/monster_picture.png"); + picture.currentFrame = 0; + picture.framesCounter = 0; + picture.numFrames = 4; + picture.bounds = (Rectangle){ picture.position.x + 44, picture.position.y, 174, 264 }; + picture.frameRec = (Rectangle) { 0, 0, picture.texture.width/picture.numFrames, picture.texture.height }; + picture.selected = false; + picture.active = false; + picture.spooky = true; + + // Monster init: arc + arc.position = (Vector2){ 388, 423 }; + arc.texture = LoadTexture("resources/textures/monster_arc.png"); + arc.currentFrame = 0; + arc.framesCounter = 0; + arc.numFrames = 4; + arc.bounds = (Rectangle){ arc.position.x + 44, arc.position.y + 70, 220, 120 }; + arc.frameRec = (Rectangle) { 0, 0, arc.texture.width/arc.numFrames, arc.texture.height }; + arc.selected = false; + arc.active = false; + arc.spooky = true; +} + +// Gameplay Screen Update logic +void UpdateAisle02Screen(void) +{ + // Update doors bounds + doorLeft.bound.x = doorLeft.position.x - scroll; + + if (player.key) + { + // Door: left + if ((CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) || + (CheckCollisionRecs(player.bounds, doorLeft.bound))) doorLeft.selected = true; + else doorLeft.selected = false; + + if ((doorLeft.selected) && (CheckCollisionRecs(player.bounds, doorLeft.bound))) + { + if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) || (IsKeyPressed(KEY_SPACE))) + { + if (doorLeft.locked) + { + doorLeft.frameRec.y = 0; + doorLeft.locked = false; + PlaySound(sndDoor); + } + else finishScreen = 1; + } + } + } + + if (msgState > 2) + { + UpdatePlayer(); + + // Monsters logic + UpdateMonster(&lamp); + UpdateMonster(&chair); + UpdateMonster(&picture); + UpdateMonster(&arc); + } + + // Update monster bounds + lamp.bounds.x = lamp.position.x + 200 - scroll; + chair.bounds.x = chair.position.x + 50 - scroll; + picture.bounds.x = picture.position.x + 44 - scroll; + arc.bounds.x = arc.position.x + 44 - scroll; + + // Check player hover monsters to interact + if (((CheckCollisionRecs(player.bounds, lamp.bounds)) && !lamp.active) || + ((CheckCollisionRecs(player.bounds, chair.bounds)) && !chair.active) || + ((CheckCollisionRecs(player.bounds, picture.bounds)) && !picture.active) || + ((CheckCollisionRecs(player.bounds, arc.bounds)) && !arc.active)) monsterHover = true; + else monsterHover = false; + + + // Monters logic: lamp + if ((CheckCollisionRecs(player.bounds, lamp.bounds)) && !lamp.active) + { + lamp.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), lamp.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 1; + } + } + else lamp.selected = false; + + // Monters logic: chair + if ((CheckCollisionRecs(player.bounds, chair.bounds)) && !chair.active) + { + chair.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), chair.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 2; + } + } + else chair.selected = false; + + // Monters logic: picture + if ((CheckCollisionRecs(player.bounds, picture.bounds)) && !picture.active) + { + picture.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), picture.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 3; + } + } + else picture.selected = false; + + // Monters logic: arc + if ((CheckCollisionRecs(player.bounds, arc.bounds)) && !arc.active) + { + arc.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), arc.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 4; + } + } + else arc.selected = false; + + if (searching) + { + framesCounter++; + + if (framesCounter > 180) + { + if (monsterCheck == 1) + { + if (lamp.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + lamp.active = true; + lamp.selected = false; + } + else if (monsterCheck == 2) + { + if (chair.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + chair.active = true; + chair.selected = false; + } + else if (monsterCheck == 3) + { + if (picture.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + picture.active = true; + picture.selected = false; + } + else if (monsterCheck == 4) + { + if (arc.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + arc.active = true; + arc.selected = false; + } + + searching = false; + framesCounter = 0; + } + } + + // Text animation + framesCounter++; + + if ((framesCounter%2) == 0) lettersCounter++; + + if (msgState == 0) + { + if (lettersCounter <= (int)strlen(message)) strncpy(msgBuffer, message, lettersCounter); + else + { + for (int i = 0; i < (int)strlen(msgBuffer); i++) msgBuffer[i] = '\0'; + + lettersCounter = 0; + msgState = 1; + } + + if (IsKeyPressed(KEY_ENTER)) msgState = 1; + } + else if (msgState == 1) + { + msgCounter++; + + if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + { + msgState = 2; + msgCounter = 0; + } + } + else if (msgState == 2) + { + msgCounter++; + + if (msgCounter > 180) msgState = 3; + } + else msgCounter++; + + if (player.position.x > 200) + { + scroll = player.position.x - 200; + + if (scroll > 620) scroll = 620; + } +} + +// Gameplay Screen Draw logic +void DrawAisle02Screen(void) +{ + DrawTexture(background, -scroll, 0, WHITE); + + // Draw monsters + DrawMonster(lamp, scroll); + DrawMonster(arc, scroll); + DrawMonster(picture, scroll); + DrawMonster(chair, scroll); + + // Draw door + Vector2 doorScrollPos = { doorLeft.position.x - scroll, doorLeft.position.y }; + + if (doorLeft.selected) DrawTextureRec(doors, doorLeft.frameRec, doorScrollPos, GREEN); + else DrawTextureRec(doors, doorLeft.frameRec, doorScrollPos, WHITE); + + // Draw messsages + if (msgState < 2) DrawRectangle(0, 40, GetScreenWidth(), 200, Fade(LIGHTGRAY, 0.5f)); + else if (msgState == 2) DrawRectangle(0, 80, GetScreenWidth(), 100, Fade(LIGHTGRAY, 0.5f)); + + if (msgState == 0) + { + DrawTextEx(font, msgBuffer, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE); + } + else if (msgState == 1) + { + DrawTextEx(font, message, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE); + + if ((msgCounter/30)%2) DrawText("PRESS ENTER or CLICK", GetScreenWidth() - 280, 200, 20, BLACK); + } + else if (msgState == 2) + { + if ((msgCounter/30)%2) + { + DrawTextEx(font, "CHOOSE WISELY!", (Vector2){ 300, 95 }, font.size*2, 2, WHITE); + + DrawRectangleRec(lamp.bounds, Fade(RED, 0.6f)); + DrawRectangleRec(arc.bounds, Fade(RED, 0.6f)); + DrawRectangleRec(chair.bounds, Fade(RED, 0.6f)); + DrawRectangleRec(picture.bounds, Fade(RED, 0.6f)); + } + } + else + { + if ((monsterHover) && ((msgCounter/30)%2)) + { + DrawRectangle(0, 0, GetScreenWidth(), 50, Fade(LIGHTGRAY, 0.5f)); + DrawText("PRESS SPACE or CLICK to INTERACT", 420, 15, 20, BLACK); + } + } + + DrawPlayer(); // NOTE: Also draws mouse pointer! +} + +// Gameplay Screen Unload logic +void UnloadAisle02Screen(void) +{ + // TODO: Unload GAMEPLAY screen variables here! + UnloadTexture(background); + + UnloadMonster(lamp); + UnloadMonster(chair); + UnloadMonster(picture); + UnloadMonster(arc); +} + +// Gameplay Screen should finish? +int FinishAisle02Screen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/skully_escape/screens/screen_armory.c b/games/skully_escape/screens/screen_armory.c new file mode 100644 index 00000000..622299f0 --- /dev/null +++ b/games/skully_escape/screens/screen_armory.c @@ -0,0 +1,404 @@ +/********************************************************************************************** +* +* raylib - Advance Game template +* +* Gameplay 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 "../player.h" +#include "../monster.h" + +#include + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Gameplay screen global variables +static int framesCounter; +static int finishScreen; + +static Texture2D background; + +// Declare doors +static Door doorLeft; +static Door doorRight; + +// Decalre monsters +static Monster blazon01; +static Monster blazon02; +static Monster blazon03; + +static bool monsterHover = false; +static int monsterCheck = -1; // Identify checking monster + +static const char message[256] = "NO MORE TIPS...\nFOLLOW YOUR INSTINCT!"; +static int msgPosX = 100; + +static int msgState = 0; // 0-writting, 1-wait, 2-choose +static int lettersCounter = 0; +static char msgBuffer[256] = { '\0' }; +static int msgCounter = 0; + +static bool searching = false; + +//---------------------------------------------------------------------------------- +// Gameplay Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Gameplay Screen Initialization logic +void InitArmoryScreen(void) +{ + ResetPlayer(); + + // Reset Screen variables + monsterHover = false; + monsterCheck = -1; + msgState = 0; + msgCounter = 0; + lettersCounter = 0; + for (int i = 0; i < 256; i++) msgBuffer[i] = '\0'; + + framesCounter = 0; + finishScreen = 0; + + background = LoadTexture("resources/textures/background_armory.png"); + + // Initialize doors + doorLeft.position = (Vector2) { -50, 145 }; + doorLeft.facing = 0; + doorLeft.locked = true; + doorLeft.frameRec =(Rectangle) {((doors.width/3)*doorLeft.facing), doors.height/2, doors.width/3, doors.height/2}; + doorLeft.bound = (Rectangle) { doorLeft.position.x, doorLeft.position.y, doors.width/3, doors.height/2}; + doorLeft.selected = false; + + doorRight.position = (Vector2) { 1074, 140 }; + doorRight.facing = 2; + doorRight.locked = true; + doorRight.frameRec =(Rectangle) {((doors.width/3)*doorRight.facing), doors.height/2, doors.width/3, doors.height/2}; + doorRight.bound = (Rectangle) { doorRight.position.x, doorRight.position.y, doors.width/3, doors.height/2}; + doorRight.selected = false; + + // Monster init: blazon01 + blazon01.position = (Vector2){ 300, 260 }; + blazon01.texture = LoadTexture("resources/textures/monster_blazon01.png"); + blazon01.currentFrame = 0; + blazon01.framesCounter = 0; + blazon01.numFrames = 4; + blazon01.bounds = (Rectangle){ blazon01.position.x, blazon01.position.y + 20, 160, 230 }; + blazon01.frameRec = (Rectangle) { 0, 0, blazon01.texture.width/blazon01.numFrames, blazon01.texture.height }; + blazon01.selected = false; + blazon01.active = false; + blazon01.spooky = true; + + // Monster init: blazon02 + blazon02.position = (Vector2){ 550, 260 }; + blazon02.texture = LoadTexture("resources/textures/monster_blazon02.png"); + blazon02.currentFrame = 0; + blazon02.framesCounter = 0; + blazon02.numFrames = 4; + blazon02.bounds = (Rectangle){ blazon02.position.x, blazon02.position.y + 20, 160, 230 }; + blazon02.frameRec = (Rectangle) { 0, 0, blazon02.texture.width/blazon02.numFrames, blazon02.texture.height }; + blazon02.selected = false; + blazon02.active = false; + blazon02.spooky = true; + + // Monster init: blazon03 + blazon03.position = (Vector2){ 800, 260 }; + blazon03.texture = LoadTexture("resources/textures/monster_blazon03.png"); + blazon03.currentFrame = 0; + blazon03.framesCounter = 0; + blazon03.numFrames = 4; + blazon03.bounds = (Rectangle){ blazon03.position.x, blazon03.position.y + 20, 160, 230 }; + blazon03.frameRec = (Rectangle) { 0, 0, blazon03.texture.width/blazon03.numFrames, blazon03.texture.height }; + blazon03.selected = false; + blazon03.active = false; + blazon03.spooky = false; +} + +// Gameplay Screen Update logic +void UpdateArmoryScreen(void) +{ + if (player.key) + { + // Door: left + if ((CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) || + (CheckCollisionRecs(player.bounds, doorLeft.bound))) doorLeft.selected = true; + else doorLeft.selected = false; + + if ((doorLeft.selected) && (CheckCollisionRecs(player.bounds, doorLeft.bound))) + { + if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) || (IsKeyPressed(KEY_SPACE))) + { + if (doorLeft.locked) + { + doorLeft.frameRec.y = 0; + doorLeft.locked = false; + PlaySound(sndDoor); + } + else finishScreen = 1; + } + } + + // Door: right + if ((CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) || + (CheckCollisionRecs(player.bounds, doorRight.bound))) doorRight.selected = true; + else doorRight.selected = false; + + if ((doorRight.selected) && (CheckCollisionRecs(player.bounds, doorRight.bound))) + { + if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) || (IsKeyPressed(KEY_SPACE))) + { + if (doorRight.locked) + { + doorRight.frameRec.y = 0; + doorRight.locked = false; + PlaySound(sndDoor); + } + else finishScreen = 2; + } + } + } + + if (msgState > 2) + { + UpdatePlayer(); + + // Monsters logic + UpdateMonster(&blazon01); + UpdateMonster(&blazon02); + UpdateMonster(&blazon03); + } + + // Check player hover monsters to interact + if (((CheckCollisionRecs(player.bounds, blazon01.bounds)) && !blazon01.active) || + ((CheckCollisionRecs(player.bounds, blazon02.bounds)) && !blazon02.active) || + ((CheckCollisionRecs(player.bounds, blazon03.bounds)) && !blazon03.active)) monsterHover = true; + else monsterHover = false; + + // Monters logic: blazon01 + if ((CheckCollisionRecs(player.bounds, blazon01.bounds)) && !blazon01.active) + { + blazon01.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), blazon01.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 1; + } + } + else blazon01.selected = false; + + // Monters logic: blazon02 + if ((CheckCollisionRecs(player.bounds, blazon02.bounds)) && !blazon02.active) + { + blazon02.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), blazon02.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 2; + } + } + else blazon02.selected = false; + + // Monters logic: blazon03 + if ((CheckCollisionRecs(player.bounds, blazon03.bounds)) && !blazon03.active) + { + blazon03.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), blazon03.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 3; + } + } + else blazon03.selected = false; + + if (searching) + { + framesCounter++; + + if (framesCounter > 180) + { + if (monsterCheck == 1) + { + if (blazon01.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + blazon01.active = true; + blazon01.selected = false; + } + else if (monsterCheck == 2) + { + if (blazon02.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + blazon02.active = true; + blazon02.selected = false; + } + else if (monsterCheck == 3) + { + if (blazon03.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + blazon03.active = true; + blazon03.selected = false; + } + + searching = false; + framesCounter = 0; + } + } + + // Text animation + framesCounter++; + + if ((framesCounter%2) == 0) lettersCounter++; + + if (msgState == 0) + { + if (lettersCounter <= (int)strlen(message)) strncpy(msgBuffer, message, lettersCounter); + else + { + for (int i = 0; i < (int)strlen(msgBuffer); i++) msgBuffer[i] = '\0'; + + lettersCounter = 0; + msgState = 1; + } + + if (IsKeyPressed(KEY_ENTER)) msgState = 1; + } + else if (msgState == 1) + { + msgCounter++; + + if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + { + msgState = 2; + msgCounter = 0; + } + } + else if (msgState == 2) + { + msgCounter++; + + if (msgCounter > 180) msgState = 3; + } + else msgCounter++; +} + +// Gameplay Screen Draw logic +void DrawArmoryScreen(void) +{ + DrawTexture(background, 0, 0, WHITE); + + // Draw monsters + DrawMonster(blazon01, 0); + DrawMonster(blazon02, 0); + DrawMonster(blazon03, 0); + + // Draw door + if (doorLeft.selected) DrawTextureRec(doors, doorLeft.frameRec, doorLeft.position, GREEN); + else DrawTextureRec(doors, doorLeft.frameRec, doorLeft.position, WHITE); + + if (doorRight.selected) DrawTextureRec(doors, doorRight.frameRec, doorRight.position, GREEN); + else DrawTextureRec(doors, doorRight.frameRec, doorRight.position, WHITE); + + // Draw messsages + if (msgState < 2) DrawRectangle(0, 40, GetScreenWidth(), 200, Fade(LIGHTGRAY, 0.5f)); + else if (msgState == 2) DrawRectangle(0, 80, GetScreenWidth(), 100, Fade(LIGHTGRAY, 0.5f)); + + if (msgState == 0) + { + DrawTextEx(font, msgBuffer, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE); + } + else if (msgState == 1) + { + DrawTextEx(font, message, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE); + + if ((msgCounter/30)%2) DrawText("PRESS ENTER or CLICK", GetScreenWidth() - 280, 200, 20, BLACK); + } + else if (msgState == 2) + { + if ((msgCounter/30)%2) + { + DrawTextEx(font, "CHOOSE WISELY!", (Vector2){ 300, 95 }, font.size*2, 2, WHITE); + + DrawRectangleRec(blazon01.bounds, Fade(RED, 0.6f)); + DrawRectangleRec(blazon02.bounds, Fade(RED, 0.6f)); + DrawRectangleRec(blazon03.bounds, Fade(RED, 0.6f)); + } + } + else + { + if ((monsterHover) && ((msgCounter/30)%2)) + { + DrawRectangle(0, 0, GetScreenWidth(), 50, Fade(LIGHTGRAY, 0.5f)); + DrawText("PRESS SPACE or CLICK to INTERACT", 420, 15, 20, BLACK); + } + } + + DrawPlayer(); // NOTE: Also draws mouse pointer! +} + +// Gameplay Screen Unload logic +void UnloadArmoryScreen(void) +{ + // TODO: Unload GAMEPLAY screen variables here! + UnloadTexture(background); + + UnloadMonster(blazon01); + UnloadMonster(blazon02); + UnloadMonster(blazon03); +} + +// Gameplay Screen should finish? +int FinishArmoryScreen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/skully_escape/screens/screen_attic.c b/games/skully_escape/screens/screen_attic.c new file mode 100644 index 00000000..a8bc0a6b --- /dev/null +++ b/games/skully_escape/screens/screen_attic.c @@ -0,0 +1,332 @@ +/********************************************************************************************** +* +* raylib - Advance Game template +* +* Gameplay 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 "../player.h" +#include "../monster.h" + +#include + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Gameplay screen global variables +static int framesCounter; +static int finishScreen; + +static Texture2D background; + +// Declare doors +static Door doorRight; + +// Decalre monsters +static Monster lamp; +static Monster arc; + +static bool monsterHover; +static int monsterCheck; // Identify checking monster + +static const char message[256] = "YOUR PARENTS ARE GONE! TIME TO ESCAPE!\nTHE DOOR IS LOCKED... TURN ON THE LIGHTS! ;)"; +static int msgPosX = 100; + +static int msgState = 0; // 0-writting, 1-wait, 2-choose +static int lettersCounter = 0; +static char msgBuffer[256] = { '\0' }; +static int msgCounter = 0; + +static bool searching = false; + +//---------------------------------------------------------------------------------- +// Gameplay Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Gameplay Screen Initialization logic +void InitAtticScreen(void) +{ + ResetPlayer(); + + // Reset Screen variables + monsterHover = false; + monsterCheck = -1; + msgState = 0; + msgCounter = 0; + lettersCounter = 0; + for (int i = 0; i < 256; i++) msgBuffer[i] = '\0'; + + framesCounter = 0; + finishScreen = 0; + + background = LoadTexture("resources/textures/background_attic.png"); + + // Initialize doors + doorRight.position = (Vector2) { 1074, 140 }; + doorRight.facing = 2; + doorRight.locked = true; + doorRight.frameRec =(Rectangle) {((doors.width/3)*doorRight.facing), doors.height/2, doors.width/3, doors.height/2}; + doorRight.bound = (Rectangle) { doorRight.position.x, doorRight.position.y, doors.width/3, doors.height/2}; + doorRight.selected = false; + + // Monster init: lamp + lamp.position = (Vector2){ 50, 316 }; + lamp.texture = LoadTexture("resources/textures/monster_lamp_left.png"); + lamp.currentFrame = 0; + lamp.framesCounter = 0; + lamp.numFrames = 4; + lamp.bounds = (Rectangle){ lamp.position.x + 20, lamp.position.y, 90, 380 }; + lamp.frameRec = (Rectangle) { 0, 0, lamp.texture.width/lamp.numFrames, lamp.texture.height }; + lamp.selected = false; + lamp.active = false; + lamp.spooky = false; + + // Monster init: arc + arc.position = (Vector2){ 760, 430 }; + arc.texture = LoadTexture("resources/textures/monster_arc.png"); + arc.currentFrame = 0; + arc.framesCounter = 0; + arc.numFrames = 4; + arc.bounds = (Rectangle){ arc.position.x + 44, arc.position.y + 70, 220, 120 }; + arc.frameRec = (Rectangle) { 0, 0, arc.texture.width/arc.numFrames, arc.texture.height }; + arc.selected = false; + arc.active = false; + arc.spooky = true; +} + +// Gameplay Screen Update logic +void UpdateAtticScreen(void) +{ + if (player.key) + { + // Door: right + if ((CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) || + (CheckCollisionRecs(player.bounds, doorRight.bound))) doorRight.selected = true; + else doorRight.selected = false; + + if ((doorRight.selected) && (CheckCollisionRecs(player.bounds, doorRight.bound))) + { + if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) || (IsKeyPressed(KEY_SPACE))) + { + if (doorRight.locked) + { + doorRight.frameRec.y = 0; + doorRight.locked = false; + PlaySound(sndDoor); + } + else finishScreen = 1; + } + } + } + + if (msgState > 2) + { + UpdatePlayer(); + + // Monsters logic + UpdateMonster(&lamp); + UpdateMonster(&arc); + } + + // Check player hover monsters to interact + if (((CheckCollisionRecs(player.bounds, lamp.bounds)) && !lamp.active) || + ((CheckCollisionRecs(player.bounds, arc.bounds)) && !arc.active)) monsterHover = true; + else monsterHover = false; + + // Monters logic: lamp + if ((CheckCollisionRecs(player.bounds, lamp.bounds)) && !lamp.active) + { + lamp.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), lamp.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 1; + } + } + else lamp.selected = false; + + // Monters logic: arc + if ((CheckCollisionRecs(player.bounds, arc.bounds)) && !arc.active) + { + arc.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), arc.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 2; + } + } + else arc.selected = false; + + if (searching) + { + framesCounter++; + + if (framesCounter > 180) + { + if (monsterCheck == 1) + { + if (lamp.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + lamp.active = true; + lamp.selected = false; + } + else if (monsterCheck == 2) + { + if (arc.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + arc.active = true; + arc.selected = false; + } + + searching = false; + framesCounter = 0; + } + } + + // Text animation + framesCounter++; + + if ((framesCounter%2) == 0) lettersCounter++; + + if (msgState == 0) + { + if (lettersCounter <= (int)strlen(message)) strncpy(msgBuffer, message, lettersCounter); + else + { + for (int i = 0; i < (int)strlen(msgBuffer); i++) msgBuffer[i] = '\0'; + + lettersCounter = 0; + msgState = 1; + } + + if (IsKeyPressed(KEY_ENTER)) msgState = 1; + } + else if (msgState == 1) + { + msgCounter++; + + if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + { + msgState = 2; + msgCounter = 0; + } + } + else if (msgState == 2) + { + msgCounter++; + + if (msgCounter > 180) msgState = 3; + } + else msgCounter++; + + if (IsKeyPressed('M')) + { + finishScreen = 1; + } +} + +// Gameplay Screen Draw logic +void DrawAtticScreen(void) +{ + DrawTexture(background, 0, 0, WHITE); + + // Draw monsters + DrawMonster(lamp, 0); + DrawMonster(arc, 0); + + // Draw door + if (doorRight.selected) DrawTextureRec(doors, doorRight.frameRec, doorRight.position, GREEN); + else DrawTextureRec(doors, doorRight.frameRec, doorRight.position, WHITE); + + // Draw messsages + if (msgState < 2) DrawRectangle(0, 40, GetScreenWidth(), 200, Fade(LIGHTGRAY, 0.5f)); + else if (msgState == 2) DrawRectangle(0, 80, GetScreenWidth(), 100, Fade(LIGHTGRAY, 0.5f)); + + if (msgState == 0) + { + DrawTextEx(font, msgBuffer, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE); + } + else if (msgState == 1) + { + DrawTextEx(font, message, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE); + + if ((msgCounter/30)%2) DrawText("PRESS ENTER or CLICK", GetScreenWidth() - 280, 200, 20, BLACK); + } + else if (msgState == 2) + { + if ((msgCounter/30)%2) + { + DrawTextEx(font, "CHOOSE WISELY!", (Vector2){ 300, 95 }, font.size*2, 2, WHITE); + + DrawRectangleRec(lamp.bounds, Fade(RED, 0.6f)); + DrawRectangleRec(arc.bounds, Fade(RED, 0.6f)); + } + } + else + { + if ((monsterHover) && ((msgCounter/30)%2)) + { + DrawRectangle(0, 0, GetScreenWidth(), 50, Fade(LIGHTGRAY, 0.5f)); + DrawText("PRESS SPACE or CLICK to INTERACT", 420, 15, 20, BLACK); + } + } + + DrawPlayer(); // NOTE: Also draws mouse pointer! +} + +// Gameplay Screen Unload logic +void UnloadAtticScreen(void) +{ + // TODO: Unload GAMEPLAY screen variables here! + UnloadTexture(background); + + UnloadMonster(lamp); + UnloadMonster(arc); +} + +// Gameplay Screen should finish? +int FinishAtticScreen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/skully_escape/screens/screen_bathroom.c b/games/skully_escape/screens/screen_bathroom.c new file mode 100644 index 00000000..176967a7 --- /dev/null +++ b/games/skully_escape/screens/screen_bathroom.c @@ -0,0 +1,383 @@ +/********************************************************************************************** +* +* raylib - Advance Game template +* +* Gameplay 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 "../player.h" +#include "../monster.h" + +#include + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Gameplay screen global variables +static int framesCounter; +static int finishScreen; + +static Texture2D background; + +// Declare doors +static Door doorRight; + +// Decalre monst +static Monster lamp; +static Monster chair; +static Monster mirror; + +static bool monsterHover = false; +static int monsterCheck = -1; // Identify checking monster + +static const char message[256] = "TRICK OR TREAT! WHO IS THE MOST BEAUTIFUL\nSKELETON IN THE WORLD?"; +static int msgPosX = 100; + +static int msgState = 0; // 0-writting, 1-wait, 2-choose +static int lettersCounter = 0; +static char msgBuffer[256] = { '\0' }; +static int msgCounter = 0; + +static bool searching = false; + +//---------------------------------------------------------------------------------- +// Gameplay Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Gameplay Screen Initialization logic +void InitBathroomScreen(void) +{ + ResetPlayer(); + + // Reset Screen variables + monsterHover = false; + monsterCheck = -1; + msgState = 0; + msgCounter = 0; + lettersCounter = 0; + for (int i = 0; i < 256; i++) msgBuffer[i] = '\0'; + + framesCounter = 0; + finishScreen = 0; + + background = LoadTexture("resources/textures/background_bathroom.png"); + + // Reset Screen variables + monsterHover = false; + monsterCheck = -1; + msgState = 0; + msgCounter = 0; + lettersCounter = 0; + for (int i = 0; i < 256; i++) msgBuffer[i] = '\0'; + + // Initialize doors + doorRight.position = (Vector2) { 1070, 135 }; + doorRight.facing = 2; + doorRight.locked = true; + doorRight.frameRec =(Rectangle) {((doors.width/3)*doorRight.facing), doors.height/2, doors.width/3, doors.height/2}; + doorRight.bound = (Rectangle) { doorRight.position.x, doorRight.position.y, doors.width/3, doors.height/2}; + doorRight.selected = false; + + // Monster init: lamp + lamp.position = (Vector2){ 35, 334 }; + lamp.texture = LoadTexture("resources/textures/monster_lamp_left.png"); + lamp.currentFrame = 0; + lamp.framesCounter = 0; + lamp.numFrames = 4; + lamp.bounds = (Rectangle){ lamp.position.x + 20, lamp.position.y + 0, 90, 380}; + lamp.frameRec = (Rectangle) { 0, 0, lamp.texture.width/lamp.numFrames, lamp.texture.height }; + lamp.selected = false; + lamp.active = false; + lamp.spooky = true; + + // Monster init: mirror + mirror.position = (Vector2){ 300, 200 }; + mirror.texture = LoadTexture("resources/textures/monster_mirror.png"); + mirror.currentFrame = 0; + mirror.framesCounter = 0; + mirror.numFrames = 4; + mirror.bounds = (Rectangle){ mirror.position.x + 40, mirror.position.y + 20, 190, 200 }; + mirror.frameRec = (Rectangle) { 0, 0, mirror.texture.width/mirror.numFrames, mirror.texture.height }; + mirror.selected = false; + mirror.active = false; + mirror.spooky = false; + + // Monster init: chair + chair.position = (Vector2){ 760, 430 }; + chair.texture = LoadTexture("resources/textures/monster_chair_right.png"); + chair.currentFrame = 0; + chair.framesCounter = 0; + chair.numFrames = 4; + chair.bounds = (Rectangle){ chair.position.x + 30, chair.position.y + 30, 120, 190 }; + chair.frameRec = (Rectangle) { 0, 0, chair.texture.width/chair.numFrames, chair.texture.height }; + chair.selected = false; + chair.active = false; + chair.spooky = true; +} + +// Gameplay Screen Update logic +void UpdateBathroomScreen(void) +{ + if (player.key) + { + // Door: right + if ((CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) || + (CheckCollisionRecs(player.bounds, doorRight.bound))) doorRight.selected = true; + else doorRight.selected = false; + + if ((doorRight.selected) && (CheckCollisionRecs(player.bounds, doorRight.bound))) + { + if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) || (IsKeyPressed(KEY_SPACE))) + { + if (doorRight.locked) + { + doorRight.frameRec.y = 0; + doorRight.locked = false; + PlaySound(sndDoor); + } + else finishScreen = 1; + } + } + } + + if (msgState > 2) + { + UpdatePlayer(); + + // Monsters logic + UpdateMonster(&lamp); + UpdateMonster(&mirror); + UpdateMonster(&chair); + } + + // Check player hover monsters to interact + if (((CheckCollisionRecs(player.bounds, lamp.bounds)) && !lamp.active) || + ((CheckCollisionRecs(player.bounds, mirror.bounds)) && !mirror.active) || + ((CheckCollisionRecs(player.bounds, chair.bounds)) && !chair.active)) monsterHover = true; + else monsterHover = false; + + + // Monters logic: lamp + if ((CheckCollisionRecs(player.bounds, lamp.bounds)) && !lamp.active) + { + lamp.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), lamp.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 1; + } + } + else lamp.selected = false; + + // Monters logic: mirror + if ((CheckCollisionRecs(player.bounds, mirror.bounds)) && !mirror.active) + { + mirror.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), mirror.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 2; + } + } + else mirror.selected = false; + + // Monters logic: chair + if ((CheckCollisionRecs(player.bounds, chair.bounds)) && !chair.active) + { + chair.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), chair.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 3; + } + } + else chair.selected = false; + + if (searching) + { + framesCounter++; + + if (framesCounter > 180) + { + if (monsterCheck == 1) + { + if (lamp.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + lamp.active = true; + lamp.selected = false; + } + else if (monsterCheck == 2) + { + if (mirror.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + mirror.active = true; + mirror.selected = false; + } + else if (monsterCheck == 3) + { + if (chair.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + chair.active = true; + chair.selected = false; + } + + searching = false; + framesCounter = 0; + } + } + + // Text animation + framesCounter++; + + if ((framesCounter%2) == 0) lettersCounter++; + + if (msgState == 0) + { + if (lettersCounter <= (int)strlen(message)) strncpy(msgBuffer, message, lettersCounter); + else + { + for (int i = 0; i < (int)strlen(msgBuffer); i++) msgBuffer[i] = '\0'; + + lettersCounter = 0; + msgState = 1; + } + + if (IsKeyPressed(KEY_ENTER)) msgState = 1; + } + else if (msgState == 1) + { + msgCounter++; + + if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + { + msgState = 2; + msgCounter = 0; + } + } + else if (msgState == 2) + { + msgCounter++; + + if (msgCounter > 180) msgState = 3; + } + else msgCounter++; +} + +// Gameplay Screen Draw logic +void DrawBathroomScreen(void) +{ + DrawTexture(background, 0, 0, WHITE); + + // Draw monsters + DrawMonster(lamp, 0); + DrawMonster(mirror, 0); + DrawMonster(chair, 0); + + // Draw door + if (doorRight.selected) DrawTextureRec(doors, doorRight.frameRec, doorRight.position, GREEN); + else DrawTextureRec(doors, doorRight.frameRec, doorRight.position, WHITE); + + // Draw messsages + if (msgState < 2) DrawRectangle(0, 40, GetScreenWidth(), 200, Fade(LIGHTGRAY, 0.5f)); + else if (msgState == 2) DrawRectangle(0, 80, GetScreenWidth(), 100, Fade(LIGHTGRAY, 0.5f)); + + if (msgState == 0) + { + DrawTextEx(font, msgBuffer, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE); + } + else if (msgState == 1) + { + DrawTextEx(font, message, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE); + + if ((msgCounter/30)%2) DrawText("PRESS ENTER or CLICK", GetScreenWidth() - 280, 200, 20, BLACK); + } + else if (msgState == 2) + { + if ((msgCounter/30)%2) + { + DrawTextEx(font, "CHOOSE WISELY!", (Vector2){ 300, 95 }, font.size*2, 2, WHITE); + + DrawRectangleRec(lamp.bounds, Fade(RED, 0.6f)); + DrawRectangleRec(mirror.bounds, Fade(RED, 0.6f)); + DrawRectangleRec(chair.bounds, Fade(RED, 0.6f)); + } + } + else + { + if ((monsterHover) && ((msgCounter/30)%2)) + { + DrawRectangle(0, 0, GetScreenWidth(), 50, Fade(LIGHTGRAY, 0.5f)); + DrawText("PRESS SPACE or CLICK to INTERACT", 420, 15, 20, BLACK); + } + } + + DrawPlayer(); // NOTE: Also draws mouse pointer! +} + +// Gameplay Screen Unload logic +void UnloadBathroomScreen(void) +{ + // TODO: Unload GAMEPLAY screen variables here! + UnloadTexture(background); + + UnloadMonster(lamp); + UnloadMonster(chair); + UnloadMonster(mirror); +} + +// Gameplay Screen should finish? +int FinishBathroomScreen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/skully_escape/screens/screen_ending.c b/games/skully_escape/screens/screen_ending.c new file mode 100644 index 00000000..120d9071 --- /dev/null +++ b/games/skully_escape/screens/screen_ending.c @@ -0,0 +1,90 @@ +/********************************************************************************************** +* +* raylib - Advance Game template +* +* Ending 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) +//---------------------------------------------------------------------------------- + +// Ending screen global variables +static int framesCounter; +static int finishScreen; + +static float alpha = 0.0f; + +//---------------------------------------------------------------------------------- +// Ending Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Ending Screen Initialization logic +void InitEndingScreen(void) +{ + // TODO: Initialize ENDING screen variables here! + framesCounter = 0; + finishScreen = 0; + alpha = 0.0f; +} + +// Ending Screen Update logic +void UpdateEndingScreen(void) +{ + // TODO: Update ENDING screen variables here! + framesCounter++; + + alpha += 0.005f; + + if (alpha >= 1.0f) alpha = 1.0f; + + // Press enter to change to ATTIC screen + if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + { + finishScreen = 1; + } +} + +// Ending Screen Draw logic +void DrawEndingScreen(void) +{ + DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), DARKGRAY); + + DrawTextEx(font, "CONGRATULATIONS!", (Vector2){ 50, 160 }, font.size*3, 2, Fade(WHITE, alpha)); + DrawTextEx(font, "SKULLY ESCAPED!", (Vector2){ 100, 300 }, font.size*3, 2, Fade(WHITE, alpha)); + + if ((framesCounter > 180) && ((framesCounter/40)%2)) DrawText("PRESS ENTER or CLICK", 380, 545, 40, BLACK); +} + +// Ending Screen Unload logic +void UnloadEndingScreen(void) +{ + // TODO: Unload ENDING screen variables here! +} + +// Ending Screen should finish? +int FinishEndingScreen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/skully_escape/screens/screen_kitchen.c b/games/skully_escape/screens/screen_kitchen.c new file mode 100644 index 00000000..a6b8924d --- /dev/null +++ b/games/skully_escape/screens/screen_kitchen.c @@ -0,0 +1,403 @@ +/********************************************************************************************** +* +* raylib - Advance Game template +* +* Gameplay 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 "../player.h" +#include "../monster.h" + +#include + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Gameplay screen global variables +static int framesCounter; +static int finishScreen; + +static Texture2D background; + +// Declare doors +static Door doorLeft; +static Door doorRight; + +// Decalre monsters +static Monster closet; +static Monster chair; +static Monster window; + +static bool monsterHover = false; +static int monsterCheck = -1; // Identify checking monster + +static const char message[256] = "QUITE BORING AROUND...\nANY BETTER ENTERTAINING?"; +static int msgPosX = 100; + +static int msgState = 0; // 0-writting, 1-wait, 2-choose +static int lettersCounter = 0; +static char msgBuffer[256] = { '\0' }; +static int msgCounter = 0; + +static bool searching = false; + +//---------------------------------------------------------------------------------- +// Gameplay Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Gameplay Screen Initialization logic +void InitKitchenScreen(void) +{ + ResetPlayer(); + + // Reset Screen variables + monsterHover = false; + monsterCheck = -1; + msgState = 0; + msgCounter = 0; + lettersCounter = 0; + for (int i = 0; i < 256; i++) msgBuffer[i] = '\0'; + + framesCounter = 0; + finishScreen = 0; + + background = LoadTexture("resources/textures/background_kitchen.png"); + + // Initialize doors + doorLeft.position = (Vector2) { -45, 136 }; + doorLeft.facing = 0; + doorLeft.locked = true; + doorLeft.frameRec =(Rectangle) {((doors.width/3)*doorLeft.facing), doors.height/2, doors.width/3, doors.height/2}; + doorLeft.bound = (Rectangle) { doorLeft.position.x, doorLeft.position.y, doors.width/3, doors.height/2}; + doorLeft.selected = false; + + doorRight.position = (Vector2) { 1090, 148 }; + doorRight.facing = 2; + doorRight.locked = true; + doorRight.frameRec =(Rectangle) {((doors.width/3)*doorRight.facing), doors.height/2, doors.width/3, doors.height/2}; + doorRight.bound = (Rectangle) { doorRight.position.x, doorRight.position.y, doors.width/3, doors.height/2}; + doorRight.selected = false; + + // Monster init: lamp + closet.position = (Vector2){ 280, 260 }; + closet.texture = LoadTexture("resources/textures/monster_closet.png"); + closet.currentFrame = 0; + closet.framesCounter = 0; + closet.numFrames = 4; + closet.bounds = (Rectangle){ closet.position.x + 100, closet.position.y+25, 272,348 }; + closet.frameRec = (Rectangle) { 0, 0, closet.texture.width/closet.numFrames, closet.texture.height }; + closet.selected = false; + closet.active = false; + closet.spooky = true; + + // Monster init: chair + chair.position = (Vector2){ 230, 410 }; + chair.texture = LoadTexture("resources/textures/monster_chair_left.png"); + chair.currentFrame = 0; + chair.framesCounter = 0; + chair.numFrames = 4; + chair.bounds = (Rectangle){ chair.position.x + 30, chair.position.y + 60, 100, 160 }; + chair.frameRec = (Rectangle) { 0, 0, chair.texture.width/chair.numFrames, chair.texture.height }; + chair.selected = false; + chair.active = false; + chair.spooky = true; + + // Monster init: window + window.position = (Vector2){ 715, 88 }; + window.texture = LoadTexture("resources/textures/monster_window.png"); + window.currentFrame = 0; + window.framesCounter = 0; + window.numFrames = 4; + window.bounds = (Rectangle){ window.position.x + 100, window.position.y + 10, 200, 370 }; + window.frameRec = (Rectangle) { 0, 0, window.texture.width/window.numFrames, window.texture.height }; + window.selected = false; + window.active = false; + window.spooky = false; +} + +// Gameplay Screen Update logic +void UpdateKitchenScreen(void) +{ + if (player.key) + { + // Door: left + if ((CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) || + (CheckCollisionRecs(player.bounds, doorLeft.bound))) doorLeft.selected = true; + else doorLeft.selected = false; + + if ((doorLeft.selected) && (CheckCollisionRecs(player.bounds, doorLeft.bound))) + { + if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) || (IsKeyPressed(KEY_SPACE))) + { + if (doorLeft.locked) + { + doorLeft.frameRec.y = 0; + doorLeft.locked = false; + PlaySound(sndDoor); + } + else finishScreen = 1; + } + } + + // Door: right + if ((CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) || + (CheckCollisionRecs(player.bounds, doorRight.bound))) doorRight.selected = true; + else doorRight.selected = false; + + if ((doorRight.selected) && (CheckCollisionRecs(player.bounds, doorRight.bound))) + { + if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) || (IsKeyPressed(KEY_SPACE))) + { + if (doorRight.locked) + { + doorRight.frameRec.y = 0; + doorRight.locked = false; + PlaySound(sndDoor); + } + else finishScreen = 2; + } + } + } + + if (msgState > 2) + { + UpdatePlayer(); + + // Monsters logic + UpdateMonster(&closet); + UpdateMonster(&chair); + UpdateMonster(&window); + } + + // Check player hover monsters to interact + if (((CheckCollisionRecs(player.bounds, closet.bounds)) && !closet.active) || + ((CheckCollisionRecs(player.bounds, window.bounds)) && !window.active)) monsterHover = true; + else monsterHover = false; + + // Monters logic: closet + if ((CheckCollisionRecs(player.bounds, closet.bounds)) && !closet.active) + { + closet.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), closet.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 1; + } + } + else closet.selected = false; + + // Monters logic: chair + if ((CheckCollisionRecs(player.bounds, chair.bounds)) && !chair.active) + { + chair.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), chair.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 2; + } + } + else chair.selected = false; + + // Monters logic: window + if ((CheckCollisionRecs(player.bounds, window.bounds)) && !window.active) + { + window.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), window.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 3; + } + } + else window.selected = false; + + if (searching) + { + framesCounter++; + + if (framesCounter > 180) + { + if (monsterCheck == 1) + { + if (closet.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + closet.active = true; + closet.selected = false; + } + else if (monsterCheck == 2) + { + if (chair.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + chair.active = true; + chair.selected = false; + } + else if (monsterCheck == 3) + { + if (window.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + window.active = true; + window.selected = false; + } + + searching = false; + framesCounter = 0; + } + } + + // Text animation + framesCounter++; + + if ((framesCounter%2) == 0) lettersCounter++; + + if (msgState == 0) + { + if (lettersCounter <= (int)strlen(message)) strncpy(msgBuffer, message, lettersCounter); + else + { + for (int i = 0; i < (int)strlen(msgBuffer); i++) msgBuffer[i] = '\0'; + + lettersCounter = 0; + msgState = 1; + } + + if (IsKeyPressed(KEY_ENTER)) msgState = 1; + } + else if (msgState == 1) + { + msgCounter++; + + if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + { + msgState = 2; + msgCounter = 0; + } + } + else if (msgState == 2) + { + msgCounter++; + + if (msgCounter > 180) msgState = 3; + } + else msgCounter++; +} + +// Gameplay Screen Draw logic +void DrawKitchenScreen(void) +{ + DrawTexture(background, 0, 0, WHITE); + + // Draw monsters + DrawMonster(closet, 0); + DrawMonster(chair, 0); + DrawMonster(window, 0); + + // Draw door + if (doorRight.selected) DrawTextureRec(doors, doorRight.frameRec, doorRight.position, GREEN); + else DrawTextureRec(doors, doorRight.frameRec, doorRight.position, WHITE); + + if (doorLeft.selected) DrawTextureRec(doors, doorLeft.frameRec, doorLeft.position, GREEN); + else DrawTextureRec(doors, doorLeft.frameRec, doorLeft.position, WHITE); + + // Draw messsages + if (msgState < 2) DrawRectangle(0, 40, GetScreenWidth(), 200, Fade(LIGHTGRAY, 0.5f)); + else if (msgState == 2) DrawRectangle(0, 80, GetScreenWidth(), 100, Fade(LIGHTGRAY, 0.5f)); + + if (msgState == 0) + { + DrawTextEx(font, msgBuffer, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE); + } + else if (msgState == 1) + { + DrawTextEx(font, message, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE); + + if ((msgCounter/30)%2) DrawText("PRESS ENTER or CLICK", GetScreenWidth() - 280, 200, 20, BLACK); + } + else if (msgState == 2) + { + if ((msgCounter/30)%2) + { + DrawTextEx(font, "CHOOSE WISELY!", (Vector2){ 300, 95 }, font.size*2, 2, WHITE); + + DrawRectangleRec(closet.bounds, Fade(RED, 0.6f)); + DrawRectangleRec(window.bounds, Fade(RED, 0.6f)); + DrawRectangleRec(chair.bounds, Fade(RED, 0.6f)); + } + } + else + { + if ((monsterHover) && ((msgCounter/30)%2)) + { + DrawRectangle(0, 0, GetScreenWidth(), 50, Fade(LIGHTGRAY, 0.5f)); + DrawText("PRESS SPACE or CLICK to INTERACT", 420, 15, 20, BLACK); + } + } + + DrawPlayer(); // NOTE: Also draws mouse pointer! +} + +// Gameplay Screen Unload logic +void UnloadKitchenScreen(void) +{ + // TODO: Unload GAMEPLAY screen variables here! + UnloadTexture(background); + + UnloadMonster(closet); + UnloadMonster(chair); + UnloadMonster(window); +} + +// Gameplay Screen should finish? +int FinishKitchenScreen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/skully_escape/screens/screen_livingroom.c b/games/skully_escape/screens/screen_livingroom.c new file mode 100644 index 00000000..b2b09d9a --- /dev/null +++ b/games/skully_escape/screens/screen_livingroom.c @@ -0,0 +1,403 @@ +/********************************************************************************************** +* +* raylib - Advance Game template +* +* Gameplay 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 "../player.h" +#include "../monster.h" + +#include + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Gameplay screen global variables +static int framesCounter; +static int finishScreen; + +static Texture2D background; + +// Declare doors +static Door doorCenter; +static Door doorLeft; + +// Decalre monsters +static Monster candle; +static Monster picture; +static Monster phone; + +static bool monsterHover = false; +static int monsterCheck = -1; // Identify checking monster + +static const char message[256] = "WHEN WIND BLOWS, IT KNOWS THE DIRECTION\nLET IT GUIDE YOU!"; +static int msgPosX = 100; + +static int msgState = 0; // 0-writting, 1-wait, 2-choose +static int lettersCounter = 0; +static char msgBuffer[256] = { '\0' }; +static int msgCounter = 0; + +static bool searching = false; + +//---------------------------------------------------------------------------------- +// Gameplay Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Gameplay Screen Initialization logic +void InitLivingroomScreen(void) +{ + ResetPlayer(); + + // Reset Screen variables + monsterHover = false; + monsterCheck = -1; + msgState = 0; + msgCounter = 0; + lettersCounter = 0; + for (int i = 0; i < 256; i++) msgBuffer[i] = '\0'; + + framesCounter = 0; + finishScreen = 0; + + background = LoadTexture("resources/textures/background_livingroom.png"); + + // Initialize doors + doorLeft.position = (Vector2) { -45, 140}; + doorLeft.facing = 0; + doorLeft.locked = true; + doorLeft.frameRec =(Rectangle) {((doors.width/3)*doorLeft.facing), doors.height/2, doors.width/3, doors.height/2}; + doorLeft.bound = (Rectangle) { doorLeft.position.x, doorLeft.position.y, doors.width/3, doors.height/2}; + doorLeft.selected = false; + + doorCenter.position = (Vector2) { 830, 108 }; + doorCenter.facing = 1; + doorCenter.locked = true; + doorCenter.frameRec =(Rectangle) {((doors.width/3)*doorCenter.facing), doors.height/2, doors.width/3, doors.height/2}; + doorCenter.bound = (Rectangle) { doorCenter.position.x, doorCenter.position.y, doors.width/3, doors.height/2}; + doorCenter.selected = false; + + // Monster init: lamp + candle.position = (Vector2){ 154, 256 }; + candle.texture = LoadTexture("resources/textures/monster_candle.png"); + candle.currentFrame = 0; + candle.framesCounter = 0; + candle.numFrames = 4; + candle.bounds = (Rectangle){ candle.position.x + 90, candle.position.y + 30, 185, 340 }; + candle.frameRec = (Rectangle) { 0, 0, candle.texture.width/candle.numFrames, candle.texture.height }; + candle.selected = false; + candle.active = false; + candle.spooky = false; + + // Monster init: arc + picture.position = (Vector2){ 504, 164 }; + picture.texture = LoadTexture("resources/textures/monster_picture.png"); + picture.currentFrame = 0; + picture.framesCounter = 0; + picture.numFrames = 4; + picture.bounds = (Rectangle){ picture.position.x + 44, picture.position.y, 174, 264 }; + picture.frameRec = (Rectangle) { 0, 0, picture.texture.width/picture.numFrames, picture.texture.height }; + picture.selected = false; + picture.active = false; + picture.spooky = true; + + // Monster init: phone + phone.position = (Vector2){ 1054, 404 }; + phone.texture = LoadTexture("resources/textures/monster_phone.png"); + phone.currentFrame = 0; + phone.framesCounter = 0; + phone.numFrames = 4; + phone.bounds = (Rectangle){ phone.position.x + 64, phone.position.y +120, 100, 160 }; + phone.frameRec = (Rectangle) { 0, 0, phone.texture.width/phone.numFrames, phone.texture.height }; + phone.selected = false; + phone.active = false; + phone.spooky = true; +} + +// Gameplay Screen Update logic +void UpdateLivingroomScreen(void) +{ + if (player.key) + { + // Door: left + if ((CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) || + (CheckCollisionRecs(player.bounds, doorLeft.bound))) doorLeft.selected = true; + else doorLeft.selected = false; + + if ((doorLeft.selected) && (CheckCollisionRecs(player.bounds, doorLeft.bound))) + { + if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) || (IsKeyPressed(KEY_SPACE))) + { + if (doorLeft.locked) + { + doorLeft.frameRec.y = 0; + doorLeft.locked = false; + PlaySound(sndDoor); + } + else finishScreen = 1; + } + } + + // Door: center + if ((CheckCollisionPointRec(GetMousePosition(), doorCenter.bound)) || + (CheckCollisionRecs(player.bounds, doorCenter.bound))) doorCenter.selected = true; + else doorCenter.selected = false; + + if ((doorCenter.selected) && (CheckCollisionRecs(player.bounds, doorCenter.bound))) + { + if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorCenter.bound)) || (IsKeyPressed(KEY_SPACE))) + { + if (doorCenter.locked) + { + doorCenter.frameRec.y = 0; + doorCenter.locked = false; + PlaySound(sndDoor); + } + else finishScreen = 2; + } + } + } + + if (msgState > 2) + { + UpdatePlayer(); + + // Monsters logic + UpdateMonster(&candle); + UpdateMonster(&picture); + UpdateMonster(&phone); + } + + // Check player hover monsters to interact + if (((CheckCollisionRecs(player.bounds, candle.bounds)) && !candle.active) || + ((CheckCollisionRecs(player.bounds, picture.bounds)) && !picture.active) || + ((CheckCollisionRecs(player.bounds, phone.bounds)) && !phone.active)) monsterHover = true; + else monsterHover = false; + + // Monters logic: candle + if ((CheckCollisionRecs(player.bounds, candle.bounds)) && !candle.active) + { + candle.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), candle.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 1; + } + } + else candle.selected = false; + + // Monters logic: picture + if ((CheckCollisionRecs(player.bounds, picture.bounds)) && !picture.active) + { + picture.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), picture.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 2; + } + } + else picture.selected = false; + + // Monters logic: phone + if ((CheckCollisionRecs(player.bounds, phone.bounds)) && !phone.active) + { + phone.selected = true; + + if ((IsKeyPressed(KEY_SPACE)) || + ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), phone.bounds)))) + { + SearchKeyPlayer(); + searching = true; + framesCounter = 0; + + monsterCheck = 3; + } + } + else phone.selected = false; + + if (searching) + { + framesCounter++; + + if (framesCounter > 180) + { + if (monsterCheck == 1) + { + if (candle.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + candle.active = true; + candle.selected = false; + } + else if (monsterCheck == 2) + { + if (picture.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + picture.active = true; + picture.selected = false; + } + else if (monsterCheck == 3) + { + if (phone.spooky) + { + ScarePlayer(); + PlaySound(sndScream); + } + else FindKeyPlayer(); + + phone.active = true; + phone.selected = false; + } + + searching = false; + framesCounter = 0; + } + } + + // Text animation + framesCounter++; + + if ((framesCounter%2) == 0) lettersCounter++; + + if (msgState == 0) + { + if (lettersCounter <= (int)strlen(message)) strncpy(msgBuffer, message, lettersCounter); + else + { + for (int i = 0; i < (int)strlen(msgBuffer); i++) msgBuffer[i] = '\0'; + + lettersCounter = 0; + msgState = 1; + } + + if (IsKeyPressed(KEY_ENTER)) msgState = 1; + } + else if (msgState == 1) + { + msgCounter++; + + if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + { + msgState = 2; + msgCounter = 0; + } + } + else if (msgState == 2) + { + msgCounter++; + + if (msgCounter > 180) msgState = 3; + } + else msgCounter++; +} + +// Gameplay Screen Draw logic +void DrawLivingroomScreen(void) +{ + DrawTexture(background, 0, 0, WHITE); + + // Draw monsters + DrawMonster(picture, 0); + DrawMonster(candle, 0); + DrawMonster(phone, 0); + + // Draw door + if (doorCenter.selected) DrawTextureRec(doors, doorCenter.frameRec, doorCenter.position, GREEN); + else DrawTextureRec(doors, doorCenter.frameRec, doorCenter.position, WHITE); + if (doorLeft.selected) DrawTextureRec(doors, doorLeft.frameRec, doorLeft.position, GREEN); + else DrawTextureRec(doors, doorLeft.frameRec, doorLeft.position, WHITE); + + // Draw messsages + if (msgState < 2) DrawRectangle(0, 40, GetScreenWidth(), 200, Fade(LIGHTGRAY, 0.5f)); + else if (msgState == 2) DrawRectangle(0, 80, GetScreenWidth(), 100, Fade(LIGHTGRAY, 0.5f)); + + if (msgState == 0) + { + DrawTextEx(font, msgBuffer, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE); + } + else if (msgState == 1) + { + DrawTextEx(font, message, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE); + + if ((msgCounter/30)%2) DrawText("PRESS ENTER or CLICK", GetScreenWidth() - 280, 200, 20, BLACK); + } + else if (msgState == 2) + { + if ((msgCounter/30)%2) + { + DrawTextEx(font, "CHOOSE WISELY!", (Vector2){ 300, 95 }, font.size*2, 2, WHITE); + + DrawRectangleRec(candle.bounds, Fade(RED, 0.6f)); + DrawRectangleRec(phone.bounds, Fade(RED, 0.6f)); + DrawRectangleRec(picture.bounds, Fade(RED, 0.6f)); + } + } + else + { + if ((monsterHover) && ((msgCounter/30)%2)) + { + DrawRectangle(0, 0, GetScreenWidth(), 50, Fade(LIGHTGRAY, 0.5f)); + DrawText("PRESS SPACE or CLICK to INTERACT", 420, 15, 20, BLACK); + } + } + + DrawPlayer(); // NOTE: Also draws mouse pointer! +} + +// Gameplay Screen Unload logic +void UnloadLivingroomScreen(void) +{ + // TODO: Unload GAMEPLAY screen variables here! + UnloadTexture(background); + + UnloadMonster(candle); + UnloadMonster(picture); + UnloadMonster(phone); +} + +// Gameplay Screen should finish? +int FinishLivingroomScreen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/skully_escape/screens/screen_logo.c b/games/skully_escape/screens/screen_logo.c new file mode 100644 index 00000000..f07f5f54 --- /dev/null +++ b/games/skully_escape/screens/screen_logo.c @@ -0,0 +1,108 @@ +/********************************************************************************************** +* +* raylib - Advance 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" + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Logo screen global variables +static int framesCounter = 0; +static int finishScreen; + +static Texture2D logo; +static float logoAlpha = 0; + +static int state = 0; + +//---------------------------------------------------------------------------------- +// Logo Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Logo Screen Initialization logic +void InitLogoScreen(void) +{ + // Initialize LOGO screen variables here! + finishScreen = 0; + + logo = LoadTexture("resources/textures/skully_logo.png"); +} + +// Logo Screen Update logic +void UpdateLogoScreen(void) +{ + // Update LOGO screen variables here! + if (state == 0) + { + logoAlpha += 0.04f; + + if (logoAlpha >= 1.0f) state = 1; + } + else if (state == 1) + { + framesCounter++; + + if (framesCounter > 180) state = 2; + } + else if (state == 2) + { + logoAlpha -= 0.04f; + + if (logoAlpha <= 0.0f) + { + framesCounter = 0; + state = 3; + } + } + else if (state == 3) + { + finishScreen = 1; + } +} + +// Logo Screen Draw logic +void DrawLogoScreen(void) +{ + DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), RAYWHITE); + + DrawTexture(logo, GetScreenWidth()/2 - logo.width/2, 130, Fade(WHITE, logoAlpha)); + + DrawText("GRAY TEAM", 340, 450, 100, Fade(DARKGRAY, logoAlpha)); +} + +// Logo Screen Unload logic +void UnloadLogoScreen(void) +{ + // Unload LOGO screen variables here! + UnloadTexture(logo); +} + +// Logo Screen should finish? +int FinishLogoScreen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/skully_escape/screens/screen_logo_raylib.c b/games/skully_escape/screens/screen_logo_raylib.c new file mode 100644 index 00000000..e5efe843 --- /dev/null +++ b/games/skully_escape/screens/screen_logo_raylib.c @@ -0,0 +1,201 @@ +/********************************************************************************************** +* +* raylib - Advance 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" + +#define LOGO_RECS_SIDE 16 + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Logo screen global variables +static int framesCounter = 0; +static int finishScreen; + +static int logoPositionX; +static int logoPositionY; + +static int lettersCount = 0; + +static int topSideRecWidth = LOGO_RECS_SIDE; +static int leftSideRecHeight = LOGO_RECS_SIDE; + +static int bottomSideRecWidth = LOGO_RECS_SIDE; +static int rightSideRecHeight = LOGO_RECS_SIDE; + +static char raylib[8]; // raylib text array, max 8 letters +static int state = 0; // Tracking animation states (State Machine) +static float alpha = 1.0f; // Useful for fading + +//---------------------------------------------------------------------------------- +// Logo Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Logo Screen Initialization logic +void rlInitLogoScreen(void) +{ + // TODO: Initialize LOGO screen variables here! + finishScreen = 0; + + logoPositionX = GetScreenWidth()/2 - 128; + logoPositionY = GetScreenHeight()/2 - 128; + + for (int i = 0; i < 8; i++) raylib[i] = '\0'; +} + +// Logo Screen Update logic +void rlUpdateLogoScreen(void) +{ + // Update LOGO screen variables here! + if (state == 0) // State 0: Small box blinking + { + framesCounter++; + + if (framesCounter == 80) + { + state = 1; + framesCounter = 0; // Reset counter... will be used later... + } + } + else if (state == 1) // State 1: Top and left bars growing + { + topSideRecWidth += 8; + leftSideRecHeight += 8; + + if (topSideRecWidth == 256) state = 2; + } + else if (state == 2) // State 2: Bottom and right bars growing + { + bottomSideRecWidth += 8; + rightSideRecHeight += 8; + + if (bottomSideRecWidth == 256) state = 3; + } + else if (state == 3) // State 3: Letters appearing (one by one) + { + framesCounter++; + + if (framesCounter/10) // Every 12 frames, one more letter! + { + lettersCount++; + framesCounter = 0; + } + + switch (lettersCount) + { + 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; + } + + // When all letters have appeared... + if (lettersCount >= 10) + { + state = 4; + framesCounter = 0; + } + } + else if (state == 4) + { + framesCounter++; + + if (framesCounter > 100) + { + alpha -= 0.02f; + + if (alpha <= 0.0f) + { + alpha = 0.0f; + finishScreen = 1; + } + } + } +} + +// Logo Screen Draw logic +void rlDrawLogoScreen(void) +{ + if (state == 0) + { + if ((framesCounter/10)%2) DrawRectangle(logoPositionX, logoPositionY, 16, 16, BLACK); + } + else if (state == 1) + { + DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK); + DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK); + } + else if (state == 2) + { + DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK); + DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK); + + DrawRectangle(logoPositionX + 240, logoPositionY, 16, rightSideRecHeight, BLACK); + DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, BLACK); + } + else if (state == 3) + { + DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha)); + DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha)); + + DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha)); + DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha)); + + DrawRectangle(GetScreenWidth()/2 - 112, GetScreenHeight()/2 - 112, 224, 224, Fade(RAYWHITE, alpha)); + + DrawText(raylib, GetScreenWidth()/2 - 44, GetScreenHeight()/2 + 48, 50, Fade(BLACK, alpha)); + } + else if (state == 4) + { + DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha)); + DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha)); + + DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha)); + DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha)); + + DrawRectangle(GetScreenWidth()/2 - 112, GetScreenHeight()/2 - 112, 224, 224, Fade(RAYWHITE, alpha)); + + DrawText(raylib, GetScreenWidth()/2 - 44, GetScreenHeight()/2 + 48, 50, Fade(BLACK, alpha)); + + if (framesCounter > 20) DrawText("powered by", logoPositionX, logoPositionY - 27, 20, Fade(DARKGRAY, alpha)); + } +} + +// Logo Screen Unload logic +void rlUnloadLogoScreen(void) +{ + // TODO: Unload LOGO screen variables here! +} + +// Logo Screen should finish? +int rlFinishLogoScreen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/skully_escape/screens/screen_title.c b/games/skully_escape/screens/screen_title.c new file mode 100644 index 00000000..837b5112 --- /dev/null +++ b/games/skully_escape/screens/screen_title.c @@ -0,0 +1,92 @@ +/********************************************************************************************** +* +* raylib - Advance Game template +* +* Title 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) +//---------------------------------------------------------------------------------- + +// Title screen global variables +static int framesCounter; +static int finishScreen; + +static Texture2D title; +static float titleAlpha = 0.0f; + +//---------------------------------------------------------------------------------- +// Title Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Title Screen Initialization logic +void InitTitleScreen(void) +{ + // Initialize TITLE screen variables here! + framesCounter = 0; + finishScreen = 0; + + title = LoadTexture("resources/textures/title.png"); +} + +// Title Screen Update logic +void UpdateTitleScreen(void) +{ + // Update TITLE screen variables here! + framesCounter++; + + titleAlpha += 0.005f; + + if (titleAlpha >= 1.0f) titleAlpha = 1.0f; + + // Press enter to change to ATTIC screen + if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + { + finishScreen = 1; + } +} + +// Title Screen Draw logic +void DrawTitleScreen(void) +{ + //DrawText("TITLE SCREEN", 100, 100, 140, Fade(BLACK, titleAlpha)); + DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), DARKGRAY); + DrawTexture(title, GetScreenWidth()/2 - title.width/2, 20, Fade(WHITE, titleAlpha)); + + if ((framesCounter > 180) && ((framesCounter/40)%2)) DrawText("PRESS ENTER to START", 380, 545, 40, BLACK); +} + +// Title Screen Unload logic +void UnloadTitleScreen(void) +{ + // Unload TITLE screen variables here! + UnloadTexture(title); +} + +// Title Screen should finish? +int FinishTitleScreen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/skully_escape/screens/screens.h b/games/skully_escape/screens/screens.h new file mode 100644 index 00000000..790df9ff --- /dev/null +++ b/games/skully_escape/screens/screens.h @@ -0,0 +1,164 @@ +/********************************************************************************************** +* +* raylib - Advance 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 + +#define PLAYER_ANIM_FRAMES 7 +#define PLAYER_ANIM_SEQ 2 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum GameScreen { LOGO = 0, LOGO_RL, TITLE, ATTIC, AISLE01, AISLE02, BATHROOM, LIVINGROOM, KITCHEN, ARMORY, ENDING } GameScreen; + +typedef struct Door { + Vector2 position; + int facing; + bool locked; + bool selected; + Rectangle frameRec; + Rectangle bound; +} Door; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +GameScreen currentScreen; +SpriteFont font; + +Texture2D doors; +Sound sndDoor; +Sound sndScream; + + +#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); + +//---------------------------------------------------------------------------------- +// raylib Logo Screen Functions Declaration +//---------------------------------------------------------------------------------- +void rlInitLogoScreen(void); +void rlUpdateLogoScreen(void); +void rlDrawLogoScreen(void); +void rlUnloadLogoScreen(void); +int rlFinishLogoScreen(void); + +//---------------------------------------------------------------------------------- +// Title Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitTitleScreen(void); +void UpdateTitleScreen(void); +void DrawTitleScreen(void); +void UnloadTitleScreen(void); +int FinishTitleScreen(void); + +//---------------------------------------------------------------------------------- +// Attic Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitAtticScreen(void); +void UpdateAtticScreen(void); +void DrawAtticScreen(void); +void UnloadAtticScreen(void); +int FinishAtticScreen(void); + +//---------------------------------------------------------------------------------- +// Aisle01 Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitAisle01Screen(void); +void UpdateAisle01Screen(void); +void DrawAisle01Screen(void); +void UnloadAisle01Screen(void); +int FinishAisle01Screen(void); + +//---------------------------------------------------------------------------------- +// Aisle02 Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitAisle02Screen(void); +void UpdateAisle02Screen(void); +void DrawAisle02Screen(void); +void UnloadAisle02Screen(void); +int FinishAisle02Screen(void); + +//---------------------------------------------------------------------------------- +// Bathroom Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitBathroomScreen(void); +void UpdateBathroomScreen(void); +void DrawBathroomScreen(void); +void UnloadBathroomScreen(void); +int FinishBathroomScreen(void); + +//---------------------------------------------------------------------------------- +// Livingroom Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitLivingroomScreen(void); +void UpdateLivingroomScreen(void); +void DrawLivingroomScreen(void); +void UnloadLivingroomScreen(void); +int FinishLivingroomScreen(void); + +//---------------------------------------------------------------------------------- +// Kitchen Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitKitchenScreen(void); +void UpdateKitchenScreen(void); +void DrawKitchenScreen(void); +void UnloadKitchenScreen(void); +int FinishKitchenScreen(void); + +//---------------------------------------------------------------------------------- +// Armory Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitArmoryScreen(void); +void UpdateArmoryScreen(void); +void DrawArmoryScreen(void); +void UnloadArmoryScreen(void); +int FinishArmoryScreen(void); + +//---------------------------------------------------------------------------------- +// Ending Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitEndingScreen(void); +void UpdateEndingScreen(void); +void DrawEndingScreen(void); +void UnloadEndingScreen(void); +int FinishEndingScreen(void); + +#ifdef __cplusplus +} +#endif + +#endif // SCREENS_H \ No newline at end of file diff --git a/games/skully_escape/skully_escape.c b/games/skully_escape/skully_escape.c new file mode 100644 index 00000000..22cc04e4 --- /dev/null +++ b/games/skully_escape/skully_escape.c @@ -0,0 +1,403 @@ +/******************************************************************************************* +* +* SKULLY ESCAPE [KING GAME JAM 2015] +* +* This game has been created using raylib (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" +#include "screens/screens.h" // NOTE: Defines global variable: currentScreen + +#include "player.h" + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- +const int screenWidth = 1280; +const int screenHeight = 720; + +// 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; + +static int framesCounter = 0; + +//---------------------------------------------------------------------------------- +// Local Functions Declaration +//---------------------------------------------------------------------------------- +void TransitionToScreen(int screen); +void ChangeToScreen(int screen); // No transition effect +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] = "SKULLY ESCAPE [KING GAMEJAM]"; + + InitWindow(screenWidth, screenHeight, windowTitle); + + // Global data loading (assets that must be available in all screens, i.e. fonts) + InitAudioDevice(); + + PlayMusicStream("resources/audio/come_play_with_me.ogg"); + + font = LoadSpriteFont("resources/textures/alagard.png"); + doors = LoadTexture("resources/textures/doors.png"); + sndDoor = LoadSound("resources/audio/door.ogg"); + sndScream = LoadSound("resources/audio/scream.ogg"); + + InitPlayer(); + + // 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 + { + UpdateDrawFrame(); + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + + // Unload all global loaded data (i.e. fonts) here! + UnloadPlayer(); + UnloadSpriteFont(font); + UnloadTexture(doors); + UnloadSound(sndDoor); + UnloadSound(sndScream); + + CloseAudioDevice(); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +void TransitionToScreen(int screen) +{ + onTransition = true; + transFromScreen = currentScreen; + transToScreen = screen; +} + +void ChangeToScreen(int screen) +{ + switch (currentScreen) + { + case LOGO: UnloadLogoScreen(); break; + case LOGO_RL: rlUnloadLogoScreen(); break; + case TITLE: UnloadTitleScreen(); break; + case ATTIC: UnloadAtticScreen(); break; + case AISLE01: UnloadAisle01Screen();break; + case AISLE02: UnloadAisle02Screen();break; + case ARMORY: UnloadArmoryScreen();break; + case LIVINGROOM: UnloadLivingroomScreen();break; + case KITCHEN: UnloadKitchenScreen(); break; + case BATHROOM: UnloadBathroomScreen(); break; + case ENDING: UnloadEndingScreen(); break; + default: break; + } + + switch (screen) + { + case LOGO: InitLogoScreen(); break; + case LOGO_RL: rlInitLogoScreen(); break; + case TITLE: InitTitleScreen(); break; + case ATTIC: InitAtticScreen(); break; + case AISLE01: InitAisle01Screen();break; + case AISLE02: InitAisle02Screen();break; + case ARMORY: InitArmoryScreen();break; + case LIVINGROOM: InitLivingroomScreen();break; + case KITCHEN: InitKitchenScreen(); break; + case BATHROOM: InitBathroomScreen(); break; + case ENDING: InitEndingScreen(); break; + default: break; + } + + currentScreen = screen; +} + +void UpdateTransition(void) +{ + if (!transFadeOut) + { + transAlpha += 0.05f; + + if (transAlpha >= 1.0) + { + transAlpha = 1.0; + + switch (transFromScreen) + { + case LOGO: UnloadLogoScreen(); break; + case LOGO_RL: rlUnloadLogoScreen(); break; + case TITLE: UnloadTitleScreen(); break; + case ATTIC: UnloadAtticScreen(); break; + case AISLE01: UnloadAisle01Screen();break; + case AISLE02: UnloadAisle02Screen();break; + case ARMORY: UnloadArmoryScreen();break; + case LIVINGROOM: UnloadLivingroomScreen();break; + case KITCHEN: UnloadKitchenScreen(); break; + case BATHROOM: UnloadBathroomScreen(); break; + case ENDING: UnloadEndingScreen(); break; + default: break; + } + + switch (transToScreen) + { + case LOGO: + { + InitLogoScreen(); + currentScreen = LOGO; + } break; + case LOGO_RL: + { + rlInitLogoScreen(); + currentScreen = LOGO_RL; + } break; + case TITLE: + { + InitTitleScreen(); + currentScreen = TITLE; + } break; + case ATTIC: + { + InitAtticScreen(); + currentScreen = ATTIC; + } break; + case AISLE01: + { + InitAisle01Screen(); + currentScreen = AISLE01; + } break; + case AISLE02: + { + InitAisle02Screen(); + currentScreen = AISLE02; + } break; + case BATHROOM: + { + InitBathroomScreen(); + currentScreen = BATHROOM; + } break; + case LIVINGROOM: + { + InitLivingroomScreen(); + currentScreen = LIVINGROOM; + } break; + case KITCHEN: + { + InitKitchenScreen(); + currentScreen = KITCHEN; + } break; + case ARMORY: + { + InitArmoryScreen(); + currentScreen = ARMORY; + } break; + case ENDING: + { + InitEndingScreen(); + currentScreen = ENDING; + } break; + default: break; + } + + transFadeOut = true; + } + } + else // Transition fade out logic + { + transAlpha -= 0.05f; + + if (transAlpha <= 0) + { + transAlpha = 0; + transFadeOut = false; + onTransition = false; + transFromScreen = -1; + transToScreen = -1; + } + } +} + +void DrawTransition(void) +{ + DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(BLACK, transAlpha)); +} + +// Update and draw game frame +void UpdateDrawFrame(void) +{ + // Update + //---------------------------------------------------------------------------------- + if (!onTransition) + { + if (player.dead) + { + framesCounter++; + + if (framesCounter > 80) + { + framesCounter = 0; + player.dead = false; + player.numLifes = 4; + + TransitionToScreen(TITLE); + } + } + + switch(currentScreen) + { + case LOGO: + { + UpdateLogoScreen(); + + if (FinishLogoScreen()) ChangeToScreen(LOGO_RL); + + } break; + case LOGO_RL: + { + rlUpdateLogoScreen(); + + if (rlFinishLogoScreen()) TransitionToScreen(TITLE); + + } break; + case TITLE: + { + UpdateTitleScreen(); + + if (FinishTitleScreen() == 1) TransitionToScreen(ATTIC); + + } break; + case ATTIC: + { + UpdateAtticScreen(); + + if (FinishAtticScreen() == 1) TransitionToScreen(AISLE01); + + } break; + case AISLE01: + { + UpdateAisle01Screen(); + + if (FinishAisle01Screen() == 1) TransitionToScreen(BATHROOM); + else if(FinishAisle01Screen() == 2) TransitionToScreen(KITCHEN); + else if(FinishAisle01Screen() == 3) TransitionToScreen(LIVINGROOM); + + } break; + case BATHROOM: + { + UpdateBathroomScreen(); + + if (FinishBathroomScreen() == 1) TransitionToScreen(AISLE01); + + } break; + case LIVINGROOM: + { + UpdateLivingroomScreen(); + + if (FinishLivingroomScreen() == 1) TransitionToScreen(AISLE01); + else if(FinishLivingroomScreen() == 2)TransitionToScreen(AISLE02); + + } break; + case AISLE02: + { + UpdateAisle02Screen(); + + if (FinishAisle02Screen() == 1) TransitionToScreen(KITCHEN); + + } break; + case KITCHEN: + { + UpdateKitchenScreen(); + + if (FinishKitchenScreen() == 1) TransitionToScreen(ARMORY); + else if(FinishKitchenScreen() == 2)TransitionToScreen(AISLE02); + + } break; + case ARMORY: + { + UpdateArmoryScreen(); + + if(FinishArmoryScreen() == 1) TransitionToScreen(ENDING); + else if(FinishArmoryScreen() == 2) TransitionToScreen(KITCHEN); + + } break; + case ENDING: + { + UpdateEndingScreen(); + + if (FinishEndingScreen()) TransitionToScreen(TITLE); + + } break; + default: break; + } + } + else + { + // Update transition (fade-in, fade-out) + UpdateTransition(); + } + + UpdateMusicStream(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + switch(currentScreen) + { + case LOGO: DrawLogoScreen(); break; + case LOGO_RL: rlDrawLogoScreen(); break; + case TITLE: DrawTitleScreen(); break; + case ATTIC: DrawAtticScreen(); break; + case AISLE01: DrawAisle01Screen();break; + case AISLE02: DrawAisle02Screen();break; + case BATHROOM: DrawBathroomScreen();break; + case LIVINGROOM: DrawLivingroomScreen();break; + case KITCHEN: DrawKitchenScreen();break; + case ARMORY: DrawArmoryScreen();break; + case ENDING: DrawEndingScreen(); break; + default: break; + } + + if (onTransition) DrawTransition(); + + //DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- +} + -- cgit v1.2.3 From 4ad375a3783472b8629387d45fb90619115c973a Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 7 Feb 2016 11:23:12 +0100 Subject: Code review Most of this code was developed by students, it requires some additional review to be used for teaching. --- games/samples/asteroids.c | 125 ++++---- games/samples/asteroids_survival.c | 72 ++--- games/samples/floppy.c | 12 +- games/samples/gold_fever.c | 69 ++-- games/samples/pang.c | 630 +++++++++++++++++-------------------- games/samples/space_invaders.c | 19 +- games/samples/tetris.c | 23 +- 7 files changed, 427 insertions(+), 523 deletions(-) diff --git a/games/samples/asteroids.c b/games/samples/asteroids.c index 676b0154..53ebbd8e 100644 --- a/games/samples/asteroids.c +++ b/games/samples/asteroids.c @@ -22,13 +22,14 @@ //---------------------------------------------------------------------------------- // Some Defines //---------------------------------------------------------------------------------- -#define MAX_SPEED 6 +#define PLAYER_BASE_SIZE 20.0f +#define PLAYER_SPEED 6.0f +#define PLAYER_MAX_SHOOTS 10 + #define METEORS_SPEED 2 -#define NUM_SHOOTS 10 -#define NUM_BIG_METEORS 4 -#define NUM_MEDIUM_METEORS 8 -#define NUM_SMALL_METEORS 16 -#define SHIP_BASE_SIZE 20.0f +#define MAX_BIG_METEORS 4 +#define MAX_MEDIUM_METEORS 8 +#define MAX_SMALL_METEORS 16 //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -53,29 +54,13 @@ typedef struct Shoot { Color color; } Shoot; -typedef struct BigMeteor { - Vector2 position; - Vector2 speed; - float radius; - bool active; - Color color; -} BigMeteor; - -typedef struct MediumMeteor { +typedef struct Meteor { Vector2 position; Vector2 speed; float radius; bool active; Color color; -} MediumMeteor; - -typedef struct SmallMeteor { - Vector2 position; - Vector2 speed; - float radius; - bool active; - Color color; -} SmallMeteor; +} Meteor; //------------------------------------------------------------------------------------ // Global Variables Declaration @@ -92,10 +77,10 @@ static bool victory; static float shipHeight; static Player player; -static Shoot shoot[NUM_SHOOTS]; -static BigMeteor bigMeteor[NUM_BIG_METEORS]; -static MediumMeteor mediumMeteor[NUM_MEDIUM_METEORS]; -static SmallMeteor smallMeteor[NUM_SMALL_METEORS]; +static Shoot shoot[PLAYER_MAX_SHOOTS]; +static Meteor bigMeteor[MAX_BIG_METEORS]; +static Meteor mediumMeteor[MAX_MEDIUM_METEORS]; +static Meteor smallMeteor[MAX_SMALL_METEORS]; static int countMediumMeteors; static int countSmallMeteors; @@ -169,7 +154,7 @@ void InitGame(void) victory = false; pause = false; - shipHeight = (SHIP_BASE_SIZE/2)/tanf(20*DEG2RAD); + shipHeight = (PLAYER_BASE_SIZE/2)/tanf(20*DEG2RAD); // Initialization player player.position = (Vector2){screenWidth/2, screenHeight/2 - shipHeight/2}; @@ -181,10 +166,8 @@ void InitGame(void) meteorsDestroyed = 0; - //InitShoot(&shoot); - // Initialization shoot - for (int i = 0; i < NUM_SHOOTS; i++) + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) { shoot[i].position = (Vector2){0, 0}; shoot[i].speed = (Vector2){0, 0}; @@ -194,7 +177,7 @@ void InitGame(void) shoot[i].color = WHITE; } - for (int i = 0; i < NUM_BIG_METEORS; i++) + for (int i = 0; i < MAX_BIG_METEORS; i++) { posx = GetRandomValue(0, screenWidth); @@ -236,7 +219,7 @@ void InitGame(void) bigMeteor[i].color = BLUE; } - for (int i = 0; i < NUM_MEDIUM_METEORS; i++) + for (int i = 0; i < MAX_MEDIUM_METEORS; i++) { mediumMeteor[i].position = (Vector2){-100, -100}; mediumMeteor[i].speed = (Vector2){0,0}; @@ -245,7 +228,7 @@ void InitGame(void) mediumMeteor[i].color = BLUE; } - for (int i = 0; i < NUM_SMALL_METEORS; i++) + for (int i = 0; i < MAX_SMALL_METEORS; i++) { smallMeteor[i].position = (Vector2){-100, -100}; smallMeteor[i].speed = (Vector2){0,0}; @@ -274,8 +257,8 @@ void UpdateGame(void) if (IsKeyDown(KEY_RIGHT)) player.rotation += 5; // Speed - player.speed.x = sin(player.rotation*DEG2RAD)*MAX_SPEED; - player.speed.y = cos(player.rotation*DEG2RAD)*MAX_SPEED; + player.speed.x = sin(player.rotation*DEG2RAD)*PLAYER_SPEED; + player.speed.y = cos(player.rotation*DEG2RAD)*PLAYER_SPEED; // Controller if (IsKeyDown(KEY_UP)) @@ -306,14 +289,14 @@ void UpdateGame(void) // Activation of shoot if (IsKeyPressed(KEY_SPACE)) { - for (int i = 0; i < NUM_SHOOTS; i++) + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) { if (!shoot[i].active) { shoot[i].position = (Vector2){ player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight) }; shoot[i].active = true; - shoot[i].speed.x = 1.5*sin(player.rotation*DEG2RAD)*MAX_SPEED; - shoot[i].speed.y = 1.5*cos(player.rotation*DEG2RAD)*MAX_SPEED; + shoot[i].speed.x = 1.5*sin(player.rotation*DEG2RAD)*PLAYER_SPEED; + shoot[i].speed.y = 1.5*cos(player.rotation*DEG2RAD)*PLAYER_SPEED; shoot[i].rotation = player.rotation; break; } @@ -321,13 +304,13 @@ void UpdateGame(void) } // Shoot life timer - for (int i = 0; i < NUM_SHOOTS; i++) + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) { if (shoot[i].active) shoot[i].lifeSpawn++; } // Shot logic - for (int i = 0; i < NUM_SHOOTS; i++) + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) { if (shoot[i].active) { @@ -371,23 +354,23 @@ void UpdateGame(void) // Collision Player to meteors player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12}; - for (int a = 0; a < NUM_BIG_METEORS; a++) + for (int a = 0; a < MAX_BIG_METEORS; a++) { if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, bigMeteor[a].position, bigMeteor[a].radius) && bigMeteor[a].active) gameOver = true; } - for (int a = 0; a < NUM_MEDIUM_METEORS; a++) + for (int a = 0; a < MAX_MEDIUM_METEORS; a++) { if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, mediumMeteor[a].position, mediumMeteor[a].radius) && mediumMeteor[a].active) gameOver = true; } - for (int a = 0; a < NUM_SMALL_METEORS; a++) + for (int a = 0; a < MAX_SMALL_METEORS; a++) { if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, smallMeteor[a].position, smallMeteor[a].radius) && smallMeteor[a].active) gameOver = true; } // Meteor logic - for (int i = 0; i < NUM_BIG_METEORS; i++) + for (int i = 0; i < MAX_BIG_METEORS; i++) { if (bigMeteor[i].active) { @@ -403,7 +386,7 @@ void UpdateGame(void) } } - for (int i = 0; i < NUM_MEDIUM_METEORS; i++) + for (int i = 0; i < MAX_MEDIUM_METEORS; i++) { if (mediumMeteor[i].active) { @@ -419,7 +402,7 @@ void UpdateGame(void) } } - for (int i = 0; i < NUM_SMALL_METEORS; i++) + for (int i = 0; i < MAX_SMALL_METEORS; i++) { if (smallMeteor[i].active) { @@ -436,11 +419,11 @@ void UpdateGame(void) } // Collision behaviour - for (int i = 0; i < NUM_SHOOTS; i++) + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) { if ((shoot[i].active)) { - for (int a = 0; a < NUM_BIG_METEORS; a++) + for (int a = 0; a < MAX_BIG_METEORS; a++) { if (bigMeteor[a].active && CheckCollisionCircles(shoot[i].position, shoot[i].radius, bigMeteor[a].position, bigMeteor[a].radius)) { @@ -466,13 +449,13 @@ void UpdateGame(void) } //bigMeteor[a].position = (Vector2){-100, -100}; bigMeteor[a].color = RED; - a = NUM_BIG_METEORS; + a = MAX_BIG_METEORS; } } } if ((shoot[i].active)) { - for (int b = 0; b < NUM_MEDIUM_METEORS; b++) + for (int b = 0; b < MAX_MEDIUM_METEORS; b++) { if (mediumMeteor[b].active && CheckCollisionCircles(shoot[i].position, shoot[i].radius, mediumMeteor[b].position, mediumMeteor[b].radius)) { @@ -498,13 +481,13 @@ void UpdateGame(void) } //mediumMeteor[b].position = (Vector2){-100, -100}; mediumMeteor[b].color = GREEN; - b = NUM_MEDIUM_METEORS; + b = MAX_MEDIUM_METEORS; } } } if ((shoot[i].active)) { - for (int c = 0; c < NUM_SMALL_METEORS; c++) + for (int c = 0; c < MAX_SMALL_METEORS; c++) { if (smallMeteor[c].active && CheckCollisionCircles(shoot[i].position, shoot[i].radius, smallMeteor[c].position, smallMeteor[c].radius)) { @@ -514,14 +497,14 @@ void UpdateGame(void) meteorsDestroyed++; smallMeteor[c].color = YELLOW; // smallMeteor[c].position = (Vector2){-100, -100}; - c = NUM_SMALL_METEORS; + c = MAX_SMALL_METEORS; } } } } } - if (meteorsDestroyed == NUM_BIG_METEORS + NUM_MEDIUM_METEORS + NUM_SMALL_METEORS) victory = true; + if (meteorsDestroyed == MAX_BIG_METEORS + MAX_MEDIUM_METEORS + MAX_SMALL_METEORS) victory = true; } else { @@ -538,39 +521,39 @@ void DrawGame(void) { BeginDrawing(); - ClearBackground(DARKGRAY); + ClearBackground(RAYWHITE); if (!gameOver) { // Draw spaceship Vector2 v1 = { player.position.x + sinf(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cosf(player.rotation*DEG2RAD)*(shipHeight) }; - Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2) }; - Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2) }; - DrawTriangleLines(v1, v2, v3, player.color); + Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; + Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; + DrawTriangle(v1, v2, v3, MAROON); // Draw meteors - for (int i = 0; i < NUM_BIG_METEORS; i++) + for (int i = 0; i < MAX_BIG_METEORS; i++) { - if (bigMeteor[i].active) DrawCircleV(bigMeteor[i].position, bigMeteor[i].radius, bigMeteor[i].color); - else DrawCircleV(bigMeteor[i].position, bigMeteor[i].radius, Fade(bigMeteor[i].color, 0.25f)); + if (bigMeteor[i].active) DrawCircleV(bigMeteor[i].position, bigMeteor[i].radius, DARKGRAY); + else DrawCircleV(bigMeteor[i].position, bigMeteor[i].radius, Fade(LIGHTGRAY, 0.3f)); } - for (int i = 0; i < NUM_MEDIUM_METEORS; i++) + for (int i = 0; i < MAX_MEDIUM_METEORS; i++) { - if (mediumMeteor[i].active) DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, mediumMeteor[i].color); - else DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, Fade(mediumMeteor[i].color, 0.25f)); + if (mediumMeteor[i].active) DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, GRAY); + else DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, Fade(LIGHTGRAY, 0.3f)); } - for (int i = 0; i < NUM_SMALL_METEORS; i++) + for (int i = 0; i < MAX_SMALL_METEORS; i++) { - if (smallMeteor[i].active) DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, smallMeteor[i].color); - else DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, Fade(smallMeteor[i].color, 0.25f)); + if (smallMeteor[i].active) DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, GRAY); + else DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, Fade(LIGHTGRAY, 0.3f)); } // Draw shoot - for (int i = 0; i < NUM_SHOOTS; i++) + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) { - if (shoot[i].active) DrawCircleV(shoot[i].position, shoot[i].radius, shoot[i].color); + if (shoot[i].active) DrawCircleV(shoot[i].position, shoot[i].radius, BLACK); } if (victory) DrawText("VICTORY", screenWidth/2 - MeasureText("VICTORY", 20)/2, screenHeight/2, 20, LIGHTGRAY); diff --git a/games/samples/asteroids_survival.c b/games/samples/asteroids_survival.c index e2be9366..aa21112d 100644 --- a/games/samples/asteroids_survival.c +++ b/games/samples/asteroids_survival.c @@ -22,13 +22,13 @@ //---------------------------------------------------------------------------------- // Some Defines //---------------------------------------------------------------------------------- -#define MAX_SPEED 6 +#define PLAYER_BASE_SIZE 20.0f +#define PLAYER_SPEED 6.0f +#define PLAYER_MAX_SHOOTS 10 + #define METEORS_SPEED 2 -#define NUM_SHOOTS 10 -#define NUM_BIG_METEORS 4 -#define NUM_MEDIUM_METEORS 8 -#define NUM_SMALL_METEORS 16 -#define SHIP_BASE_SIZE 20.0f +#define MAX_MEDIUM_METEORS 8 +#define MAX_SMALL_METEORS 16 //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -43,22 +43,13 @@ typedef struct Player { Color color; } Player; -typedef struct MediumMeteor { - Vector2 position; - Vector2 speed; - float radius; - bool active; - Color color; -} MediumMeteor; - -typedef struct SmallMeteor { +typedef struct Meteor { Vector2 position; Vector2 speed; float radius; bool active; Color color; -} SmallMeteor; - +} Meteor; //------------------------------------------------------------------------------------ // Global Variables Declaration @@ -74,8 +65,8 @@ static bool pause; static float shipHeight; static Player player; -static MediumMeteor mediumMeteor[NUM_MEDIUM_METEORS]; -static SmallMeteor smallMeteor[NUM_SMALL_METEORS]; +static Meteor mediumMeteor[MAX_MEDIUM_METEORS]; +static Meteor smallMeteor[MAX_SMALL_METEORS]; //------------------------------------------------------------------------------------ // Module Functions Declaration (local) @@ -86,8 +77,6 @@ static void DrawGame(void); // Draw game (one frame) static void UnloadGame(void); // Unload game static void UpdateDrawFrame(void); // Update and Draw (one frame) -static void DrawSpaceship(Vector2 position, float rotation, Color color); - //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ @@ -146,7 +135,7 @@ void InitGame(void) framesCounter = 0; - shipHeight = (SHIP_BASE_SIZE/2)/tanf(20*DEG2RAD); + shipHeight = (PLAYER_BASE_SIZE/2)/tanf(20*DEG2RAD); // Initialization player player.position = (Vector2){screenWidth/2, screenHeight/2 - shipHeight/2}; @@ -156,7 +145,7 @@ void InitGame(void) player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12}; player.color = LIGHTGRAY; - for (int i = 0; i < NUM_MEDIUM_METEORS; i++) + for (int i = 0; i < MAX_MEDIUM_METEORS; i++) { posx = GetRandomValue(0, screenWidth); @@ -196,7 +185,7 @@ void InitGame(void) mediumMeteor[i].color = GREEN; } - for (int i = 0; i < NUM_SMALL_METEORS; i++) + for (int i = 0; i < MAX_SMALL_METEORS; i++) { posx = GetRandomValue(0, screenWidth); @@ -255,8 +244,8 @@ void UpdateGame(void) if (IsKeyDown(KEY_RIGHT)) player.rotation += 5; // Speed - player.speed.x = sin(player.rotation*DEG2RAD)*MAX_SPEED; - player.speed.y = cos(player.rotation*DEG2RAD)*MAX_SPEED; + player.speed.x = sin(player.rotation*DEG2RAD)*PLAYER_SPEED; + player.speed.y = cos(player.rotation*DEG2RAD)*PLAYER_SPEED; // Controller if (IsKeyDown(KEY_UP)) @@ -287,19 +276,19 @@ void UpdateGame(void) // Collision Player to meteors player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12}; - for (int a = 0; a < NUM_MEDIUM_METEORS; a++) + for (int a = 0; a < MAX_MEDIUM_METEORS; a++) { if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, mediumMeteor[a].position, mediumMeteor[a].radius) && mediumMeteor[a].active) gameOver = true; } - for (int a = 0; a < NUM_SMALL_METEORS; a++) + for (int a = 0; a < MAX_SMALL_METEORS; a++) { if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, smallMeteor[a].position, smallMeteor[a].radius) && smallMeteor[a].active) gameOver = true; } // Meteor logic - for (int i = 0; i < NUM_MEDIUM_METEORS; i++) + for (int i = 0; i < MAX_MEDIUM_METEORS; i++) { if (mediumMeteor[i].active) { @@ -315,7 +304,7 @@ void UpdateGame(void) } } - for (int i = 0; i < NUM_SMALL_METEORS; i++) + for (int i = 0; i < MAX_SMALL_METEORS; i++) { if (smallMeteor[i].active) { @@ -347,31 +336,30 @@ void DrawGame(void) { BeginDrawing(); - ClearBackground(DARKGRAY); + ClearBackground(RAYWHITE); if (!gameOver) { // Draw spaceship Vector2 v1 = { player.position.x + sinf(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cosf(player.rotation*DEG2RAD)*(shipHeight) }; - Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2) }; - Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2) }; - - DrawTriangleLines(v1, v2, v3, player.color); + Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; + Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; + DrawTriangle(v1, v2, v3, MAROON); // Draw meteor - for (int i = 0;i < NUM_MEDIUM_METEORS; i++) + for (int i = 0;i < MAX_MEDIUM_METEORS; i++) { - if (mediumMeteor[i].active) DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, mediumMeteor[i].color); - else DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, Fade(mediumMeteor[i].color, 0.25f)); + if (mediumMeteor[i].active) DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, GRAY); + else DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, Fade(LIGHTGRAY, 0.3f)); } - for (int i = 0;i < NUM_SMALL_METEORS; i++) + for (int i = 0;i < MAX_SMALL_METEORS; i++) { - if (smallMeteor[i].active) DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, smallMeteor[i].color); - else DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, Fade(smallMeteor[i].color, 0.25f)); + if (smallMeteor[i].active) DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, DARKGRAY); + else DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, Fade(LIGHTGRAY, 0.3f)); } - DrawText(FormatText("SURVIVAL TIME: %.02f", (float)framesCounter/60), 10, 10, 20, WHITE); + DrawText(FormatText("TIME: %.02f", (float)framesCounter/60), 10, 10, 20, BLACK); if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); } diff --git a/games/samples/floppy.c b/games/samples/floppy.c index d66f5bbe..f48ea235 100644 --- a/games/samples/floppy.c +++ b/games/samples/floppy.c @@ -206,24 +206,24 @@ void DrawGame(void) if (!gameOver) { - DrawCircle(floppy.position.x, floppy.position.y, floppy.radius, BLUE); + DrawCircle(floppy.position.x, floppy.position.y, floppy.radius, DARKGRAY); // Draw tubes for (int i = 0; i < MAX_TUBES; i++) { - DrawRectangle(tubes[i*2].rec.x, tubes[i*2].rec.y, tubes[i*2].rec.width, tubes[i*2].rec.height, RED); - DrawRectangle(tubes[i*2 + 1].rec.x, tubes[i*2 + 1].rec.y, tubes[i*2 + 1].rec.width, tubes[i*2 + 1].rec.height, RED); + DrawRectangle(tubes[i*2].rec.x, tubes[i*2].rec.y, tubes[i*2].rec.width, tubes[i*2].rec.height, GRAY); + DrawRectangle(tubes[i*2 + 1].rec.x, tubes[i*2 + 1].rec.y, tubes[i*2 + 1].rec.width, tubes[i*2 + 1].rec.height, GRAY); } // Draw flashing fx (one frame only) if (superfx) { - DrawRectangle(0, 0, screenWidth, screenHeight, GOLD); + DrawRectangle(0, 0, screenWidth, screenHeight, WHITE); superfx = false; } - DrawText(FormatText("%04i", score), 20, 20, 40, PINK); - DrawText(FormatText("HI-SCORE: %04i", hiScore), 20, 70, 20, VIOLET); + DrawText(FormatText("%04i", score), 20, 20, 40, GRAY); + DrawText(FormatText("HI-SCORE: %04i", hiScore), 20, 70, 20, LIGHTGRAY); if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); } diff --git a/games/samples/gold_fever.c b/games/samples/gold_fever.c index d4c0d99f..5a435027 100644 --- a/games/samples/gold_fever.c +++ b/games/samples/gold_fever.c @@ -22,19 +22,16 @@ //---------------------------------------------------------------------------------- typedef struct Player { Vector2 position; - int radius; Vector2 speed; - Color color; + int radius; } Player; typedef struct Enemy { Vector2 position; + Vector2 speed; int radius; int radiusBounds; - Vector2 speed; - bool moveRight; - Color colorBounds; - Color color; + bool moveRight; // RAY: o__O } Enemy; typedef struct Points { @@ -42,15 +39,14 @@ typedef struct Points { int radius; int value; bool active; - Color color; } Points; -typedef struct Exit { +typedef struct Home { Rectangle rec; bool active; bool save; Color color; -} Exit; +} Home; //------------------------------------------------------------------------------------ // Global Variables Declaration @@ -67,7 +63,7 @@ static int hiScore = 0; static Player player; static Enemy enemy; static Points points; -static Exit exit; +static Home home; static bool follow; //------------------------------------------------------------------------------------ @@ -136,30 +132,25 @@ void InitGame(void) player.position = (Vector2){50, 50}; player.radius = 20; player.speed = (Vector2){5, 5}; - player.color = DARKGRAY; enemy.position = (Vector2){screenWidth - 50, screenHeight/2}; enemy.radius = 20; enemy.radiusBounds = 150; enemy.speed = (Vector2){3, 3}; enemy.moveRight = true; - enemy.color = MAROON; - enemy.colorBounds = RED; follow = false; points.radius = 10; points.position = (Vector2){GetRandomValue(points.radius, screenWidth - points.radius), GetRandomValue(points.radius, screenHeight - points.radius)}; points.value = 100; points.active = true; - points.color = GOLD; - - exit.rec.width = 50; - exit.rec.height = 50; - exit.rec.x = GetRandomValue(0, screenWidth - exit.rec.width); - exit.rec.y = GetRandomValue(0, screenHeight - exit.rec.height); - exit.active = false; - exit.save = false; - exit.color = PINK; + + home.rec.width = 50; + home.rec.height = 50; + home.rec.x = GetRandomValue(0, screenWidth - home.rec.width); + home.rec.y = GetRandomValue(0, screenHeight - home.rec.height); + home.active = false; + home.save = false; } // Update game (one frame) @@ -184,7 +175,7 @@ void UpdateGame(void) if (player.position.y + player.radius >= screenHeight) player.position.y = screenHeight - player.radius; //IA Enemy - if ( (follow || CheckCollisionCircles(player.position, player.radius, enemy.position, enemy.radiusBounds)) && !exit.save) + if ( (follow || CheckCollisionCircles(player.position, player.radius, enemy.position, enemy.radiusBounds)) && !home.save) { if (player.position.x > enemy.position.x) enemy.position.x += enemy.speed.x; if (player.position.x < enemy.position.x) enemy.position.x -= enemy.speed.x; @@ -212,17 +203,17 @@ void UpdateGame(void) { follow = true; points.active = false; - exit.active = true; + home.active = true; } - if (CheckCollisionCircles(player.position, player.radius, enemy.position, enemy.radius) && !exit.save) + if (CheckCollisionCircles(player.position, player.radius, enemy.position, enemy.radius) && !home.save) { gameOver = true; if (hiScore < score) hiScore = score; } - if (CheckCollisionCircleRec(player.position, player.radius, exit.rec)) + if (CheckCollisionCircleRec(player.position, player.radius, home.rec)) { follow = false; @@ -235,9 +226,9 @@ void UpdateGame(void) points.position = (Vector2){GetRandomValue(points.radius, screenWidth - points.radius), GetRandomValue(points.radius, screenHeight - points.radius)}; } - exit.save = true; + home.save = true; } - else exit.save = false; + else home.save = false; } } else @@ -259,18 +250,22 @@ void DrawGame(void) if (!gameOver) { - if (follow) ClearBackground(RED); - - DrawCircleLines(enemy.position.x, enemy.position.y, enemy.radiusBounds, enemy.colorBounds); - DrawCircleV(enemy.position, enemy.radius, enemy.color); + if (follow) + { + DrawRectangle(0, 0, screenWidth, screenHeight, RED); + DrawRectangle(10, 10, screenWidth - 20, screenHeight - 20, RAYWHITE); + } - DrawCircleV(player.position, player.radius, player.color); - DrawCircleV(points.position, points.radius, points.color); + DrawRectangleLines(home.rec.x, home.rec.y, home.rec.width, home.rec.height, BLUE); + + DrawCircleLines(enemy.position.x, enemy.position.y, enemy.radiusBounds, RED); + DrawCircleV(enemy.position, enemy.radius, MAROON); - if (exit.active) DrawRectangleRec(exit.rec, exit.color); + DrawCircleV(player.position, player.radius, GRAY); + if (points.active) DrawCircleV(points.position, points.radius, GOLD); - DrawText(FormatText("SCORE: %04i", score), 10, 10, 20, GRAY); - DrawText(FormatText("HI-SCORE: %04i", hiScore), 300, 10, 20, GRAY); + DrawText(FormatText("SCORE: %04i", score), 20, 15, 20, GRAY); + DrawText(FormatText("HI-SCORE: %04i", hiScore), 300, 15, 20, GRAY); if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); } diff --git a/games/samples/pang.c b/games/samples/pang.c index e7b2bb86..fe1c3005 100644 --- a/games/samples/pang.c +++ b/games/samples/pang.c @@ -2,7 +2,7 @@ * * raylib - sample game: pang * -* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria +* Sample game developed by Ian Eito and Albert Martos and Ramon Santamaria * * This game has been created using raylib v1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) @@ -22,13 +22,12 @@ //---------------------------------------------------------------------------------- // Some Defines //---------------------------------------------------------------------------------- -#define MAX_SPEED 5 -#define METEORS_SPEED 2 -#define NUM_SHOOTS 1 -#define NUM_BIG_METEORS 2 -#define NUM_MEDIUM_METEORS 4 -#define NUM_SMALL_METEORS 8 -#define SHIP_BASE_SIZE 20.0f +#define PLAYER_BASE_SIZE 20.0f +#define PLAYER_SPEED 5.0f +#define PLAYER_MAX_SHOOTS 1 + +#define MAX_BIG_BALLS 2 +#define BALLS_SPEED 2.0f //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -37,9 +36,8 @@ typedef struct Player { Vector2 position; Vector2 speed; - float rotation; Vector3 collider; - Color color; + float rotation; } Player; typedef struct Shoot { @@ -49,41 +47,19 @@ typedef struct Shoot { float rotation; int lifeSpawn; bool active; - Color color; } Shoot; -typedef struct BigMeteor { - Vector2 position; - Vector2 speed; - float radius; - int points; - bool active; - Color color; -} BigMeteor; - -typedef struct MediumMeteor { +typedef struct Ball { Vector2 position; Vector2 speed; float radius; int points; bool active; - Color color; -} MediumMeteor; - -typedef struct SmallMeteor { - Vector2 position; - Vector2 speed; - float radius; - int points; - bool active; - Color color; -} SmallMeteor; +} Ball; typedef struct Points { - char letter; Vector2 position; int value; - Color color; float alpha; } Points; @@ -99,18 +75,18 @@ static bool pause; static int score; static Player player; -static Shoot shoot[NUM_SHOOTS]; -static BigMeteor bigMeteor[NUM_BIG_METEORS]; -static MediumMeteor mediumMeteor[NUM_MEDIUM_METEORS]; -static SmallMeteor smallMeteor[NUM_SMALL_METEORS]; +static Shoot shoot[PLAYER_MAX_SHOOTS]; +static Ball bigBalls[MAX_BIG_BALLS]; +static Ball mediumBalls[MAX_BIG_BALLS*2]; +static Ball smallBalls[MAX_BIG_BALLS*4]; static Points points[5]; // NOTE: Defined triangle is isosceles with common angles of 70 degrees. static float shipHeight; static float gravity; -static int countMediumMeteors; -static int countSmallMeteors; +static int countmediumBallss; +static int countsmallBallss; static int meteorsDestroyed; static Vector2 linePosition; @@ -127,9 +103,6 @@ static void DrawGame(void); // Draw game (one frame) static void UnloadGame(void); // Unload game static void UpdateDrawFrame(void); // Update and Draw (one frame) -static void InitShoot(Shoot shoot); -static void DrawSpaceship(Vector2 position, float rotation, Color color); - //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ @@ -193,69 +166,64 @@ static void InitGame(void) gravity = 0.25f; linePosition = (Vector2){ 0.0f , 0.0f }; - shipHeight = (SHIP_BASE_SIZE/2)/tanf(20*DEG2RAD); + shipHeight = (PLAYER_BASE_SIZE/2)/tanf(20*DEG2RAD); // Initialization player player.position = (Vector2){ screenWidth/2, screenHeight }; - player.speed = (Vector2){ MAX_SPEED, MAX_SPEED }; + player.speed = (Vector2){ PLAYER_SPEED, PLAYER_SPEED }; player.rotation = 0; player.collider = (Vector3){ player.position.x, player.position.y - shipHeight/2.0f, 12.0f }; - player.color = LIGHTGRAY; meteorsDestroyed = 0; // Initialize shoots - for (int i = 0; i < NUM_SHOOTS; i++) + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) { shoot[i].position = (Vector2){ 0, 0 }; shoot[i].speed = (Vector2){ 0, 0 }; shoot[i].radius = 2; shoot[i].active = false; shoot[i].lifeSpawn = 0; - shoot[i].color = WHITE; } // Initialize big meteors - for (int i = 0; i < NUM_BIG_METEORS; i++) + for (int i = 0; i < MAX_BIG_BALLS; i++) { - bigMeteor[i].radius = 40.0f; - posx = GetRandomValue(0 + bigMeteor[i].radius, screenWidth - bigMeteor[i].radius); - posy = GetRandomValue(0 + bigMeteor[i].radius, screenHeight/2); + bigBalls[i].radius = 40.0f; + posx = GetRandomValue(0 + bigBalls[i].radius, screenWidth - bigBalls[i].radius); + posy = GetRandomValue(0 + bigBalls[i].radius, screenHeight/2); - bigMeteor[i].position = (Vector2){ posx, posy }; + bigBalls[i].position = (Vector2){ posx, posy }; while ((velx == 0) || (vely == 0)) { - velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); - vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + velx = GetRandomValue(-BALLS_SPEED, BALLS_SPEED); + vely = GetRandomValue(-BALLS_SPEED, BALLS_SPEED); } - bigMeteor[i].speed = (Vector2){ velx, vely }; - bigMeteor[i].points = 200; - bigMeteor[i].active = true; - bigMeteor[i].color = BLUE; + bigBalls[i].speed = (Vector2){ velx, vely }; + bigBalls[i].points = 200; + bigBalls[i].active = true; } // Initialize medium meteors - for (int i = 0; i < NUM_MEDIUM_METEORS; i++) + for (int i = 0; i < MAX_BIG_BALLS*2; i++) { - mediumMeteor[i].position = (Vector2){-100, -100}; - mediumMeteor[i].speed = (Vector2){0,0}; - mediumMeteor[i].radius = 20.0f; - mediumMeteor[i].points = 100; - mediumMeteor[i].active = false; - mediumMeteor[i].color = BLUE; + mediumBalls[i].position = (Vector2){-100, -100}; + mediumBalls[i].speed = (Vector2){0,0}; + mediumBalls[i].radius = 20.0f; + mediumBalls[i].points = 100; + mediumBalls[i].active = false; } // Initialize small meteors - for (int i = 0; i < NUM_SMALL_METEORS; i++) + for (int i = 0; i < MAX_BIG_BALLS*4; i++) { - smallMeteor[i].position = (Vector2){ -100, -100 }; - smallMeteor[i].speed = (Vector2){ 0, 0 }; - smallMeteor[i].radius = 10.0f; - smallMeteor[i].points = 50; - smallMeteor[i].active = false; - smallMeteor[i].color = BLUE; + smallBalls[i].position = (Vector2){ -100, -100 }; + smallBalls[i].speed = (Vector2){ 0, 0 }; + smallBalls[i].radius = 10.0f; + smallBalls[i].points = 50; + smallBalls[i].active = false; } // Initialize animated points @@ -266,333 +234,297 @@ static void InitGame(void) points[i].alpha = 0.0f; } - countMediumMeteors = 0; - countSmallMeteors = 0; + countmediumBallss = 0; + countsmallBallss = 0; } // Update game (one frame) void UpdateGame(void) { - if (!gameOver) + if (!gameOver && !victory) { if (IsKeyPressed('P')) pause = !pause; if (!pause) { - if (awake) - { - // Player logic - if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x; - if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x; + // Player logic + if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x; + if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x; - // Wall behaviour for player - if (player.position.x + SHIP_BASE_SIZE/2 > screenWidth) player.position.x = screenWidth - SHIP_BASE_SIZE/2; - else if (player.position.x - SHIP_BASE_SIZE/2 < 0) player.position.x = 0 + SHIP_BASE_SIZE/2; + // Player vs wall collision logic + if (player.position.x + PLAYER_BASE_SIZE/2 > screenWidth) player.position.x = screenWidth - PLAYER_BASE_SIZE/2; + else if (player.position.x - PLAYER_BASE_SIZE/2 < 0) player.position.x = 0 + PLAYER_BASE_SIZE/2; - // Activation of shoot - if (IsKeyPressed(KEY_SPACE)) + // Player shot logic + if (IsKeyPressed(KEY_SPACE)) + { + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) { - for (int i = 0; i < NUM_SHOOTS; i++) + if (!shoot[i].active) { - if (!shoot[i].active) - { - shoot[i].position = (Vector2){ player.position.x, player.position.y - shipHeight }; - linePosition = (Vector2){ player.position.x, player.position.y}; - shoot[i].active = true; - shoot[i].speed.y = MAX_SPEED; - break; - } + shoot[i].position = (Vector2){ player.position.x, player.position.y - shipHeight }; + shoot[i].speed.y = PLAYER_SPEED; + shoot[i].active = true; + + linePosition = (Vector2){ player.position.x, player.position.y}; + + break; } } + } - // Shoot life timer - for (int i = 0; i < NUM_SHOOTS; i++) - { - if (shoot[i].active) shoot[i].lifeSpawn++; - } + // Shoot life timer + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) + { + if (shoot[i].active) shoot[i].lifeSpawn++; + } - // Shot logic - for (int i = 0; i < NUM_SHOOTS; i++) + // Shot logic + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) + { + if (shoot[i].active) { - if (shoot[i].active) - { - // Movement - shoot[i].position.y -= shoot[i].speed.y; + shoot[i].position.y -= shoot[i].speed.y; - // Wall behaviour for shoot - if (shoot[i].position.x > screenWidth + shoot[i].radius) - { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - } - else if (shoot[i].position.x < 0 - shoot[i].radius) - { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - } - - if (shoot[i].position.y > screenHeight + shoot[i].radius) - { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - } - else if (shoot[i].position.y < 0 - shoot[i].radius) - { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - } + // Shot vs walls collision logic + if ((shoot[i].position.x > screenWidth + shoot[i].radius) || (shoot[i].position.x < 0 - shoot[i].radius) || + (shoot[i].position.y > screenHeight + shoot[i].radius) || (shoot[i].position.y < 0 - shoot[i].radius)) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + } - // Life of shoot - if (shoot[i].lifeSpawn >= 120) - { - shoot[i].position = (Vector2){0, 0}; - shoot[i].speed = (Vector2){0, 0}; - shoot[i].lifeSpawn = 0; - shoot[i].active = false; - } + // Player shot life spawn + if (shoot[i].lifeSpawn >= 120) + { + shoot[i].position = (Vector2){ 0.0f, 0.0f }; + shoot[i].speed = (Vector2){ 0.0f, 0.0f }; + shoot[i].lifeSpawn = 0; + shoot[i].active = false; } } + } - // Player collision with meteors - player.collider = (Vector3){player.position.x, player.position.y - shipHeight/2, 12}; + // Player vs meteors collision logic + player.collider = (Vector3){player.position.x, player.position.y - shipHeight/2, 12}; - for (int i = 0; i < NUM_BIG_METEORS; i++) + for (int i = 0; i < MAX_BIG_BALLS; i++) + { + if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, bigBalls[i].position, bigBalls[i].radius) && bigBalls[i].active) { - if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, bigMeteor[i].position, bigMeteor[i].radius) && bigMeteor[i].active) - { - gameOver = true; - } + gameOver = true; } + } - for (int i = 0; i < NUM_MEDIUM_METEORS; i++) + for (int i = 0; i < MAX_BIG_BALLS*2; i++) + { + if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, mediumBalls[i].position, mediumBalls[i].radius) && mediumBalls[i].active) { - if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, mediumMeteor[i].position, mediumMeteor[i].radius) && mediumMeteor[i].active) - { - gameOver = true; - } + gameOver = true; } + } - for (int i = 0; i < NUM_SMALL_METEORS; i++) + for (int i = 0; i < MAX_BIG_BALLS*4; i++) + { + if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, smallBalls[i].position, smallBalls[i].radius) && smallBalls[i].active) { - if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, smallMeteor[i].position, smallMeteor[i].radius) && smallMeteor[i].active) - { - gameOver = true; - } + gameOver = true; } + } - // Meteor logic - for (int i = 0; i < NUM_BIG_METEORS; i++) + // Meteors logic (big) + for (int i = 0; i < MAX_BIG_BALLS; i++) + { + if (bigBalls[i].active) { - if (bigMeteor[i].active) - { - // movement - bigMeteor[i].position.x += bigMeteor[i].speed.x; - bigMeteor[i].position.y += bigMeteor[i].speed.y; - - // wall behaviour - if (((bigMeteor[i].position.x + bigMeteor[i].radius) >= screenWidth) || ((bigMeteor[i].position.x - bigMeteor[i].radius) <= 0)) bigMeteor[i].speed.x *= -1; - if ((bigMeteor[i].position.y - bigMeteor[i].radius) <= 0) bigMeteor[i].speed.y *= -1.5; - - if ((bigMeteor[i].position.y + bigMeteor[i].radius) >= screenHeight) - { - bigMeteor[i].speed.y *= -1; - bigMeteor[i].position.y = screenHeight - bigMeteor[i].radius; - } + // Meteor movement logic + bigBalls[i].position.x += bigBalls[i].speed.x; + bigBalls[i].position.y += bigBalls[i].speed.y; - bigMeteor[i].speed.y += gravity; + // Meteor vs wall collision logic + if (((bigBalls[i].position.x + bigBalls[i].radius) >= screenWidth) || ((bigBalls[i].position.x - bigBalls[i].radius) <= 0)) bigBalls[i].speed.x *= -1; + if ((bigBalls[i].position.y - bigBalls[i].radius) <= 0) bigBalls[i].speed.y *= -1.5; + + if ((bigBalls[i].position.y + bigBalls[i].radius) >= screenHeight) + { + bigBalls[i].speed.y *= -1; + bigBalls[i].position.y = screenHeight - bigBalls[i].radius; } + + bigBalls[i].speed.y += gravity; } + } - for (int i = 0; i < NUM_MEDIUM_METEORS; i++) + // Meteors logic (medium) + for (int i = 0; i < MAX_BIG_BALLS*2; i++) + { + if (mediumBalls[i].active) { - if (mediumMeteor[i].active) + // Meteor movement logic + mediumBalls[i].position.x += mediumBalls[i].speed.x; + mediumBalls[i].position.y += mediumBalls[i].speed.y; + + // Meteor vs wall collision logic + if (mediumBalls[i].position.x + mediumBalls[i].radius >= screenWidth || mediumBalls[i].position.x - mediumBalls[i].radius <= 0) mediumBalls[i].speed.x *= -1; + if (mediumBalls[i].position.y - mediumBalls[i].radius <= 0) mediumBalls[i].speed.y *= -1; + if (mediumBalls[i].position.y + mediumBalls[i].radius >= screenHeight) { - // Movement logic - mediumMeteor[i].position.x += mediumMeteor[i].speed.x; - mediumMeteor[i].position.y += mediumMeteor[i].speed.y; - - // Wall behaviour - if (mediumMeteor[i].position.x + mediumMeteor[i].radius >= screenWidth || mediumMeteor[i].position.x - mediumMeteor[i].radius <= 0) mediumMeteor[i].speed.x *= -1; - if (mediumMeteor[i].position.y - mediumMeteor[i].radius <= 0) mediumMeteor[i].speed.y *= -1; - if (mediumMeteor[i].position.y + mediumMeteor[i].radius >= screenHeight) - { - mediumMeteor[i].speed.y *= -1; - mediumMeteor[i].position.y = screenHeight - mediumMeteor[i].radius; - } - - mediumMeteor[i].speed.y += gravity + 0.12f; + mediumBalls[i].speed.y *= -1; + mediumBalls[i].position.y = screenHeight - mediumBalls[i].radius; } + + mediumBalls[i].speed.y += gravity + 0.12f; } + } - for (int i = 0; i < NUM_SMALL_METEORS; i++) + // Meteors logic (small) + for (int i = 0; i < MAX_BIG_BALLS*4; i++) + { + if (smallBalls[i].active) { - if (smallMeteor[i].active) + // Meteor movement logic + smallBalls[i].position.x += smallBalls[i].speed.x; + smallBalls[i].position.y += smallBalls[i].speed.y; + + // Meteor vs wall collision logic + if (smallBalls[i].position.x + smallBalls[i].radius >= screenWidth || smallBalls[i].position.x - smallBalls[i].radius <= 0) smallBalls[i].speed.x *= -1; + if (smallBalls[i].position.y - smallBalls[i].radius <= 0) smallBalls[i].speed.y *= -1; + if (smallBalls[i].position.y + smallBalls[i].radius >= screenHeight) { - // movement - smallMeteor[i].position.x += smallMeteor[i].speed.x; - smallMeteor[i].position.y += smallMeteor[i].speed.y; - - // wall behaviour - if (smallMeteor[i].position.x + smallMeteor[i].radius >= screenWidth || smallMeteor[i].position.x - smallMeteor[i].radius <= 0) smallMeteor[i].speed.x *= -1; - if (smallMeteor[i].position.y - smallMeteor[i].radius <= 0) smallMeteor[i].speed.y *= -1; - if (smallMeteor[i].position.y + smallMeteor[i].radius >= screenHeight) - { - smallMeteor[i].speed.y *= -1; - smallMeteor[i].position.y = screenHeight - smallMeteor[i].radius; - } - - smallMeteor[i].speed.y += gravity + 0.25f; + smallBalls[i].speed.y *= -1; + smallBalls[i].position.y = screenHeight - smallBalls[i].radius; } + + smallBalls[i].speed.y += gravity + 0.25f; } + } - // Collision behaviour - for (int i = 0; i < NUM_SHOOTS; i++) + // Player-shot vs meteors logic + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) + { + if ((shoot[i].active)) { - if ((shoot[i].active)) + for (int a = 0; a < MAX_BIG_BALLS; a++) { - for (int a = 0; a < NUM_BIG_METEORS; a++) + if (bigBalls[a].active && (bigBalls[a].position.x - bigBalls[a].radius <= linePosition.x && bigBalls[a].position.x + bigBalls[a].radius >= linePosition.x) + && (bigBalls[a].position.y + bigBalls[a].radius >= shoot[i].position.y)) { - if (bigMeteor[a].active && (bigMeteor[a].position.x - bigMeteor[a].radius <= linePosition.x && bigMeteor[a].position.x + bigMeteor[a].radius >= linePosition.x) - && (bigMeteor[a].position.y + bigMeteor[a].radius >= shoot[i].position.y)) - { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - bigMeteor[a].active = false; - meteorsDestroyed++; - score += bigMeteor[a].points; + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + bigBalls[a].active = false; + meteorsDestroyed++; + score += bigBalls[a].points; - for (int z = 0; z < 5; z++) + for (int z = 0; z < 5; z++) + { + if (points[z].alpha == 0.0f) { - if (points[z].alpha == 0.0f) - { - points[z].position = bigMeteor[a].position; - points[z].value = bigMeteor[a].points; - points[z].color = RED; - points[z].alpha = 1.0f; - z = 5; - } + points[z].position = bigBalls[a].position; + points[z].value = bigBalls[a].points; + points[z].alpha = 1.0f; + z = 5; } + } - for (int j = 0; j < 2; j ++) + for (int j = 0; j < 2; j ++) + { + if ((countmediumBallss%2) == 0) + { + mediumBalls[countmediumBallss].position = (Vector2){bigBalls[a].position.x, bigBalls[a].position.y}; + mediumBalls[countmediumBallss].speed = (Vector2){ -1*BALLS_SPEED, BALLS_SPEED }; + } + else { - if ((countMediumMeteors%2) == 0) - { - mediumMeteor[countMediumMeteors].position = (Vector2){bigMeteor[a].position.x, bigMeteor[a].position.y}; - mediumMeteor[countMediumMeteors].speed = (Vector2){METEORS_SPEED*-1, METEORS_SPEED}; - } - else - { - mediumMeteor[countMediumMeteors].position = (Vector2){bigMeteor[a].position.x, bigMeteor[a].position.y}; - mediumMeteor[countMediumMeteors].speed = (Vector2){METEORS_SPEED, METEORS_SPEED}; - } - - mediumMeteor[countMediumMeteors].active = true; - countMediumMeteors ++; + mediumBalls[countmediumBallss].position = (Vector2){bigBalls[a].position.x, bigBalls[a].position.y}; + mediumBalls[countmediumBallss].speed = (Vector2){ BALLS_SPEED, BALLS_SPEED }; } - bigMeteor[a].color = RED; - a = NUM_BIG_METEORS; + mediumBalls[countmediumBallss].active = true; + countmediumBallss ++; } + + a = MAX_BIG_BALLS; } } + } - if ((shoot[i].active)) + if ((shoot[i].active)) + { + for (int b = 0; b < MAX_BIG_BALLS*2; b++) { - for (int b = 0; b < NUM_MEDIUM_METEORS; b++) + if (mediumBalls[b].active && (mediumBalls[b].position.x - mediumBalls[b].radius <= linePosition.x && mediumBalls[b].position.x + mediumBalls[b].radius >= linePosition.x) + && (mediumBalls[b].position.y + mediumBalls[b].radius >= shoot[i].position.y)) { - if (mediumMeteor[b].active && (mediumMeteor[b].position.x - mediumMeteor[b].radius <= linePosition.x && mediumMeteor[b].position.x + mediumMeteor[b].radius >= linePosition.x) - && (mediumMeteor[b].position.y + mediumMeteor[b].radius >= shoot[i].position.y)) - { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - mediumMeteor[b].active = false; - meteorsDestroyed++; - score += mediumMeteor[b].points; + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + mediumBalls[b].active = false; + meteorsDestroyed++; + score += mediumBalls[b].points; - for (int z = 0; z < 5; z++) + for (int z = 0; z < 5; z++) + { + if (points[z].alpha == 0.0f) { - if (points[z].alpha == 0.0f) - { - points[z].position = mediumMeteor[b].position; - points[z].value = mediumMeteor[b].points; - points[z].color = GREEN; - points[z].alpha = 1.0f; - z = 5; - } + points[z].position = mediumBalls[b].position; + points[z].value = mediumBalls[b].points; + points[z].alpha = 1.0f; + z = 5; } + } - for (int j = 0; j < 2; j ++) + for (int j = 0; j < 2; j ++) + { + if (countsmallBallss%2 == 0) { - if (countSmallMeteors%2 == 0) - { - smallMeteor[countSmallMeteors].position = (Vector2){mediumMeteor[b].position.x, mediumMeteor[b].position.y}; - smallMeteor[countSmallMeteors].speed = (Vector2){METEORS_SPEED*-1, METEORS_SPEED*-1}; - } - else - { - smallMeteor[countSmallMeteors].position = (Vector2){mediumMeteor[b].position.x, mediumMeteor[b].position.y}; - smallMeteor[countSmallMeteors].speed = (Vector2){METEORS_SPEED, METEORS_SPEED*-1}; - } - - smallMeteor[countSmallMeteors].active = true; - countSmallMeteors ++; + smallBalls[countsmallBallss].position = (Vector2){mediumBalls[b].position.x, mediumBalls[b].position.y}; + smallBalls[countsmallBallss].speed = (Vector2){ BALLS_SPEED*-1, BALLS_SPEED*-1}; } - mediumMeteor[b].color = GREEN; - b = NUM_MEDIUM_METEORS; + else + { + smallBalls[countsmallBallss].position = (Vector2){mediumBalls[b].position.x, mediumBalls[b].position.y}; + smallBalls[countsmallBallss].speed = (Vector2){ BALLS_SPEED, BALLS_SPEED*-1}; + } + + smallBalls[countsmallBallss].active = true; + countsmallBallss ++; } + + b = MAX_BIG_BALLS*2; } } + } - if ((shoot[i].active)) + if ((shoot[i].active)) + { + for (int c = 0; c < MAX_BIG_BALLS*4; c++) { - for (int c = 0; c < NUM_SMALL_METEORS; c++) + if (smallBalls[c].active && (smallBalls[c].position.x - smallBalls[c].radius <= linePosition.x && smallBalls[c].position.x + smallBalls[c].radius >= linePosition.x) + && (smallBalls[c].position.y + smallBalls[c].radius >= shoot[i].position.y)) { - if (smallMeteor[c].active && (smallMeteor[c].position.x - smallMeteor[c].radius <= linePosition.x && smallMeteor[c].position.x + smallMeteor[c].radius >= linePosition.x) - && (smallMeteor[c].position.y + smallMeteor[c].radius >= shoot[i].position.y)) + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + smallBalls[c].active = false; + meteorsDestroyed++; + score += smallBalls[c].points; + + for (int z = 0; z < 5; z++) { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - smallMeteor[c].active = false; - meteorsDestroyed++; - smallMeteor[c].color = YELLOW; - score += smallMeteor[c].points; - - for (int z = 0; z < 5; z++) + if (points[z].alpha == 0.0f) { - if (points[z].alpha == 0.0f) - { - points[z].position = smallMeteor[c].position; - points[z].value = smallMeteor[c].points; - points[z].color = YELLOW; - points[z].alpha = 1.0f; - z = 5; - } + points[z].position = smallBalls[c].position; + points[z].value = smallBalls[c].points; + points[z].alpha = 1.0f; + z = 5; } - - c = NUM_SMALL_METEORS; } - } - } - } - for (int z = 0; z < 5; z++) - { - if (points[z].alpha > 0.0f) - { - points[z].position.y -= 2; - points[z].alpha -= 0.02f; + c = MAX_BIG_BALLS*4; + } } - - if (points[z].alpha < 0.0f) points[z].alpha = 0.0f; } - - if (meteorsDestroyed == (NUM_BIG_METEORS + NUM_MEDIUM_METEORS + NUM_SMALL_METEORS)) victory = true; - } - else - { - framesCounter++; - if (framesCounter%180 == 0) awake = false; } + + if (meteorsDestroyed == (MAX_BIG_BALLS + MAX_BIG_BALLS*2 + MAX_BIG_BALLS*4)) victory = true; } } else @@ -603,6 +535,18 @@ void UpdateGame(void) gameOver = false; } } + + // Points move-up and fade logic + for (int z = 0; z < 5; z++) + { + if (points[z].alpha > 0.0f) + { + points[z].position.y -= 2; + points[z].alpha -= 0.02f; + } + + if (points[z].alpha < 0.0f) points[z].alpha = 0.0f; + } } // Draw game (one frame) @@ -610,66 +554,60 @@ void DrawGame(void) { BeginDrawing(); - ClearBackground(DARKGRAY); + ClearBackground(RAYWHITE); if (!gameOver) { // Draw player Vector2 v1 = { player.position.x + sinf(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cosf(player.rotation*DEG2RAD)*(shipHeight) }; - Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2) }; - Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(SHIP_BASE_SIZE/2) }; - DrawTriangleLines(v1, v2, v3, player.color); + Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; + Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; + DrawTriangle(v1, v2, v3, MAROON); - // Draw meteor - for (int i = 0;i < NUM_BIG_METEORS; i++) + // Draw meteors (big) + for (int i = 0;i < MAX_BIG_BALLS; i++) { - if (bigMeteor[i].active) DrawCircleV(bigMeteor[i].position, bigMeteor[i].radius, bigMeteor[i].color); - else - { - DrawCircleV(bigMeteor[i].position, bigMeteor[i].radius, Fade(bigMeteor[i].color, 0.25f)); - //DrawText(FormatText("%i", bigMeteor[i].points), bigMeteor[i].position.x - MeasureText("200", 20)/2, bigMeteor[i].position.y - 10, 20, Fade(WHITE, 0.25f)); - } + if (bigBalls[i].active) DrawCircleV(bigBalls[i].position, bigBalls[i].radius, DARKGRAY); + else DrawCircleV(bigBalls[i].position, bigBalls[i].radius, Fade(LIGHTGRAY, 0.3f)); } - for (int i = 0;i < NUM_MEDIUM_METEORS; i++) + // Draw meteors (medium) + for (int i = 0;i < MAX_BIG_BALLS*2; i++) { - if (mediumMeteor[i].active) DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, mediumMeteor[i].color); - else - { - DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, Fade(mediumMeteor[i].color, 0.25f)); - //DrawText(FormatText("%i", mediumMeteor[i].points), mediumMeteor[i].position.x - MeasureText("100", 20)/2, mediumMeteor[i].position.y - 10, 20, Fade(WHITE, 0.25f)); - } + if (mediumBalls[i].active) DrawCircleV(mediumBalls[i].position, mediumBalls[i].radius, GRAY); + else DrawCircleV(mediumBalls[i].position, mediumBalls[i].radius, Fade(LIGHTGRAY, 0.3f)); } - for (int i = 0;i < NUM_SMALL_METEORS; i++) + // Draw meteors (small) + for (int i = 0;i < MAX_BIG_BALLS*4; i++) { - if (smallMeteor[i].active) DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, smallMeteor[i].color); - else - { - DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, Fade(smallMeteor[i].color, 0.25f)); - //DrawText(FormatText("%i", smallMeteor[i].points), smallMeteor[i].position.x - MeasureText("50", 10)/2, smallMeteor[i].position.y - 5, 10, Fade(WHITE, 0.25f)); - } + if (smallBalls[i].active) DrawCircleV(smallBalls[i].position, smallBalls[i].radius, GRAY); + else DrawCircleV(smallBalls[i].position, smallBalls[i].radius, Fade(LIGHTGRAY, 0.3f)); } // Draw shoot - - for (int i = 0; i < NUM_SHOOTS; i++) + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) { if (shoot[i].active) DrawLine(linePosition.x, linePosition.y, shoot[i].position.x, shoot[i].position.y, RED); } + // Draw score points for (int z = 0; z < 5; z++) { if (points[z].alpha > 0.0f) { - DrawText(FormatText("+%i", points[z].value), points[z].position.x, points[z].position.y, 20, Fade(points[z].color, points[z].alpha)); + DrawText(FormatText("+%02i", points[z].value), points[z].position.x, points[z].position.y, 20, Fade(BLUE, points[z].alpha)); } } - // Draw Text + // Draw score (UI) DrawText(FormatText("SCORE: %i", score), 10, 10, 20, LIGHTGRAY); - if (victory) DrawText("VICTORY", screenWidth/2 - MeasureText("VICTORY", 40)/2, screenHeight/2 - 40, 40, LIGHTGRAY); + if (victory) + { + DrawText("YOU WIN!", screenWidth/2 - MeasureText("YOU WIN!", 60)/2, 100, 60, LIGHTGRAY); + DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, LIGHTGRAY); + } if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, LIGHTGRAY); } diff --git a/games/samples/space_invaders.c b/games/samples/space_invaders.c index 9f380628..c2dd0c61 100644 --- a/games/samples/space_invaders.c +++ b/games/samples/space_invaders.c @@ -29,7 +29,7 @@ //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- -typedef enum { FIRST = 0, SECOND, THIRD } enemyWave; +typedef enum { FIRST = 0, SECOND, THIRD } EnemyWave; typedef struct Player{ Rectangle rec; @@ -66,7 +66,7 @@ static bool victory; static Player player; static Enemy enemy[NUM_MAX_ENEMIES]; static Shoot shoot[NUM_SHOOTS]; -static enemyWave wave; +static EnemyWave wave; static int shootRate; static float alpha; @@ -149,8 +149,8 @@ void InitGame(void) // Initialize player player.rec.x = 20; player.rec.y = 50; - player.rec.width = 10; - player.rec.height = 10; + player.rec.width = 20; + player.rec.height = 20; player.speed.x = 5; player.speed.y = 5; player.color = BLACK; @@ -165,7 +165,7 @@ void InitGame(void) enemy[i].speed.x = 5; enemy[i].speed.y = 5; enemy[i].active = true; - enemy[i].color = DARKGRAY; + enemy[i].color = GRAY; } // Initialize shoots @@ -178,7 +178,7 @@ void InitGame(void) shoot[i].speed.x = 7; shoot[i].speed.y = 0; shoot[i].active = false; - shoot[i].color = WHITE; + shoot[i].color = MAROON; } } @@ -325,10 +325,9 @@ void UpdateGame(void) { if (enemy[j].active) { - if (CheckCollisionRecs(shoot[i].rec, enemy[j].rec)) + if (CheckCollisionRecs(shoot[i].rec, enemy[j].rec)) { shoot[i].active = false; - enemy[j].active = false; enemy[j].rec.x = GetRandomValue(screenWidth, screenWidth + 1000); enemy[j].rec.y = GetRandomValue(0, screenHeight - enemy[j].rec.height); shootRate = 0; @@ -362,7 +361,7 @@ void DrawGame(void) { BeginDrawing(); - ClearBackground(LIGHTGRAY); + ClearBackground(RAYWHITE); if (!gameOver) { @@ -382,7 +381,7 @@ void DrawGame(void) if (shoot[i].active) DrawRectangleRec(shoot[i].rec, shoot[i].color); } - DrawText(FormatText("%04i", score), 20, 20, 40, DARKGRAY); + DrawText(FormatText("%04i", score), 20, 20, 40, GRAY); if (victory) DrawText("YOU WIN", screenWidth/2 - MeasureText("YOU WIN", 40)/2, screenHeight/2 - 40, 40, BLACK); diff --git a/games/samples/tetris.c b/games/samples/tetris.c index 8d550f3d..62400201 100644 --- a/games/samples/tetris.c +++ b/games/samples/tetris.c @@ -25,7 +25,7 @@ //---------------------------------------------------------------------------------- // Some Defines //---------------------------------------------------------------------------------- -#define SQUARE_SIZE 30 +#define SQUARE_SIZE 20 #define GRID_HORIZONTAL_SIZE 12 #define GRID_VERTICAL_SIZE 20 @@ -45,7 +45,7 @@ typedef enum GridSquare { EMPTY, MOVING, FULL, BLOCK, FADING } GridSquare; // Global Variables Declaration //------------------------------------------------------------------------------------ static int screenWidth = 800; -static int screenHeight = 620; +static int screenHeight = 450; static bool gameOver = false; static bool pause = false; @@ -289,6 +289,8 @@ void UpdateGame(void) DeleteCompleteLines(); fadeLineCounter = 0; lineToDelete = false; + + lines++; } } } @@ -314,10 +316,10 @@ void DrawGame(void) { // Draw gameplay area Vector2 offset; - offset.x = screenWidth/2 - (GRID_HORIZONTAL_SIZE*SQUARE_SIZE/2); + offset.x = screenWidth/2 - (GRID_HORIZONTAL_SIZE*SQUARE_SIZE/2) - 50; offset.y = screenHeight/2 - ((GRID_VERTICAL_SIZE - 1)*SQUARE_SIZE/2) + SQUARE_SIZE*2; - offset.y -= 60; // NOTE: Harcoded position! + offset.y -= 50; // NOTE: Harcoded position! int controller = offset.x; @@ -360,13 +362,9 @@ void DrawGame(void) offset.y += SQUARE_SIZE; } - // Draw incoming piece - //offset.x = screenWidth/2 - (4*SQUARE_SIZE/2); - //offset.y = (screenHeight/2 - ((GRID_VERTICAL_SIZE - 1)*SQUARE_SIZE/2)) - (3*SQUARE_SIZE); - - // NOTE: Harcoded positions for the demo! - offset.x = 850; - offset.y = 75; + // Draw incoming piece (hardcoded) + offset.x = 500; + offset.y = 45; int controler = offset.x; @@ -393,6 +391,9 @@ void DrawGame(void) offset.y += SQUARE_SIZE; } + DrawText("INCOMING:", offset.x, offset.y - 100, 10, GRAY); + DrawText(FormatText("LINES: %04i", lines), offset.x, offset.y + 20, 10, GRAY); + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); } else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); -- cgit v1.2.3 From c00062655fcb7de99164a4f5fb0babb7696fbc67 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 7 Feb 2016 11:35:36 +0100 Subject: GLAD only available on PLATFORM_DESKTOP --- src/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core.c b/src/core.c index c872d43e..2996033a 100644 --- a/src/core.c +++ b/src/core.c @@ -1427,6 +1427,7 @@ static void InitDisplay(int width, int height) glfwMakeContextCurrent(window); +#if defined(PLATFORM_DESKTOP) // Extensions initialization for OpenGL 3.3 if (rlGetVersion() == OPENGL_33) { @@ -1458,6 +1459,7 @@ static void InitDisplay(int width, int height) //if (GLAD_GL_ARB_vertex_array_object) // Use GL_ARB_vertex_array_object #endif } +#endif // 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 -- cgit v1.2.3 From 6a392f0eb2f4a3126ea5de444116aad18f3c685f Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 3 Feb 2016 19:00:56 +0100 Subject: GLAD not used on HTML5 --- src/core.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/core.c b/src/core.c index 2996033a..699cc2b7 100644 --- a/src/core.c +++ b/src/core.c @@ -53,8 +53,7 @@ #include // String function definitions, memset() #include // Macros for reporting and retrieving error conditions through error codes -#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) - +#if defined(PLATFORM_DESKTOP) #define GLAD_EXTENSIONS_LOADER #if defined(GLEW_EXTENSIONS_LOADER) #define GLEW_STATIC @@ -62,14 +61,16 @@ #elif defined(GLAD_EXTENSIONS_LOADER) #include "glad.h" // GLAD library: Manage OpenGL headers and extensions #endif +#endif +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) //#define GLFW_INCLUDE_NONE // Disable the standard OpenGL header inclusion on GLFW3 - #include // GLFW3 library: Windows, OpenGL context and Input management + #include // 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 // which are required for hiding mouse + #define GLFW_EXPOSE_NATIVE_X11 // Linux specific definitions for getting + #define GLFW_EXPOSE_NATIVE_GLX // native functions like glfwGetX11Window + #include // which are required for hiding mouse #endif //#include // OpenGL functions (GLFW3 already includes gl.h) //#define GLFW_DLL // Using GLFW DLL on Windows -> No, we use static version! -- cgit v1.2.3 From 2ef9552454db2119e1e6df0999d77525dbc31609 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 3 Feb 2016 19:01:16 +0100 Subject: WARNING message shortened --- src/rlgl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rlgl.c b/src/rlgl.c index 6810cb4b..421dda02 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -981,7 +981,7 @@ void rlglInit(void) else TraceLog(WARNING, "[EXTENSION] VAO extension not found, VAO usage not supported"); if (npotSupported) TraceLog(INFO, "[EXTENSION] NPOT textures extension detected, full NPOT textures supported"); - else TraceLog(WARNING, "[EXTENSION] NPOT textures extension not found, NPOT textures support is limited (no-mipmaps, no-repeat)"); + else TraceLog(WARNING, "[EXTENSION] NPOT textures extension not found, limited NPOT support (no-mipmaps, no-repeat)"); #endif if (texCompDXTSupported) TraceLog(INFO, "[EXTENSION] DXT compressed textures supported"); -- cgit v1.2.3 From e98ea900cfc3b20bc4c09424a58893524f90534d Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 3 Feb 2016 19:29:59 +0100 Subject: Reviewing gestures module (IN PROGRESS) --- src/gestures.c | 99 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 58 insertions(+), 41 deletions(-) diff --git a/src/gestures.c b/src/gestures.c index 8c690066..13c7845a 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -1,8 +1,10 @@ /********************************************************************************************** * -* raylib Gestures System - Gestures Detection and Usage Functions (Android and HTML5) +* raylib Gestures System - Gestures Processing based on input gesture events (touch/mouse) * -* Copyright (c) 2015 Marc Palau and Ramon Santamaria +* Reviewed by Ramon Santamaria +* Redesigned by Albert Martos and Ian Eito +* Initial design by Marc Palau * * 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. @@ -56,18 +58,14 @@ //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- -typedef enum { - TYPE_MOTIONLESS, - TYPE_DRAG, - TYPE_DUAL_INPUT -} GestureType; +// ... //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- // Drag gesture variables -static Vector2 dragVector = { 0, 0 }; +static Vector2 dragVector = { 0.0f , 0.0f }; // Touch gesture variables static Vector2 touchDownPosition = { 0, 0 }; @@ -81,15 +79,15 @@ static int numHold = 0; static int pointCount = 0; static int touchId = -1; -static double eventTime = 0; +static double eventTime = 0.0; -static float magnitude = 0; // Distance traveled dragging -static float angle = 0; // Angle direction of the drag -static float intensity = 0; // How fast we did the drag (pixels per frame) -static int draggingTimeCounter = 0; // Time that have passed while dragging +static float dragDistance = 0.0f; // DRAG distance (from initial touch point to current) +static float dragAngle = 0; // DRAG angle direction +static float dragIntensity = 0; // DRAG intensity, how far why did the DRAG (pixels per frame) +static int draggingTimeCounter = 0; // DRAG time // RAY: WTF!!! Counting... frames??? // Pinch gesture variables -static float pinchDelta = 0; // Pinch delta displacement +static float pinchDistance = 0.0f; // Pinch displacement distance // RAY: Not used! o__O // Detected gestures static int previousGesture = GESTURE_NONE; @@ -112,9 +110,9 @@ static double GetCurrentTime(); // Process gesture event and translate it into gestures void ProcessGestureEvent(GestureEvent event) { - // Resets - dragVector = (Vector2){ 0, 0 }; - pinchDelta = 0; + // Reset required variables + dragVector = (Vector2){ 0.0f, 0.0f }; // RAY: Not used??? + pinchDistance = 0.0f; previousGesture = currentGesture; @@ -150,25 +148,25 @@ void ProcessGestureEvent(GestureEvent event) if (currentGesture == GESTURE_DRAG) touchUpPosition = event.position[0]; // Calculate for swipe - magnitude = Vector2Distance(touchDownPosition, touchUpPosition); - intensity = magnitude / (float)draggingTimeCounter; + dragDistance = Vector2Distance(touchDownPosition, touchUpPosition); + dragIntensity = dragDistance/(float)draggingTimeCounter; // RAY: WTF!!! Counting frames??? // Detect GESTURE_SWIPE - if ((intensity > FORCE_TO_SWIPE) && (touchId == 0)) + if ((dragIntensity > FORCE_TO_SWIPE) && (touchId == 0)) // RAY: why check (touchId == 0)??? { - angle = CalculateAngle(touchDownPosition, touchUpPosition, magnitude); + dragAngle = CalculateAngle(touchDownPosition, touchUpPosition, dragDistance); - if ((angle < 30) || (angle > 330)) currentGesture = GESTURE_SWIPE_RIGHT; // Right - else if ((angle > 30) && (angle < 120)) currentGesture = GESTURE_SWIPE_UP; // Up - else if ((angle > 120) && (angle < 210)) currentGesture = GESTURE_SWIPE_LEFT; // Left - else if ((angle > 210) && (angle < 300)) currentGesture = GESTURE_SWIPE_DOWN; // Down + if ((dragAngle < 30) || (dragAngle > 330)) currentGesture = GESTURE_SWIPE_RIGHT; // Right + else if ((dragAngle > 30) && (dragAngle < 120)) currentGesture = GESTURE_SWIPE_UP; // Up + else if ((dragAngle > 120) && (dragAngle < 210)) currentGesture = GESTURE_SWIPE_LEFT; // Left + else if ((dragAngle > 210) && (dragAngle < 300)) currentGesture = GESTURE_SWIPE_DOWN; // Down else currentGesture = GESTURE_NONE; } else { - magnitude = 0; - angle = 0; - intensity = 0; + dragDistance = 0.0f; + dragIntensity = 0.0f; + dragAngle = 0.0f; currentGesture = GESTURE_NONE; } @@ -187,13 +185,13 @@ void ProcessGestureEvent(GestureEvent event) numHold = 2; - magnitude = Vector2Distance(touchDownPosition, moveDownPosition); + dragDistance = Vector2Distance(touchDownPosition, moveDownPosition); // Detect GESTURE_DRAG - if (magnitude >= FORCE_TO_DRAG) currentGesture = GESTURE_DRAG; + if (dragDistance >= FORCE_TO_DRAG) currentGesture = GESTURE_DRAG; } - draggingTimeCounter++; + draggingTimeCounter++; // RAY: What do you count??? Move event actions? } } else // Two touch points @@ -207,7 +205,7 @@ void ProcessGestureEvent(GestureEvent event) } else if (event.touchAction == TOUCH_MOVE) { - magnitude = Vector2Distance(moveDownPosition, moveDownPosition2); + pinchDistance = Vector2Distance(moveDownPosition, moveDownPosition2); touchDownPosition = moveDownPosition; touchDownPosition2 = moveDownPosition2; @@ -217,7 +215,7 @@ void ProcessGestureEvent(GestureEvent event) if ((Vector2Distance(touchDownPosition, moveDownPosition) > FORCE_TO_PINCH) || (Vector2Distance(touchDownPosition2, moveDownPosition2) > FORCE_TO_PINCH)) { - if ((Vector2Distance(moveDownPosition, moveDownPosition2) - magnitude) < 0) currentGesture = GESTURE_PINCH_IN; + if ((Vector2Distance(moveDownPosition, moveDownPosition2) - pinchDistance) < 0) currentGesture = GESTURE_PINCH_IN; else currentGesture = GESTURE_PINCH_OUT; } else @@ -227,6 +225,8 @@ void ProcessGestureEvent(GestureEvent event) } else if (event.touchAction == TOUCH_UP) { + pinchDistance = 0.0f; + currentGesture = GESTURE_NONE; } } @@ -272,41 +272,47 @@ void SetGesturesEnabled(unsigned int gestureFlags) enabledGestures = gestureFlags; } -// Get drag intensity (pixels per frame) -float GetGestureDragIntensity(void) +// Get drag dragIntensity (pixels per frame) +float GetGestureDragdragIntensity(void) { - return intensity; + return dragIntensity; } // Get drag angle // NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise float GetGestureDragAngle(void) { - return angle; + return dragAngle; } // Get drag vector (between initial and final position) Vector2 GetGestureDragVector(void) { + // TODO: Calculate DRAG vector + return dragVector; } -// Hold time measured in frames +// Hold time measured in ms int GetGestureHoldDuration(void) { + // TODO: Return last hold time in ms + return 0; } -// Get magnitude between two pinch points +// Get distance between two pinch points float GetGesturePinchDelta(void) { - return pinchDelta; + return pinchDistance; } // Get angle beween two pinch points // NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise float GetGesturePinchAngle(void) { + // TODO: Calculate pinch angle + return 0; } @@ -314,13 +320,23 @@ float GetGesturePinchAngle(void) // Module specific Functions Definition //---------------------------------------------------------------------------------- +// RAY: Do we really need magnitude??? why??? +// TODO: Remove magnitude dependency... static float CalculateAngle(Vector2 initialPosition, Vector2 finalPosition, float magnitude) { float angle; - // Calculate arcsinus of the movement + // Calculate arcsinus of the movement // RAY: o__O angle = asin((finalPosition.y - initialPosition.y)/magnitude); angle *= RAD2DEG; + + // RAY: review this (better) solution + //angle = atan2(p1.y - p2.y, p1.x - p2.x); + //angle *= RAD2DEG; + + // http://stackoverflow.com/questions/21483999/using-atan2-to-find-angle-between-two-vectors + + // TODO: Remove sector dependency (self-note: check moving eyes exercise) // Calculate angle depending on the sector if ((finalPosition.x - initialPosition.x) >= 0) @@ -349,6 +365,7 @@ static float CalculateAngle(Vector2 initialPosition, Vector2 finalPosition, floa return angle; } +// Calculate distance between two Vector2 static float Vector2Distance(Vector2 v1, Vector2 v2) { float result; -- cgit v1.2.3 From 687fe2c3c79bac68e6eab3ae393fefed0a7a4b07 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 8 Feb 2016 09:04:33 +0100 Subject: Updated --- src/gestures.c | 54 +++++++++++++----------------------------------------- 1 file changed, 13 insertions(+), 41 deletions(-) diff --git a/src/gestures.c b/src/gestures.c index 13c7845a..09c18fc4 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -99,7 +99,7 @@ static unsigned int enabledGestures = 0b0000001111111111; //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- -static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, float magnitude); +static float Vector2Angle(Vector2 initialPosition, Vector2 finalPosition); static float Vector2Distance(Vector2 v1, Vector2 v2); static double GetCurrentTime(); @@ -152,9 +152,9 @@ void ProcessGestureEvent(GestureEvent event) dragIntensity = dragDistance/(float)draggingTimeCounter; // RAY: WTF!!! Counting frames??? // Detect GESTURE_SWIPE - if ((dragIntensity > FORCE_TO_SWIPE) && (touchId == 0)) // RAY: why check (touchId == 0)??? + if ((dragIntensity > FORCE_TO_SWIPE) && (touchId == 0)) // RAY: why check (touchId == 0)??? { - dragAngle = CalculateAngle(touchDownPosition, touchUpPosition, dragDistance); + dragAngle = Vector2Angle(touchDownPosition, touchUpPosition); if ((dragAngle < 30) || (dragAngle > 330)) currentGesture = GESTURE_SWIPE_RIGHT; // Right else if ((dragAngle > 30) && (dragAngle < 120)) currentGesture = GESTURE_SWIPE_UP; // Up @@ -322,46 +322,18 @@ float GetGesturePinchAngle(void) // RAY: Do we really need magnitude??? why??? // TODO: Remove magnitude dependency... -static float CalculateAngle(Vector2 initialPosition, Vector2 finalPosition, float magnitude) +static float Vector2Angle(Vector2 initialPosition, Vector2 finalPosition) { float angle; - - // Calculate arcsinus of the movement // RAY: o__O - angle = asin((finalPosition.y - initialPosition.y)/magnitude); - angle *= RAD2DEG; - + // RAY: review this (better) solution - //angle = atan2(p1.y - p2.y, p1.x - p2.x); - //angle *= RAD2DEG; - - // http://stackoverflow.com/questions/21483999/using-atan2-to-find-angle-between-two-vectors - - // TODO: Remove sector dependency (self-note: check moving eyes exercise) + angle = atan2(finalPosition.y - initialPosition.y, finalPosition.x - initialPosition.x); + angle *= RAD2DEG; - // Calculate angle depending on the sector - if ((finalPosition.x - initialPosition.x) >= 0) - { - // Sector 4 - if ((finalPosition.y - initialPosition.y) >= 0) - { - angle *= -1; - angle += 360; - } - // Sector 1 - else angle *= -1; - } - else - { - // Sector 3 - if ((finalPosition.y - initialPosition.y) >= 0) angle += 180; - // Sector 2 - else - { - angle *= -1; - angle = 180 - angle; - } - } + if (angle < 0) angle += 360; + // http://stackoverflow.com/questions/21483999/using-atan2-to-find-angle-between-two-vectors + return angle; } @@ -389,16 +361,16 @@ static double GetCurrentTime() QueryPerformanceFrequency(&clockFrequency); QueryPerformanceCounter(¤tTime); - time = (double)currentTime/clockFrequency*1000.0f; // time in miliseconds + time = (double)currentTime/clockFrequency*1000.0f; // Time in miliseconds #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 + uint64_t nowTime = (uint64_t)now.tv_sec*1000000000LLU + (uint64_t)now.tv_nsec; // Time in nanoseconds - time = ((double)nowTime/1000000.0); // time in miliseconds + time = ((double)nowTime/1000000.0); // Time in miliseconds #endif return time; -- cgit v1.2.3 From a847df921f94a7fd118fcb608b23f11d8255c236 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 10 Feb 2016 10:31:06 +0100 Subject: Reviewed gestures module --- src/core.c | 30 ++++++++++------ src/gestures.c | 110 +++++++++++++++++++++++++++++++++++---------------------- src/gestures.h | 1 + src/raylib.h | 9 ++--- 4 files changed, 94 insertions(+), 56 deletions(-) diff --git a/src/core.c b/src/core.c index 699cc2b7..05ec0c0a 100644 --- a/src/core.c +++ b/src/core.c @@ -117,7 +117,8 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define STORAGE_FILENAME "storage.data" +#define STORAGE_FILENAME "storage.data" +#define MAX_TOUCH_POINTS 2 //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -182,7 +183,7 @@ static bool fullscreen = false; // Fullscreen mode (useful only for static Matrix downscaleView; // Matrix to downscale view (in case screen size bigger than display size) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) -static Vector2 touchPosition; // Touch position on screen +static Vector2 touchPosition[MAX_TOUCH_POINTS]; // Touch position on screen #endif #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) @@ -1228,7 +1229,7 @@ bool IsGamepadButtonUp(int gamepad, int button) int GetTouchX(void) { #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) - return (int)touchPosition.x; + return (int)touchPosition[0].x; #else // PLATFORM_DESKTOP, PLATFORM_RPI return GetMouseX(); #endif @@ -1238,7 +1239,7 @@ int GetTouchX(void) int GetTouchY(void) { #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) - return (int)touchPosition.y; + return (int)touchPosition[0].y; #else // PLATFORM_DESKTOP, PLATFORM_RPI return GetMouseY(); #endif @@ -1246,10 +1247,13 @@ int GetTouchY(void) // Returns touch position XY // TODO: touch position should be scaled depending on display size and render size -Vector2 GetTouchPosition(void) +Vector2 GetTouchPosition(int index) { + Vector2 position = { -1.0f, -1.0f }; + #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) - Vector2 position = touchPosition; + if (index < MAX_TOUCH_POINTS) position = touchPosition[index]; + else TraceLog(WARNING, "Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS); if ((screenWidth > displayWidth) || (screenHeight > displayHeight)) { @@ -1263,7 +1267,7 @@ Vector2 GetTouchPosition(void) position.y = position.y*((float)renderHeight/(float)displayHeight) - renderOffsetY/2; } #else // PLATFORM_DESKTOP, PLATFORM_RPI - Vector2 position = GetMousePosition(); + if (index == 0) position = GetMousePosition(); #endif return position; @@ -1916,8 +1920,13 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) if (type == AINPUT_EVENT_TYPE_MOTION) { - touchPosition.x = AMotionEvent_getX(event, 0); - touchPosition.y = AMotionEvent_getY(event, 0); + // Get first touch position + touchPosition[0].x = AMotionEvent_getX(event, 0); + touchPosition[0].y = AMotionEvent_getY(event, 0); + + // Get second touch position + touchPosition[1].x = AMotionEvent_getX(event, 1); + touchPosition[1].y = AMotionEvent_getY(event, 1); } else if (type == AINPUT_EVENT_TYPE_KEY) { @@ -2535,7 +2544,8 @@ static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent gestureEvent.position[0] = (Vector2){ touchEvent->touches[0].targetX, touchEvent->touches[0].targetY }; gestureEvent.position[1] = (Vector2){ touchEvent->touches[1].targetX, touchEvent->touches[1].targetY }; - touchPosition = gestureEvent.position[0]; + touchPosition[0] = gestureEvent.position[0]; + touchPosition[1] = gestureEvent.position[1]; // Gesture data is sent to gestures system for processing ProcessGestureEvent(gestureEvent); // Process obtained gestures data diff --git a/src/gestures.c b/src/gestures.c index 09c18fc4..e5a8eb9e 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -31,9 +31,7 @@ #include "raylib.h" // Required for typedef(s): Vector2, Gestures #endif -#include // malloc(), free() -#include // printf(), fprintf() -#include // Used for ... +#include // Used for: atan2(), sqrt() #include // Defines int32_t, int64_t #if defined(_WIN32) @@ -47,13 +45,12 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define FORCE_TO_SWIPE 20 +#define FORCE_TO_SWIPE 1 #define FORCE_TO_DRAG 20 #define FORCE_TO_PINCH 5 #define TAP_TIMEOUT 300 // Time in milliseconds #define PINCH_TIMEOUT 300 // Time in milliseconds #define DOUBLETAP_RANGE 30 -//#define MAX_TOUCH_POINTS 4 //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -64,30 +61,33 @@ // Global Variables Definition //---------------------------------------------------------------------------------- -// Drag gesture variables -static Vector2 dragVector = { 0.0f , 0.0f }; - // Touch gesture variables -static Vector2 touchDownPosition = { 0, 0 }; -static Vector2 touchDownPosition2 = { 0, 0 }; -static Vector2 touchUpPosition = { 0, 0 }; -static Vector2 moveDownPosition = { 0, 0 }; -static Vector2 moveDownPosition2 = { 0, 0 }; +static Vector2 touchDownPosition = { 0.0f, 0.0f }; +static Vector2 touchDownPosition2 = { 0.0f, 0.0f }; +static Vector2 touchDownDragPosition = { 0.0f, 0.0f }; +static Vector2 touchUpPosition = { 0.0f, 0.0f }; +static Vector2 moveDownPosition = { 0.0f, 0.0f }; +static Vector2 moveDownPosition2 = { 0.0f, 0.0f }; static int numTap = 0; static int numHold = 0; +static bool isMoving = false; +static float timeHold = 0.0f; static int pointCount = 0; static int touchId = -1; static double eventTime = 0.0; +static double swipeTime = 0.0; +// Drag gesture variables +static Vector2 dragVector = { 0.0f , 0.0f }; static float dragDistance = 0.0f; // DRAG distance (from initial touch point to current) -static float dragAngle = 0; // DRAG angle direction -static float dragIntensity = 0; // DRAG intensity, how far why did the DRAG (pixels per frame) -static int draggingTimeCounter = 0; // DRAG time // RAY: WTF!!! Counting... frames??? +static float dragAngle = 0.0f; // DRAG angle direction +static float dragIntensity = 0.0f; // DRAG intensity, how far why did the DRAG (pixels per frame) // Pinch gesture variables static float pinchDistance = 0.0f; // Pinch displacement distance // RAY: Not used! o__O +static float pinchAngle = 0.0f; // Pinch displacement distance // RAY: Not used! o__O // Detected gestures static int previousGesture = GESTURE_NONE; @@ -111,9 +111,6 @@ static double GetCurrentTime(); void ProcessGestureEvent(GestureEvent event) { // Reset required variables - dragVector = (Vector2){ 0.0f, 0.0f }; // RAY: Not used??? - pinchDistance = 0.0f; - previousGesture = currentGesture; pointCount = event.pointCount; // Required on UpdateGestures() @@ -139,9 +136,12 @@ void ProcessGestureEvent(GestureEvent event) } touchDownPosition = event.position[0]; + touchDownDragPosition = event.position[0]; touchUpPosition = touchDownPosition; eventTime = GetCurrentTime(); + + dragVector = (Vector2){ 0.0f, 0.0f }; } else if (event.touchAction == TOUCH_UP) { @@ -149,12 +149,15 @@ void ProcessGestureEvent(GestureEvent event) // Calculate for swipe dragDistance = Vector2Distance(touchDownPosition, touchUpPosition); - dragIntensity = dragDistance/(float)draggingTimeCounter; // RAY: WTF!!! Counting frames??? + dragIntensity = dragDistance/(float)((GetCurrentTime() - swipeTime)); + + isMoving = false; // Detect GESTURE_SWIPE if ((dragIntensity > FORCE_TO_SWIPE) && (touchId == 0)) // RAY: why check (touchId == 0)??? { - dragAngle = Vector2Angle(touchDownPosition, touchUpPosition); + // NOTE: Angle should be inverted in Y + dragAngle = 360.0f - Vector2Angle(touchDownPosition, touchUpPosition);; if ((dragAngle < 30) || (dragAngle > 330)) currentGesture = GESTURE_SWIPE_RIGHT; // Right else if ((dragAngle > 30) && (dragAngle < 120)) currentGesture = GESTURE_SWIPE_UP; // Up @@ -171,12 +174,18 @@ void ProcessGestureEvent(GestureEvent event) currentGesture = GESTURE_NONE; } - draggingTimeCounter = 0; + touchDownPosition = (Vector2){ 0.0f, 0.0f }; } else if (event.touchAction == TOUCH_MOVE) { if (Vector2Distance(moveDownPosition, event.position[0]) > 5) eventTime = GetCurrentTime(); + if (!isMoving) + { + swipeTime = GetCurrentTime(); + isMoving = true; + } + moveDownPosition = event.position[0]; if (currentGesture == GESTURE_HOLD) @@ -190,8 +199,9 @@ void ProcessGestureEvent(GestureEvent event) // Detect GESTURE_DRAG if (dragDistance >= FORCE_TO_DRAG) currentGesture = GESTURE_DRAG; } - - draggingTimeCounter++; // RAY: What do you count??? Move event actions? + + dragVector.x = moveDownPosition.x - touchDownDragPosition.x; + dragVector.y = moveDownPosition.y - touchDownDragPosition.y; } } else // Two touch points @@ -200,13 +210,15 @@ void ProcessGestureEvent(GestureEvent event) { touchDownPosition = event.position[0]; touchDownPosition2 = event.position[1]; + pinchDistance = Vector2Distance(touchDownPosition, touchDownPosition2); currentGesture = GESTURE_HOLD; + timeHold = GetCurrentTime(); } else if (event.touchAction == TOUCH_MOVE) { pinchDistance = Vector2Distance(moveDownPosition, moveDownPosition2); - + touchDownPosition = moveDownPosition; touchDownPosition2 = moveDownPosition2; @@ -220,12 +232,17 @@ void ProcessGestureEvent(GestureEvent event) } else { - currentGesture = GESTURE_HOLD; + currentGesture = GESTURE_HOLD; + timeHold = GetCurrentTime(); } + + // NOTE: Angle should be inverted in Y + pinchAngle = 360.0f - Vector2Angle(moveDownPosition, moveDownPosition2); } else if (event.touchAction == TOUCH_UP) { pinchDistance = 0.0f; + pinchAngle = 0.0f; currentGesture = GESTURE_NONE; } @@ -238,11 +255,16 @@ void UpdateGestures(void) // NOTE: Gestures are processed through system callbacks on touch events // Detect GESTURE_HOLD - if (((currentGesture == GESTURE_TAP) || (currentGesture == GESTURE_DOUBLETAP)) && pointCount < 2) currentGesture = GESTURE_HOLD; + if (((currentGesture == GESTURE_TAP) || (currentGesture == GESTURE_DOUBLETAP)) && (pointCount < 2)) + { + currentGesture = GESTURE_HOLD; + timeHold = GetCurrentTime(); + } - if ((GetCurrentTime() - eventTime) > TAP_TIMEOUT && (currentGesture == GESTURE_DRAG) && pointCount < 2) + if (((GetCurrentTime() - eventTime) > TAP_TIMEOUT) && (currentGesture == GESTURE_DRAG) && (pointCount < 2)) { currentGesture = GESTURE_HOLD; + timeHold = GetCurrentTime(); numHold = 1; } @@ -288,17 +310,19 @@ float GetGestureDragAngle(void) // Get drag vector (between initial and final position) Vector2 GetGestureDragVector(void) { - // TODO: Calculate DRAG vector - + // NOTE: Calculated in... return dragVector; } // Hold time measured in ms -int GetGestureHoldDuration(void) +float GetGestureHoldDuration(void) { - // TODO: Return last hold time in ms + float time = 0.0f; + + // DONE: Return last hold time in ms + if (currentGesture == GESTURE_HOLD) time = (float)GetCurrentTime() - timeHold; - return 0; + return time; } // Get distance between two pinch points @@ -307,32 +331,34 @@ float GetGesturePinchDelta(void) return pinchDistance; } +// Get number of touch points +int GetTouchPointsCount(void) +{ + return pointCount; +} + // Get angle beween two pinch points // NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise float GetGesturePinchAngle(void) { - // TODO: Calculate pinch angle + // NOTE: pinch angle is calculated on two touch points TOUCH_MOVE - return 0; + return pinchAngle; } //---------------------------------------------------------------------------------- // Module specific Functions Definition //---------------------------------------------------------------------------------- -// RAY: Do we really need magnitude??? why??? -// TODO: Remove magnitude dependency... +// Returns angle from two-points vector with X-axis static float Vector2Angle(Vector2 initialPosition, Vector2 finalPosition) { float angle; - - // RAY: review this (better) solution + angle = atan2(finalPosition.y - initialPosition.y, finalPosition.x - initialPosition.x); angle *= RAD2DEG; - if (angle < 0) angle += 360; - - // http://stackoverflow.com/questions/21483999/using-atan2-to-find-angle-between-two-vectors + if (angle < 0) angle += 360.0f; return angle; } diff --git a/src/gestures.h b/src/gestures.h index b5cf2767..52f778be 100644 --- a/src/gestures.h +++ b/src/gestures.h @@ -102,6 +102,7 @@ Vector2 GetGestureDragVector(void); // Get gesture drag vect int GetGestureHoldDuration(void); // Get gesture hold time in frames float GetGesturePinchDelta(void); // Get gesture pinch delta float GetGesturePinchAngle(void); // Get gesture pinch angle +int GetTouchPointsCount(void); // Get touch points count #ifdef __cplusplus } diff --git a/src/raylib.h b/src/raylib.h index 3d8100b3..55a68ad1 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -600,9 +600,9 @@ 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 -int GetTouchX(void); // Returns touch position X (relative to screen size) -int GetTouchY(void); // Returns touch position Y (relative to screen size) -Vector2 GetTouchPosition(void); // Returns touch position XY (relative to screen size) +int GetTouchX(void); // Returns touch position X for touch point 0 (relative to screen size) +int GetTouchY(void); // Returns touch position Y for touch point 0 (relative to screen size) +Vector2 GetTouchPosition(int index) // Returns touch position XY for a touch point index (relative to screen size) #if defined(PLATFORM_ANDROID) bool IsButtonPressed(int button); // Detect if an android physic button has been pressed @@ -622,9 +622,10 @@ void ProcessGestureEvent(GestureEvent event); // Process gesture event float GetGestureDragIntensity(void); // Get gesture drag intensity float GetGestureDragAngle(void); // Get gesture drag angle Vector2 GetGestureDragVector(void); // Get gesture drag vector -int GetGestureHoldDuration(void); // Get gesture hold time in frames +float GetGestureHoldDuration(void); // Get gesture hold time in ms float GetGesturePinchDelta(void); // Get gesture pinch delta float GetGesturePinchAngle(void); // Get gesture pinch angle +int GetTouchPointsCount(void); // Get touch points count //------------------------------------------------------------------------------------ // Camera System Functions (Module: camera) -- cgit v1.2.3 From 84a6724b33efd9ddea9782c3df88855cff2d9d3a Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 10 Feb 2016 11:24:02 +0100 Subject: Fixed a bug --- src/raylib.h | 2 +- src_android/jni/Android.mk | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index 55a68ad1..a5dd6ad2 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -602,7 +602,7 @@ bool IsGamepadButtonUp(int gamepad, int button); // Detect if a gamepad b int GetTouchX(void); // Returns touch position X for touch point 0 (relative to screen size) int GetTouchY(void); // Returns touch position Y for touch point 0 (relative to screen size) -Vector2 GetTouchPosition(int index) // Returns touch position XY for a touch point index (relative to screen size) +Vector2 GetTouchPosition(int index); // Returns touch position XY for a touch point index (relative to screen size) #if defined(PLATFORM_ANDROID) bool IsButtonPressed(int button); // Detect if an android physic button has been pressed diff --git a/src_android/jni/Android.mk b/src_android/jni/Android.mk index f9c20e66..20073760 100644 --- a/src_android/jni/Android.mk +++ b/src_android/jni/Android.mk @@ -39,7 +39,6 @@ LOCAL_MODULE := raylib LOCAL_SRC_FILES :=\ ../../src/core.c \ ../../src/rlgl.c \ - ../../src/raymath.c \ ../../src/textures.c \ ../../src/text.c \ ../../src/shapes.c \ -- cgit v1.2.3 From c69ce1d7504b94108721403c867bddbf50d7b890 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 10 Feb 2016 13:54:32 +0100 Subject: Updated comments --- src/gestures.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/gestures.c b/src/gestures.c index e5a8eb9e..a2744460 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -45,7 +45,7 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define FORCE_TO_SWIPE 1 +#define FORCE_TO_SWIPE 1 // Time in milliseconds #define FORCE_TO_DRAG 20 #define FORCE_TO_PINCH 5 #define TAP_TIMEOUT 300 // Time in milliseconds @@ -80,14 +80,14 @@ static double eventTime = 0.0; static double swipeTime = 0.0; // Drag gesture variables -static Vector2 dragVector = { 0.0f , 0.0f }; -static float dragDistance = 0.0f; // DRAG distance (from initial touch point to current) -static float dragAngle = 0.0f; // DRAG angle direction -static float dragIntensity = 0.0f; // DRAG intensity, how far why did the DRAG (pixels per frame) +static Vector2 dragVector = { 0.0f , 0.0f }; // DRAG vector (between initial and current position) +static float dragDistance = 0.0f; // DRAG distance (from initial touch point to final) for SWIPE GESTURE +static float dragAngle = 0.0f; // DRAG angle direction for SWIPE GESTURE +static float dragIntensity = 0.0f; // DRAG intensity, how far why did the DRAG (pixels per frame) for SWIPE GESTURE // Pinch gesture variables -static float pinchDistance = 0.0f; // Pinch displacement distance // RAY: Not used! o__O -static float pinchAngle = 0.0f; // Pinch displacement distance // RAY: Not used! o__O +static float pinchDistance = 0.0f; // Pinch displacement distance +static float pinchAngle = 0.0f; // Pinch displacement distance // Detected gestures static int previousGesture = GESTURE_NONE; @@ -122,7 +122,7 @@ void ProcessGestureEvent(GestureEvent event) if (event.touchAction == TOUCH_DOWN) { numTap++; // Tap counter - + // Detect GESTURE_DOUBLE_TAP if ((currentGesture == GESTURE_NONE) && (numTap >= 2) && ((GetCurrentTime() - eventTime) < TAP_TIMEOUT) && (Vector2Distance(touchDownPosition, event.position[0]) < DOUBLETAP_RANGE)) { @@ -174,7 +174,7 @@ void ProcessGestureEvent(GestureEvent event) currentGesture = GESTURE_NONE; } - touchDownPosition = (Vector2){ 0.0f, 0.0f }; + touchDownDragPosition = (Vector2){ 0.0f, 0.0f }; } else if (event.touchAction == TOUCH_MOVE) { @@ -297,6 +297,8 @@ void SetGesturesEnabled(unsigned int gestureFlags) // Get drag dragIntensity (pixels per frame) float GetGestureDragdragIntensity(void) { + // NOTE: drag intensity is calculated on one touch points TOUCH_UP + return dragIntensity; } @@ -304,22 +306,26 @@ float GetGestureDragdragIntensity(void) // NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise float GetGestureDragAngle(void) { + // NOTE: drag angle is calculated on one touch points TOUCH_UP + return dragAngle; } -// Get drag vector (between initial and final position) +// Get drag vector (between initial touch point to current) Vector2 GetGestureDragVector(void) { - // NOTE: Calculated in... + // NOTE: drag vector is calculated on one touch points TOUCH_MOVE + return dragVector; } // Hold time measured in ms float GetGestureHoldDuration(void) { + // NOTE: time is calculated on current gesture HOLD + float time = 0.0f; - // DONE: Return last hold time in ms if (currentGesture == GESTURE_HOLD) time = (float)GetCurrentTime() - timeHold; return time; @@ -328,12 +334,17 @@ float GetGestureHoldDuration(void) // Get distance between two pinch points float GetGesturePinchDelta(void) { + // NOTE: The position values used for pinchDistance are not modified like the position values of [core.c]-->GetTouchPosition(int index) + // NOTE: pinch distance is calculated on two touch points TOUCH_MOVE + return pinchDistance; } // Get number of touch points int GetTouchPointsCount(void) { + // NOTE: point count is calculated when ProcessGestureEvent(GestureEvent event) is called + return pointCount; } -- cgit v1.2.3 From 54c7fa491ef285838a64a8ee015de888c3d24a75 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 11 Feb 2016 12:26:45 +0100 Subject: Added 6 new examples --- examples/core_gestures_detection.c | 115 ++++++++++++++++++++++++ examples/core_gestures_detection.png | Bin 0 -> 19480 bytes examples/core_storage_values.c | 2 +- examples/makefile | 60 ++++++++++--- examples/models_billboard.png | Bin 53998 -> 54859 bytes examples/resources/cat.png | Bin 0 -> 663451 bytes examples/resources/fonts/bmfont.fnt | 99 ++++++++++++++++++++ examples/resources/fonts/bmfont.png | Bin 0 -> 14471 bytes examples/resources/fonts/pixantiqua.ttf | Bin 0 -> 35408 bytes examples/resources/parrots.png | Bin 0 -> 295054 bytes examples/text_bmfont_ttf.c | 68 ++++++++++++++ examples/text_bmfont_ttf.png | Bin 0 -> 19542 bytes examples/text_writing_anim.c | 60 +++++++++++++ examples/text_writing_anim.png | Bin 0 -> 15773 bytes examples/textures_image_drawing.c | 78 ++++++++++++++++ examples/textures_image_drawing.png | Bin 0 -> 420135 bytes examples/textures_image_processing.c | 154 ++++++++++++++++++++++++++++++++ examples/textures_image_processing.png | Bin 0 -> 259470 bytes 18 files changed, 621 insertions(+), 15 deletions(-) create mode 100644 examples/core_gestures_detection.c create mode 100644 examples/core_gestures_detection.png create mode 100644 examples/resources/cat.png create mode 100644 examples/resources/fonts/bmfont.fnt create mode 100644 examples/resources/fonts/bmfont.png create mode 100644 examples/resources/fonts/pixantiqua.ttf create mode 100644 examples/resources/parrots.png create mode 100644 examples/text_bmfont_ttf.c create mode 100644 examples/text_bmfont_ttf.png create mode 100644 examples/text_writing_anim.c create mode 100644 examples/text_writing_anim.png create mode 100644 examples/textures_image_drawing.c create mode 100644 examples/textures_image_drawing.png create mode 100644 examples/textures_image_processing.c create mode 100644 examples/textures_image_processing.png diff --git a/examples/core_gestures_detection.c b/examples/core_gestures_detection.c new file mode 100644 index 00000000..b69497c5 --- /dev/null +++ b/examples/core_gestures_detection.c @@ -0,0 +1,115 @@ +/******************************************************************************************* +* +* raylib [core] example - Gestures Detection +* +* This example has been created using raylib 1.4 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2016 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" +#include + +#define MAX_GESTURE_STRINGS 20 + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [core] example - gestures detection"); + + Vector2 touchPosition = { 0, 0 }; + Rectangle touchArea = { 220, 10, screenWidth - 230, screenHeight - 20 }; + + int gesturesCount = 0; + char gestureStrings[MAX_GESTURE_STRINGS][32]; + + int currentGesture = GESTURE_NONE; + int lastGesture = GESTURE_NONE; + + //SetGesturesEnabled(0b0000000000001001); // Enable only some gestures to be detected + + SetTargetFPS(30); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + lastGesture = currentGesture; + touchPosition = GetTouchPosition(0); + + if (CheckCollisionPointRec(touchPosition, touchArea) && IsGestureDetected()) + { + currentGesture = GetGestureType(); + + if (currentGesture != lastGesture) + { + // Store gesture string + switch (currentGesture) + { + case GESTURE_TAP: strcpy(gestureStrings[gesturesCount], "GESTURE TAP"); break; + case GESTURE_DOUBLETAP: strcpy(gestureStrings[gesturesCount], "GESTURE DOUBLETAP"); break; + case GESTURE_HOLD: strcpy(gestureStrings[gesturesCount], "GESTURE HOLD"); break; + case GESTURE_DRAG: strcpy(gestureStrings[gesturesCount], "GESTURE DRAG"); break; + case GESTURE_SWIPE_RIGHT: strcpy(gestureStrings[gesturesCount], "GESTURE SWIPE RIGHT"); break; + case GESTURE_SWIPE_LEFT: strcpy(gestureStrings[gesturesCount], "GESTURE SWIPE LEFT"); break; + case GESTURE_SWIPE_UP: strcpy(gestureStrings[gesturesCount], "GESTURE SWIPE UP"); break; + case GESTURE_SWIPE_DOWN: strcpy(gestureStrings[gesturesCount], "GESTURE SWIPE DOWN"); break; + default: break; + } + + gesturesCount++; + + // Reset gestures strings + if (gesturesCount >= MAX_GESTURE_STRINGS) + { + for (int i = 0; i < MAX_GESTURE_STRINGS; i++) strcpy(gestureStrings[i], "\0"); + + gesturesCount = 0; + } + } + } + else currentGesture = GESTURE_NONE; + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + DrawRectangleRec(touchArea, GRAY); + DrawRectangle(225, 15, screenWidth - 240, screenHeight - 30, RAYWHITE); + + DrawText("GESTURES TEST AREA", screenWidth - 270, screenHeight - 40, 20, Fade(GRAY, 0.5f)); + + for (int i = 0; i < gesturesCount; i++) + { + if (i%2 == 0) DrawRectangle(10, 30 + 20*i, 200, 20, Fade(LIGHTGRAY, 0.5f)); + else DrawRectangle(10, 30 + 20*i, 200, 20, Fade(LIGHTGRAY, 0.3f)); + + if (i < gesturesCount - 1) DrawText(gestureStrings[i], 35, 36 + 20*i, 10, DARKGRAY); + else DrawText(gestureStrings[i], 35, 36 + 20*i, 10, MAROON); + } + + DrawRectangleLines(10, 29, 200, screenHeight - 50, GRAY); + DrawText("DETECTED GESTURES", 50, 15, 10, GRAY); + + if (currentGesture != GESTURE_NONE) DrawCircleV(touchPosition, 30, MAROON); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- +} \ No newline at end of file diff --git a/examples/core_gestures_detection.png b/examples/core_gestures_detection.png new file mode 100644 index 00000000..d2bbb5d7 Binary files /dev/null and b/examples/core_gestures_detection.png differ diff --git a/examples/core_storage_values.c b/examples/core_storage_values.c index 3190d0a0..43f0882f 100644 --- a/examples/core_storage_values.c +++ b/examples/core_storage_values.c @@ -5,7 +5,7 @@ * This example has been created using raylib 1.4 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2014 Ramon Santamaria (@raysan5) +* Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/makefile b/examples/makefile index 04dc7756..62428155 100644 --- a/examples/makefile +++ b/examples/makefile @@ -85,8 +85,8 @@ else # external libraries headers # GLFW3 INCLUDES += -I../external/glfw3/include -# GLEW - INCLUDES += -I../external/glew/include +# GLEW - Not required any more, replaced by GLAD + #INCLUDES += -I../external/glew/include # OpenAL Soft INCLUDES += -I../external/openal_soft/include endif @@ -102,8 +102,8 @@ else ifneq ($(PLATFORM_OS),OSX) # OpenAL Soft LFLAGS += -L../external/openal_soft/lib/$(LIBPATH) - # GLEW - LFLAGS += -L../external/glew/lib/$(LIBPATH) + # GLEW - Not required any more, replaced by GLAD + #LFLAGS += -L../external/glew/lib/$(LIBPATH) endif endif @@ -126,7 +126,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) else # libraries for Windows desktop compiling # NOTE: GLFW3 and OpenAL Soft libraries should be installed - LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32 + LIBS = -lraylib -lglfw3 -lopengl32 -lopenal32 -lgdi32 endif endif endif @@ -161,6 +161,8 @@ EXAMPLES = \ core_random_values \ core_color_select \ core_drop_files \ + core_storage_values \ + core_gestures_detection \ core_3d_mode \ core_3d_picking \ core_3d_camera_free \ @@ -177,10 +179,14 @@ EXAMPLES = \ textures_raw_data \ textures_formats_loading \ textures_particles_trail_blending \ + textures_image_processing \ + textures_image_drawing \ text_sprite_fonts \ + text_bmfont_ttf \ text_rbmf_fonts \ text_format_text \ text_font_select \ + text_writing_anim \ models_geometric_shapes \ models_box_collisions \ models_billboard \ @@ -195,8 +201,6 @@ EXAMPLES = \ audio_music_stream \ fix_dylib \ - #core_input_gamepad \ - # typing 'make' will invoke the first target entry in the file, # in this case, the 'default' target entry is raylib @@ -217,6 +221,10 @@ core_input_keys: core_input_keys.c core_input_mouse: core_input_mouse.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) +# compile [core] example - mouse wheel +core_mouse_wheel: core_mouse_wheel.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + # compile [core] example - gamepad input core_input_gamepad: core_input_gamepad.c ifeq ($(PLATFORM),PLATFORM_DESKTOP) @@ -225,8 +233,12 @@ else @echo core_input_gamepad: Only supported on desktop platform endif -# compile [core] example - mouse wheel -core_mouse_wheel: core_mouse_wheel.c +# compile [core] example - generate random values +core_random_values: core_random_values.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + +# compile [core] example - color selection (collision detection) +core_color_select: core_color_select.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) # compile [core] example - drop files @@ -236,13 +248,17 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) else @echo core_drop_files: Only supported on desktop platform endif - -# compile [core] example - generate random values -core_random_values: core_random_values.c + +# compile [core] example - storage values +core_storage_values: core_storage_values.c +ifeq ($(PLATFORM),PLATFORM_DESKTOP) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) +else + @echo core_storage_values: Only supported on desktop platform +endif -# compile [core] example - color selection (collision detection) -core_color_select: core_color_select.c +# compile [core] example - gestures detection +core_gestures_detection: core_gestures_detection.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) # compile [core] example - 3d mode @@ -309,9 +325,21 @@ textures_formats_loading: textures_formats_loading.c textures_particles_trail_blending: textures_particles_trail_blending.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) +# compile [textures] example - texture image processing +textures_image_processing: textures_image_processing.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + +# compile [textures] example - texture image drawing +textures_image_drawing: textures_image_drawing.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + # compile [text] example - sprite fonts loading text_sprite_fonts: text_sprite_fonts.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + +# compile [text] example - bmfonts and ttf loading +text_bmfont_ttf: text_bmfont_ttf.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) # compile [text] example - raylib bitmap fonts (rBMF) text_rbmf_fonts: text_rbmf_fonts.c @@ -325,6 +353,10 @@ text_format_text: text_format_text.c text_font_select: text_font_select.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) +# compile [text] example - text writing animation +text_writing_anim: text_writing_anim.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + # compile [models] example - basic geometric 3d shapes models_geometric_shapes: models_geometric_shapes.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) diff --git a/examples/models_billboard.png b/examples/models_billboard.png index f1ed9239..dad1e55b 100644 Binary files a/examples/models_billboard.png and b/examples/models_billboard.png differ diff --git a/examples/resources/cat.png b/examples/resources/cat.png new file mode 100644 index 00000000..9b5c08d2 Binary files /dev/null and b/examples/resources/cat.png differ diff --git a/examples/resources/fonts/bmfont.fnt b/examples/resources/fonts/bmfont.fnt new file mode 100644 index 00000000..372c2c88 --- /dev/null +++ b/examples/resources/fonts/bmfont.fnt @@ -0,0 +1,99 @@ +info face="Arial Black" size=-32 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=2,2 outline=0 +common lineHeight=45 base=35 scaleW=512 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4 +page id=0 file="bmfont.png" +chars count=95 +char id=32 x=423 y=141 width=3 height=45 xoffset=-1 yoffset=0 xadvance=11 page=0 chnl=15 +char id=33 x=323 y=141 width=9 height=45 xoffset=1 yoffset=0 xadvance=11 page=0 chnl=15 +char id=34 x=123 y=141 width=16 height=45 xoffset=0 yoffset=0 xadvance=16 page=0 chnl=15 +char id=35 x=221 y=47 width=21 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=36 x=244 y=47 width=21 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=37 x=70 y=0 width=30 height=45 xoffset=1 yoffset=0 xadvance=32 page=0 chnl=15 +char id=38 x=390 y=0 width=25 height=45 xoffset=2 yoffset=0 xadvance=28 page=0 chnl=15 +char id=39 x=378 y=141 width=8 height=45 xoffset=1 yoffset=0 xadvance=9 page=0 chnl=15 +char id=40 x=222 y=141 width=11 height=45 xoffset=1 yoffset=0 xadvance=12 page=0 chnl=15 +char id=41 x=499 y=94 width=11 height=45 xoffset=1 yoffset=0 xadvance=12 page=0 chnl=15 +char id=42 x=497 y=47 width=13 height=45 xoffset=2 yoffset=0 xadvance=18 page=0 chnl=15 +char id=43 x=394 y=94 width=19 height=45 xoffset=1 yoffset=0 xadvance=21 page=0 chnl=15 +char id=44 x=367 y=141 width=9 height=45 xoffset=1 yoffset=0 xadvance=11 page=0 chnl=15 +char id=45 x=261 y=141 width=11 height=45 xoffset=0 yoffset=0 xadvance=11 page=0 chnl=15 +char id=46 x=356 y=141 width=9 height=45 xoffset=1 yoffset=0 xadvance=11 page=0 chnl=15 +char id=47 x=248 y=141 width=11 height=45 xoffset=-1 yoffset=0 xadvance=9 page=0 chnl=15 +char id=48 x=382 y=47 width=21 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=49 x=496 y=0 width=14 height=45 xoffset=2 yoffset=0 xadvance=21 page=0 chnl=15 +char id=50 x=134 y=94 width=20 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=51 x=359 y=47 width=21 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=52 x=313 y=47 width=21 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=53 x=336 y=47 width=21 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=54 x=178 y=94 width=20 height=45 xoffset=1 yoffset=0 xadvance=21 page=0 chnl=15 +char id=55 x=478 y=94 width=19 height=45 xoffset=1 yoffset=0 xadvance=21 page=0 chnl=15 +char id=56 x=290 y=47 width=21 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=57 x=90 y=94 width=20 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=58 x=345 y=141 width=9 height=45 xoffset=1 yoffset=0 xadvance=11 page=0 chnl=15 +char id=59 x=334 y=141 width=9 height=45 xoffset=1 yoffset=0 xadvance=11 page=0 chnl=15 +char id=60 x=0 y=141 width=19 height=45 xoffset=1 yoffset=0 xadvance=21 page=0 chnl=15 +char id=61 x=21 y=141 width=19 height=45 xoffset=1 yoffset=0 xadvance=21 page=0 chnl=15 +char id=62 x=310 y=94 width=19 height=45 xoffset=1 yoffset=0 xadvance=21 page=0 chnl=15 +char id=63 x=352 y=94 width=19 height=45 xoffset=1 yoffset=0 xadvance=20 page=0 chnl=15 +char id=64 x=279 y=0 width=26 height=45 xoffset=-1 yoffset=0 xadvance=24 page=0 chnl=15 +char id=65 x=193 y=0 width=27 height=45 xoffset=-1 yoffset=0 xadvance=25 page=0 chnl=15 +char id=66 x=150 y=47 width=22 height=45 xoffset=2 yoffset=0 xadvance=25 page=0 chnl=15 +char id=67 x=444 y=0 width=24 height=45 xoffset=1 yoffset=0 xadvance=25 page=0 chnl=15 +char id=68 x=174 y=47 width=22 height=45 xoffset=2 yoffset=0 xadvance=25 page=0 chnl=15 +char id=69 x=156 y=94 width=20 height=45 xoffset=2 yoffset=0 xadvance=23 page=0 chnl=15 +char id=70 x=63 y=141 width=18 height=45 xoffset=2 yoffset=0 xadvance=21 page=0 chnl=15 +char id=71 x=417 y=0 width=25 height=45 xoffset=1 yoffset=0 xadvance=27 page=0 chnl=15 +char id=72 x=125 y=47 width=23 height=45 xoffset=2 yoffset=0 xadvance=27 page=0 chnl=15 +char id=73 x=388 y=141 width=8 height=45 xoffset=2 yoffset=0 xadvance=12 page=0 chnl=15 +char id=74 x=200 y=94 width=20 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=75 x=251 y=0 width=26 height=45 xoffset=2 yoffset=0 xadvance=27 page=0 chnl=15 +char id=76 x=373 y=94 width=19 height=45 xoffset=2 yoffset=0 xadvance=21 page=0 chnl=15 +char id=77 x=134 y=0 width=28 height=45 xoffset=1 yoffset=0 xadvance=30 page=0 chnl=15 +char id=78 x=100 y=47 width=23 height=45 xoffset=2 yoffset=0 xadvance=27 page=0 chnl=15 +char id=79 x=363 y=0 width=25 height=45 xoffset=1 yoffset=0 xadvance=27 page=0 chnl=15 +char id=80 x=112 y=94 width=20 height=45 xoffset=2 yoffset=0 xadvance=23 page=0 chnl=15 +char id=81 x=335 y=0 width=26 height=45 xoffset=1 yoffset=0 xadvance=27 page=0 chnl=15 +char id=82 x=470 y=0 width=24 height=45 xoffset=2 yoffset=0 xadvance=25 page=0 chnl=15 +char id=83 x=75 y=47 width=23 height=45 xoffset=0 yoffset=0 xadvance=23 page=0 chnl=15 +char id=84 x=50 y=47 width=23 height=45 xoffset=0 yoffset=0 xadvance=23 page=0 chnl=15 +char id=85 x=25 y=47 width=23 height=45 xoffset=2 yoffset=0 xadvance=27 page=0 chnl=15 +char id=86 x=307 y=0 width=26 height=45 xoffset=0 yoffset=0 xadvance=25 page=0 chnl=15 +char id=87 x=0 y=0 width=34 height=45 xoffset=-1 yoffset=0 xadvance=32 page=0 chnl=15 +char id=88 x=222 y=0 width=27 height=45 xoffset=-1 yoffset=0 xadvance=25 page=0 chnl=15 +char id=89 x=164 y=0 width=27 height=45 xoffset=-1 yoffset=0 xadvance=25 page=0 chnl=15 +char id=90 x=0 y=47 width=23 height=45 xoffset=0 yoffset=0 xadvance=23 page=0 chnl=15 +char id=91 x=274 y=141 width=11 height=45 xoffset=1 yoffset=0 xadvance=12 page=0 chnl=15 +char id=92 x=300 y=141 width=10 height=45 xoffset=-1 yoffset=0 xadvance=9 page=0 chnl=15 +char id=93 x=287 y=141 width=11 height=45 xoffset=0 yoffset=0 xadvance=12 page=0 chnl=15 +char id=94 x=457 y=94 width=19 height=45 xoffset=1 yoffset=0 xadvance=21 page=0 chnl=15 +char id=95 x=103 y=141 width=18 height=45 xoffset=-1 yoffset=0 xadvance=16 page=0 chnl=15 +char id=96 x=312 y=141 width=9 height=45 xoffset=0 yoffset=0 xadvance=11 page=0 chnl=15 +char id=97 x=474 y=47 width=21 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=98 x=68 y=94 width=20 height=45 xoffset=1 yoffset=0 xadvance=21 page=0 chnl=15 +char id=99 x=267 y=47 width=21 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=100 x=46 y=94 width=20 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=101 x=198 y=47 width=21 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=102 x=141 y=141 width=15 height=45 xoffset=-1 yoffset=0 xadvance=12 page=0 chnl=15 +char id=103 x=222 y=94 width=20 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=104 x=415 y=94 width=19 height=45 xoffset=1 yoffset=0 xadvance=21 page=0 chnl=15 +char id=105 x=398 y=141 width=7 height=45 xoffset=2 yoffset=0 xadvance=11 page=0 chnl=15 +char id=106 x=235 y=141 width=11 height=45 xoffset=-2 yoffset=0 xadvance=11 page=0 chnl=15 +char id=107 x=405 y=47 width=21 height=45 xoffset=1 yoffset=0 xadvance=21 page=0 chnl=15 +char id=108 x=407 y=141 width=7 height=45 xoffset=2 yoffset=0 xadvance=11 page=0 chnl=15 +char id=109 x=102 y=0 width=30 height=45 xoffset=1 yoffset=0 xadvance=32 page=0 chnl=15 +char id=110 x=331 y=94 width=19 height=45 xoffset=1 yoffset=0 xadvance=21 page=0 chnl=15 +char id=111 x=428 y=47 width=21 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=112 x=266 y=94 width=20 height=45 xoffset=1 yoffset=0 xadvance=21 page=0 chnl=15 +char id=113 x=288 y=94 width=20 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=114 x=158 y=141 width=15 height=45 xoffset=1 yoffset=0 xadvance=14 page=0 chnl=15 +char id=115 x=244 y=94 width=20 height=45 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 +char id=116 x=175 y=141 width=14 height=45 xoffset=0 yoffset=0 xadvance=14 page=0 chnl=15 +char id=117 x=436 y=94 width=19 height=45 xoffset=1 yoffset=0 xadvance=21 page=0 chnl=15 +char id=118 x=451 y=47 width=21 height=45 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 +char id=119 x=36 y=0 width=32 height=45 xoffset=-1 yoffset=0 xadvance=30 page=0 chnl=15 +char id=120 x=0 y=94 width=21 height=45 xoffset=0 yoffset=0 xadvance=21 page=0 chnl=15 +char id=121 x=23 y=94 width=21 height=45 xoffset=0 yoffset=0 xadvance=20 page=0 chnl=15 +char id=122 x=83 y=141 width=18 height=45 xoffset=0 yoffset=0 xadvance=18 page=0 chnl=15 +char id=123 x=191 y=141 width=14 height=45 xoffset=-1 yoffset=0 xadvance=12 page=0 chnl=15 +char id=124 x=416 y=141 width=5 height=45 xoffset=2 yoffset=0 xadvance=9 page=0 chnl=15 +char id=125 x=207 y=141 width=13 height=45 xoffset=0 yoffset=0 xadvance=12 page=0 chnl=15 +char id=126 x=42 y=141 width=19 height=45 xoffset=1 yoffset=0 xadvance=21 page=0 chnl=15 diff --git a/examples/resources/fonts/bmfont.png b/examples/resources/fonts/bmfont.png new file mode 100644 index 00000000..9d621594 Binary files /dev/null and b/examples/resources/fonts/bmfont.png differ diff --git a/examples/resources/fonts/pixantiqua.ttf b/examples/resources/fonts/pixantiqua.ttf new file mode 100644 index 00000000..e012875d Binary files /dev/null and b/examples/resources/fonts/pixantiqua.ttf differ diff --git a/examples/resources/parrots.png b/examples/resources/parrots.png new file mode 100644 index 00000000..d6ec60ba Binary files /dev/null and b/examples/resources/parrots.png differ diff --git a/examples/text_bmfont_ttf.c b/examples/text_bmfont_ttf.c new file mode 100644 index 00000000..caece548 --- /dev/null +++ b/examples/text_bmfont_ttf.c @@ -0,0 +1,68 @@ +/******************************************************************************************* +* +* raylib [text] example - BMFont and TTF SpriteFonts loading +* +* This example has been created using raylib 1.4 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2016 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [text] example - bmfont and ttf sprite fonts loading"); + + const char msgBm[64] = "THIS IS AN AngelCode SPRITE FONT"; + const char msgTtf[64] = "THIS SPRITE FONT has been GENERATED from a TTF"; + + // NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) + SpriteFont fontBm = LoadSpriteFont("resources/fonts/bmfont.fnt"); // BMFont (AngelCode) + SpriteFont fontTtf = LoadSpriteFont("resources/fonts/pixantiqua.ttf"); // TTF font + + Vector2 fontPosition; + + fontPosition.x = screenWidth/2 - MeasureTextEx(fontBm, msgBm, fontBm.size, 0).x/2; + fontPosition.y = screenHeight/2 - fontBm.size/2 - 80; + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // TODO: Update variables here... + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + DrawTextEx(fontBm, msgBm, fontPosition, fontBm.size, 0, MAROON); + DrawTextEx(fontTtf, msgTtf, (Vector2){ 75.0f, 240.0f }, fontTtf.size*0.8f, 2, LIME); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadSpriteFont(fontBm); // AngelCode SpriteFont unloading + UnloadSpriteFont(fontTtf); // TTF SpriteFont unloading + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/text_bmfont_ttf.png b/examples/text_bmfont_ttf.png new file mode 100644 index 00000000..8305d36b Binary files /dev/null and b/examples/text_bmfont_ttf.png differ diff --git a/examples/text_writing_anim.c b/examples/text_writing_anim.c new file mode 100644 index 00000000..5f19b468 --- /dev/null +++ b/examples/text_writing_anim.c @@ -0,0 +1,60 @@ +/******************************************************************************************* +* +* raylib [text] example - Text Writing Animation +* +* This example has been created using raylib 1.4 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2016 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [text] example - text writing anim"); + + const char message[128] = "This sample illustrates a text writing\nanimation effect! Check it out! ;)"; + + int framesCounter = 0; + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + framesCounter++; + + if (IsKeyPressed(KEY_ENTER)) framesCounter = 0; + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + DrawText(SubText(message, 0, framesCounter/10), 210, 160, 20, MAROON); + + DrawText("PRESS [ENTER] to RESTART!", 240, 280, 20, LIGHTGRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/text_writing_anim.png b/examples/text_writing_anim.png new file mode 100644 index 00000000..d6752dd8 Binary files /dev/null and b/examples/text_writing_anim.png differ diff --git a/examples/textures_image_drawing.c b/examples/textures_image_drawing.c new file mode 100644 index 00000000..e09828d5 --- /dev/null +++ b/examples/textures_image_drawing.c @@ -0,0 +1,78 @@ +/******************************************************************************************* +* +* raylib [textures] example - Image loading and drawing on it +* +* NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) +* +* This example has been created using raylib 1.4 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2016 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [textures] example - image drawing"); + + // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) + + Image cat = LoadImage("resources/cat.png"); // Load image in CPU memory (RAM) + ImageCrop(&cat, (Rectangle){ 170, 120, 280, 380 }); // Crop an image piece + ImageFlipHorizontal(&cat); // Flip cropped image horizontally + ImageResize(&cat, 150, 200); // Resize flipped-cropped image + + Image parrots = LoadImage("resources/parrots.png"); // Load image in CPU memory (RAM) + + // Draw one image over the other with a scaling of 1.5f + ImageDraw(&parrots, cat, (Rectangle){ 0, 0, cat.width, cat.height}, (Rectangle){ 30, 40, cat.width*1.5f, cat.height*1.5f }); + ImageCrop(&parrots, (Rectangle){ 0, 50, parrots.width, parrots.height - 100 }); // Crop resulting image + + UnloadImage(cat); // Unload image from RAM + + Texture2D texture = LoadTextureFromImage(parrots); // Image converted to texture, uploaded to GPU memory (VRAM) + UnloadImage(parrots); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM + + SetTargetFPS(60); + //--------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // TODO: Update your variables here + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2 - 40, WHITE); + DrawRectangleLines(screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2 - 40, texture.width, texture.height, DARKGRAY); + + DrawText("We are drawing only one texture from various images composed!", 240, 350, 10, DARKGRAY); + DrawText("Source images have been cropped, scaled, flipped and copied one over the other.", 190, 370, 10, DARKGRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadTexture(texture); // Texture unloading + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/textures_image_drawing.png b/examples/textures_image_drawing.png new file mode 100644 index 00000000..acfee069 Binary files /dev/null and b/examples/textures_image_drawing.png differ diff --git a/examples/textures_image_processing.c b/examples/textures_image_processing.c new file mode 100644 index 00000000..58b746e0 --- /dev/null +++ b/examples/textures_image_processing.c @@ -0,0 +1,154 @@ +/******************************************************************************************* +* +* raylib [textures] example - Image processing +* +* NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM) +* +* This example has been created using raylib 1.4 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2016 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include // Required for: free() + +#define NUM_PROCESSES 8 + +typedef enum { + NONE = 0, + COLOR_GRAYSCALE, + COLOR_TINT, + COLOR_INVERT, + COLOR_CONTRAST, + COLOR_BRIGHTNESS, + FLIP_VERTICAL, + FLIP_HORIZONTAL +} ImageProcess; + +static const char *processText[] = { + "NO PROCESSING", + "COLOR GRAYSCALE", + "COLOR TINT", + "COLOR INVERT", + "COLOR CONTRAST", + "COLOR BRIGHTNESS", + "FLIP VERTICAL", + "FLIP HORIZONTAL" +}; + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [textures] example - image processing"); + + // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) + + Image image = LoadImage("resources/parrots.png"); // Loaded in CPU memory (RAM) + ImageFormat(&image, UNCOMPRESSED_R8G8B8A8); // Format image to RGBA 32bit (required for texture update) + Texture2D texture = LoadTextureFromImage(image); // Image converted to texture, GPU memory (VRAM) + + int currentProcess = NONE; + bool textureReload = false; + + Rectangle selectRecs[NUM_PROCESSES]; + + for (int i = 0; i < NUM_PROCESSES; i++) selectRecs[i] = (Rectangle){ 40, 50 + 32*i, 150, 30 }; + + SetTargetFPS(60); + //--------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + if (IsKeyPressed(KEY_DOWN)) + { + currentProcess++; + if (currentProcess > 7) currentProcess = 0; + textureReload = true; + } + else if (IsKeyPressed(KEY_UP)) + { + currentProcess--; + if (currentProcess < 0) currentProcess = 7; + textureReload = true; + } + + if (textureReload) + { + UnloadImage(image); // Unload current image data + image = LoadImage("resources/parrots.png"); // Re-load image data + + // NOTE: Image processing is a costly CPU process to be done every frame, + // If image processing is required in a frame-basis, it should be done + // with a texture and by shaders + switch (currentProcess) + { + case COLOR_GRAYSCALE: ImageColorGrayscale(&image); break; + case COLOR_TINT: ImageColorTint(&image, GREEN); break; + case COLOR_INVERT: ImageColorInvert(&image); break; + case COLOR_CONTRAST: ImageColorContrast(&image, -40); break; + case COLOR_BRIGHTNESS: ImageColorBrightness(&image, -80); break; + case FLIP_VERTICAL: ImageFlipVertical(&image); break; + case FLIP_HORIZONTAL: ImageFlipHorizontal(&image); break; + default: break; + } + + Color *pixels = GetImageData(image); // Get pixel data from image (RGBA 32bit) + UpdateTexture(texture, pixels); // Update texture with new image data + free(pixels); // Unload pixels data from RAM + + textureReload = false; + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + DrawText("IMAGE PROCESSING:", 40, 30, 10, DARKGRAY); + + // Draw rectangles + for (int i = 0; i < NUM_PROCESSES; i++) + { + if (i == currentProcess) + { + DrawRectangleRec(selectRecs[i], SKYBLUE); + DrawRectangleLines(selectRecs[i].x, selectRecs[i].y, selectRecs[i].width, selectRecs[i].height, BLUE); + DrawText(processText[i], selectRecs[i].x + selectRecs[i].width/2 - MeasureText(processText[i], 10)/2, selectRecs[i].y + 11, 10, DARKBLUE); + } + else + { + DrawRectangleRec(selectRecs[i], LIGHTGRAY); + DrawRectangleLines(selectRecs[i].x, selectRecs[i].y, selectRecs[i].width, selectRecs[i].height, GRAY); + DrawText(processText[i], selectRecs[i].x + selectRecs[i].width/2 - MeasureText(processText[i], 10)/2, selectRecs[i].y + 11, 10, DARKGRAY); + } + } + + DrawTexture(texture, screenWidth - texture.width - 60, screenHeight/2 - texture.height/2, WHITE); + DrawRectangleLines(screenWidth - texture.width - 60, screenHeight/2 - texture.height/2, texture.width, texture.height, BLACK); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadTexture(texture); // Unload texture from VRAM + UnloadImage(image); // Unload image from RAM + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/textures_image_processing.png b/examples/textures_image_processing.png new file mode 100644 index 00000000..c15e19f9 Binary files /dev/null and b/examples/textures_image_processing.png differ -- cgit v1.2.3 From fca83c9ff8a808194cd74821640ed3f17a90010e Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 11 Feb 2016 14:27:18 +0100 Subject: Solve bug on matrix multiply order for scale and rotation --- src/rlgl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rlgl.c b/src/rlgl.c index 421dda02..2ea06e1c 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1464,7 +1464,7 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float ro Matrix matRotation = MatrixRotate(rotationAxis, rotationAngle*DEG2RAD); Matrix matScale = MatrixScale(scale.x, scale.y, scale.z); Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z); - Matrix matTransform = MatrixMultiply(MatrixMultiply(matRotation, matScale), matTranslation); + Matrix matTransform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); // Combine model internal transformation matrix (model.transform) with matrix generated by function parameters (matTransform) Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates -- cgit v1.2.3 From 9cbfcbb8200252d846f447438a33cf47d32ffaf9 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 11 Feb 2016 14:56:00 +0100 Subject: Add a note about an issue --- src/shapes.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shapes.c b/src/shapes.c index 3b4be071..65e3621b 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -412,6 +412,7 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec) } // Get collision rectangle for two rectangles collision +// TODO: Depending on rec1 and rec2 order, it fails -> Review! Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2) { Rectangle retRec = { 0, 0, 0, 0 }; -- cgit v1.2.3 From 15cd4dce4ed19bb80a765eb8eeeca0c6583d7b2a Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 11 Feb 2016 14:56:27 +0100 Subject: Updated examples to make them clearer --- examples/core_3d_camera_first_person.c | 2 +- examples/core_3d_camera_free.c | 8 ++++---- examples/core_3d_mode.c | 6 +++--- examples/core_3d_picking.c | 5 ++++- examples/textures_srcrec_dstrec.c | 4 ++++ 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/examples/core_3d_camera_first_person.c b/examples/core_3d_camera_first_person.c index 8a092275..2b8dc7fc 100644 --- a/examples/core_3d_camera_first_person.c +++ b/examples/core_3d_camera_first_person.c @@ -22,7 +22,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera first person"); - // Define the camera to look into our 3d world + // Define the camera to look into our 3d world (position, target, up vector) Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; // Generates some random columns diff --git a/examples/core_3d_camera_free.c b/examples/core_3d_camera_free.c index df1b480c..4b45373d 100644 --- a/examples/core_3d_camera_free.c +++ b/examples/core_3d_camera_free.c @@ -22,10 +22,10 @@ int main() // Define the camera to look into our 3d world Camera camera; - camera.position = (Vector3){ 0.0f, 10.0f, 10.0f }; - camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; - camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; - + camera.position = (Vector3){ 0.0f, 10.0f, 10.0f }; // Camera position + camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) + Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; SetCameraMode(CAMERA_FREE); // Set a free camera mode diff --git a/examples/core_3d_mode.c b/examples/core_3d_mode.c index 40415fea..7be5dd45 100644 --- a/examples/core_3d_mode.c +++ b/examples/core_3d_mode.c @@ -22,9 +22,9 @@ int main() // Define the camera to look into our 3d world Camera camera; - camera.position = (Vector3){ 0.0f, 10.0f, 10.0f }; - camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; - camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; + camera.position = (Vector3){ 0.0f, 10.0f, 10.0f }; // Camera position + camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; diff --git a/examples/core_3d_picking.c b/examples/core_3d_picking.c index 9a6cc138..fdf77030 100644 --- a/examples/core_3d_picking.c +++ b/examples/core_3d_picking.c @@ -21,7 +21,10 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d picking"); // Define the camera to look into our 3d world - Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; + Camera camera; + camera.position = (Vector3){ 0.0f, 10.0f, 10.0f }; // Camera position + camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) Vector3 cubePosition = { 0.0f, 1.0f, 0.0f }; Vector3 cubeSize = { 2.0f, 2.0f, 2.0f }; diff --git a/examples/textures_srcrec_dstrec.c b/examples/textures_srcrec_dstrec.c index 58917421..6d824ce6 100644 --- a/examples/textures_srcrec_dstrec.c +++ b/examples/textures_srcrec_dstrec.c @@ -55,6 +55,10 @@ int main() ClearBackground(RAYWHITE); // NOTE: Using DrawTexturePro() we can easily rotate and scale the part of the texture we draw + // sourceRec defines the part of the texture we use for drawing + // destRec defines the rectangle where our texture part will fit (scaling it to fit) + // origin defines the point of the texture used as reference for rotation and scaling + // rotation defines the texture rotation (using origin as rotation point) DrawTexturePro(guybrush, sourceRec, destRec, origin, rotation, WHITE); DrawLine(destRec.x, 0, destRec.x, screenHeight, GRAY); -- cgit v1.2.3 From 685273675bc9247e215c213939c017e506296a70 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 11 Feb 2016 15:51:04 +0100 Subject: Improved LoadHeightmap() --- examples/models_heightmap.c | 16 ++++++----- examples/models_heightmap.png | Bin 123602 -> 96976 bytes src/models.c | 60 +++++++++++++++++++----------------------- src/raylib.h | 2 +- 4 files changed, 37 insertions(+), 41 deletions(-) diff --git a/examples/models_heightmap.c b/examples/models_heightmap.c index ac578c61..f1da3301 100644 --- a/examples/models_heightmap.c +++ b/examples/models_heightmap.c @@ -21,13 +21,13 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [models] example - heightmap loading and drawing"); // Define our custom camera to look into our 3d world - Camera camera = {{ 24.0f, 18.0f, 24.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; + Camera camera = {{ 18.0f, 16.0f, 18.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; - Image image = LoadImage("resources/heightmap.png"); // Load heightmap image (RAM) - Texture2D texture = LoadTextureFromImage(image); // Convert image to texture (VRAM) - Model map = LoadHeightmap(image, 32); // Load heightmap model - SetModelTexture(&map, texture); // Bind texture to model - Vector3 mapPosition = { -16.0f, 0.0f, -16.0f }; // Set model position (depends on model scaling!) + Image image = LoadImage("resources/heightmap.png"); // Load heightmap image (RAM) + Texture2D texture = LoadTextureFromImage(image); // Convert image to texture (VRAM) + Model map = LoadHeightmap(image, (Vector3){ 16, 8, 16 }); // Load heightmap model with defined size + SetModelTexture(&map, texture); // Bind texture to model + Vector3 mapPosition = { -8.0f, 0.0f, -8.0f }; // Set model position (depends on model scaling!) UnloadImage(image); // Unload heightmap image from RAM, already uploaded to VRAM @@ -54,7 +54,9 @@ int main() Begin3dMode(camera); // NOTE: Model is scaled to 1/4 of its original size (128x128 units) - DrawModel(map, mapPosition, 1/4.0f, RED); + DrawModel(map, mapPosition, 1.0f, RED); + + DrawGrid(20, 1.0f); End3dMode(); diff --git a/examples/models_heightmap.png b/examples/models_heightmap.png index 9ed04586..6dcf01f0 100644 Binary files a/examples/models_heightmap.png and b/examples/models_heightmap.png differ diff --git a/src/models.c b/src/models.c index 91cb5813..94e61d84 100644 --- a/src/models.c +++ b/src/models.c @@ -55,7 +55,6 @@ extern unsigned int whiteTexture; //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- -static float GetHeightValue(Color pixel); static Mesh LoadOBJ(const char *fileName); //---------------------------------------------------------------------------------- @@ -608,17 +607,19 @@ Model LoadModelEx(Mesh data) } // Load a heightmap image as a 3d model -Model LoadHeightmap(Image heightmap, float maxHeight) +// NOTE: model map size is defined in generic units +Model LoadHeightmap(Image heightmap, Vector3 size) { + #define GRAY_VALUE(c) ((c.r+c.g+c.b)/3) + Mesh mesh; int mapX = heightmap.width; int mapZ = heightmap.height; - Color *heightmapPixels = GetImageData(heightmap); + Color *pixels = GetImageData(heightmap); // NOTE: One vertex per pixel - // TODO: Consider resolution when generating model data? int numTriangles = (mapX-1)*(mapZ-1)*2; // One quad every four pixels mesh.vertexCount = numTriangles*3; @@ -634,7 +635,7 @@ Model LoadHeightmap(Image heightmap, float maxHeight) int trisCounter = 0; - float scaleFactor = maxHeight/255; // TODO: Review scaleFactor calculation + Vector3 scaleFactor = { size.x/mapX, size.y/255.0f, size.z/mapZ }; for(int z = 0; z < mapZ-1; z++) { @@ -644,17 +645,17 @@ Model LoadHeightmap(Image heightmap, float maxHeight) //---------------------------------------------------------- // one triangle - 3 vertex - mesh.vertices[vCounter] = x; - mesh.vertices[vCounter + 1] = GetHeightValue(heightmapPixels[x + z*mapX])*scaleFactor; - mesh.vertices[vCounter + 2] = z; + mesh.vertices[vCounter] = (float)x*scaleFactor.x; + mesh.vertices[vCounter + 1] = (float)GRAY_VALUE(pixels[x + z*mapX])*scaleFactor.y; + mesh.vertices[vCounter + 2] = (float)z*scaleFactor.z; - mesh.vertices[vCounter + 3] = x; - mesh.vertices[vCounter + 4] = GetHeightValue(heightmapPixels[x + (z+1)*mapX])*scaleFactor; - mesh.vertices[vCounter + 5] = z+1; + mesh.vertices[vCounter + 3] = (float)x*scaleFactor.x; + mesh.vertices[vCounter + 4] = (float)GRAY_VALUE(pixels[x + (z + 1)*mapX])*scaleFactor.y; + mesh.vertices[vCounter + 5] = (float)(z + 1)*scaleFactor.z; - mesh.vertices[vCounter + 6] = x+1; - mesh.vertices[vCounter + 7] = GetHeightValue(heightmapPixels[(x+1) + z*mapX])*scaleFactor; - mesh.vertices[vCounter + 8] = z; + mesh.vertices[vCounter + 6] = (float)(x + 1)*scaleFactor.x; + mesh.vertices[vCounter + 7] = (float)GRAY_VALUE(pixels[(x + 1) + z*mapX])*scaleFactor.y; + mesh.vertices[vCounter + 8] = (float)z*scaleFactor.z; // another triangle - 3 vertex mesh.vertices[vCounter + 9] = mesh.vertices[vCounter + 6]; @@ -665,21 +666,21 @@ Model LoadHeightmap(Image heightmap, float maxHeight) mesh.vertices[vCounter + 13] = mesh.vertices[vCounter + 4]; mesh.vertices[vCounter + 14] = mesh.vertices[vCounter + 5]; - mesh.vertices[vCounter + 15] = x+1; - mesh.vertices[vCounter + 16] = GetHeightValue(heightmapPixels[(x+1) + (z+1)*mapX])*scaleFactor; - mesh.vertices[vCounter + 17] = z+1; + mesh.vertices[vCounter + 15] = (float)(x + 1)*scaleFactor.x; + mesh.vertices[vCounter + 16] = (float)GRAY_VALUE(pixels[(x + 1) + (z + 1)*mapX])*scaleFactor.y; + mesh.vertices[vCounter + 17] = (float)(z + 1)*scaleFactor.z; vCounter += 18; // 6 vertex, 18 floats // Fill texcoords array with data //-------------------------------------------------------------- - mesh.texcoords[tcCounter] = (float)x / (mapX-1); - mesh.texcoords[tcCounter + 1] = (float)z / (mapZ-1); + mesh.texcoords[tcCounter] = (float)x/(mapX - 1); + mesh.texcoords[tcCounter + 1] = (float)z/(mapZ - 1); - mesh.texcoords[tcCounter + 2] = (float)x / (mapX-1); - mesh.texcoords[tcCounter + 3] = (float)(z+1) / (mapZ-1); + mesh.texcoords[tcCounter + 2] = (float)x/(mapX - 1); + mesh.texcoords[tcCounter + 3] = (float)(z + 1)/(mapZ - 1); - mesh.texcoords[tcCounter + 4] = (float)(x+1) / (mapX-1); - mesh.texcoords[tcCounter + 5] = (float)z / (mapZ-1); + mesh.texcoords[tcCounter + 4] = (float)(x + 1)/(mapX - 1); + mesh.texcoords[tcCounter + 5] = (float)z/(mapZ - 1); mesh.texcoords[tcCounter + 6] = mesh.texcoords[tcCounter + 4]; mesh.texcoords[tcCounter + 7] = mesh.texcoords[tcCounter + 5]; @@ -687,13 +688,12 @@ Model LoadHeightmap(Image heightmap, float maxHeight) mesh.texcoords[tcCounter + 8] = mesh.texcoords[tcCounter + 2]; mesh.texcoords[tcCounter + 9] = mesh.texcoords[tcCounter + 3]; - mesh.texcoords[tcCounter + 10] = (float)(x+1) / (mapX-1); - mesh.texcoords[tcCounter + 11] = (float)(z+1) / (mapZ-1); + mesh.texcoords[tcCounter + 10] = (float)(x + 1)/(mapX - 1); + mesh.texcoords[tcCounter + 11] = (float)(z + 1)/(mapZ - 1); tcCounter += 12; // 6 texcoords, 12 floats // Fill normals array with data //-------------------------------------------------------------- - // NOTE: Current Model implementation doe not use normals! for (int i = 0; i < 18; i += 3) { mesh.normals[nCounter + i] = 0.0f; @@ -709,7 +709,7 @@ Model LoadHeightmap(Image heightmap, float maxHeight) } } - free(heightmapPixels); + free(pixels); // Fill color data // NOTE: Not used any more... just one plain color defined at DrawModel() @@ -1688,12 +1688,6 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p // Module specific Functions Definition //---------------------------------------------------------------------------------- -// Get current vertex y altitude (proportional to pixel colors in grayscale) -static float GetHeightValue(Color pixel) -{ - return (((float)pixel.r + (float)pixel.g + (float)pixel.b)/3); -} - // Load OBJ mesh data static Mesh LoadOBJ(const char *fileName) { diff --git a/src/raylib.h b/src/raylib.h index a5dd6ad2..f9241533 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -759,7 +759,7 @@ void DrawGizmo(Vector3 position); Model LoadModel(const char *fileName); // Load a 3d model (.OBJ) Model LoadModelEx(Mesh 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 LoadHeightmap(Image heightmap, Vector3 size); // 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 -- cgit v1.2.3 From 823abf666e09e96ccbf5230c96f2d3a61ff60895 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 12 Feb 2016 12:22:56 +0100 Subject: Reviewed code TODOs --- src/audio.c | 2 +- src/camera.c | 2 +- src/core.c | 17 +++++++---------- src/models.c | 1 - src/rlgl.c | 10 +++------- src/text.c | 2 +- src/textures.c | 10 ++++++---- 7 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/audio.c b/src/audio.c index e40fdd41..260f6778 100644 --- a/src/audio.c +++ b/src/audio.c @@ -280,9 +280,9 @@ Sound LoadSoundFromWave(Wave wave) } // Load sound to memory from rRES file (raylib Resource) +// TODO: Maybe rresName could be directly a char array with all the data? Sound LoadSoundFromRES(const char *rresName, int resId) { - // NOTE: rresName could be directly a char array with all the data!!! --> TODO Sound sound = { 0 }; #if defined(AUDIO_STANDALONE) diff --git a/src/camera.c b/src/camera.c index 6539da5f..517e4a2b 100644 --- a/src/camera.c +++ b/src/camera.c @@ -375,7 +375,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) } // Focus to center - // TODO: Move this function out of the module? + // TODO: Move this function out of this module? if (IsKeyDown('Z')) camera->target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera position update diff --git a/src/core.c b/src/core.c index 05ec0c0a..413006e4 100644 --- a/src/core.c +++ b/src/core.c @@ -359,7 +359,7 @@ void InitWindow(int width, int height, struct android_app *state) if (orientation == ACONFIGURATION_ORIENTATION_PORT) TraceLog(INFO, "PORTRAIT window orientation"); else if (orientation == ACONFIGURATION_ORIENTATION_LAND) TraceLog(INFO, "LANDSCAPE window orientation"); - // TODO: Review, it doesn't work... + // TODO: Automatic orientation doesn't seem to work if (width <= height) { AConfiguration_setOrientation(app->config, ACONFIGURATION_ORIENTATION_PORT); @@ -1246,7 +1246,7 @@ int GetTouchY(void) } // Returns touch position XY -// TODO: touch position should be scaled depending on display size and render size +// TODO: Touch position should be scaled depending on display size and render size Vector2 GetTouchPosition(int index) { Vector2 position = { -1.0f, -1.0f }; @@ -1257,7 +1257,7 @@ Vector2 GetTouchPosition(int index) if ((screenWidth > displayWidth) || (screenHeight > displayHeight)) { - // TODO: Seems to work ok but... review! + // TODO: Review touch position scaling for screenSize vs displaySize position.x = position.x*((float)screenWidth/(float)(displayWidth - renderOffsetX)) - renderOffsetX/2; position.y = position.y*((float)screenHeight/(float)(displayHeight - renderOffsetY)) - renderOffsetY/2; } @@ -1668,8 +1668,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i #endif else currentKeyState[key] = action; - // HACK for GuiTextBox, to deteck back key - // TODO: Review... + // TODO: Review (and remove) this HACK for GuiTextBox, to deteck back key if ((key == 259) && (action == GLFW_PRESS)) lastKeyPressed = 3; } @@ -1678,8 +1677,6 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int { currentMouseState[button] = action; - // TODO: Test mouse gestures - #define ENABLE_MOUSE_GESTURES #if defined(ENABLE_MOUSE_GESTURES) // Process mouse events as touches to be able to use mouse-gestures @@ -2046,7 +2043,7 @@ static bool GetKeyStatus(int key) #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) return glfwGetKey(window, key); #elif defined(PLATFORM_ANDROID) - // TODO: Check virtual keyboard (?) + // TODO: Check for virtual keyboard return false; #elif defined(PLATFORM_RPI) // NOTE: Keys states are filled in PollInputEvents() @@ -2061,7 +2058,7 @@ static bool GetMouseButtonStatus(int button) #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) return glfwGetMouseButton(window, button); #elif defined(PLATFORM_ANDROID) - // TODO: Check virtual keyboard (?) + // TODO: Check for virtual keyboard return false; #elif defined(PLATFORM_RPI) // NOTE: mouse buttons array is filled on PollInputEvents() @@ -2382,7 +2379,7 @@ static void RestoreKeyboard(void) // Init gamepad system static void InitGamepad(void) { - // TODO: Gamepad support + // TODO: Add Gamepad support if ((gamepadStream = open(DEFAULT_GAMEPAD_DEV, O_RDONLY|O_NONBLOCK)) < 0) TraceLog(WARNING, "Gamepad device could not be opened, no gamepad available"); else TraceLog(INFO, "Gamepad device initialized successfully"); } diff --git a/src/models.c b/src/models.c index 94e61d84..8a36c279 100644 --- a/src/models.c +++ b/src/models.c @@ -704,7 +704,6 @@ Model LoadHeightmap(Image heightmap, Vector3 size) // TODO: Calculate normals in an efficient way nCounter += 18; // 6 vertex, 18 floats - trisCounter += 2; } } diff --git a/src/rlgl.c b/src/rlgl.c index 2ea06e1c..5f8a5ea1 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -171,7 +171,7 @@ typedef struct { typedef struct { GLuint textureId; int vertexCount; - // TODO: DrawState state -> Blending mode, shader + // TODO: Store draw state -> blending mode, shader } DrawCall; // pixel type (same as Color type) @@ -1475,11 +1475,7 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float ro // Calculate model-view-projection matrix (MVP) Matrix matMVP = MatrixMultiply(matModelView, matProjection); // Transform to screen-space coordinates - // NOTE: Drawing in OpenGL 3.3+, matrices are passed to shader - // TODO: Reduce number of matrices passed to shaders, use only matMVP - //glUniformMatrix4fv(model.material.shader.modelLoc, 1, false, MatrixToFloat(matModel)); - //glUniformMatrix4fv(model.material.shader.viewLoc, 1, false, MatrixToFloat(matView)); - + // Send combined model-view-projection matrix to shader glUniformMatrix4fv(model.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); // Apply color tinting to model @@ -1900,7 +1896,7 @@ void rlglGenerateMipmaps(Texture2D texture) int mipmapCount = GenerateMipmaps(data, texture.width, texture.height); // TODO: Adjust mipmap size depending on texture format! - int size = texture.width*texture.height*4; + int size = texture.width*texture.height*4; // RGBA 32bit only int offset = size; int mipWidth = texture.width/2; diff --git a/src/text.c b/src/text.c index 3755932d..e4c7bbf3 100644 --- a/src/text.c +++ b/src/text.c @@ -346,7 +346,7 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, int f for(int i = 0; i < length; i++) { - // TODO: Right now we are supposing characters follow a continous order and start at FONT_FIRST_CHAR, + // TODO: Right now we are supposing characters that follow a continous order and start at FONT_FIRST_CHAR, // this sytem can be improved to support any characters order and init value... // An intermediate table could be created to link char values with predefined char position index in chars rectangle array diff --git a/src/textures.c b/src/textures.c index f03d2d9a..36819daf 100644 --- a/src/textures.c +++ b/src/textures.c @@ -712,7 +712,7 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp) { oldpixel = pixels[y*image->width + x]; - // TODO: New pixel obtained by bits truncate, it would be better to round values (check ImageFormat()) + // NOTE: New pixel obtained by bits truncate, it would be better to round values (check ImageFormat()) newpixel.r = oldpixel.r>>(8 - rBpp); // R bits newpixel.g = oldpixel.g>>(8 - gBpp); // G bits newpixel.b = oldpixel.b>>(8 - bBpp); // B bits @@ -769,7 +769,7 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp) } // Convert image to POT (power-of-two) -// NOTE: Requirement on OpenGL ES 2.0 (RPI, HTML5) +// NOTE: It could be useful on OpenGL ES 2.0 (RPI, HTML5) void ImageToPOT(Image *image, Color fillColor) { Color *pixels = GetImageData(*image); // Get pixels data @@ -784,7 +784,7 @@ void ImageToPOT(Image *image, Color fillColor) Color *pixelsPOT = NULL; // Generate POT array from NPOT data - pixelsPOT = (Color *)malloc(potWidth * potHeight * sizeof(Color)); + pixelsPOT = (Color *)malloc(potWidth*potHeight*sizeof(Color)); for (int j = 0; j < potHeight; j++) { @@ -896,7 +896,9 @@ void ImageCrop(Image *image, Rectangle crop) } // Resize and image to new size -// NOTE: Uses stb default scaling filter +// NOTE: Uses stb default scaling filters (both bicubic): +// STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM +// STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL (high-quality Catmull-Rom) void ImageResize(Image *image, int newWidth, int newHeight) { // Get data as Color pixels array to work with it -- cgit v1.2.3 From cbbe9485294032d680579809976f7035785d3694 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 12 Feb 2016 19:02:23 +0100 Subject: Some code tweaks --- examples/shaders_basic_lighting.c | 12 ++++++------ src/core.c | 5 ++++- src/raylib.h | 14 ++++++++------ 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/examples/shaders_basic_lighting.c b/examples/shaders_basic_lighting.c index 649eab74..84bd1af4 100644 --- a/examples/shaders_basic_lighting.c +++ b/examples/shaders_basic_lighting.c @@ -77,9 +77,9 @@ int main() light.specIntensity = 1.0f; // Material initialization - matBlinn.diffuse = WHITE; - matBlinn.ambient = (Color){ 50, 50, 50, 255 }; - matBlinn.specular = WHITE; + matBlinn.colDiffuse = WHITE; + matBlinn.colAmbient = (Color){ 50, 50, 50, 255 }; + matBlinn.colSpecular = WHITE; matBlinn.glossiness = 50.0f; // Setup camera @@ -129,8 +129,8 @@ int main() SetShaderValue(shader, lSpecIntensityLoc, &light.specIntensity, 1); // Send material values to shader - SetShaderValue(shader, mAmbientLoc, ColorToFloat(matBlinn.ambient), 3); - SetShaderValue(shader, mSpecularLoc, ColorToFloat(matBlinn.specular), 3); + SetShaderValue(shader, mAmbientLoc, ColorToFloat(matBlinn.colAmbient), 3); + SetShaderValue(shader, mSpecularLoc, ColorToFloat(matBlinn.colSpecular), 3); SetShaderValue(shader, mGlossLoc, &matBlinn.glossiness, 1); // Send camera and light transform values to shader @@ -146,7 +146,7 @@ int main() Begin3dMode(camera); - DrawModel(model, position, 4.0f, matBlinn.diffuse); + DrawModel(model, position, 4.0f, matBlinn.colDiffuse); DrawSphere(light.position, 0.5f, GOLD); DrawGrid(20, 1.0f); diff --git a/src/core.c b/src/core.c index 413006e4..cff90ba9 100644 --- a/src/core.c +++ b/src/core.c @@ -118,7 +118,6 @@ // Defines and Macros //---------------------------------------------------------------------------------- #define STORAGE_FILENAME "storage.data" -#define MAX_TOUCH_POINTS 2 //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -324,6 +323,10 @@ void InitWindow(int width, int height, const char *title) emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenInputCallback); emscripten_set_touchmove_callback("#canvas", NULL, 1, EmscriptenInputCallback); emscripten_set_touchcancel_callback("#canvas", NULL, 1, EmscriptenInputCallback); + + // TODO: Add gamepad support (not provided by GLFW3 on emscripten) + //emscripten_set_gamepadconnected_callback(NULL, 1, EmscriptenInputCallback); + //emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenInputCallback); #endif mousePosition.x = (float)screenWidth/2.0f; diff --git a/src/raylib.h b/src/raylib.h index f9241533..c2067a0e 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -166,6 +166,9 @@ #define MOUSE_MIDDLE_BUTTON 2 #endif +// Touch points registered +#define MAX_TOUCH_POINTS 2 + // Gamepad Number #define GAMEPAD_PLAYER1 0 #define GAMEPAD_PLAYER2 1 @@ -348,9 +351,6 @@ typedef struct Shader { // Uniforms int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) - - int modelLoc; // Model transformation matrix uniform location point (vertex shader) - int viewLoc; // View transformation matrix uniform location point (vertex shader) int tintColorLoc; // Color uniform location point (fragment shader) int mapDiffuseLoc; // Diffuse map texture uniform location point (fragment shader) @@ -448,15 +448,16 @@ typedef enum { GESTURE_PINCH_OUT = 512 } Gestures; +// Touch action (fingers or mouse) typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction; // Gesture events -// NOTE: MAX_TOUCH_POINTS fixed to 4 +// NOTE: MAX_TOUCH_POINTS fixed to 2 typedef struct { int touchAction; int pointCount; - int pointerId[4]; - Vector2 position[4]; + int pointerId[MAX_TOUCH_POINTS]; + Vector2 position[MAX_TOUCH_POINTS]; } GestureEvent; // Camera system modes @@ -798,6 +799,7 @@ bool IsPosproShaderEnabled(void); // Check if int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float) void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int) +void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4) void SetShaderMapDiffuse(Shader *shader, Texture2D texture); // Default diffuse shader map texture assignment void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture); // Normal map texture shader assignment void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture); // Specular map texture shader assignment -- cgit v1.2.3 From 9c9aeaef47fe612dbc0f446920fca9cb54781aef Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 13 Feb 2016 12:21:29 +0100 Subject: Added web template (shell) for html5 games --- templates/web_shell/shell.html | 239 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 templates/web_shell/shell.html diff --git a/templates/web_shell/shell.html b/templates/web_shell/shell.html new file mode 100644 index 00000000..c154ee7e --- /dev/null +++ b/templates/web_shell/shell.html @@ -0,0 +1,239 @@ + + + + + + + raylib HTML5 GAME + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
Downloading...
+ + + + + +
+ +
+
+ +
+ +
+ + + + + {{{ SCRIPT }}} + + \ No newline at end of file -- cgit v1.2.3 From 94c92a58a1a8131c4d71ba32f18e836f6178231c Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 13 Feb 2016 17:08:09 +0100 Subject: Some tweaks --- src/gestures.c | 4 ++-- src/raygui.c | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/gestures.c b/src/gestures.c index a2744460..16442e45 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -2,9 +2,9 @@ * * raylib Gestures System - Gestures Processing based on input gesture events (touch/mouse) * -* Reviewed by Ramon Santamaria -* Redesigned by Albert Martos and Ian Eito * Initial design by Marc Palau +* Redesigned by Albert Martos and Ian Eito +* Reviewed by Ramon Santamaria (@raysan5) * * 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. diff --git a/src/raygui.c b/src/raygui.c index 2c68c96f..60df2121 100644 --- a/src/raygui.c +++ b/src/raygui.c @@ -2,7 +2,8 @@ * * raygui - raylib IMGUI system (Immedite Mode GUI) * -* Copyright (c) 2015 Kevin Gato, Daniel Nicolás, Sergio Martinez and Ramon Santamaria +* Initial design by Kevin Gato and Daniel Nicolás +* Reviewed by Albert Martos, Ian Eito, Sergio Martinez and Ramon Santamaria (@raysan5) * * 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. @@ -856,10 +857,6 @@ char *GuiTextBox(Rectangle bounds, char *text) return text; } -// TODO: GuiBox? -// TODO: GuiWindow? -// TODO: GuiPanel? - // Save current GUI style into a text file void SaveGuiStyle(const char *fileName) { @@ -873,12 +870,14 @@ void SaveGuiStyle(const char *fileName) // Load GUI style from a text file void LoadGuiStyle(const char *fileName) { + #define MAX_STYLE_PROPERTIES 128 + typedef struct { char id[64]; int value; } StyleProperty; - StyleProperty *styleProp = (StyleProperty *)malloc(128*sizeof(StyleProperty));; + StyleProperty *styleProp = (StyleProperty *)malloc(MAX_STYLE_PROPERTIES*sizeof(StyleProperty));; int counter = 0; FILE *styleFile = fopen(fileName, "rt"); -- cgit v1.2.3 From ed1906440560d5b6b6e2cb1c1927e53b28e302db Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 13 Feb 2016 17:09:53 +0100 Subject: Reviewed physics module A deeper revision required, not clear enough for the user Key: Create a PhysicObjects pool --- examples/physics_basic_rigidbody.c | 44 +++++++-------------------- examples/physics_rigidbody_force.c | 33 ++++++++------------- src/physac.c | 61 ++++++++++++++++++++++---------------- src/physac.h | 11 ++----- src/raylib.h | 13 ++------ 5 files changed, 64 insertions(+), 98 deletions(-) diff --git a/examples/physics_basic_rigidbody.c b/examples/physics_basic_rigidbody.c index b82fe638..6c354eb7 100644 --- a/examples/physics_basic_rigidbody.c +++ b/examples/physics_basic_rigidbody.c @@ -2,20 +2,10 @@ * * raylib [physac] physics example - Basic rigidbody * -* Welcome to raylib! -* -* To test examples, just press F6 and execute raylib_compile_execute script -* Note that compiled executable is placed in the same folder as .c file -* -* You can find all basic examples on C:\raylib\raylib\examples folder or -* raylib official webpage: www.raylib.com -* -* Enjoy using raylib. :) -* -* This example has been created using raylib 1.3 (www.raylib.com) +* This example has been created using raylib 1.4 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* Copyright (c) 2016 Victor Fisac and Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -33,13 +23,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [physics] example - basic rigidbody"); - InitPhysics(); // Initialize internal physics values (max rigidbodies/colliders available: 1024) - - // Physics initialization - Physics worldPhysics = { true, false, (Vector2){ 0, -9.81f } }; - - // Set internal physics settings - SetPhysics(worldPhysics); + InitPhysics(3); // Initialize physics system with maximum physic objects // Object initialization Transform player = (Transform){(Vector2){(screenWidth - OBJECT_SIZE) / 2, (screenHeight - OBJECT_SIZE) / 2}, 0.0f, (Vector2){OBJECT_SIZE, OBJECT_SIZE}}; @@ -55,6 +39,8 @@ int main() float moveSpeed = 6.0f; float jumpForce = 5.0f; + bool physicsDebug = false; + SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -91,14 +77,7 @@ int main() } // Check debug mode toggle button input - if(IsKeyPressed(KEY_P)) - { - // Update program physics value - worldPhysics.debug = !worldPhysics.debug; - - // Update internal physics value - SetPhysics(worldPhysics); - } + if (IsKeyPressed(KEY_P)) physicsDebug = !physicsDebug; //---------------------------------------------------------------------------------- // Draw @@ -112,7 +91,7 @@ int main() DrawText("Use P to switch DEBUG MODE", (screenWidth - MeasureText("Use P to switch DEBUG MODE", 20)) / 2, screenHeight * 0.3f, 20, LIGHTGRAY); // Check if debug mode is enabled - if (worldPhysics.debug) + if (physicsDebug) { // Draw every internal physics stored collider if it is active for (int i = 0; i < 2; i++) @@ -122,14 +101,11 @@ int main() DrawRectangleLines(GetCollider(i).bounds.x, GetCollider(i).bounds.y, GetCollider(i).bounds.width, GetCollider(i).bounds.height, GREEN); } } - } else { - // Draw player + // Draw player and floor DrawRectangleRec((Rectangle){player.position.x, player.position.y, player.scale.x, player.scale.y}, GRAY); - - // Draw floor DrawRectangleRec((Rectangle){floor.position.x, floor.position.y, floor.scale.x, floor.scale.y}, BLACK); } @@ -138,7 +114,9 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- + UnloadPhysics(); // Unload physic objects + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/physics_rigidbody_force.c b/examples/physics_rigidbody_force.c index 3ac560c5..74a88a97 100644 --- a/examples/physics_rigidbody_force.c +++ b/examples/physics_rigidbody_force.c @@ -2,10 +2,10 @@ * * raylib [physac] physics example - Rigidbody forces * -* This example has been created using raylib 1.3 (www.raylib.com) +* This example has been created using raylib 1.4 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2014 Ramon Santamaria (@raysan5) +* Copyright (c) 2016 Victor Fisac and Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -26,15 +26,9 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [physics] example - rigidbodies forces"); - InitPhysics(); // Initialize internal physics values (max rigidbodies/colliders available: 1024) + InitPhysics(MAX_OBJECTS + 1); // Initialize physics system with maximum physic objects - // Physics initialization - Physics worldPhysics = {true, false, (Vector2){0, -9.81f}}; - - // Set internal physics settings - SetPhysics(worldPhysics); - - // Objects initialization + // Physic Objects initialization Transform objects[MAX_OBJECTS]; for (int i = 0; i < MAX_OBJECTS; i++) @@ -49,6 +43,8 @@ int main() Transform floor = (Transform){(Vector2){0, screenHeight * 0.8f}, 0.0f, (Vector2){screenWidth, screenHeight * 0.2f}}; AddCollider(MAX_OBJECTS, (Collider){true, COLLIDER_RECTANGLE, (Rectangle){floor.position.x, floor.position.y, floor.scale.x, floor.scale.y}, 0}); + bool physicsDebug = false; + SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -72,14 +68,7 @@ int main() } // Check debug mode toggle button input - if (IsKeyPressed(KEY_P)) - { - // Update program physics value - worldPhysics.debug = !worldPhysics.debug; - - // Update internal physics value - SetPhysics(worldPhysics); - } + if (IsKeyPressed(KEY_P)) physicsDebug = !physicsDebug; //---------------------------------------------------------------------------------- // Draw @@ -89,10 +78,10 @@ int main() ClearBackground(RAYWHITE); // Check if debug mode is enabled - if (worldPhysics.debug) + if (physicsDebug) { // Draw every internal physics stored collider if it is active (floor included) - for (int i = 0; i < MAX_OBJECTS + 1; i++) + for (int i = 0; i < MAX_OBJECTS; i++) { if (GetCollider(i).enabled) { @@ -136,7 +125,9 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- + UnloadPhysics(); // Unload physic objects + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/src/physac.c b/src/physac.c index 891f0123..4c50dd41 100644 --- a/src/physac.c +++ b/src/physac.c @@ -30,13 +30,12 @@ #endif #include -#include +#include // Required for: malloc(), free() //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define MAX_ELEMENTS 1024 // Stored rigidbodies and colliders array length -#define DECIMAL_FIX 0.26f // Decimal margin for collision checks (avoid rigidbodies shake) +#define DECIMAL_FIX 0.26f // Decimal margin for collision checks (avoid rigidbodies shake) //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -46,10 +45,13 @@ //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -static Physics physics; -static Collider colliders[MAX_ELEMENTS]; -static Rigidbody rigidbodies[MAX_ELEMENTS]; -static bool collisionChecker = false; +static Collider *colliders; // Colliders array, dynamically allocated at runtime +static Rigidbody *rigidbodies; // Rigitbody array, dynamically allocated at runtime +static bool collisionChecker; + +static int maxElements; // Max physic elements to compute +static bool enabled; // Physics enabled? (true by default) +static Vector2 gravity; // Gravity value used for physic calculations //---------------------------------------------------------------------------------- // Module specific Functions Declarations @@ -61,30 +63,39 @@ static void Vector2Normalize(Vector2 *vector); //---------------------------------------------------------------------------------- // Module Functions Definitions //---------------------------------------------------------------------------------- -void InitPhysics(void) -{ - for (int i = 0; i < MAX_ELEMENTS; i++) +void InitPhysics(int maxPhysicElements) +{ + maxElements = maxPhysicElements; + + colliders = (Collider *)malloc(maxElements*sizeof(Collider)); + rigidbodies = (Rigidbody *)malloc(maxElements*sizeof(Rigidbody)); + + for (int i = 0; i < maxElements; i++) { + colliders[i].enabled = false; + colliders[i].bounds = (Rectangle){ 0, 0, 0, 0 }; + colliders[i].radius = 0; + rigidbodies[i].enabled = false; rigidbodies[i].mass = 0.0f; - rigidbodies[i].velocity = (Vector2){0, 0}; - rigidbodies[i].acceleration = (Vector2){0, 0}; + rigidbodies[i].velocity = (Vector2){ 0.0f, 0.0f }; + rigidbodies[i].acceleration = (Vector2){ 0.0f, 0.0f }; rigidbodies[i].isGrounded = false; rigidbodies[i].isContact = false; rigidbodies[i].friction = 0.0f; - - colliders[i].enabled = false; - colliders[i].bounds = (Rectangle){0, 0, 0, 0}; - colliders[i].radius = 0; } + + collisionChecker = false; + enabled = true; + + // NOTE: To get better results, gravity needs to be 1:10 from original parameter + gravity = (Vector2){ 0.0f, -9.81f/10.0f }; // By default, standard gravity } -void SetPhysics(Physics settings) +void UnloadPhysics() { - physics = settings; - - // To get good results, gravity needs to be 1:10 from original parameter - physics.gravity = (Vector2){physics.gravity.x / 10, physics.gravity.y / 10}; + free(colliders); + free(rigidbodies); } void AddCollider(int index, Collider collider) @@ -159,8 +170,8 @@ void ApplyPhysics(int index, Vector2 *position) } // Apply gravity - rigidbodies[index].velocity.y += physics.gravity.y; - rigidbodies[index].velocity.x += physics.gravity.x; + rigidbodies[index].velocity.y += gravity.y; + rigidbodies[index].velocity.x += gravity.x; // Apply acceleration rigidbodies[index].velocity.y += rigidbodies[index].acceleration.y; @@ -177,7 +188,7 @@ void ApplyPhysics(int index, Vector2 *position) // Check collision with other colliders collisionChecker = false; rigidbodies[index].isContact = false; - for (int j = 0; j < MAX_ELEMENTS; j++) + for (int j = 0; j < maxElements; j++) { if (index != j) { @@ -269,7 +280,7 @@ void AddRigidbodyForce(int index, Vector2 force) void AddForceAtPosition(Vector2 position, float intensity, float radius) { - for(int i = 0; i < MAX_ELEMENTS; i++) + for(int i = 0; i < maxElements; i++) { if(rigidbodies[i].enabled) { diff --git a/src/physac.h b/src/physac.h index 12209987..9e1b0b88 100644 --- a/src/physac.h +++ b/src/physac.h @@ -35,13 +35,6 @@ // Collider types typedef enum { COLLIDER_CIRCLE, COLLIDER_RECTANGLE, COLLIDER_CAPSULE } ColliderType; -// Physics struct -typedef struct Physics { - bool enabled; - bool debug; // Should be used by programmer for testing purposes - Vector2 gravity; -} Physics; - // Transform struct typedef struct Transform { Vector2 position; @@ -77,8 +70,8 @@ extern "C" { // Prevents name mangling of functions //---------------------------------------------------------------------------------- // Module Functions Declarations //---------------------------------------------------------------------------------- -void InitPhysics(void); // Initialize all internal physics values -void SetPhysics(Physics settings); // Set physics settings values using Physics data type to overwrite internal physics settings +void InitPhysics(int maxPhysicElements); // Initialize all internal physics values +void UnloadPhysics(); // Unload physic elements arrays void AddRigidbody(int index, Rigidbody rigidbody); // Initialize a new rigidbody with parameters to internal index slot void AddCollider(int index, Collider collider); // Initialize a new Collider with parameters to internal index slot diff --git a/src/raylib.h b/src/raylib.h index c2067a0e..43819b14 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -466,13 +466,6 @@ typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERS // Collider types typedef enum { COLLIDER_CIRCLE, COLLIDER_RECTANGLE, COLLIDER_CAPSULE } ColliderType; -// Physics struct -typedef struct Physics { - bool enabled; - bool debug; // Should be used by programmer for testing purposes - Vector2 gravity; -} Physics; - // Transform struct typedef struct Transform { Vector2 position; @@ -808,10 +801,10 @@ void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textur void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied) //---------------------------------------------------------------------------------- -// Physics System Functions (engine-module: physics) +// Physics System Functions (engine-module: physac) //---------------------------------------------------------------------------------- -void InitPhysics(void); // Initialize all internal physics values -void SetPhysics(Physics settings); // Set physics settings values using Physics data type to overwrite internal physics settings +void InitPhysics(int maxPhysicElements); // Initialize all internal physics values +void UnloadPhysics(); // Unload physic elements arrays void AddRigidbody(int index, Rigidbody rigidbody); // Initialize a new rigidbody with parameters to internal index slot void AddCollider(int index, Collider collider); // Initialize a new Collider with parameters to internal index slot -- cgit v1.2.3 From 30fafb77db920f165253cbd0c3a9e688fa5b93f3 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 13 Feb 2016 17:39:38 +0100 Subject: Updated fullscreen issue comment --- src/core.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/core.c b/src/core.c index cff90ba9..7ecedee0 100644 --- a/src/core.c +++ b/src/core.c @@ -470,6 +470,7 @@ bool IsWindowMinimized(void) } // Fullscreen toggle +// TODO: When destroying window context is lost and resources too, take care! void ToggleFullscreen(void) { #if defined(PLATFORM_DESKTOP) @@ -1379,10 +1380,24 @@ static void InitDisplay(int width, int height) if (fullscreen) { // At this point we need to manage render size vs screen size - // NOTE: This function uses and modifies global module variables: screenWidth/screenHeight and renderWidth/renderHeight and downscaleView + // NOTE: This function uses and modifies global module variables: + // screenWidth/screenHeight - renderWidth/renderHeight - downscaleView SetupFramebufferSize(displayWidth, displayHeight); + + // TODO: SetupFramebufferSize() does not consider properly display video modes. + // It setups a renderWidth/renderHeight with black bars that could not match a valid video mode, + // and so, framebuffer is not scaled properly to some monitors. + + int count; + const GLFWvidmode *modes = glfwGetVideoModes(glfwGetPrimaryMonitor(), &count); + + for (int i = 0; i < count; i++) + { + // TODO: Check modes[i]->width; + // TODO: Check modes[i]->height; + } - window = glfwCreateWindow(renderWidth, renderHeight, windowTitle, glfwGetPrimaryMonitor(), NULL); + window = glfwCreateWindow(screenWidth, screenHeight, windowTitle, glfwGetPrimaryMonitor(), NULL); } else { @@ -1391,10 +1406,8 @@ static void InitDisplay(int width, int height) #if defined(PLATFORM_DESKTOP) // Center window on screen - const GLFWvidmode *mode = glfwGetVideoMode(glfwGetPrimaryMonitor()); - - int windowPosX = mode->width/2 - screenWidth/2; - int windowPosY = mode->height/2 - screenHeight/2; + int windowPosX = displayWidth/2 - screenWidth/2; + int windowPosY = displayHeight/2 - screenHeight/2; if (windowPosX < 0) windowPosX = 0; if (windowPosY < 0) windowPosY = 0; @@ -2402,6 +2415,10 @@ static void SwapBuffers(void) // NOTE: Global variables renderWidth/renderHeight can be modified static void SetupFramebufferSize(int displayWidth, int displayHeight) { + // TODO: SetupFramebufferSize() does not consider properly display video modes. + // It setups a renderWidth/renderHeight with black bars that could not match a valid video mode, + // and so, framebuffer is not scaled properly to some monitors. + // Calculate renderWidth and renderHeight, we have the display size (input params) and the desired screen size (global var) if ((screenWidth > displayWidth) || (screenHeight > displayHeight)) { -- cgit v1.2.3 From 0018522031b8b06c447d49273bf288ec5e7a8a63 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 13 Feb 2016 19:14:22 +0100 Subject: Updated show-logo and start reviewing RPI inputs --- examples/shapes_logo_raylib_anim.c | 30 ++++++------------------------ src/core.c | 32 ++++++++++---------------------- src/raylib.h | 2 +- 3 files changed, 17 insertions(+), 47 deletions(-) diff --git a/examples/shapes_logo_raylib_anim.c b/examples/shapes_logo_raylib_anim.c index b1bdc3a8..c6d3796e 100644 --- a/examples/shapes_logo_raylib_anim.c +++ b/examples/shapes_logo_raylib_anim.c @@ -2,7 +2,7 @@ * * raylib [shapes] example - raylib logo animation * -* This example has been created using raylib 1.1 (www.raylib.com) +* This example has been created using raylib 1.4 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2014 Ramon Santamaria (@raysan5) @@ -32,8 +32,6 @@ int main() int bottomSideRecWidth = 16; int rightSideRecHeight = 16; - char raylib[8] = " \0"; // raylib text array, max 8 letters - int state = 0; // Tracking animation states (State Machine) float alpha = 1.0f; // Useful for fading @@ -79,24 +77,13 @@ int main() framesCounter = 0; } - switch (lettersCount) - { - 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 (lettersCount >= 10) // When all letters have appeared, just fade out everything { - alpha -= 0.02; + alpha -= 0.02f; - if (alpha <= 0) + if (alpha <= 0.0f) { - alpha = 0; + alpha = 0.0f; state = 4; } } @@ -114,12 +101,7 @@ int main() bottomSideRecWidth = 16; rightSideRecHeight = 16; - for (int i = 0; i < 7; i++) raylib[i] = ' '; - - raylib[7] = '\0'; // Last character is end-of-line - - alpha = 1.0; - + alpha = 1.0f; state = 0; // Return to State 0 } } @@ -158,7 +140,7 @@ int main() DrawRectangle(screenWidth/2 - 112, screenHeight/2 - 112, 224, 224, Fade(RAYWHITE, alpha)); - DrawText(raylib, screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha)); + DrawText(SubText("raylib", 0, lettersCount), screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha)); } else if (state == 4) { diff --git a/src/core.c b/src/core.c index 7ecedee0..0c85ab26 100644 --- a/src/core.c +++ b/src/core.c @@ -151,7 +151,7 @@ pthread_t mouseThreadId; // Mouse reading thread id static int defaultKeyboardMode; // Used to store default keyboard mode static struct termios defaultKeyboardSettings; // Used to staore default keyboard settings -static int keyboardMode = 0; // Keyboard mode: 1 (KEYCODES), 2 (ASCII) +static int keyboardMode = 0; // Keyboard mode: 1 - KEYCODES, 2 - ASCII // This array maps Unix keycodes to ASCII equivalent and to GLFW3 equivalent for special function keys (>256) const short UnixKeycodeToASCII[128] = { 256, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 45, 61, 259, 9, 81, 87, 69, 82, 84, 89, 85, 73, 79, 80, 91, 93, 257, 341, 65, 83, 68, @@ -1128,7 +1128,7 @@ bool IsCursorHidden() { return cursorHidden; } -#endif +#endif //defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) // TODO: Enable gamepad usage on Rapsberry Pi // NOTE: emscripten not implemented @@ -2077,7 +2077,7 @@ static bool GetMouseButtonStatus(int button) // TODO: Check for virtual keyboard return false; #elif defined(PLATFORM_RPI) - // NOTE: mouse buttons array is filled on PollInputEvents() + // NOTE: Mouse buttons states are filled in PollInputEvents() return currentMouseState[button]; #endif } @@ -2099,8 +2099,7 @@ static void PollInputEvents(void) mousePosition.x = (float)mouseX; mousePosition.y = (float)mouseY; - // Keyboard polling - // Automatically managed by GLFW3 through callback + // Keyboard input polling (automatically managed by GLFW3 through callback) lastKeyPressed = -1; // Register previous keys states @@ -2157,7 +2156,7 @@ static void PollInputEvents(void) int key = keysBuffer[i]; - if (keyboardMode == 2) // scancodes + if (keyboardMode == 2) // ASCII chars (K_XLATE mode) { // NOTE: If (key == 0x1b), depending on next key, it could be a special keymap code! // Up -> 1b 5b 41 / Left -> 1b 5b 44 / Right -> 1b 5b 43 / Down -> 1b 5b 42 @@ -2215,8 +2214,7 @@ static void PollInputEvents(void) if (key == 0x01) windowShouldClose = true; } - - // Same fucnionality as GLFW3 KeyCallback() + // Same functionality as GLFW3 KeyCallback() /* if (asciiKey == exitKey) windowShouldClose = true; else if (key == GLFW_KEY_F12 && action == GLFW_PRESS) @@ -2356,7 +2354,7 @@ static void InitKeyboard(void) // Set new keyboard settings (change occurs immediately) tcsetattr(STDIN_FILENO, TCSANOW, &keyboardNewSettings); - // NOTE: Reading directly from stdin will give chars already key-mapped by kernel to ASCII or UNICODE, we change that! + // NOTE: Reading directly from stdin will give chars already key-mapped by kernel to ASCII or UNICODE, we change that! -> WHY??? // Save old keyboard mode to restore it at the end if (ioctl(STDIN_FILENO, KDGKBMODE, &defaultKeyboardMode) < 0) @@ -2374,6 +2372,8 @@ static void InitKeyboard(void) // - ASCII chars (K_XLATE) // - UNICODE chars (K_UNICODE) ioctl(STDIN_FILENO, KDSKBMODE, K_MEDIUMRAW); + + //http://lct.sourceforge.net/lct/x60.html keyboardMode = 1; // keycodes } @@ -2587,7 +2587,6 @@ static void LogoAnimation(void) int bottomSideRecWidth = 16; int rightSideRecHeight = 16; - char raylib[8] = " "; // raylib text array, max 8 letters int state = 0; // Tracking animation states (State Machine) float alpha = 1.0f; // Useful for fading @@ -2629,17 +2628,6 @@ static void LogoAnimation(void) framesCounter = 0; } - switch (lettersCount) - { - 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 (lettersCount >= 10) // When all letters have appeared, just fade out everything { alpha -= 0.02f; @@ -2686,7 +2674,7 @@ static void LogoAnimation(void) DrawRectangle(screenWidth/2 - 112, screenHeight/2 - 112, 224, 224, Fade(RAYWHITE, alpha)); - DrawText(raylib, screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha)); + DrawText(SubText("raylib", 0, lettersCount), screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha)); } EndDrawing(); diff --git a/src/raylib.h b/src/raylib.h index 43819b14..f5a3cc31 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -118,7 +118,7 @@ #define KEY_RIGHT_CONTROL 345 #define KEY_RIGHT_ALT 346 -// Keyboard Alhpa Numeric Keys +// Keyboard Alpha Numeric Keys #define KEY_ZERO 48 #define KEY_ONE 49 #define KEY_TWO 50 -- cgit v1.2.3 From b99b21fa382ba05b404dd18b157aa8a09266b0d8 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 14 Feb 2016 01:14:49 +0100 Subject: Added raylib promotional T-shirt design --- logo/tshirt/raylib_tshirt_back.svg | 36 +++++++++++++++++++++++++++++++++++ logo/tshirt/raylib_tshirt_female.png | Bin 0 -> 125301 bytes logo/tshirt/raylib_tshirt_front.svg | 14 ++++++++++++++ logo/tshirt/raylib_tshirt_male.png | Bin 0 -> 118419 bytes 4 files changed, 50 insertions(+) create mode 100644 logo/tshirt/raylib_tshirt_back.svg create mode 100644 logo/tshirt/raylib_tshirt_female.png create mode 100644 logo/tshirt/raylib_tshirt_front.svg create mode 100644 logo/tshirt/raylib_tshirt_male.png diff --git a/logo/tshirt/raylib_tshirt_back.svg b/logo/tshirt/raylib_tshirt_back.svg new file mode 100644 index 00000000..05c587ec --- /dev/null +++ b/logo/tshirt/raylib_tshirt_back.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/logo/tshirt/raylib_tshirt_female.png b/logo/tshirt/raylib_tshirt_female.png new file mode 100644 index 00000000..4dcf0b7a Binary files /dev/null and b/logo/tshirt/raylib_tshirt_female.png differ diff --git a/logo/tshirt/raylib_tshirt_front.svg b/logo/tshirt/raylib_tshirt_front.svg new file mode 100644 index 00000000..7d1414f8 --- /dev/null +++ b/logo/tshirt/raylib_tshirt_front.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/logo/tshirt/raylib_tshirt_male.png b/logo/tshirt/raylib_tshirt_male.png new file mode 100644 index 00000000..2de06ed7 Binary files /dev/null and b/logo/tshirt/raylib_tshirt_male.png differ -- cgit v1.2.3 From 825e42dc008793c16da9f267bf1c8d020d2d9ece Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 14 Feb 2016 12:25:32 +0100 Subject: Updated logo size on t-shirt --- logo/tshirt/raylib_tshirt_female.png | Bin 125301 -> 125347 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/logo/tshirt/raylib_tshirt_female.png b/logo/tshirt/raylib_tshirt_female.png index 4dcf0b7a..e693a262 100644 Binary files a/logo/tshirt/raylib_tshirt_female.png and b/logo/tshirt/raylib_tshirt_female.png differ -- cgit v1.2.3 From afd2ffb74a84bf48b9129c613e1673ceae0bd46b Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 17 Feb 2016 13:00:48 +0100 Subject: Updated gestures module Using normalized [0..1] input points --- src/core.c | 28 +++++++++++- src/gestures.c | 134 ++++++++++++++++++++++++++++++--------------------------- src/gestures.h | 12 +++--- src/raylib.h | 11 +++-- 4 files changed, 109 insertions(+), 76 deletions(-) diff --git a/src/core.c b/src/core.c index 0c85ab26..7b981097 100644 --- a/src/core.c +++ b/src/core.c @@ -1700,14 +1700,22 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int // Register touch actions if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_DOWN; - //else if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_MOVE; else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_UP; + // NOTE: TOUCH_MOVE event is registered in MouseCursorPosCallback() + + // Assign a pointer ID + gestureEvent.pointerId[0] = 0; + // Register touch points count gestureEvent.pointCount = 1; // Register touch points position, only one point registered gestureEvent.position[0] = GetMousePosition(); + + // Normalize gestureEvent.position[0] for screenWidth and screenHeight + gestureEvent.position[0].x /= (float)GetScreenWidth(); + gestureEvent.position[0].y /= (float)GetScreenHeight(); // Gesture data is sent to gestures system for processing ProcessGestureEvent(gestureEvent); @@ -1729,6 +1737,10 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y) // Register touch points position, only one point registered gestureEvent.position[0] = (Vector2){ (float)x, (float)y }; + + // Normalize gestureEvent.position[0] for screenWidth and screenHeight + gestureEvent.position[0].x /= (float)GetScreenWidth(); + gestureEvent.position[0].y /= (float)GetScreenHeight(); // Gesture data is sent to gestures system for processing ProcessGestureEvent(gestureEvent); @@ -1992,6 +2004,13 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) gestureEvent.position[0] = (Vector2){ AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0) }; gestureEvent.position[1] = (Vector2){ AMotionEvent_getX(event, 1), AMotionEvent_getY(event, 1) }; + // Normalize gestureEvent.position[x] for screenWidth and screenHeight + gestureEvent.position[0].x /= (float)GetScreenWidth(); + gestureEvent.position[0].y /= (float)GetScreenHeight(); + + gestureEvent.position[1].x /= (float)GetScreenWidth(); + gestureEvent.position[1].y /= (float)GetScreenHeight(); + // Gesture data is sent to gestures system for processing ProcessGestureEvent(gestureEvent); @@ -2564,6 +2583,13 @@ static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent touchPosition[0] = gestureEvent.position[0]; touchPosition[1] = gestureEvent.position[1]; + // Normalize gestureEvent.position[x] for screenWidth and screenHeight + gestureEvent.position[0].x /= (float)GetScreenWidth(); + gestureEvent.position[0].y /= (float)GetScreenHeight(); + + gestureEvent.position[1].x /= (float)GetScreenWidth(); + gestureEvent.position[1].y /= (float)GetScreenHeight(); + // Gesture data is sent to gestures system for processing ProcessGestureEvent(gestureEvent); // Process obtained gestures data diff --git a/src/gestures.c b/src/gestures.c index 16442e45..af92ba3d 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -45,12 +45,12 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define FORCE_TO_SWIPE 1 // Time in milliseconds -#define FORCE_TO_DRAG 20 -#define FORCE_TO_PINCH 5 -#define TAP_TIMEOUT 300 // Time in milliseconds -#define PINCH_TIMEOUT 300 // Time in milliseconds -#define DOUBLETAP_RANGE 30 +#define FORCE_TO_SWIPE 0.0005f // Measured in normalized pixels / time +#define MINIMUM_DRAG 0.015f // Measured in normalized pixels [0..1] +#define MINIMUM_PINCH 0.005f // Measured in normalized pixels [0..1] +#define TAP_TIMEOUT 300 // Time in milliseconds +#define PINCH_TIMEOUT 300 // Time in milliseconds +#define DOUBLETAP_RANGE 0.03f //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -68,26 +68,29 @@ static Vector2 touchDownDragPosition = { 0.0f, 0.0f }; static Vector2 touchUpPosition = { 0.0f, 0.0f }; static Vector2 moveDownPosition = { 0.0f, 0.0f }; static Vector2 moveDownPosition2 = { 0.0f, 0.0f }; - static int numTap = 0; -static int numHold = 0; -static bool isMoving = false; -static float timeHold = 0.0f; + static int pointCount = 0; static int touchId = -1; static double eventTime = 0.0; static double swipeTime = 0.0; +// Hold gesture variables +static int numHold = 0; +static float timeHold = 0.0f; + // Drag gesture variables static Vector2 dragVector = { 0.0f , 0.0f }; // DRAG vector (between initial and current position) -static float dragDistance = 0.0f; // DRAG distance (from initial touch point to final) for SWIPE GESTURE -static float dragAngle = 0.0f; // DRAG angle direction for SWIPE GESTURE -static float dragIntensity = 0.0f; // DRAG intensity, how far why did the DRAG (pixels per frame) for SWIPE GESTURE +static float dragAngle = 0.0f; // DRAG angle (relative to x-axis) +static float dragDistance = 0.0f; // DRAG distance (from initial touch point to final) (normalized [0..1]) +static float dragIntensity = 0.0f; // DRAG intensity, how far why did the DRAG (pixels per frame) +static bool startMoving = false; // SWIPE used to define when start measuring swipeTime // Pinch gesture variables -static float pinchDistance = 0.0f; // Pinch displacement distance -static float pinchAngle = 0.0f; // Pinch displacement distance +static Vector2 pinchVector = { 0.0f , 0.0f }; // PINCH vector (between first and second touch points) +static float pinchAngle = 0.0f; // PINCH angle (relative to x-axis) +static float pinchDistance = 0.0f; // PINCH displacement distance (normalized [0..1]) // Detected gestures static int previousGesture = GESTURE_NONE; @@ -101,7 +104,7 @@ static unsigned int enabledGestures = 0b0000001111111111; //---------------------------------------------------------------------------------- static float Vector2Angle(Vector2 initialPosition, Vector2 finalPosition); static float Vector2Distance(Vector2 v1, Vector2 v2); -static double GetCurrentTime(); +static double GetCurrentTime(void); //---------------------------------------------------------------------------------- // Module Functions Definition @@ -147,17 +150,19 @@ void ProcessGestureEvent(GestureEvent event) { if (currentGesture == GESTURE_DRAG) touchUpPosition = event.position[0]; - // Calculate for swipe + // NOTE: dragIntensity dependend on the resolution of the screen dragDistance = Vector2Distance(touchDownPosition, touchUpPosition); dragIntensity = dragDistance/(float)((GetCurrentTime() - swipeTime)); + + // TODO: Make getures detection resolution independant - isMoving = false; + startMoving = false; // Detect GESTURE_SWIPE if ((dragIntensity > FORCE_TO_SWIPE) && (touchId == 0)) // RAY: why check (touchId == 0)??? { // NOTE: Angle should be inverted in Y - dragAngle = 360.0f - Vector2Angle(touchDownPosition, touchUpPosition);; + dragAngle = 360.0f - Vector2Angle(touchDownPosition, touchUpPosition); if ((dragAngle < 30) || (dragAngle > 330)) currentGesture = GESTURE_SWIPE_RIGHT; // Right else if ((dragAngle > 30) && (dragAngle < 120)) currentGesture = GESTURE_SWIPE_UP; // Up @@ -178,26 +183,28 @@ void ProcessGestureEvent(GestureEvent event) } else if (event.touchAction == TOUCH_MOVE) { - if (Vector2Distance(moveDownPosition, event.position[0]) > 5) eventTime = GetCurrentTime(); + if ((currentGesture == GESTURE_DRAG)) eventTime = GetCurrentTime(); - if (!isMoving) + if (!startMoving) { swipeTime = GetCurrentTime(); - isMoving = true; + startMoving = true; } moveDownPosition = event.position[0]; - if (currentGesture == GESTURE_HOLD) + if (currentGesture == GESTURE_HOLD) { if (numHold == 1) touchDownPosition = event.position[0]; numHold = 2; - - dragDistance = Vector2Distance(touchDownPosition, moveDownPosition); // Detect GESTURE_DRAG - if (dragDistance >= FORCE_TO_DRAG) currentGesture = GESTURE_DRAG; + if (Vector2Distance(touchDownPosition, moveDownPosition) >= MINIMUM_DRAG) + { + eventTime = GetCurrentTime(); + currentGesture = GESTURE_DRAG; + } } dragVector.x = moveDownPosition.x - touchDownDragPosition.x; @@ -210,7 +217,11 @@ void ProcessGestureEvent(GestureEvent event) { touchDownPosition = event.position[0]; touchDownPosition2 = event.position[1]; - pinchDistance = Vector2Distance(touchDownPosition, touchDownPosition2); + + //pinchDistance = Vector2Distance(touchDownPosition, touchDownPosition2); + + pinchVector.x = touchDownPosition2.x - touchDownPosition.x; + pinchVector.y = touchDownPosition2.y - touchDownPosition.y; currentGesture = GESTURE_HOLD; timeHold = GetCurrentTime(); @@ -218,22 +229,25 @@ void ProcessGestureEvent(GestureEvent event) else if (event.touchAction == TOUCH_MOVE) { pinchDistance = Vector2Distance(moveDownPosition, moveDownPosition2); - + touchDownPosition = moveDownPosition; touchDownPosition2 = moveDownPosition2; moveDownPosition = event.position[0]; moveDownPosition2 = event.position[1]; - if ((Vector2Distance(touchDownPosition, moveDownPosition) > FORCE_TO_PINCH) || (Vector2Distance(touchDownPosition2, moveDownPosition2) > FORCE_TO_PINCH)) + pinchVector.x = moveDownPosition2.x - moveDownPosition.x; + pinchVector.y = moveDownPosition2.y - moveDownPosition.y; + + if ((Vector2Distance(touchDownPosition, moveDownPosition) >= MINIMUM_PINCH) || (Vector2Distance(touchDownPosition2, moveDownPosition2) >= MINIMUM_PINCH)) { if ((Vector2Distance(moveDownPosition, moveDownPosition2) - pinchDistance) < 0) currentGesture = GESTURE_PINCH_IN; else currentGesture = GESTURE_PINCH_OUT; } - else + else { - currentGesture = GESTURE_HOLD; - timeHold = GetCurrentTime(); + currentGesture = GESTURE_HOLD; + timeHold = GetCurrentTime(); } // NOTE: Angle should be inverted in Y @@ -243,6 +257,7 @@ void ProcessGestureEvent(GestureEvent event) { pinchDistance = 0.0f; pinchAngle = 0.0f; + pinchVector = (Vector2){ 0.0f, 0.0f }; currentGesture = GESTURE_NONE; } @@ -289,26 +304,30 @@ int GetGestureType(void) return (enabledGestures & currentGesture); } -void SetGesturesEnabled(unsigned int gestureFlags) +// Get number of touch points +int GetTouchPointsCount(void) { - enabledGestures = gestureFlags; + // NOTE: point count is calculated when ProcessGestureEvent(GestureEvent event) is called + + return pointCount; } -// Get drag dragIntensity (pixels per frame) -float GetGestureDragdragIntensity(void) +// Enable only desired getures to be detected +void SetGesturesEnabled(unsigned int gestureFlags) { - // NOTE: drag intensity is calculated on one touch points TOUCH_UP - - return dragIntensity; + enabledGestures = gestureFlags; } -// Get drag angle -// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise -float GetGestureDragAngle(void) +// Hold time measured in ms +float GetGestureHoldDuration(void) { - // NOTE: drag angle is calculated on one touch points TOUCH_UP + // NOTE: time is calculated on current gesture HOLD - return dragAngle; + float time = 0.0f; + + if (currentGesture == GESTURE_HOLD) time = (float)GetCurrentTime() - timeHold; + + return time; } // Get drag vector (between initial touch point to current) @@ -319,33 +338,22 @@ Vector2 GetGestureDragVector(void) return dragVector; } -// Hold time measured in ms -float GetGestureHoldDuration(void) +// Get drag angle +// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise +float GetGestureDragAngle(void) { - // NOTE: time is calculated on current gesture HOLD - - float time = 0.0f; - - if (currentGesture == GESTURE_HOLD) time = (float)GetCurrentTime() - timeHold; + // NOTE: drag angle is calculated on one touch points TOUCH_UP - return time; + return dragAngle; } // Get distance between two pinch points -float GetGesturePinchDelta(void) +Vector2 GetGesturePinchVector(void) { // NOTE: The position values used for pinchDistance are not modified like the position values of [core.c]-->GetTouchPosition(int index) // NOTE: pinch distance is calculated on two touch points TOUCH_MOVE - return pinchDistance; -} - -// Get number of touch points -int GetTouchPointsCount(void) -{ - // NOTE: point count is calculated when ProcessGestureEvent(GestureEvent event) is called - - return pointCount; + return pinchVector; } // Get angle beween two pinch points @@ -388,7 +396,7 @@ static float Vector2Distance(Vector2 v1, Vector2 v2) } // Time measure returned are milliseconds -static double GetCurrentTime() +static double GetCurrentTime(void) { double time = 0; diff --git a/src/gestures.h b/src/gestures.h index 52f778be..5468eb54 100644 --- a/src/gestures.h +++ b/src/gestures.h @@ -90,19 +90,19 @@ extern "C" { // Prevents name mangling of functions //---------------------------------------------------------------------------------- // Module Functions Declaration //---------------------------------------------------------------------------------- +void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures void UpdateGestures(void); // Update gestures detected (must be called every frame) bool IsGestureDetected(void); // Check if a gesture have been detected int GetGestureType(void); // Get latest detected gesture void SetGesturesEnabled(unsigned int gestureFlags); // Enable a set of gestures using flags -void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures +int GetTouchPointsCount(void); // Get touch points count -float GetGestureDragIntensity(void); // Get gesture drag intensity -float GetGestureDragAngle(void); // Get gesture drag angle +float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds Vector2 GetGestureDragVector(void); // Get gesture drag vector -int GetGestureHoldDuration(void); // Get gesture hold time in frames -float GetGesturePinchDelta(void); // Get gesture pinch delta +float GetGestureDragAngle(void); // Get gesture drag angle +Vector2 GetGesturePinchVector(void); // Get gesture pinch delta float GetGesturePinchAngle(void); // Get gesture pinch angle -int GetTouchPointsCount(void); // Get touch points count + #ifdef __cplusplus } diff --git a/src/raylib.h b/src/raylib.h index f5a3cc31..def56ee2 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -607,19 +607,18 @@ bool IsButtonReleased(int button); // Detect if an android //------------------------------------------------------------------------------------ // Gestures and Touch Handling Functions (Module: gestures) //------------------------------------------------------------------------------------ +void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures void UpdateGestures(void); // Update gestures detected (must be called every frame) bool IsGestureDetected(void); // Check if a gesture have been detected int GetGestureType(void); // Get latest detected gesture void SetGesturesEnabled(unsigned int gestureFlags); // Enable a set of gestures using flags -void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures +int GetTouchPointsCount(void); // Get touch points count -float GetGestureDragIntensity(void); // Get gesture drag intensity -float GetGestureDragAngle(void); // Get gesture drag angle +float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds Vector2 GetGestureDragVector(void); // Get gesture drag vector -float GetGestureHoldDuration(void); // Get gesture hold time in ms -float GetGesturePinchDelta(void); // Get gesture pinch delta +float GetGestureDragAngle(void); // Get gesture drag angle +Vector2 GetGesturePinchVector(void); // Get gesture pinch delta float GetGesturePinchAngle(void); // Get gesture pinch angle -int GetTouchPointsCount(void); // Get touch points count //------------------------------------------------------------------------------------ // Camera System Functions (Module: camera) -- cgit v1.2.3 From 8aab52aeda47ce283d1446be27a7e2e20f027434 Mon Sep 17 00:00:00 2001 From: Ray San Date: Thu, 18 Feb 2016 14:05:48 +0100 Subject: Redesigned RPI input system -IN PROGRESS- --- examples/core_input_mouse.c | 14 +- examples/makefile | 10 +- src/core.c | 421 +++++++++++++++++++++++++++----------------- src/makefile | 8 +- src/raylib.h | 2 - 5 files changed, 279 insertions(+), 176 deletions(-) diff --git a/examples/core_input_mouse.c b/examples/core_input_mouse.c index 358b5fd6..24d2dfcd 100644 --- a/examples/core_input_mouse.c +++ b/examples/core_input_mouse.c @@ -21,6 +21,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [core] example - mouse input"); Vector2 ballPosition = { -100.0f, -100.0f }; + Color ballColor = DARKBLUE; SetTargetFPS(60); //--------------------------------------------------------------------------------------- @@ -30,10 +31,11 @@ int main() { // Update //---------------------------------------------------------------------------------- - if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) - { - ballPosition = GetMousePosition(); - } + ballPosition = GetMousePosition(); + + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) ballColor = MAROON; + else if (IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) ballColor = LIME; + else if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) ballColor = DARKBLUE; //---------------------------------------------------------------------------------- // Draw @@ -42,9 +44,9 @@ int main() ClearBackground(RAYWHITE); - DrawCircleV(ballPosition, 40, GOLD); + DrawCircleV(ballPosition, 40, ballColor); - DrawText("mouse click to draw the ball", 10, 10, 20, DARKGRAY); + DrawText("move ball with mouse and click mouse button to change color", 10, 10, 20, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- diff --git a/examples/makefile b/examples/makefile index 62428155..2a9e88ba 100644 --- a/examples/makefile +++ b/examples/makefile @@ -227,10 +227,10 @@ core_mouse_wheel: core_mouse_wheel.c # compile [core] example - gamepad input core_input_gamepad: core_input_gamepad.c -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(PLATFORM), $(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_RPI)) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) else - @echo core_input_gamepad: Only supported on desktop platform + @echo core_input_gamepad: Example not supported on PLATFORM_ANDROID or PLATFORM_WEB endif # compile [core] example - generate random values @@ -246,15 +246,15 @@ core_drop_files: core_drop_files.c ifeq ($(PLATFORM),PLATFORM_DESKTOP) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) else - @echo core_drop_files: Only supported on desktop platform + @echo core_drop_files: Example not supported on PLATFORM_ANDROID or PLATFORM_WEB or PLATFORM_RPI endif # compile [core] example - storage values core_storage_values: core_storage_values.c -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(PLATFORM), $(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_RPI)) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) else - @echo core_storage_values: Only supported on desktop platform + @echo core_storage_values: Example not supported on PLATFORM_ANDROID or PLATFORM_WEB endif # compile [core] example - gestures detection diff --git a/src/core.c b/src/core.c index 7b981097..c7d93355 100644 --- a/src/core.c +++ b/src/core.c @@ -102,11 +102,16 @@ #include "EGL/egl.h" // Khronos EGL library - Native platform display device control functions #include "EGL/eglext.h" // Khronos EGL library - Extensions #include "GLES2/gl2.h" // Khronos OpenGL ES 2.0 library + + // Old device inputs system + #define DEFAULT_KEYBOARD_DEV STDIN_FILENO // Standard input + #define DEFAULT_MOUSE_DEV "/dev/input/mouse0" + #define DEFAULT_GAMEPAD_DEV "/dev/input/js0" - #define DEFAULT_KEYBOARD_DEV "/dev/input/event0" // Not used, keyboard inputs are read raw from stdin - #define DEFAULT_MOUSE_DEV "/dev/input/event1" - //#define DEFAULT_MOUSE_DEV "/dev/input/mouse0" - #define DEFAULT_GAMEPAD_DEV "/dev/input/js0" + // New device input events (evdev) (must be detected) + //#define DEFAULT_KEYBOARD_DEV "/dev/input/eventN" + //#define DEFAULT_MOUSE_DEV "/dev/input/eventN" + //#define DEFAULT_GAMEPAD_DEV "/dev/input/eventN" #endif #if defined(PLATFORM_WEB) @@ -142,16 +147,11 @@ static int currentButtonState[128] = { 1 }; // Required to check if button p #elif defined(PLATFORM_RPI) static EGL_DISPMANX_WINDOW_T nativeWindow; // Native window (graphic device) -// Input variables (mouse/keyboard) -static int mouseStream = -1; // Mouse device file descriptor -static bool mouseReady = false; // Flag to know if mouse is ready -pthread_t mouseThreadId; // Mouse reading thread id - +// Keyboard input variables // NOTE: For keyboard we will use the standard input (but reconfigured...) +static struct termios defaultKeyboardSettings; // Used to store default keyboard settings static int defaultKeyboardMode; // Used to store default keyboard mode -static struct termios defaultKeyboardSettings; // Used to staore default keyboard settings - -static int keyboardMode = 0; // Keyboard mode: 1 - KEYCODES, 2 - ASCII +static int keyboardMode = 0; // Register Keyboard mode: 1 - KEYCODES, 2 - ASCII // This array maps Unix keycodes to ASCII equivalent and to GLFW3 equivalent for special function keys (>256) const short UnixKeycodeToASCII[128] = { 256, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 45, 61, 259, 9, 81, 87, 69, 82, 84, 89, 85, 73, 79, 80, 91, 93, 257, 341, 65, 83, 68, @@ -159,7 +159,15 @@ const short UnixKeycodeToASCII[128] = { 256, 49, 50, 51, 52, 53, 54, 55, 56, 57, 297, 298, 299, -1, -1, -1, -1, -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 257, 345, 47, -1, 346, -1, -1, 265, -1, 263, 262, -1, 264, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; +// Mouse input variables +static int mouseStream = -1; // Mouse device file descriptor +static bool mouseReady = false; // Flag to know if mouse is ready +pthread_t mouseThreadId; // Mouse reading thread id + +// Gamepad input variables static int gamepadStream = -1; // Gamepad device file descriptor +static bool gamepadReady = false; // Flag to know if gamepad is ready +pthread_t gamepadThreadId; // Gamepad reading thread id #endif #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) @@ -244,11 +252,13 @@ static void LogoAnimation(void); // Plays raylib logo app 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 static void InitKeyboard(void); // Init raw keyboard system (standard input reading) +static void ProcessKeyboard(void); // Process keyboard events static void RestoreKeyboard(void); // Restore keyboard system +static void InitMouse(void); // Mouse initialization (including mouse thread) +static void *MouseThread(void *arg); // Mouse reading thread static void InitGamepad(void); // Init raw gamepad input +static void *GamepadThread(void *arg); // Mouse reading thread #endif #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) @@ -1128,18 +1138,21 @@ bool IsCursorHidden() { return cursorHidden; } -#endif //defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) -// TODO: Enable gamepad usage on Rapsberry Pi -// NOTE: emscripten not implemented -#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) +// NOTE: Gamepad support not implemented in emscripten GLFW3 (PLATFORM_WEB) + // Detect if a gamepad is available bool IsGamepadAvailable(int gamepad) { - int result = glfwJoystickPresent(gamepad); + bool result = false; + +#if defined(PLATFORM_RPI) + if (gamepadReady && (gamepad == 0)) result = true; +#else + if (glfwJoystickPresent(gamepad) == 1) result = true; +#endif - if (result == 1) return true; - else return false; + return result; } // Return axis movement vector for a gamepad @@ -1148,10 +1161,14 @@ Vector2 GetGamepadMovement(int gamepad) Vector2 vec = { 0, 0 }; const float *axes; - int axisCount; - + int axisCount = 0; + +#if defined(PLATFORM_RPI) + // TODO: Get gamepad axis information +#else axes = glfwGetJoystickAxes(gamepad, &axisCount); - +#endif + if (axisCount >= 2) { vec.x = axes[0]; // Left joystick X @@ -1184,16 +1201,20 @@ bool IsGamepadButtonPressed(int gamepad, int button) // Detect if a gamepad button is being pressed bool IsGamepadButtonDown(int gamepad, int button) { + bool result = false; const unsigned char *buttons; int buttonsCount; - + +#if defined(PLATFORM_RPI) + // TODO: Get gamepad buttons information +#else buttons = glfwGetJoystickButtons(gamepad, &buttonsCount); - if ((buttons != NULL) && (buttons[button] == GLFW_PRESS)) - { - return true; - } - else return false; + if ((buttons != NULL) && (buttons[button] == GLFW_PRESS)) result = true; + else result = false; +#endif + + return result; } // Detect if a gamepad button has NOT been pressed once @@ -1216,19 +1237,23 @@ bool IsGamepadButtonReleased(int gamepad, int button) // Detect if a mouse button is NOT being pressed bool IsGamepadButtonUp(int gamepad, int button) { + bool result = false; const unsigned char *buttons; int buttonsCount; +#if defined(PLATFORM_RPI) + // TODO: Get gamepad buttons information +#else buttons = glfwGetJoystickButtons(gamepad, &buttonsCount); - if ((buttons != NULL) && (buttons[button] == GLFW_RELEASE)) - { - return true; - } - else return false; -} + if ((buttons != NULL) && (buttons[button] == GLFW_RELEASE)) result = true; + else result = false; #endif + return result; +} +#endif //defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) + // Returns touch position X int GetTouchX(void) { @@ -2157,7 +2182,68 @@ static void PollInputEvents(void) // NOTE: Keyboard reading could be done using input_event(s) reading or just read from stdin, // we use method 2 (stdin) but maybe in a future we should change to method 1... + ProcessKeyboard(); + + // NOTE: Gamepad (Joystick) input events polling is done asynchonously in another pthread - GamepadThread() + +#endif +} +#if defined(PLATFORM_RPI) +// Initialize Keyboard system (using standard input) +static void InitKeyboard(void) +{ + // NOTE: We read directly from Standard Input (stdin) - STDIN_FILENO file descriptor + + // Make stdin non-blocking (not enough, need to configure to non-canonical mode) + int flags = fcntl(STDIN_FILENO, F_GETFL, 0); // F_GETFL: Get the file access mode and the file status flags + fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK); // F_SETFL: Set the file status flags to the value specified + + // Save terminal keyboard settings and reconfigure terminal with new settings + struct termios keyboardNewSettings; + tcgetattr(STDIN_FILENO, &defaultKeyboardSettings); // Get current keyboard settings + keyboardNewSettings = defaultKeyboardSettings; + + // New terminal settings for keyboard: turn off buffering (non-canonical mode), echo and key processing + // NOTE: ISIG controls if ^C and ^Z generate break signals or not + keyboardNewSettings.c_lflag &= ~(ICANON | ECHO | ISIG); + //keyboardNewSettings.c_iflag &= ~(ISTRIP | INLCR | ICRNL | IGNCR | IXON | IXOFF); + keyboardNewSettings.c_cc[VMIN] = 1; + keyboardNewSettings.c_cc[VTIME] = 0; + + // Set new keyboard settings (change occurs immediately) + tcsetattr(STDIN_FILENO, TCSANOW, &keyboardNewSettings); + + // NOTE: Reading directly from stdin will give chars already key-mapped by kernel to ASCII or UNICODE, we change that! -> WHY??? + + // Save old keyboard mode to restore it at the end + if (ioctl(STDIN_FILENO, KDGKBMODE, &defaultKeyboardMode) < 0) + { + // NOTE: It could mean we are using a remote keyboard through ssh! + TraceLog(WARNING, "Could not change keyboard mode (SSH keyboard?)"); + + keyboardMode = 2; // ASCII + } + else + { + // We reconfigure keyboard mode to get: + // - scancodes (K_RAW) + // - keycodes (K_MEDIUMRAW) + // - ASCII chars (K_XLATE) + // - UNICODE chars (K_UNICODE) + ioctl(STDIN_FILENO, KDSKBMODE, K_XLATE); + + //http://lct.sourceforge.net/lct/x60.html + + keyboardMode = 2; // keycodes + } + + // Register keyboard restore when program finishes + atexit(RestoreKeyboard); +} + +static void ProcessKeyboard(void) +{ // Keyboard input polling (fill keys[256] array with status) int numKeysBuffer = 0; // Keys available on buffer char keysBuffer[32]; // Max keys to be read at a time @@ -2242,45 +2328,18 @@ static void PollInputEvents(void) } */ } +} - // TODO: Gamepad support (use events, easy!) -/* - struct js_event gamepadEvent; - - read(gamepadStream, &gamepadEvent, sizeof(struct js_event)); - - if (gamepadEvent.type == JS_EVENT_BUTTON) - { - switch (gamepadEvent.number) - { - case 0: // 1st Axis X - case 1: // 1st Axis Y - case 2: // 2st Axis X - case 3: // 2st Axis Y - case 4: - { - if (gamepadEvent.value == 1) // Button pressed, 0 release - - } break; - // Buttons is similar, variable for every joystick - } - } - else if (gamepadEvent.type == JS_EVENT_AXIS) - { - switch (gamepadEvent.number) - { - case 0: // 1st Axis X - case 1: // 1st Axis Y - case 2: // 2st Axis X - case 3: // 2st Axis Y - // Buttons is similar, variable for every joystick - } - } -*/ -#endif +// Restore default keyboard input +static void RestoreKeyboard(void) +{ + // Reset to default keyboard settings + tcsetattr(STDIN_FILENO, TCSANOW, &defaultKeyboardSettings); + + // Reconfigure keyboard to default mode + ioctl(STDIN_FILENO, KDSKBMODE, defaultKeyboardMode); } -#if defined(PLATFORM_RPI) // Mouse initialization (including mouse thread) static void InitMouse(void) { @@ -2305,118 +2364,156 @@ static void InitMouse(void) // if too much time passes between reads, queue gets full and new events override older ones... static void *MouseThread(void *arg) { - struct input_event mouseEvent; + const unsigned char XSIGN = 1<<4, YSIGN = 1<<5; + + typedef struct { + char buttons; + char dx, dy; + } MouseEvent; + + MouseEvent mouse; + + int mouseRelX = 0; + int mouseRelY = 0; while(1) { - // NOTE: read() will return -1 if the events queue is empty - read(mouseStream, &mouseEvent, sizeof(struct input_event)); - - // Check event types - if (mouseEvent.type == EV_REL) // Relative motion event + if (read(mouseStream, &mouse, sizeof(MouseEvent)) == (int)sizeof(MouseEvent)) { - if (mouseEvent.code == REL_X) - { - mousePosition.x += (float)mouseEvent.value; - - // Screen limits X check - if (mousePosition.x < 0) mousePosition.x = 0; - if (mousePosition.x > screenWidth) mousePosition.x = screenWidth; - } - - if (mouseEvent.code == REL_Y) - { - mousePosition.y += (float)mouseEvent.value; - - // Screen limits Y check - if (mousePosition.y < 0) mousePosition.y = 0; - if (mousePosition.y > screenHeight) mousePosition.y = screenHeight; - } + if ((mouse.buttons & 0x08) == 0) break; // This bit should always be set + + // Check Left button pressed + if ((mouse.buttons & 0x01) > 0) currentMouseState[0] = 1; + else currentMouseState[0] = 0; - if (mouseEvent.code == REL_WHEEL) - { - // mouseEvent.value give 1 or -1 (direction) - } - } - else if (mouseEvent.type == EV_KEY) // Mouse button event - { - if (mouseEvent.code == BTN_LEFT) currentMouseState[0] = mouseEvent.value; - if (mouseEvent.code == BTN_RIGHT) currentMouseState[1] = mouseEvent.value; - if (mouseEvent.code == BTN_MIDDLE) currentMouseState[2] = mouseEvent.value; - } + // Check Right button pressed + if ((mouse.buttons & 0x02) > 0) currentMouseState[1] = 1; + else currentMouseState[1] = 0; + + // Check Middle button pressed + if ((mouse.buttons & 0x04) > 0) currentMouseState[2] = 1; + else currentMouseState[2] = 0; + + mouseRelX = (int)mouse.dx; + mouseRelY = (int)mouse.dy; + + if ((mouse.buttons & XSIGN) > 0) mouseRelX = -1*(255 - mouseRelX); + if ((mouse.buttons & YSIGN) > 0) mouseRelY = -1*(255 - mouseRelY); + + mousePosition.x += (float)mouseRelX; + mousePosition.y -= (float)mouseRelY; + + if (mousePosition.x < 0) mousePosition.x = 0; + if (mousePosition.y < 0) mousePosition.y = 0; + + if (mousePosition.x > screenWidth) mousePosition.x = screenWidth; + if (mousePosition.y > screenHeight) mousePosition.y = screenHeight; + } + //else read(mouseStream, &mouse, 1); // Try to sync up again } return NULL; } -// Initialize Keyboard system (using standard input) -static void InitKeyboard(void) +// Init gamepad system +static void InitGamepad(void) { - // NOTE: We read directly from Standard Input (stdin) - STDIN_FILENO file descriptor - - // Make stdin non-blocking (not enough, need to configure to non-canonical mode) - int flags = fcntl(STDIN_FILENO, F_GETFL, 0); // F_GETFL: Get the file access mode and the file status flags - fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK); // F_SETFL: Set the file status flags to the value specified - - // Save terminal keyboard settings and reconfigure terminal with new settings - struct termios keyboardNewSettings; - tcgetattr(STDIN_FILENO, &defaultKeyboardSettings); // Get current keyboard settings - keyboardNewSettings = defaultKeyboardSettings; - - // New terminal settings for keyboard: turn off buffering (non-canonical mode), echo and key processing - // NOTE: ISIG controls if ^C and ^Z generate break signals or not - keyboardNewSettings.c_lflag &= ~(ICANON | ECHO | ISIG); - //keyboardNewSettings.c_iflag &= ~(ISTRIP | INLCR | ICRNL | IGNCR | IXON | IXOFF); - keyboardNewSettings.c_cc[VMIN] = 1; - keyboardNewSettings.c_cc[VTIME] = 0; - - // Set new keyboard settings (change occurs immediately) - tcsetattr(STDIN_FILENO, TCSANOW, &keyboardNewSettings); - - // NOTE: Reading directly from stdin will give chars already key-mapped by kernel to ASCII or UNICODE, we change that! -> WHY??? - - // Save old keyboard mode to restore it at the end - if (ioctl(STDIN_FILENO, KDGKBMODE, &defaultKeyboardMode) < 0) + if ((gamepadStream = open(DEFAULT_GAMEPAD_DEV, O_RDONLY|O_NONBLOCK)) < 0) { - // NOTE: It could mean we are using a remote keyboard through ssh! - TraceLog(WARNING, "Could not change keyboard mode (SSH keyboard?)"); - - keyboardMode = 2; // ASCII + TraceLog(WARNING, "Gamepad device could not be opened, no gamepad available"); } else { - // We reconfigure keyboard mode to get: - // - scancodes (K_RAW) - // - keycodes (K_MEDIUMRAW) - // - ASCII chars (K_XLATE) - // - UNICODE chars (K_UNICODE) - ioctl(STDIN_FILENO, KDSKBMODE, K_MEDIUMRAW); - - //http://lct.sourceforge.net/lct/x60.html + gamepadReady = true; - keyboardMode = 1; // keycodes - } + int error = pthread_create(&gamepadThreadId, NULL, &GamepadThread, NULL); - // Register keyboard restore when program finishes - atexit(RestoreKeyboard); + if (error != 0) TraceLog(WARNING, "Error creating gamepad input event thread"); + else TraceLog(INFO, "Gamepad device initialized successfully"); + } } -// Restore default keyboard input -static void RestoreKeyboard(void) +// Process Gamepad (/dev/input/js0) +static void *GamepadThread(void *arg) { - // Reset to default keyboard settings - tcsetattr(STDIN_FILENO, TCSANOW, &defaultKeyboardSettings); + #define JS_EVENT_BUTTON 0x01 // Button pressed/released + #define JS_EVENT_AXIS 0x02 // Joystick axis moved + #define JS_EVENT_INIT 0x80 // Initial state of device + + struct js_event { + unsigned int time; // event timestamp in milliseconds + short value; // event value + unsigned char type; // event type + unsigned char number; // event axis/button number + }; + + // These values are sensible on Logitech Dual Action Rumble and Xbox360 controller + const int joystickAxisX = 0; + const int joystickAxisY = 1; + + // Read gamepad event + struct js_event gamepadEvent; + int bytes; - // Reconfigure keyboard to default mode - ioctl(STDIN_FILENO, KDSKBMODE, defaultKeyboardMode); -} + int buttons[11]; + int stickX; + int stickY; + + while (1) + { + if (read(gamepadStream, &gamepadEvent, sizeof(struct js_event)) == (int)sizeof(struct js_event)) + { + gamepadEvent.type &= ~JS_EVENT_INIT; // Ignore synthetic events + + // Process gamepad events by type + if (gamepadEvent.type == JS_EVENT_BUTTON) + { + if (gamepadEvent.number < 11) + { + switch (gamepadEvent.value) + { + case 0: + case 1: buttons[gamepadEvent.number] = gamepadEvent.value; break; + default: break; + } + } + /* + switch (gamepadEvent.number) + { + case 0: // 1st Axis X + case 1: // 1st Axis Y + case 2: // 2st Axis X + case 3: // 2st Axis Y + case 4: + { + if (gamepadEvent.value == 1) // Button pressed, 0 release + { + + } -// Init gamepad system -static void InitGamepad(void) -{ - // TODO: Add Gamepad support - if ((gamepadStream = open(DEFAULT_GAMEPAD_DEV, O_RDONLY|O_NONBLOCK)) < 0) TraceLog(WARNING, "Gamepad device could not be opened, no gamepad available"); - else TraceLog(INFO, "Gamepad device initialized successfully"); + } break; + // Buttons is similar, variable for every joystick + } + */ + } + else if (gamepadEvent.type == JS_EVENT_AXIS) + { + if (gamepadEvent.number == joystickAxisX) stickX = gamepadEvent.value; + if (gamepadEvent.number == joystickAxisY) stickY = gamepadEvent.value; + /* + switch (gamepadEvent.number) + { + case 0: // 1st Axis X + case 1: // 1st Axis Y + case 2: // 2st Axis X + case 3: // 2st Axis Y + // Buttons is similar, variable for every joystick + } + */ + } + } + else read(gamepadStream, &gamepadEvent, 1); // Try to sync up again + } } #endif diff --git a/src/makefile b/src/makefile index 4f65c440..2d73e646 100644 --- a/src/makefile +++ b/src/makefile @@ -91,7 +91,13 @@ else endif # define all object files required -OBJS = core.o rlgl.o glad.o shapes.o text.o textures.o models.o audio.o utils.o camera.o gestures.o stb_vorbis.o +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + OBJS = core.o rlgl.o glad.o shapes.o text.o textures.o models.o audio.o utils.o camera.o gestures.o stb_vorbis.o +else + #GLAD only required on desktop platform + OBJS = core.o rlgl.o shapes.o text.o textures.o models.o audio.o stb_vorbis.o utils.o camera.o gestures.o +endif + # typing 'make' will invoke the first target entry in the file, # in this case, the 'default' target entry is raylib diff --git a/src/raylib.h b/src/raylib.h index def56ee2..0dc8c6df 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -583,9 +583,7 @@ void HideCursor(void); // Hides cursor void EnableCursor(void); // Enables cursor void DisableCursor(void); // Disables cursor bool IsCursorHidden(void); // Returns true if cursor is not visible -#endif -#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 -- cgit v1.2.3 From 09f28d0f57d54c86f5eed8d2e7917360d8657f36 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 19 Feb 2016 00:16:16 +0100 Subject: Working on RPI gamepad support --- src/core.c | 58 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/src/core.c b/src/core.c index c7d93355..3bd36d08 100644 --- a/src/core.c +++ b/src/core.c @@ -102,16 +102,6 @@ #include "EGL/egl.h" // Khronos EGL library - Native platform display device control functions #include "EGL/eglext.h" // Khronos EGL library - Extensions #include "GLES2/gl2.h" // Khronos OpenGL ES 2.0 library - - // Old device inputs system - #define DEFAULT_KEYBOARD_DEV STDIN_FILENO // Standard input - #define DEFAULT_MOUSE_DEV "/dev/input/mouse0" - #define DEFAULT_GAMEPAD_DEV "/dev/input/js0" - - // New device input events (evdev) (must be detected) - //#define DEFAULT_KEYBOARD_DEV "/dev/input/eventN" - //#define DEFAULT_MOUSE_DEV "/dev/input/eventN" - //#define DEFAULT_GAMEPAD_DEV "/dev/input/eventN" #endif #if defined(PLATFORM_WEB) @@ -124,6 +114,21 @@ //---------------------------------------------------------------------------------- #define STORAGE_FILENAME "storage.data" +#if defined(PLATFORM_RPI) + // Old device inputs system + #define DEFAULT_KEYBOARD_DEV STDIN_FILENO // Standard input + #define DEFAULT_MOUSE_DEV "/dev/input/mouse0" + #define DEFAULT_GAMEPAD_DEV "/dev/input/js0" + + // New device input events (evdev) (must be detected) + //#define DEFAULT_KEYBOARD_DEV "/dev/input/eventN" + //#define DEFAULT_MOUSE_DEV "/dev/input/eventN" + //#define DEFAULT_GAMEPAD_DEV "/dev/input/eventN" + + #define MOUSE_SENSITIVITY 1.0f + #define MAX_GAMEPAD_BUTTONS 11 +#endif + //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- @@ -168,6 +173,10 @@ pthread_t mouseThreadId; // Mouse reading thread id static int gamepadStream = -1; // Gamepad device file descriptor static bool gamepadReady = false; // Flag to know if gamepad is ready pthread_t gamepadThreadId; // Gamepad reading thread id + +int gamepadButtons[MAX_GAMEPAD_BUTTONS]; +int gamepadAxisX = 0; +int gamepadAxisY = 0; #endif #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) @@ -1165,6 +1174,7 @@ Vector2 GetGamepadMovement(int gamepad) #if defined(PLATFORM_RPI) // TODO: Get gamepad axis information + // Use gamepadAxisX, gamepadAxisY #else axes = glfwGetJoystickAxes(gamepad, &axisCount); #endif @@ -1206,7 +1216,9 @@ bool IsGamepadButtonDown(int gamepad, int button) int buttonsCount; #if defined(PLATFORM_RPI) - // TODO: Get gamepad buttons information + // Get gamepad buttons information + if ((gamepad == 0) && (gamepadButtons[button] == 1)) result = true; + else result = false; #else buttons = glfwGetJoystickButtons(gamepad, &buttonsCount); @@ -1242,7 +1254,9 @@ bool IsGamepadButtonUp(int gamepad, int button) int buttonsCount; #if defined(PLATFORM_RPI) - // TODO: Get gamepad buttons information + // Get gamepad buttons information + if ((gamepad == 0) && (gamepadButtons[button] == 0)) result = true; + else result = false; #else buttons = glfwGetJoystickButtons(gamepad, &buttonsCount); @@ -2400,8 +2414,10 @@ static void *MouseThread(void *arg) if ((mouse.buttons & XSIGN) > 0) mouseRelX = -1*(255 - mouseRelX); if ((mouse.buttons & YSIGN) > 0) mouseRelY = -1*(255 - mouseRelY); - mousePosition.x += (float)mouseRelX; - mousePosition.y -= (float)mouseRelY; + // TODO: Mouse movement should not depend on screenWidth and screenHeight, normalize! + + mousePosition.x += (float)mouseRelX/MOUSE_SENSITIVITY; + mousePosition.y -= (float)mouseRelY/MOUSE_SENSITIVITY; if (mousePosition.x < 0) mousePosition.x = 0; if (mousePosition.y < 0) mousePosition.y = 0; @@ -2453,11 +2469,6 @@ static void *GamepadThread(void *arg) // Read gamepad event struct js_event gamepadEvent; - int bytes; - - int buttons[11]; - int stickX; - int stickY; while (1) { @@ -2468,12 +2479,12 @@ static void *GamepadThread(void *arg) // Process gamepad events by type if (gamepadEvent.type == JS_EVENT_BUTTON) { - if (gamepadEvent.number < 11) + if (gamepadEvent.number < MAX_GAMEPAD_BUTTONS) { switch (gamepadEvent.value) { case 0: - case 1: buttons[gamepadEvent.number] = gamepadEvent.value; break; + case 1: gamepadButtons[gamepadEvent.number] = (int)gamepadEvent.value; break; default: break; } } @@ -2498,8 +2509,8 @@ static void *GamepadThread(void *arg) } else if (gamepadEvent.type == JS_EVENT_AXIS) { - if (gamepadEvent.number == joystickAxisX) stickX = gamepadEvent.value; - if (gamepadEvent.number == joystickAxisY) stickY = gamepadEvent.value; + if (gamepadEvent.number == joystickAxisX) gamepadAxisX = (int)gamepadEvent.value; + if (gamepadEvent.number == joystickAxisY) gamepadAxisY = (int)gamepadEvent.value; /* switch (gamepadEvent.number) { @@ -2512,7 +2523,6 @@ static void *GamepadThread(void *arg) */ } } - else read(gamepadStream, &gamepadEvent, 1); // Try to sync up again } } #endif -- cgit v1.2.3 From 98c60838fed28958519144840a21f012995d6799 Mon Sep 17 00:00:00 2001 From: Ray San Date: Fri, 19 Feb 2016 19:57:25 +0100 Subject: Reviewed RPI inputs --- src/core.c | 206 ++++++++++++++++++++++++++++------------------------------- src/raylib.h | 2 + 2 files changed, 98 insertions(+), 110 deletions(-) diff --git a/src/core.c b/src/core.c index 3bd36d08..dbcfa6bc 100644 --- a/src/core.c +++ b/src/core.c @@ -125,7 +125,7 @@ //#define DEFAULT_MOUSE_DEV "/dev/input/eventN" //#define DEFAULT_GAMEPAD_DEV "/dev/input/eventN" - #define MOUSE_SENSITIVITY 1.0f + #define MOUSE_SENSITIVITY 0.8f #define MAX_GAMEPAD_BUTTONS 11 #endif @@ -156,13 +156,6 @@ static EGL_DISPMANX_WINDOW_T nativeWindow; // Native window (graphic device // NOTE: For keyboard we will use the standard input (but reconfigured...) static struct termios defaultKeyboardSettings; // Used to store default keyboard settings static int defaultKeyboardMode; // Used to store default keyboard mode -static int keyboardMode = 0; // Register Keyboard mode: 1 - KEYCODES, 2 - ASCII - -// This array maps Unix keycodes to ASCII equivalent and to GLFW3 equivalent for special function keys (>256) -const short UnixKeycodeToASCII[128] = { 256, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 45, 61, 259, 9, 81, 87, 69, 82, 84, 89, 85, 73, 79, 80, 91, 93, 257, 341, 65, 83, 68, - 70, 71, 72, 74, 75, 76, 59, 39, 96, 340, 92, 90, 88, 67, 86, 66, 78, 77, 44, 46, 47, 344, -1, 342, 32, -1, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, -1, -1, -1, -1, -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 257, 345, 47, -1, - 346, -1, -1, 265, -1, 263, 262, -1, 264, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; // Mouse input variables static int mouseStream = -1; // Mouse device file descriptor @@ -227,7 +220,9 @@ static int exitKey = KEY_ESCAPE; // Default exit key (ESC) static int lastKeyPressed = -1; // Register last key pressed static bool cursorHidden; // Track if cursor is hidden +#endif +#if defined(PLATFORM_DESKTOP) static char **dropFilesPath; // Store dropped files paths as strings static int dropFilesCount = 0; // Count stored strings #endif @@ -781,7 +776,7 @@ void ShowLogo(void) showLogo = true; } -#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) +#if defined(PLATFORM_DESKTOP) // Check if a file have been dropped into window bool IsFileDropped(void) { @@ -1212,14 +1207,15 @@ bool IsGamepadButtonPressed(int gamepad, int button) bool IsGamepadButtonDown(int gamepad, int button) { bool result = false; - const unsigned char *buttons; - int buttonsCount; #if defined(PLATFORM_RPI) // Get gamepad buttons information if ((gamepad == 0) && (gamepadButtons[button] == 1)) result = true; else result = false; #else + const unsigned char *buttons; + int buttonsCount; + buttons = glfwGetJoystickButtons(gamepad, &buttonsCount); if ((buttons != NULL) && (buttons[button] == GLFW_PRESS)) result = true; @@ -1250,14 +1246,15 @@ bool IsGamepadButtonReleased(int gamepad, int button) bool IsGamepadButtonUp(int gamepad, int button) { bool result = false; - const unsigned char *buttons; - int buttonsCount; #if defined(PLATFORM_RPI) // Get gamepad buttons information if ((gamepad == 0) && (gamepadButtons[button] == 0)) result = true; else result = false; #else + const unsigned char *buttons; + int buttonsCount; + buttons = glfwGetJoystickButtons(gamepad, &buttonsCount); if ((buttons != NULL) && (buttons[button] == GLFW_RELEASE)) result = true; @@ -2235,8 +2232,6 @@ static void InitKeyboard(void) { // NOTE: It could mean we are using a remote keyboard through ssh! TraceLog(WARNING, "Could not change keyboard mode (SSH keyboard?)"); - - keyboardMode = 2; // ASCII } else { @@ -2246,102 +2241,108 @@ static void InitKeyboard(void) // - ASCII chars (K_XLATE) // - UNICODE chars (K_UNICODE) ioctl(STDIN_FILENO, KDSKBMODE, K_XLATE); - - //http://lct.sourceforge.net/lct/x60.html - - keyboardMode = 2; // keycodes } // Register keyboard restore when program finishes atexit(RestoreKeyboard); } +// Process keyboard inputs +// TODO: Most probably input reading and processing should be in a separate thread static void ProcessKeyboard(void) { + #define MAX_KEYBUFFER_SIZE 32 // Max size in bytes to read + // Keyboard input polling (fill keys[256] array with status) - int numKeysBuffer = 0; // Keys available on buffer - char keysBuffer[32]; // Max keys to be read at a time + int bufferByteCount = 0; // Bytes available on the buffer + char keysBuffer[MAX_KEYBUFFER_SIZE]; // Max keys to be read at a time // Reset pressed keys array for (int i = 0; i < 512; i++) currentKeyState[i] = 0; // Read availables keycodes from stdin - numKeysBuffer = read(STDIN_FILENO, keysBuffer, 32); // POSIX system call + bufferByteCount = read(STDIN_FILENO, keysBuffer, MAX_KEYBUFFER_SIZE); // POSIX system call - // Fill array with pressed keys - for (int i = 0; i < numKeysBuffer; i++) + // Fill all read bytes (looking for keys) + for (int i = 0; i < bufferByteCount; i++) { - //TraceLog(INFO, "Bytes on keysBuffer: %i", numKeysBuffer); - - int key = keysBuffer[i]; + TraceLog(DEBUG, "Bytes on keysBuffer: %i", bufferByteCount); + + //printf("Key(s) bytes: "); + //for (int i = 0; i < bufferByteCount; i++) printf("0x%02x ", keysBuffer[i]); + //printf("\n"); - if (keyboardMode == 2) // ASCII chars (K_XLATE mode) + // NOTE: If (key == 0x1b), depending on next key, it could be a special keymap code! + // Up -> 1b 5b 41 / Left -> 1b 5b 44 / Right -> 1b 5b 43 / Down -> 1b 5b 42 + if (keysBuffer[i] == 0x1b) { - // NOTE: If (key == 0x1b), depending on next key, it could be a special keymap code! - // Up -> 1b 5b 41 / Left -> 1b 5b 44 / Right -> 1b 5b 43 / Down -> 1b 5b 42 - if (key == 0x1b) + // Detect ESC to stop program + if (bufferByteCount == 1) currentKeyState[256] = 1; // raylib key: KEY_ESCAPE + else { - if (keysBuffer[i+1] == 0x5b) // Special function key + if (keysBuffer[i + 1] == 0x5b) // Special function key { - switch (keysBuffer[i+2]) + if ((keysBuffer[i + 2] == 0x5b) || (keysBuffer[i + 2] == 0x31) || (keysBuffer[i + 2] == 0x32)) { - case 0x41: currentKeyState[265] = 1; break; - case 0x42: currentKeyState[264] = 1; break; - case 0x43: currentKeyState[262] = 1; break; - case 0x44: currentKeyState[263] = 1; break; - default: break; + // Process special function keys (F1 - F12) + switch (keysBuffer[i + 3]) + { + case 0x41: currentKeyState[290] = 1; break; // raylib KEY_F1 + case 0x42: currentKeyState[291] = 1; break; // raylib KEY_F2 + case 0x43: currentKeyState[292] = 1; break; // raylib KEY_F3 + case 0x44: currentKeyState[293] = 1; break; // raylib KEY_F4 + case 0x45: currentKeyState[294] = 1; break; // raylib KEY_F5 + case 0x37: currentKeyState[295] = 1; break; // raylib KEY_F6 + case 0x38: currentKeyState[296] = 1; break; // raylib KEY_F7 + case 0x39: currentKeyState[297] = 1; break; // raylib KEY_F8 + case 0x30: currentKeyState[298] = 1; break; // raylib KEY_F9 + case 0x31: currentKeyState[299] = 1; break; // raylib KEY_F10 + case 0x33: currentKeyState[300] = 1; break; // raylib KEY_F11 + case 0x34: currentKeyState[301] = 1; break; // raylib KEY_F12 + default: break; + } + + if (keysBuffer[i + 2] == 0x5b) i += 4; + else if ((keysBuffer[i + 2] == 0x31) || (keysBuffer[i + 2] == 0x32)) i += 5; } + else + { + switch (keysBuffer[i + 2]) + { + case 0x41: currentKeyState[265] = 1; break; // raylib KEY_UP + case 0x42: currentKeyState[264] = 1; break; // raylib KEY_DOWN + case 0x43: currentKeyState[262] = 1; break; // raylib KEY_RIGHT + case 0x44: currentKeyState[263] = 1; break; // raylib KEY_LEFT + default: break; + } - i += 2; // Jump to next key - - // NOTE: Other special function keys (F1, F2...) are not contempled for this keyboardMode... - // ...or they are just not directly keymapped (CTRL, ALT, SHIFT) + i += 3; // Jump to next key + } + + // NOTE: Some keys are not directly keymapped (CTRL, ALT, SHIFT) } } - else if (key == 0x0a) currentKeyState[257] = 1; // raylib KEY_ENTER (don't mix with KEY_*) - else if (key == 0x7f) currentKeyState[259] = 1; - else - { - TraceLog(DEBUG, "Pressed key (ASCII): 0x%02x", key); - - currentKeyState[key] = 1; - } - - // Detect ESC to stop program - if ((key == 0x1b) && (numKeysBuffer == 1)) windowShouldClose = true; } - else if (keyboardMode == 1) // keycodes (K_MEDIUMRAW mode) + else if (keysBuffer[i] == 0x0a) currentKeyState[257] = 1; // raylib KEY_ENTER (don't mix with KEY_*) + else if (keysBuffer[i] == 0x7f) currentKeyState[259] = 1; // raylib KEY_BACKSPACE + else { - TraceLog(DEBUG, "Pressed key (keycode): 0x%02x", key); - - // NOTE: Each key is 7-bits (high bit in the byte is 0 for down, 1 for up) + TraceLog(DEBUG, "Pressed key (ASCII): 0x%02x", keysBuffer[i]); - // TODO: Review (or rewrite) this code... not clear... replace by events! - - int asciiKey = -1; - - // Convert keycode to some recognized key (ASCII or GLFW3 equivalent) - if (key < 128) asciiKey = (int)UnixKeycodeToASCII[key]; - - // Record equivalent key state - if ((asciiKey >= 0) && (asciiKey < 512)) currentKeyState[asciiKey] = 1; - - // In case of letter, we also activate lower case version - if ((asciiKey >= 65) && (asciiKey <=90)) currentKeyState[asciiKey + 32] = 1; - - // Detect KEY_ESC to stop program - if (key == 0x01) windowShouldClose = true; - } - - // Same functionality as GLFW3 KeyCallback() - /* - if (asciiKey == exitKey) windowShouldClose = true; - else if (key == GLFW_KEY_F12 && action == GLFW_PRESS) - { - TakeScreenshot(); + // Translate lowercase a-z letters to A-Z + if ((keysBuffer[i] >= 97) && (keysBuffer[i] <= 122)) + { + currentKeyState[(int)keysBuffer[i] - 32] = 1; + } + else currentKeyState[(int)keysBuffer[i]] = 1; } - */ } + + // Check exit key (same functionality as GLFW3 KeyCallback()) + if (currentKeyState[exitKey] == 1) windowShouldClose = true; + + // Check screen capture key + if (currentKeyState[301] == 1) TakeScreenshot(); // raylib key: KEY_F12 (GLFW_KEY_F12) } // Restore default keyboard input @@ -2414,10 +2415,12 @@ static void *MouseThread(void *arg) if ((mouse.buttons & XSIGN) > 0) mouseRelX = -1*(255 - mouseRelX); if ((mouse.buttons & YSIGN) > 0) mouseRelY = -1*(255 - mouseRelY); - // TODO: Mouse movement should not depend on screenWidth and screenHeight, normalize! - - mousePosition.x += (float)mouseRelX/MOUSE_SENSITIVITY; - mousePosition.y -= (float)mouseRelY/MOUSE_SENSITIVITY; + // NOTE: Mouse movement is normalized to not be screen resolution dependant + // We suppose 2*255 (max relative movement) is equivalent to screenWidth (max pixels width) + // Result after normalization is multiplied by MOUSE_SENSITIVITY factor + + mousePosition.x += (float)mouseRelX*((float)screenWidth/(2*255))*MOUSE_SENSITIVITY; + mousePosition.y -= (float)mouseRelY*((float)screenHeight/(2*255))*MOUSE_SENSITIVITY; if (mousePosition.x < 0) mousePosition.x = 0; if (mousePosition.y < 0) mousePosition.y = 0; @@ -2479,36 +2482,18 @@ static void *GamepadThread(void *arg) // Process gamepad events by type if (gamepadEvent.type == JS_EVENT_BUTTON) { + TraceLog(DEBUG, "Gamepad button: %i, value: %i", gamepadEvent.number, gamepadEvent.value); + if (gamepadEvent.number < MAX_GAMEPAD_BUTTONS) { - switch (gamepadEvent.value) - { - case 0: - case 1: gamepadButtons[gamepadEvent.number] = (int)gamepadEvent.value; break; - default: break; - } + // 1 - button pressed, 0 - button released + gamepadButtons[gamepadEvent.number] = (int)gamepadEvent.value; } - /* - switch (gamepadEvent.number) - { - case 0: // 1st Axis X - case 1: // 1st Axis Y - case 2: // 2st Axis X - case 3: // 2st Axis Y - case 4: - { - if (gamepadEvent.value == 1) // Button pressed, 0 release - { - - } - - } break; - // Buttons is similar, variable for every joystick - } - */ } else if (gamepadEvent.type == JS_EVENT_AXIS) { + TraceLog(DEBUG, "Gamepad axis: %i, value: %i", gamepadEvent.number, gamepadEvent.value); + if (gamepadEvent.number == joystickAxisX) gamepadAxisX = (int)gamepadEvent.value; if (gamepadEvent.number == joystickAxisY) gamepadAxisY = (int)gamepadEvent.value; /* @@ -2518,12 +2503,13 @@ static void *GamepadThread(void *arg) case 1: // 1st Axis Y case 2: // 2st Axis X case 3: // 2st Axis Y - // Buttons is similar, variable for every joystick } */ } } } + + return NULL; } #endif diff --git a/src/raylib.h b/src/raylib.h index 0dc8c6df..c4d4392d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -111,6 +111,8 @@ #define KEY_F8 297 #define KEY_F9 298 #define KEY_F10 299 +#define KEY_F11 300 +#define KEY_F12 301 #define KEY_LEFT_SHIFT 340 #define KEY_LEFT_CONTROL 341 #define KEY_LEFT_ALT 342 -- cgit v1.2.3 From 83459159f4c8622cefe93a062138e7e2391b6761 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 20 Feb 2016 19:01:41 +0100 Subject: Corrected compiler complaint --- src/gestures.c | 2 +- src/makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gestures.c b/src/gestures.c index 9028f43b..3638f23e 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -184,7 +184,7 @@ void ProcessGestureEvent(GestureEvent event) } else if (event.touchAction == TOUCH_MOVE) { - if ((currentGesture == GESTURE_DRAG)) eventTime = GetCurrentTime(); + if (currentGesture == GESTURE_DRAG) eventTime = GetCurrentTime(); if (!startMoving) { diff --git a/src/makefile b/src/makefile index 2d73e646..cab2ced0 100644 --- a/src/makefile +++ b/src/makefile @@ -94,7 +94,7 @@ endif ifeq ($(PLATFORM),PLATFORM_DESKTOP) OBJS = core.o rlgl.o glad.o shapes.o text.o textures.o models.o audio.o utils.o camera.o gestures.o stb_vorbis.o else - #GLAD only required on desktop platform + #GLAD only required on desktop platform OBJS = core.o rlgl.o shapes.o text.o textures.o models.o audio.o stb_vorbis.o utils.o camera.o gestures.o endif -- cgit v1.2.3 From 7b360d8579c63658ee05377b44d2e0b478d12b74 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 20 Feb 2016 20:25:01 +0100 Subject: Reorganized games folder Simplified to match raylib installer package folder structure --- games/arkanoid.c | 349 ++++++++++++++++ games/asteroids.c | 579 +++++++++++++++++++++++++ games/asteroids_survival.c | 383 +++++++++++++++++ games/floppy.c | 246 +++++++++++ games/gold_fever.c | 288 +++++++++++++ games/gorilas.c | 571 +++++++++++++++++++++++++ games/missile_commander.c | 539 ++++++++++++++++++++++++ games/pang.c | 630 ++++++++++++++++++++++++++++ games/samples/arkanoid.c | 349 ---------------- games/samples/asteroids.c | 579 ------------------------- games/samples/asteroids_survival.c | 383 ----------------- games/samples/floppy.c | 246 ----------- games/samples/gold_fever.c | 288 ------------- games/samples/gorilas.c | 571 ------------------------- games/samples/missile_commander.c | 539 ------------------------ games/samples/pang.c | 630 ---------------------------- games/samples/snake.c | 293 ------------- games/samples/space_invaders.c | 406 ------------------ games/samples/tetris.c | 836 ------------------------------------- games/snake.c | 293 +++++++++++++ games/space_invaders.c | 406 ++++++++++++++++++ games/tetris.c | 836 +++++++++++++++++++++++++++++++++++++ 22 files changed, 5120 insertions(+), 5120 deletions(-) create mode 100644 games/arkanoid.c create mode 100644 games/asteroids.c create mode 100644 games/asteroids_survival.c create mode 100644 games/floppy.c create mode 100644 games/gold_fever.c create mode 100644 games/gorilas.c create mode 100644 games/missile_commander.c create mode 100644 games/pang.c delete mode 100644 games/samples/arkanoid.c delete mode 100644 games/samples/asteroids.c delete mode 100644 games/samples/asteroids_survival.c delete mode 100644 games/samples/floppy.c delete mode 100644 games/samples/gold_fever.c delete mode 100644 games/samples/gorilas.c delete mode 100644 games/samples/missile_commander.c delete mode 100644 games/samples/pang.c delete mode 100644 games/samples/snake.c delete mode 100644 games/samples/space_invaders.c delete mode 100644 games/samples/tetris.c create mode 100644 games/snake.c create mode 100644 games/space_invaders.c create mode 100644 games/tetris.c diff --git a/games/arkanoid.c b/games/arkanoid.c new file mode 100644 index 00000000..f10f9383 --- /dev/null +++ b/games/arkanoid.c @@ -0,0 +1,349 @@ +/******************************************************************************************* +* +* raylib - sample game: arkanoid +* +* Sample game Marc Palau and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include +#include +#include +#include + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- + +#define PLAYER_MAX_LIFE 5 +#define LINES_OF_BRICKS 5 +#define BRICKS_PER_LINE 20 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum GameScreen { LOGO, TITLE, GAMEPLAY, ENDING } GameScreen; + +typedef struct Player { + Vector2 position; + Vector2 size; + int life; +} Player; + +typedef struct Ball { + Vector2 position; + Vector2 speed; + int radius; + bool active; +} Ball; + +typedef struct Brick { + Vector2 position; + bool active; +} Brick; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter; +static bool gameOver; +static bool pause; + +static Player player; +static Ball ball; +static Brick brick[LINES_OF_BRICKS][BRICKS_PER_LINE]; +static Vector2 brickSize; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +// Additional module functions +static void UpdateBall(void); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: arkanoid"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + brickSize = (Vector2){ GetScreenWidth()/BRICKS_PER_LINE, 40 }; + + // Initialize player + player.position = (Vector2){ screenWidth/2, screenHeight*7/8 }; + player.size = (Vector2){ screenWidth/10, 20 }; + player.life = PLAYER_MAX_LIFE; + + // Initialize ball + ball.position = (Vector2){ screenWidth/2, screenHeight*7/8 - 30 }; + ball.speed = (Vector2){ 0, 0 }; + ball.radius = 7; + ball.active = false; + + // Initialize bricks + int initialDownPosition = 50; + + for (int i = 0; i < LINES_OF_BRICKS; i++) + { + for (int j = 0; j < BRICKS_PER_LINE; j++) + { + brick[i][j].position = (Vector2){ j*brickSize.x + brickSize.x/2, i*brickSize.y + initialDownPosition }; + brick[i][j].active = true; + } + } +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + // Player movement + if (IsKeyDown(KEY_LEFT)) player.position.x -= 5; + if ((player.position.x - player.size.x/2) <= 0) player.position.x = player.size.x/2; + if (IsKeyDown(KEY_RIGHT)) player.position.x += 5; + if ((player.position.x + player.size.x/2) >= screenWidth) player.position.x = screenWidth - player.size.x/2; + + // Launch ball + if (!ball.active) + { + if (IsKeyPressed(KEY_SPACE)) + { + ball.active = true; + ball.speed = (Vector2){ 0, -5 }; + } + } + + UpdateBall(); + + // Game over logic + if (player.life <= 0) gameOver = true; + else + { + gameOver = true; + + for (int i = 0; i < LINES_OF_BRICKS; i++) + { + for (int j = 0; j < BRICKS_PER_LINE; j++) + { + if (brick[i][j].active) gameOver = false; + } + } + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } + + +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // Draw player bar + DrawRectangle(player.position.x - player.size.x/2, player.position.y - player.size.y/2, player.size.x, player.size.y, BLACK); + + // Draw player lives + for (int i = 0; i < player.life; i++) DrawRectangle(20 + 40*i, screenHeight - 30, 35, 10, LIGHTGRAY); + + // Draw ball + DrawCircleV(ball.position, ball.radius, MAROON); + + // Draw bricks + for (int i = 0; i < LINES_OF_BRICKS; i++) + { + for (int j = 0; j < BRICKS_PER_LINE; j++) + { + if (brick[i][j].active) + { + if ((i + j) % 2 == 0) DrawRectangle(brick[i][j].position.x - brickSize.x/2, brick[i][j].position.y - brickSize.y/2, brickSize.x, brickSize.y, GRAY); + else DrawRectangle(brick[i][j].position.x - brickSize.x/2, brick[i][j].position.y - brickSize.y/2, brickSize.x, brickSize.y, DARKGRAY); + } + } + } + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} + +//-------------------------------------------------------------------------------------- +// Additional module functions +//-------------------------------------------------------------------------------------- +static void UpdateBall() +{ + // Update position + if (ball.active) + { + ball.position.x += ball.speed.x; + ball.position.y += ball.speed.y; + } + else + { + ball.position = (Vector2){ player.position.x, screenHeight*7/8 - 30 }; + } + + // Bounce in x + if (((ball.position.x + ball.radius) >= screenWidth) || ((ball.position.x - ball.radius) <= 0)) ball.speed.x *= -1; + + // Bounce in y + if ((ball.position.y - ball.radius) <= 0) ball.speed.y *= -1; + + // Ball reaches bottom of the screen + if ((ball.position.y + ball.radius) >= screenHeight) + { + ball.speed = (Vector2){ 0, 0 }; + ball.active = false; + + player.life--; + } + + // Collision logic: ball vs player + if (CheckCollisionCircleRec(ball.position, ball.radius, + (Rectangle){ player.position.x - player.size.x/2, player.position.y - player.size.y/2, player.size.x, player.size.y})) + { + if (ball.speed.y > 0) + { + ball.speed.y *= -1; + ball.speed.x = (ball.position.x - player.position.x)/(player.size.x/2)*5; + } + } + + // Collision logic: ball vs bricks + for (int i = 0; i < LINES_OF_BRICKS; i++) + { + for (int j = 0; j < BRICKS_PER_LINE; j++) + { + if (brick[i][j].active) + { + // Hit below + if (((ball.position.y - ball.radius) <= (brick[i][j].position.y + brickSize.y/2)) && + ((ball.position.y - ball.radius) > (brick[i][j].position.y + brickSize.y/2 + ball.speed.y)) && + ((fabs(ball.position.x - brick[i][j].position.x)) < (brickSize.x/2 + ball.radius*2/3)) && (ball.speed.y < 0)) + { + brick[i][j].active = false; + ball.speed.y *= -1; + } + // Hit above + else if (((ball.position.y + ball.radius) >= (brick[i][j].position.y - brickSize.y/2)) && + ((ball.position.y + ball.radius) < (brick[i][j].position.y - brickSize.y/2 + ball.speed.y)) && + ((fabs(ball.position.x - brick[i][j].position.x)) < (brickSize.x/2 + ball.radius*2/3)) && (ball.speed.y > 0)) + { + brick[i][j].active = false; + ball.speed.y *= -1; + } + // Hit left + else if (((ball.position.x + ball.radius) >= (brick[i][j].position.x - brickSize.x/2)) && + ((ball.position.x + ball.radius) < (brick[i][j].position.x - brickSize.x/2 + ball.speed.x)) && + ((fabs(ball.position.y - brick[i][j].position.y)) < (brickSize.y/2 + ball.radius*2/3)) && (ball.speed.x > 0)) + { + brick[i][j].active = false; + ball.speed.x *= -1; + } + // Hit right + else if (((ball.position.x - ball.radius) <= (brick[i][j].position.x + brickSize.x/2)) && + ((ball.position.x - ball.radius) > (brick[i][j].position.x + brickSize.x/2 + ball.speed.x)) && + ((fabs(ball.position.y - brick[i][j].position.y)) < (brickSize.y/2 + ball.radius*2/3)) && (ball.speed.x < 0)) + { + brick[i][j].active = false; + ball.speed.x *= -1; + } + } + } + } +} \ No newline at end of file diff --git a/games/asteroids.c b/games/asteroids.c new file mode 100644 index 00000000..53ebbd8e --- /dev/null +++ b/games/asteroids.c @@ -0,0 +1,579 @@ +/******************************************************************************************* +* +* raylib - sample game: asteroids +* +* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define PLAYER_BASE_SIZE 20.0f +#define PLAYER_SPEED 6.0f +#define PLAYER_MAX_SHOOTS 10 + +#define METEORS_SPEED 2 +#define MAX_BIG_METEORS 4 +#define MAX_MEDIUM_METEORS 8 +#define MAX_SMALL_METEORS 16 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- + +typedef struct Player { + Vector2 position; + Vector2 speed; + float acceleration; + float rotation; + Vector3 collider; + Color color; +} Player; + +typedef struct Shoot { + Vector2 position; + Vector2 speed; + float radius; + float rotation; + int lifeSpawn; + bool active; + Color color; +} Shoot; + +typedef struct Meteor { + Vector2 position; + Vector2 speed; + float radius; + bool active; + Color color; +} Meteor; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter; +static bool gameOver; +static bool pause; +static bool victory; + +// NOTE: Defined triangle is isosceles with common angles of 70 degrees. +static float shipHeight; + +static Player player; +static Shoot shoot[PLAYER_MAX_SHOOTS]; +static Meteor bigMeteor[MAX_BIG_METEORS]; +static Meteor mediumMeteor[MAX_MEDIUM_METEORS]; +static Meteor smallMeteor[MAX_SMALL_METEORS]; + +static int countMediumMeteors; +static int countSmallMeteors; +static int meteorsDestroyed; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +static void InitShoot(Shoot shoot); +static void DrawSpaceship(Vector2 position, float rotation, Color color); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: asteroids"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + int posx, posy; + int velx, vely; + bool correctRange = false; + victory = false; + pause = false; + + shipHeight = (PLAYER_BASE_SIZE/2)/tanf(20*DEG2RAD); + + // Initialization player + player.position = (Vector2){screenWidth/2, screenHeight/2 - shipHeight/2}; + player.speed = (Vector2){0, 0}; + player.acceleration = 0; + player.rotation = 0; + player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12}; + player.color = LIGHTGRAY; + + meteorsDestroyed = 0; + + // Initialization shoot + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) + { + shoot[i].position = (Vector2){0, 0}; + shoot[i].speed = (Vector2){0, 0}; + shoot[i].radius = 2; + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + shoot[i].color = WHITE; + } + + for (int i = 0; i < MAX_BIG_METEORS; i++) + { + posx = GetRandomValue(0, screenWidth); + + while(!correctRange) + { + if (posx > screenWidth/2 - 150 && posx < screenWidth/2 + 150) posx = GetRandomValue(0, screenWidth); + else correctRange = true; + } + + correctRange = false; + + posy = GetRandomValue(0, screenHeight); + + while(!correctRange) + { + if (posy > screenHeight/2 - 150 && posy < screenHeight/2 + 150) posy = GetRandomValue(0, screenHeight); + else correctRange = true; + } + + bigMeteor[i].position = (Vector2){posx, posy}; + + correctRange = false; + velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + + while(!correctRange) + { + if (velx == 0 && vely == 0) + { + velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + } + else correctRange = true; + } + + bigMeteor[i].speed = (Vector2){velx, vely}; + bigMeteor[i].radius = 40; + bigMeteor[i].active = true; + bigMeteor[i].color = BLUE; + } + + for (int i = 0; i < MAX_MEDIUM_METEORS; i++) + { + mediumMeteor[i].position = (Vector2){-100, -100}; + mediumMeteor[i].speed = (Vector2){0,0}; + mediumMeteor[i].radius = 20; + mediumMeteor[i].active = false; + mediumMeteor[i].color = BLUE; + } + + for (int i = 0; i < MAX_SMALL_METEORS; i++) + { + smallMeteor[i].position = (Vector2){-100, -100}; + smallMeteor[i].speed = (Vector2){0,0}; + smallMeteor[i].radius = 10; + smallMeteor[i].active = false; + smallMeteor[i].color = BLUE; + } + + countMediumMeteors = 0; + countSmallMeteors = 0; +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + // Player logic + + // Rotation + if (IsKeyDown(KEY_LEFT)) player.rotation -= 5; + if (IsKeyDown(KEY_RIGHT)) player.rotation += 5; + + // Speed + player.speed.x = sin(player.rotation*DEG2RAD)*PLAYER_SPEED; + player.speed.y = cos(player.rotation*DEG2RAD)*PLAYER_SPEED; + + // Controller + if (IsKeyDown(KEY_UP)) + { + if (player.acceleration < 1) player.acceleration += 0.04f; + } + else + { + if (player.acceleration > 0) player.acceleration -= 0.02f; + else if (player.acceleration < 0) player.acceleration = 0; + } + if (IsKeyDown(KEY_DOWN)) + { + if (player.acceleration > 0) player.acceleration -= 0.04f; + else if (player.acceleration < 0) player.acceleration = 0; + } + + // Movement + player.position.x += (player.speed.x*player.acceleration); + player.position.y -= (player.speed.y*player.acceleration); + + // Wall behaviour for player + if (player.position.x > screenWidth + shipHeight) player.position.x = -(shipHeight); + else if (player.position.x < -(shipHeight)) player.position.x = screenWidth + shipHeight; + if (player.position.y > (screenHeight + shipHeight)) player.position.y = -(shipHeight); + else if (player.position.y < -(shipHeight)) player.position.y = screenHeight + shipHeight; + + // Activation of shoot + if (IsKeyPressed(KEY_SPACE)) + { + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) + { + if (!shoot[i].active) + { + shoot[i].position = (Vector2){ player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight) }; + shoot[i].active = true; + shoot[i].speed.x = 1.5*sin(player.rotation*DEG2RAD)*PLAYER_SPEED; + shoot[i].speed.y = 1.5*cos(player.rotation*DEG2RAD)*PLAYER_SPEED; + shoot[i].rotation = player.rotation; + break; + } + } + } + + // Shoot life timer + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) + { + if (shoot[i].active) shoot[i].lifeSpawn++; + } + + // Shot logic + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) + { + if (shoot[i].active) + { + // Movement + shoot[i].position.x += shoot[i].speed.x; + shoot[i].position.y -= shoot[i].speed.y; + + // Wall behaviour for shoot + if (shoot[i].position.x > screenWidth + shoot[i].radius) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + } + else if (shoot[i].position.x < 0 - shoot[i].radius) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + } + if (shoot[i].position.y > screenHeight + shoot[i].radius) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + } + else if (shoot[i].position.y < 0 - shoot[i].radius) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + } + + // Life of shoot + if (shoot[i].lifeSpawn >= 60) + { + shoot[i].position = (Vector2){0, 0}; + shoot[i].speed = (Vector2){0, 0}; + shoot[i].lifeSpawn = 0; + shoot[i].active = false; + } + } + } + + // Collision Player to meteors + player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12}; + + for (int a = 0; a < MAX_BIG_METEORS; a++) + { + if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, bigMeteor[a].position, bigMeteor[a].radius) && bigMeteor[a].active) gameOver = true; + } + + for (int a = 0; a < MAX_MEDIUM_METEORS; a++) + { + if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, mediumMeteor[a].position, mediumMeteor[a].radius) && mediumMeteor[a].active) gameOver = true; + } + + for (int a = 0; a < MAX_SMALL_METEORS; a++) + { + if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, smallMeteor[a].position, smallMeteor[a].radius) && smallMeteor[a].active) gameOver = true; + } + + // Meteor logic + for (int i = 0; i < MAX_BIG_METEORS; i++) + { + if (bigMeteor[i].active) + { + // movement + bigMeteor[i].position.x += bigMeteor[i].speed.x; + bigMeteor[i].position.y += bigMeteor[i].speed.y; + + // wall behaviour + if (bigMeteor[i].position.x > screenWidth + bigMeteor[i].radius) bigMeteor[i].position.x = -(bigMeteor[i].radius); + else if (bigMeteor[i].position.x < 0 - bigMeteor[i].radius) bigMeteor[i].position.x = screenWidth + bigMeteor[i].radius; + if (bigMeteor[i].position.y > screenHeight + bigMeteor[i].radius) bigMeteor[i].position.y = -(bigMeteor[i].radius); + else if (bigMeteor[i].position.y < 0 - bigMeteor[i].radius) bigMeteor[i].position.y = screenHeight + bigMeteor[i].radius; + } + } + + for (int i = 0; i < MAX_MEDIUM_METEORS; i++) + { + if (mediumMeteor[i].active) + { + // movement + mediumMeteor[i].position.x += mediumMeteor[i].speed.x; + mediumMeteor[i].position.y += mediumMeteor[i].speed.y; + + // wall behaviour + if (mediumMeteor[i].position.x > screenWidth + mediumMeteor[i].radius) mediumMeteor[i].position.x = -(mediumMeteor[i].radius); + else if (mediumMeteor[i].position.x < 0 - mediumMeteor[i].radius) mediumMeteor[i].position.x = screenWidth + mediumMeteor[i].radius; + if (mediumMeteor[i].position.y > screenHeight + mediumMeteor[i].radius) mediumMeteor[i].position.y = -(mediumMeteor[i].radius); + else if (mediumMeteor[i].position.y < 0 - mediumMeteor[i].radius) mediumMeteor[i].position.y = screenHeight + mediumMeteor[i].radius; + } + } + + for (int i = 0; i < MAX_SMALL_METEORS; i++) + { + if (smallMeteor[i].active) + { + // movement + smallMeteor[i].position.x += smallMeteor[i].speed.x; + smallMeteor[i].position.y += smallMeteor[i].speed.y; + + // wall behaviour + if (smallMeteor[i].position.x > screenWidth + smallMeteor[i].radius) smallMeteor[i].position.x = -(smallMeteor[i].radius); + else if (smallMeteor[i].position.x < 0 - smallMeteor[i].radius) smallMeteor[i].position.x = screenWidth + smallMeteor[i].radius; + if (smallMeteor[i].position.y > screenHeight + smallMeteor[i].radius) smallMeteor[i].position.y = -(smallMeteor[i].radius); + else if (smallMeteor[i].position.y < 0 - smallMeteor[i].radius) smallMeteor[i].position.y = screenHeight + smallMeteor[i].radius; + } + } + + // Collision behaviour + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) + { + if ((shoot[i].active)) + { + for (int a = 0; a < MAX_BIG_METEORS; a++) + { + if (bigMeteor[a].active && CheckCollisionCircles(shoot[i].position, shoot[i].radius, bigMeteor[a].position, bigMeteor[a].radius)) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + bigMeteor[a].active = false; + meteorsDestroyed++; + for (int j = 0; j < 2; j ++) + { + if (countMediumMeteors%2 == 0) + { + mediumMeteor[countMediumMeteors].position = (Vector2){bigMeteor[a].position.x, bigMeteor[a].position.y}; + mediumMeteor[countMediumMeteors].speed = (Vector2){cos(shoot[i].rotation*DEG2RAD)*METEORS_SPEED*-1, sin(shoot[i].rotation*DEG2RAD)*METEORS_SPEED*-1}; + } + else + { + mediumMeteor[countMediumMeteors].position = (Vector2){bigMeteor[a].position.x, bigMeteor[a].position.y}; + mediumMeteor[countMediumMeteors].speed = (Vector2){cos(shoot[i].rotation*DEG2RAD)*METEORS_SPEED, sin(shoot[i].rotation*DEG2RAD)*METEORS_SPEED}; + } + + mediumMeteor[countMediumMeteors].active = true; + countMediumMeteors ++; + } + //bigMeteor[a].position = (Vector2){-100, -100}; + bigMeteor[a].color = RED; + a = MAX_BIG_METEORS; + } + } + } + if ((shoot[i].active)) + { + for (int b = 0; b < MAX_MEDIUM_METEORS; b++) + { + if (mediumMeteor[b].active && CheckCollisionCircles(shoot[i].position, shoot[i].radius, mediumMeteor[b].position, mediumMeteor[b].radius)) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + mediumMeteor[b].active = false; + meteorsDestroyed++; + for (int j = 0; j < 2; j ++) + { + if (countSmallMeteors%2 == 0) + { + smallMeteor[countSmallMeteors].position = (Vector2){mediumMeteor[b].position.x, mediumMeteor[b].position.y}; + smallMeteor[countSmallMeteors].speed = (Vector2){cos(shoot[i].rotation*DEG2RAD)*METEORS_SPEED*-1, sin(shoot[i].rotation*DEG2RAD)*METEORS_SPEED*-1}; + } + else + { + smallMeteor[countSmallMeteors].position = (Vector2){mediumMeteor[b].position.x, mediumMeteor[b].position.y}; + smallMeteor[countSmallMeteors].speed = (Vector2){cos(shoot[i].rotation*DEG2RAD)*METEORS_SPEED, sin(shoot[i].rotation*DEG2RAD)*METEORS_SPEED}; + } + + smallMeteor[countSmallMeteors].active = true; + countSmallMeteors ++; + } + //mediumMeteor[b].position = (Vector2){-100, -100}; + mediumMeteor[b].color = GREEN; + b = MAX_MEDIUM_METEORS; + } + } + } + if ((shoot[i].active)) + { + for (int c = 0; c < MAX_SMALL_METEORS; c++) + { + if (smallMeteor[c].active && CheckCollisionCircles(shoot[i].position, shoot[i].radius, smallMeteor[c].position, smallMeteor[c].radius)) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + smallMeteor[c].active = false; + meteorsDestroyed++; + smallMeteor[c].color = YELLOW; + // smallMeteor[c].position = (Vector2){-100, -100}; + c = MAX_SMALL_METEORS; + } + } + } + } + } + + if (meteorsDestroyed == MAX_BIG_METEORS + MAX_MEDIUM_METEORS + MAX_SMALL_METEORS) victory = true; + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // Draw spaceship + Vector2 v1 = { player.position.x + sinf(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cosf(player.rotation*DEG2RAD)*(shipHeight) }; + Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; + Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; + DrawTriangle(v1, v2, v3, MAROON); + + // Draw meteors + for (int i = 0; i < MAX_BIG_METEORS; i++) + { + if (bigMeteor[i].active) DrawCircleV(bigMeteor[i].position, bigMeteor[i].radius, DARKGRAY); + else DrawCircleV(bigMeteor[i].position, bigMeteor[i].radius, Fade(LIGHTGRAY, 0.3f)); + } + + for (int i = 0; i < MAX_MEDIUM_METEORS; i++) + { + if (mediumMeteor[i].active) DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, GRAY); + else DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, Fade(LIGHTGRAY, 0.3f)); + } + + for (int i = 0; i < MAX_SMALL_METEORS; i++) + { + if (smallMeteor[i].active) DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, GRAY); + else DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, Fade(LIGHTGRAY, 0.3f)); + } + + // Draw shoot + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) + { + if (shoot[i].active) DrawCircleV(shoot[i].position, shoot[i].radius, BLACK); + } + + if (victory) DrawText("VICTORY", screenWidth/2 - MeasureText("VICTORY", 20)/2, screenHeight/2, 20, LIGHTGRAY); + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} \ No newline at end of file diff --git a/games/asteroids_survival.c b/games/asteroids_survival.c new file mode 100644 index 00000000..aa21112d --- /dev/null +++ b/games/asteroids_survival.c @@ -0,0 +1,383 @@ +/******************************************************************************************* +* +* raylib - sample game: asteroids survival +* +* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define PLAYER_BASE_SIZE 20.0f +#define PLAYER_SPEED 6.0f +#define PLAYER_MAX_SHOOTS 10 + +#define METEORS_SPEED 2 +#define MAX_MEDIUM_METEORS 8 +#define MAX_SMALL_METEORS 16 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- + +typedef struct Player { + Vector2 position; + Vector2 speed; + float acceleration; + float rotation; + Vector3 collider; + Color color; +} Player; + +typedef struct Meteor { + Vector2 position; + Vector2 speed; + float radius; + bool active; + Color color; +} Meteor; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter; +static bool gameOver; +static bool pause; + +// NOTE: Defined triangle is isosceles with common angles of 70 degrees. +static float shipHeight; + +static Player player; +static Meteor mediumMeteor[MAX_MEDIUM_METEORS]; +static Meteor smallMeteor[MAX_SMALL_METEORS]; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: asteroids survival"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + int posx, posy; + int velx, vely; + bool correctRange = false; + + pause = false; + + framesCounter = 0; + + shipHeight = (PLAYER_BASE_SIZE/2)/tanf(20*DEG2RAD); + + // Initialization player + player.position = (Vector2){screenWidth/2, screenHeight/2 - shipHeight/2}; + player.speed = (Vector2){0, 0}; + player.acceleration = 0; + player.rotation = 0; + player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12}; + player.color = LIGHTGRAY; + + for (int i = 0; i < MAX_MEDIUM_METEORS; i++) + { + posx = GetRandomValue(0, screenWidth); + + while(!correctRange) + { + if (posx > screenWidth/2 - 150 && posx < screenWidth/2 + 150) posx = GetRandomValue(0, screenWidth); + else correctRange = true; + } + + correctRange = false; + + posy = GetRandomValue(0, screenHeight); + + while(!correctRange) + { + if (posy > screenHeight/2 - 150 && posy < screenHeight/2 + 150) posy = GetRandomValue(0, screenHeight); + else correctRange = true; + } + + correctRange = false; + velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + + while(!correctRange) + { + if (velx == 0 && vely == 0) + { + velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + } + else correctRange = true; + } + mediumMeteor[i].position = (Vector2){posx, posy}; + mediumMeteor[i].speed = (Vector2){velx, vely}; + mediumMeteor[i].radius = 20; + mediumMeteor[i].active = true; + mediumMeteor[i].color = GREEN; + } + + for (int i = 0; i < MAX_SMALL_METEORS; i++) + { + posx = GetRandomValue(0, screenWidth); + + while(!correctRange) + { + if (posx > screenWidth/2 - 150 && posx < screenWidth/2 + 150) posx = GetRandomValue(0, screenWidth); + else correctRange = true; + } + + correctRange = false; + + posy = GetRandomValue(0, screenHeight); + + while(!correctRange) + { + if (posy > screenHeight/2 - 150 && posy < screenHeight/2 + 150) posy = GetRandomValue(0, screenHeight); + else correctRange = true; + } + + correctRange = false; + velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + + while(!correctRange) + { + if (velx == 0 && vely == 0) + { + velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); + } + else correctRange = true; + } + smallMeteor[i].position = (Vector2){posx, posy}; + smallMeteor[i].speed = (Vector2){velx, vely}; + smallMeteor[i].radius = 10; + smallMeteor[i].active = true; + smallMeteor[i].color = YELLOW; + } +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + framesCounter++; + + // Player logic + + // Rotation + if (IsKeyDown(KEY_LEFT)) player.rotation -= 5; + if (IsKeyDown(KEY_RIGHT)) player.rotation += 5; + + // Speed + player.speed.x = sin(player.rotation*DEG2RAD)*PLAYER_SPEED; + player.speed.y = cos(player.rotation*DEG2RAD)*PLAYER_SPEED; + + // Controller + if (IsKeyDown(KEY_UP)) + { + if (player.acceleration < 1) player.acceleration += 0.04f; + } + else + { + if (player.acceleration > 0) player.acceleration -= 0.02f; + else if (player.acceleration < 0) player.acceleration = 0; + } + if (IsKeyDown(KEY_DOWN)) + { + if (player.acceleration > 0) player.acceleration -= 0.04f; + else if (player.acceleration < 0) player.acceleration = 0; + } + + // Movement + player.position.x += (player.speed.x*player.acceleration); + player.position.y -= (player.speed.y*player.acceleration); + + // Wall behaviour for player + if (player.position.x > screenWidth + shipHeight) player.position.x = -(shipHeight); + else if (player.position.x < -(shipHeight)) player.position.x = screenWidth + shipHeight; + if (player.position.y > (screenHeight + shipHeight)) player.position.y = -(shipHeight); + else if (player.position.y < -(shipHeight)) player.position.y = screenHeight + shipHeight; + + // Collision Player to meteors + player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12}; + + for (int a = 0; a < MAX_MEDIUM_METEORS; a++) + { + if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, mediumMeteor[a].position, mediumMeteor[a].radius) && mediumMeteor[a].active) gameOver = true; + } + + for (int a = 0; a < MAX_SMALL_METEORS; a++) + { + if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, smallMeteor[a].position, smallMeteor[a].radius) && smallMeteor[a].active) gameOver = true; + } + + // Meteor logic + + for (int i = 0; i < MAX_MEDIUM_METEORS; i++) + { + if (mediumMeteor[i].active) + { + // movement + mediumMeteor[i].position.x += mediumMeteor[i].speed.x; + mediumMeteor[i].position.y += mediumMeteor[i].speed.y; + + // wall behaviour + if (mediumMeteor[i].position.x > screenWidth + mediumMeteor[i].radius) mediumMeteor[i].position.x = -(mediumMeteor[i].radius); + else if (mediumMeteor[i].position.x < 0 - mediumMeteor[i].radius) mediumMeteor[i].position.x = screenWidth + mediumMeteor[i].radius; + if (mediumMeteor[i].position.y > screenHeight + mediumMeteor[i].radius) mediumMeteor[i].position.y = -(mediumMeteor[i].radius); + else if (mediumMeteor[i].position.y < 0 - mediumMeteor[i].radius) mediumMeteor[i].position.y = screenHeight + mediumMeteor[i].radius; + } + } + + for (int i = 0; i < MAX_SMALL_METEORS; i++) + { + if (smallMeteor[i].active) + { + // movement + smallMeteor[i].position.x += smallMeteor[i].speed.x; + smallMeteor[i].position.y += smallMeteor[i].speed.y; + + // wall behaviour + if (smallMeteor[i].position.x > screenWidth + smallMeteor[i].radius) smallMeteor[i].position.x = -(smallMeteor[i].radius); + else if (smallMeteor[i].position.x < 0 - smallMeteor[i].radius) smallMeteor[i].position.x = screenWidth + smallMeteor[i].radius; + if (smallMeteor[i].position.y > screenHeight + smallMeteor[i].radius) smallMeteor[i].position.y = -(smallMeteor[i].radius); + else if (smallMeteor[i].position.y < 0 - smallMeteor[i].radius) smallMeteor[i].position.y = screenHeight + smallMeteor[i].radius; + } + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // Draw spaceship + Vector2 v1 = { player.position.x + sinf(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cosf(player.rotation*DEG2RAD)*(shipHeight) }; + Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; + Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; + DrawTriangle(v1, v2, v3, MAROON); + + // Draw meteor + for (int i = 0;i < MAX_MEDIUM_METEORS; i++) + { + if (mediumMeteor[i].active) DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, GRAY); + else DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, Fade(LIGHTGRAY, 0.3f)); + } + + for (int i = 0;i < MAX_SMALL_METEORS; i++) + { + if (smallMeteor[i].active) DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, DARKGRAY); + else DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, Fade(LIGHTGRAY, 0.3f)); + } + + DrawText(FormatText("TIME: %.02f", (float)framesCounter/60), 10, 10, 20, BLACK); + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} \ No newline at end of file diff --git a/games/floppy.c b/games/floppy.c new file mode 100644 index 00000000..f48ea235 --- /dev/null +++ b/games/floppy.c @@ -0,0 +1,246 @@ +/******************************************************************************************* +* +* raylib - sample game: floppy +* +* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define MAX_TUBES 100 +#define FLOPPY_RADIUS 24 +#define TUBES_WIDTH 80 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct Floppy { + Vector2 position; + int radius; + Color color; +} Floppy; + +typedef struct Tubes { + Rectangle rec; + Color color; + bool active; +} Tubes; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter; +static bool gameOver; +static bool pause; +static int score; +static int hiScore = 0; + +static Floppy floppy; +static Tubes tubes[MAX_TUBES*2]; +static Vector2 tubesPos[MAX_TUBES]; +static int tubesSpeedX; +static bool superfx; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: floppy"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + floppy.radius = FLOPPY_RADIUS; + floppy.position = (Vector2){80, screenHeight/2 - floppy.radius}; + tubesSpeedX = 2; + + for (int i = 0; i < MAX_TUBES; i++) + { + tubesPos[i].x = 400 + 280*i; + tubesPos[i].y = -GetRandomValue(0, 120); + } + + for (int i = 0; i < MAX_TUBES*2; i += 2) + { + tubes[i].rec.x = tubesPos[i/2].x; + tubes[i].rec.y = tubesPos[i/2].y; + tubes[i].rec.width = TUBES_WIDTH; + tubes[i].rec.height = 255; + + tubes[i+1].rec.x = tubesPos[i/2].x; + tubes[i+1].rec.y = 600 + tubesPos[i/2].y - 255; + tubes[i+1].rec.width = TUBES_WIDTH; + tubes[i+1].rec.height = 255; + + tubes[i/2].active = true; + } + + score = 0; + + gameOver = false; + superfx = false; + pause = false; +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + for (int i = 0; i < MAX_TUBES; i++) tubesPos[i].x -= tubesSpeedX; + + for (int i = 0; i < MAX_TUBES*2; i += 2) + { + tubes[i].rec.x = tubesPos[i/2].x; + tubes[i+1].rec.x = tubesPos[i/2].x; + } + + if (IsKeyDown(KEY_SPACE) && !gameOver) floppy.position.y -= 3; + else floppy.position.y += 1; + + // Check Collisions + for (int i = 0; i < MAX_TUBES*2; i++) + { + if (CheckCollisionCircleRec(floppy.position, floppy.radius, tubes[i].rec)) + { + gameOver = true; + pause = false; + } + else if ((tubesPos[i/2].x < floppy.position.x) && tubes[i/2].active && !gameOver) + { + score += 100; + tubes[i/2].active = false; + + superfx = true; + + if (score > hiScore) hiScore = score; + } + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + DrawCircle(floppy.position.x, floppy.position.y, floppy.radius, DARKGRAY); + + // Draw tubes + for (int i = 0; i < MAX_TUBES; i++) + { + DrawRectangle(tubes[i*2].rec.x, tubes[i*2].rec.y, tubes[i*2].rec.width, tubes[i*2].rec.height, GRAY); + DrawRectangle(tubes[i*2 + 1].rec.x, tubes[i*2 + 1].rec.y, tubes[i*2 + 1].rec.width, tubes[i*2 + 1].rec.height, GRAY); + } + + // Draw flashing fx (one frame only) + if (superfx) + { + DrawRectangle(0, 0, screenWidth, screenHeight, WHITE); + superfx = false; + } + + DrawText(FormatText("%04i", score), 20, 20, 40, GRAY); + DrawText(FormatText("HI-SCORE: %04i", hiScore), 20, 70, 20, LIGHTGRAY); + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} \ No newline at end of file diff --git a/games/gold_fever.c b/games/gold_fever.c new file mode 100644 index 00000000..5a435027 --- /dev/null +++ b/games/gold_fever.c @@ -0,0 +1,288 @@ +/******************************************************************************************* +* +* raylib - sample game: gold fever +* +* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct Player { + Vector2 position; + Vector2 speed; + int radius; +} Player; + +typedef struct Enemy { + Vector2 position; + Vector2 speed; + int radius; + int radiusBounds; + bool moveRight; // RAY: o__O +} Enemy; + +typedef struct Points { + Vector2 position; + int radius; + int value; + bool active; +} Points; + +typedef struct Home { + Rectangle rec; + bool active; + bool save; + Color color; +} Home; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter; +static bool gameOver; +static bool pause; +static int score; +static int hiScore = 0; + +static Player player; +static Enemy enemy; +static Points points; +static Home home; +static bool follow; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + + InitWindow(screenWidth, screenHeight, "sample game: gold fever"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + pause = false; + score = 0; + + player.position = (Vector2){50, 50}; + player.radius = 20; + player.speed = (Vector2){5, 5}; + + enemy.position = (Vector2){screenWidth - 50, screenHeight/2}; + enemy.radius = 20; + enemy.radiusBounds = 150; + enemy.speed = (Vector2){3, 3}; + enemy.moveRight = true; + follow = false; + + points.radius = 10; + points.position = (Vector2){GetRandomValue(points.radius, screenWidth - points.radius), GetRandomValue(points.radius, screenHeight - points.radius)}; + points.value = 100; + points.active = true; + + home.rec.width = 50; + home.rec.height = 50; + home.rec.x = GetRandomValue(0, screenWidth - home.rec.width); + home.rec.y = GetRandomValue(0, screenHeight - home.rec.height); + home.active = false; + home.save = false; +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + //Control player + if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x; + if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x; + if (IsKeyDown(KEY_UP)) player.position.y -= player.speed.y; + if (IsKeyDown(KEY_DOWN)) player.position.y += player.speed.y; + + //wall behaviour player + if (player.position.x - player.radius <= 0) player.position.x = player.radius; + if (player.position.x + player.radius >= screenWidth) player.position.x = screenWidth - player.radius; + if (player.position.y - player.radius <= 0) player.position.y = player.radius; + if (player.position.y + player.radius >= screenHeight) player.position.y = screenHeight - player.radius; + + //IA Enemy + if ( (follow || CheckCollisionCircles(player.position, player.radius, enemy.position, enemy.radiusBounds)) && !home.save) + { + if (player.position.x > enemy.position.x) enemy.position.x += enemy.speed.x; + if (player.position.x < enemy.position.x) enemy.position.x -= enemy.speed.x; + + if (player.position.y > enemy.position.y) enemy.position.y += enemy.speed.y; + if (player.position.y < enemy.position.y) enemy.position.y -= enemy.speed.y; + } + else + { + if (enemy.moveRight) enemy.position.x += enemy.speed.x; + else enemy.position.x -= enemy.speed.x; + } + + //wall behaviour enemy + if (enemy.position.x - enemy.radius <= 0) enemy.moveRight = true; + if (enemy.position.x + enemy.radius >= screenWidth) enemy.moveRight = false; + + if (enemy.position.x - enemy.radius <= 0) enemy.position.x = enemy.radius; + if (enemy.position.x + enemy.radius >= screenWidth) enemy.position.x = screenWidth - enemy.radius; + if (enemy.position.y - enemy.radius <= 0) enemy.position.y = enemy.radius; + if (enemy.position.y + enemy.radius >= screenHeight) enemy.position.y = screenHeight - enemy.radius; + + //Collisions + if (CheckCollisionCircles(player.position, player.radius, points.position, points.radius) && points.active) + { + follow = true; + points.active = false; + home.active = true; + } + + if (CheckCollisionCircles(player.position, player.radius, enemy.position, enemy.radius) && !home.save) + { + gameOver = true; + + if (hiScore < score) hiScore = score; + } + + if (CheckCollisionCircleRec(player.position, player.radius, home.rec)) + { + follow = false; + + if (!points.active) + { + score += points.value; + points.active = true; + enemy.speed.x += 0.5; + enemy.speed.y += 0.5; + points.position = (Vector2){GetRandomValue(points.radius, screenWidth - points.radius), GetRandomValue(points.radius, screenHeight - points.radius)}; + } + + home.save = true; + } + else home.save = false; + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + if (follow) + { + DrawRectangle(0, 0, screenWidth, screenHeight, RED); + DrawRectangle(10, 10, screenWidth - 20, screenHeight - 20, RAYWHITE); + } + + DrawRectangleLines(home.rec.x, home.rec.y, home.rec.width, home.rec.height, BLUE); + + DrawCircleLines(enemy.position.x, enemy.position.y, enemy.radiusBounds, RED); + DrawCircleV(enemy.position, enemy.radius, MAROON); + + DrawCircleV(player.position, player.radius, GRAY); + if (points.active) DrawCircleV(points.position, points.radius, GOLD); + + DrawText(FormatText("SCORE: %04i", score), 20, 15, 20, GRAY); + DrawText(FormatText("HI-SCORE: %04i", hiScore), 300, 15, 20, GRAY); + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} \ No newline at end of file diff --git a/games/gorilas.c b/games/gorilas.c new file mode 100644 index 00000000..86fd3f5b --- /dev/null +++ b/games/gorilas.c @@ -0,0 +1,571 @@ +/******************************************************************************************* +* +* raylib - sample game: gorilas +* +* Sample game Marc Palau and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include +#include +#include +#include + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define MAX_BUILDINGS 15 +#define MAX_EXPLOSIONS 200 +#define MAX_PLAYERS 2 + +#define BUILDING_RELATIVE_ERROR 30 // Building size random range % +#define BUILDING_MIN_RELATIVE_HEIGHT 20 // Minimum height in % of the screenHeight +#define BUILDING_MAX_RELATIVE_HEIGHT 60 // Maximum height in % of the screenHeight +#define BUILDING_MIN_GRAYSCALE_COLOR 120 // Minimum gray color for the buildings +#define BUILDING_MAX_GRAYSCALE_COLOR 200 // Maximum gray color for the buildings + +#define MIN_PLAYER_POSITION 5 // Minimum x position % +#define MAX_PLAYER_POSITION 20 // Maximum x position % + +#define GRAVITY 9.81f +#define DELTA_FPS 60 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct Player { + Vector2 position; + Vector2 size; + + Vector2 aimingPoint; + int aimingAngle; + int aimingPower; + + Vector2 previousPoint; + int previousAngle; + int previousPower; + + Vector2 impactPoint; + + bool isLeftTeam; // This player belongs to the left or to the right team + bool isPlayer; // If is a player or an AI + bool isAlive; +} Player; + +typedef struct Building { + Rectangle rectangle; + Color color; +} Building; + +typedef struct Explosion { + Vector2 position; + int radius; + bool active; +} Explosion; + +typedef struct Ball { + Vector2 position; + Vector2 speed; + int radius; + bool active; +} Ball; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static bool gameOver = false; +static bool pause = false; + +static Player player[MAX_PLAYERS]; +static Building building[MAX_BUILDINGS]; +static Explosion explosion[MAX_EXPLOSIONS]; +static Ball ball; + +static int playerTurn = 0; +static bool ballOnAir = false; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +// Additional module functions +static void InitBuildings(void); +static void InitPlayers(void); +static bool UpdatePlayer(int playerTurn); +static bool UpdateBall(int playerTurn); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: gorilas"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + // Init shoot + ball.radius = 10; + ballOnAir = false; + ball.active = false; + + InitBuildings(); + InitPlayers(); + + // Init explosions + for (int i = 0; i < MAX_EXPLOSIONS; i++) + { + explosion[i].position = (Vector2){ 0.0f, 0.0f }; + explosion[i].radius = 30; + explosion[i].active = false; + } +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + if (!ballOnAir) ballOnAir = UpdatePlayer(playerTurn); // If we are aiming + else + { + if (UpdateBall(playerTurn)) // If collision + { + // Game over logic + bool leftTeamAlive = false; + bool rightTeamAlive = false; + + for (int i = 0; i < MAX_PLAYERS; i++) + { + if (player[i].isAlive) + { + if (player[i].isLeftTeam) leftTeamAlive = true; + if (!player[i].isLeftTeam) rightTeamAlive = true; + } + } + + if (leftTeamAlive && rightTeamAlive) + { + ballOnAir = false; + ball.active = false; + + playerTurn++; + + if (playerTurn == MAX_PLAYERS) playerTurn = 0; + } + else + { + gameOver = true; + + // if (leftTeamAlive) left team wins + // if (rightTeamAlive) right team wins + } + } + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // Draw buildings + for (int i = 0; i < MAX_BUILDINGS; i++) DrawRectangleRec(building[i].rectangle, building[i].color); + + // Draw explosions + for (int i = 0; i < MAX_EXPLOSIONS; i++) + { + if (explosion[i].active) DrawCircle(explosion[i].position.x, explosion[i].position.y, explosion[i].radius, RAYWHITE); + } + + // Draw players + for (int i = 0; i < MAX_PLAYERS; i++) + { + if (player[i].isAlive) + { + if (player[i].isLeftTeam) DrawRectangle(player[i].position.x - player[i].size.x/2, player[i].position.y - player[i].size.y/2, + player[i].size.x, player[i].size.y, BLUE); + else DrawRectangle(player[i].position.x - player[i].size.x/2, player[i].position.y - player[i].size.y/2, + player[i].size.x, player[i].size.y, RED); + } + } + + // Draw ball + if (ball.active) DrawCircle(ball.position.x, ball.position.y, ball.radius, MAROON); + + // Draw the angle and the power of the aim, and the previous ones + if (!ballOnAir) + { + // Draw shot information + /* + if (player[playerTurn].isLeftTeam) + { + DrawText(FormatText("Previous Point %i, %i", (int)player[playerTurn].previousPoint.x, (int)player[playerTurn].previousPoint.y), 20, 20, 20, DARKBLUE); + DrawText(FormatText("Previous Angle %i", player[playerTurn].previousAngle), 20, 50, 20, DARKBLUE); + DrawText(FormatText("Previous Power %i", player[playerTurn].previousPower), 20, 80, 20, DARKBLUE); + DrawText(FormatText("Aiming Point %i, %i", (int)player[playerTurn].aimingPoint.x, (int)player[playerTurn].aimingPoint.y), 20, 110, 20, DARKBLUE); + DrawText(FormatText("Aiming Angle %i", player[playerTurn].aimingAngle), 20, 140, 20, DARKBLUE); + DrawText(FormatText("Aiming Power %i", player[playerTurn].aimingPower), 20, 170, 20, DARKBLUE); + } + else + { + DrawText(FormatText("Previous Point %i, %i", (int)player[playerTurn].previousPoint.x, (int)player[playerTurn].previousPoint.y), screenWidth*3/4, 20, 20, DARKBLUE); + DrawText(FormatText("Previous Angle %i", player[playerTurn].previousAngle), screenWidth*3/4, 50, 20, DARKBLUE); + DrawText(FormatText("Previous Power %i", player[playerTurn].previousPower), screenWidth*3/4, 80, 20, DARKBLUE); + DrawText(FormatText("Aiming Point %i, %i", (int)player[playerTurn].aimingPoint.x, (int)player[playerTurn].aimingPoint.y), screenWidth*3/4, 110, 20, DARKBLUE); + DrawText(FormatText("Aiming Angle %i", player[playerTurn].aimingAngle), screenWidth*3/4, 140, 20, DARKBLUE); + DrawText(FormatText("Aiming Power %i", player[playerTurn].aimingPower), screenWidth*3/4, 170, 20, DARKBLUE); + } + */ + + // Draw aim + if (player[playerTurn].isLeftTeam) + { + // Previous aiming + DrawTriangle((Vector2){ player[playerTurn].position.x - player[playerTurn].size.x/4, player[playerTurn].position.y - player[playerTurn].size.y/4 }, + (Vector2){ player[playerTurn].position.x + player[playerTurn].size.x/4, player[playerTurn].position.y + player[playerTurn].size.y/4 }, + player[playerTurn].previousPoint, GRAY); + + // Actual aiming + DrawTriangle((Vector2){ player[playerTurn].position.x - player[playerTurn].size.x/4, player[playerTurn].position.y - player[playerTurn].size.y/4 }, + (Vector2){ player[playerTurn].position.x + player[playerTurn].size.x/4, player[playerTurn].position.y + player[playerTurn].size.y/4 }, + player[playerTurn].aimingPoint, DARKBLUE); + } + else + { + // Previous aiming + DrawTriangle((Vector2){ player[playerTurn].position.x - player[playerTurn].size.x/4, player[playerTurn].position.y + player[playerTurn].size.y/4 }, + (Vector2){ player[playerTurn].position.x + player[playerTurn].size.x/4, player[playerTurn].position.y - player[playerTurn].size.y/4 }, + player[playerTurn].previousPoint, GRAY); + + // Actual aiming + DrawTriangle((Vector2){ player[playerTurn].position.x - player[playerTurn].size.x/4, player[playerTurn].position.y + player[playerTurn].size.y/4 }, + (Vector2){ player[playerTurn].position.x + player[playerTurn].size.x/4, player[playerTurn].position.y - player[playerTurn].size.y/4 }, + player[playerTurn].aimingPoint, MAROON); + } + } + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} + +//-------------------------------------------------------------------------------------- +// Additional module functions +//-------------------------------------------------------------------------------------- +static void InitBuildings(void) +{ + // Horizontal generation + int currentWidth = 0; + + // We make sure the absolute error randomly generated for each building, has as a minimum value the screenWidth. + // This way all the screen will be filled with buildings. Each building will have a different, random width. + + float relativeWidth = 100/(100 - BUILDING_RELATIVE_ERROR); + float buildingWidthMean = (screenWidth*relativeWidth/MAX_BUILDINGS) + 1; // We add one to make sure we will cover the whole screen. + + // Vertical generation + int currentHeighth = 0; + int grayLevel; + + // Creation + for (int i = 0; i < MAX_BUILDINGS; i++) + { + // Horizontal + building[i].rectangle.x = currentWidth; + building[i].rectangle.width = GetRandomValue(buildingWidthMean*(100 - BUILDING_RELATIVE_ERROR/2)/100 + 1, buildingWidthMean*(100 + BUILDING_RELATIVE_ERROR)/100); + + currentWidth += building[i].rectangle.width; + + // Vertical + currentHeighth = GetRandomValue(BUILDING_MIN_RELATIVE_HEIGHT, BUILDING_MAX_RELATIVE_HEIGHT); + building[i].rectangle.y = screenHeight - (screenHeight*currentHeighth/100); + building[i].rectangle.height = screenHeight*currentHeighth/100 + 1; + + // Color + grayLevel = GetRandomValue(BUILDING_MIN_GRAYSCALE_COLOR, BUILDING_MAX_GRAYSCALE_COLOR); + building[i].color = (Color){ grayLevel, grayLevel, grayLevel, 255 }; + } +} + +static void InitPlayers(void) +{ + for (int i = 0; i < MAX_PLAYERS; i++) + { + player[i].isAlive = true; + + // Decide the team of this player + if (i % 2 == 0) player[i].isLeftTeam = true; + else player[i].isLeftTeam = false; + + // Now there is no AI + player[i].isPlayer = true; + + // Set size, by default by now + player[i].size = (Vector2){ 40, 40 }; + + // Set position + if (player[i].isLeftTeam) player[i].position.x = GetRandomValue(screenWidth*MIN_PLAYER_POSITION/100, screenWidth*MAX_PLAYER_POSITION/100); + else player[i].position.x = screenWidth - GetRandomValue(screenWidth*MIN_PLAYER_POSITION/100, screenWidth*MAX_PLAYER_POSITION/100); + + for (int j = 0; j < MAX_BUILDINGS; j++) + { + if (building[j].rectangle.x > player[i].position.x) + { + // Set the player in the center of the building + player[i].position.x = building[j-1].rectangle.x + building[j-1].rectangle.width/2; + // Set the player at the top of the building + player[i].position.y = building[j-1].rectangle.y - player[i].size.y/2; + break; + } + } + + // Set statistics to 0 + player[i].aimingPoint = player[i].position; + player[i].previousAngle = 0; + player[i].previousPower = 0; + player[i].previousPoint = player[i].position; + player[i].aimingAngle = 0; + player[i].aimingPower = 0; + + player[i].impactPoint = (Vector2){ -100, -100 }; + } +} + +static bool UpdatePlayer(int playerTurn) +{ + // If we are aiming at the firing quadrant, we calculate the angle + if (GetMousePosition().y <= player[playerTurn].position.y) + { + // Left team + if (player[playerTurn].isLeftTeam && GetMousePosition().x >= player[playerTurn].position.x) + { + // Distance (calculating the fire power) + player[playerTurn].aimingPower = sqrt(pow(player[playerTurn].position.x - GetMousePosition().x, 2) + pow(player[playerTurn].position.y - GetMousePosition().y, 2)); + // Calculates the angle via arcsin + player[playerTurn].aimingAngle = asin((player[playerTurn].position.y - GetMousePosition().y)/player[playerTurn].aimingPower)*RAD2DEG; + // Point of the screen we are aiming at + player[playerTurn].aimingPoint = GetMousePosition(); + + // Ball fired + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + player[playerTurn].previousPoint = player[playerTurn].aimingPoint; + player[playerTurn].previousPower = player[playerTurn].aimingPower; + player[playerTurn].previousAngle = player[playerTurn].aimingAngle; + ball.position = player[playerTurn].position; + + return true; + } + } + // Right team + else if (!player[playerTurn].isLeftTeam && GetMousePosition().x <= player[playerTurn].position.x) + { + // Distance (calculating the fire power) + player[playerTurn].aimingPower = sqrt(pow(player[playerTurn].position.x - GetMousePosition().x, 2) + pow(player[playerTurn].position.y - GetMousePosition().y, 2)); + // Calculates the angle via arcsin + player[playerTurn].aimingAngle = asin((player[playerTurn].position.y - GetMousePosition().y)/player[playerTurn].aimingPower)*RAD2DEG; + // Point of the screen we are aiming at + player[playerTurn].aimingPoint = GetMousePosition(); + + // Ball fired + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + player[playerTurn].previousPoint = player[playerTurn].aimingPoint; + player[playerTurn].previousPower = player[playerTurn].aimingPower; + player[playerTurn].previousAngle = player[playerTurn].aimingAngle; + ball.position = player[playerTurn].position; + + return true; + } + } + else + { + player[playerTurn].aimingPoint = player[playerTurn].position; + player[playerTurn].aimingPower = 0; + player[playerTurn].aimingAngle = 0; + } + } + else + { + player[playerTurn].aimingPoint = player[playerTurn].position; + player[playerTurn].aimingPower = 0; + player[playerTurn].aimingAngle = 0; + } + + return false; +} + +static bool UpdateBall(int playerTurn) +{ + static int explosionNumber = 0; + + // Activate ball + if (!ball.active) + { + if (player[playerTurn].isLeftTeam) + { + ball.speed.x = cos(player[playerTurn].previousAngle*DEG2RAD)*player[playerTurn].previousPower*3/DELTA_FPS; + ball.speed.y = -sin(player[playerTurn].previousAngle*DEG2RAD)*player[playerTurn].previousPower*3/DELTA_FPS; + ball.active = true; + } + else + { + ball.speed.x = -cos(player[playerTurn].previousAngle*DEG2RAD)*player[playerTurn].previousPower*3/DELTA_FPS; + ball.speed.y = -sin(player[playerTurn].previousAngle*DEG2RAD)*player[playerTurn].previousPower*3/DELTA_FPS; + ball.active = true; + } + } + + ball.position.x += ball.speed.x; + ball.position.y += ball.speed.y; + ball.speed.y += GRAVITY/DELTA_FPS; + + // Collision + if (ball.position.x + ball.radius < 0) return true; + else if (ball.position.x - ball.radius > screenWidth) return true; + else + { + // Player collision + for (int i = 0; i < MAX_PLAYERS; i++) + { + if (CheckCollisionCircleRec(ball.position, ball.radius, (Rectangle){ player[i].position.x - player[i].size.x/2, player[i].position.y - player[i].size.y/2, + player[i].size.x, player[i].size.y })) + { + // We can't hit ourselves + if (i == playerTurn) return false; + else + { + // We set the impact point + player[playerTurn].impactPoint.x = ball.position.x; + player[playerTurn].impactPoint.y = ball.position.y + ball.radius; + + // We destroy the player + player[i].isAlive = false; + return true; + } + } + } + + // Building collision + // NOTE: We only check building collision if we are not inside an explosion + for (int i = 0; i < MAX_BUILDINGS; i++) + { + if (CheckCollisionCircles(ball.position, ball.radius, explosion[i].position, explosion[i].radius - ball.radius)) + { + return false; + } + } + + for (int i = 0; i < MAX_BUILDINGS; i++) + { + if (CheckCollisionCircleRec(ball.position, ball.radius, building[i].rectangle)) + { + // We set the impact point + player[playerTurn].impactPoint.x = ball.position.x; + player[playerTurn].impactPoint.y = ball.position.y + ball.radius; + + // We create an explosion + explosion[explosionNumber].position = player[playerTurn].impactPoint; + explosion[explosionNumber].active = true; + explosionNumber++; + + return true; + } + } + } + + return false; +} \ No newline at end of file diff --git a/games/missile_commander.c b/games/missile_commander.c new file mode 100644 index 00000000..6317c41a --- /dev/null +++ b/games/missile_commander.c @@ -0,0 +1,539 @@ +/******************************************************************************************* +* +* raylib - sample game: missile commander +* +* Sample game Marc Palau and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include +#include +#include +#include + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define MAX_MISSILES 100 +#define MAX_INTERCEPTORS 30 +#define MAX_EXPLOSIONS 100 +#define LAUNCHERS_AMOUNT 3 // Not a variable, should not be changed +#define BUILDINGS_AMOUNT 6 // Not a variable, should not be changed + +#define LAUNCHER_SIZE 80 +#define BUILDING_SIZE 60 +#define EXPLOSION_RADIUS 40 + +#define MISSILE_SPEED 1 +#define MISSILE_LAUNCH_FRAMES 80 +#define INTERCEPTOR_SPEED 10 +#define EXPLOSION_INCREASE_TIME 90 // In frames +#define EXPLOSION_TOTAL_TIME 210 // In frames + +#define EXPLOSION_COLOR (Color){ 125, 125, 125, 125 } + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct Missile { + Vector2 origin; + Vector2 position; + Vector2 objective; + Vector2 speed; + + bool active; +} Missile; + +typedef struct Interceptor { + Vector2 origin; + Vector2 position; + Vector2 objective; + Vector2 speed; + + bool active; +} Interceptor; + +typedef struct Explosion { + Vector2 position; + float radiusMultiplier; + int frame; + bool active; +} Explosion; + +typedef struct Launcher { + Vector2 position; + bool active; +} Launcher; + +typedef struct Building { + Vector2 position; + bool active; +} Building; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter = 0; +static bool gameOver = false; +static bool pause = false; +static int score = 0; + +static Missile missile[MAX_MISSILES]; +static Interceptor interceptor[MAX_INTERCEPTORS]; +static Explosion explosion[MAX_EXPLOSIONS]; +static Launcher launcher[LAUNCHERS_AMOUNT]; +static Building building[BUILDINGS_AMOUNT]; +static int explosionIndex = 0; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +// Additional module functions +static void UpdateOutgoingFire(); +static void UpdateIncomingFire(); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: missile commander"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//-------------------------------------------------------------------------------------- +// Game Module Functions Definition +//-------------------------------------------------------------------------------------- + +// Initialize game variables +void InitGame(void) +{ + // Initialize missiles + for (int i = 0; i < MAX_MISSILES; i++) + { + missile[i].origin = (Vector2){ 0, 0 }; + missile[i].speed = (Vector2){ 0, 0 }; + missile[i].position = (Vector2){ 0, 0 }; + + missile[i].active = false; + } + + // Initialize interceptors + for (int i = 0; i < MAX_INTERCEPTORS; i++) + { + interceptor[i].origin = (Vector2){ 0, 0 }; + interceptor[i].speed = (Vector2){ 0, 0 }; + interceptor[i].position = (Vector2){ 0, 0 }; + + interceptor[i].active = false; + } + + // Initialize explosions + for (int i = 0; i < MAX_EXPLOSIONS; i++) + { + explosion[i].position = (Vector2){ 0, 0 }; + explosion[i].frame = 0; + explosion[i].active = false; + } + + // Initialize buildings and launchers + int sparcing = screenWidth/(LAUNCHERS_AMOUNT + BUILDINGS_AMOUNT + 1); + + // Buildings and launchers placing + launcher[0].position = (Vector2){ 1*sparcing, screenHeight - LAUNCHER_SIZE/2 }; + building[0].position = (Vector2){ 2*sparcing, screenHeight - BUILDING_SIZE/2 }; + building[1].position = (Vector2){ 3*sparcing, screenHeight - BUILDING_SIZE/2 }; + building[2].position = (Vector2){ 4*sparcing, screenHeight - BUILDING_SIZE/2 }; + launcher[1].position = (Vector2){ 5*sparcing, screenHeight - LAUNCHER_SIZE/2 }; + building[3].position = (Vector2){ 6*sparcing, screenHeight - BUILDING_SIZE/2 }; + building[4].position = (Vector2){ 7*sparcing, screenHeight - BUILDING_SIZE/2 }; + building[5].position = (Vector2){ 8*sparcing, screenHeight - BUILDING_SIZE/2 }; + launcher[2].position = (Vector2){ 9*sparcing, screenHeight - LAUNCHER_SIZE/2 }; + + // Buildings and launchers activation + for (int i = 0; i < LAUNCHERS_AMOUNT; i++) launcher[i].active = true; + for (int i = 0; i < BUILDINGS_AMOUNT; i++) building[i].active = true; + + // Initialize game variables + score = 0; +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + framesCounter++; + + static + float distance; + + // Interceptors update + for (int i = 0; i < MAX_INTERCEPTORS; i++) + { + if (interceptor[i].active) + { + // Update position + interceptor[i].position.x += interceptor[i].speed.x; + interceptor[i].position.y += interceptor[i].speed.y; + + // Distance to objective + distance = sqrt( pow(interceptor[i].position.x - interceptor[i].objective.x, 2) + + pow(interceptor[i].position.y - interceptor[i].objective.y, 2)); + + if (distance < INTERCEPTOR_SPEED) + { + // Interceptor dissapears + interceptor[i].active = false; + + // Explosion + explosion[explosionIndex].position = interceptor[i].position; + explosion[explosionIndex].active = true; + explosion[explosionIndex].frame = 0; + explosionIndex++; + if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0; + + break; + } + } + } + + // Missiles update + for (int i = 0; i < MAX_MISSILES; i++) + { + if (missile[i].active) + { + // Update position + missile[i].position.x += missile[i].speed.x; + missile[i].position.y += missile[i].speed.y; + + // Collision and missile out of bounds + if (missile[i].position.y > screenHeight) missile[i].active = false; + else + { + // CHeck collision with launchers + for (int j = 0; j < LAUNCHERS_AMOUNT; j++) + { + if (launcher[j].active) + { + if (CheckCollisionPointRec(missile[i].position, (Rectangle){ launcher[j].position.x - LAUNCHER_SIZE/2, launcher[j].position.y - LAUNCHER_SIZE/2, + LAUNCHER_SIZE, LAUNCHER_SIZE })) + { + // Missile dissapears + missile[i].active = false; + + // Explosion and destroy building + launcher[j].active = false; + + explosion[explosionIndex].position = missile[i].position; + explosion[explosionIndex].active = true; + explosion[explosionIndex].frame = 0; + explosionIndex++; + if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0; + + break; + } + } + } + + // CHeck collision with buildings + for (int j = 0; j < BUILDINGS_AMOUNT; j++) + { + if (building[j].active) + { + if (CheckCollisionPointRec(missile[i].position, (Rectangle){ building[j].position.x - BUILDING_SIZE/2, building[j].position.y - BUILDING_SIZE/2, + BUILDING_SIZE, BUILDING_SIZE })) + { + // Missile dissapears + missile[i].active = false; + + // Explosion and destroy building + building[j].active = false; + + explosion[explosionIndex].position = missile[i].position; + explosion[explosionIndex].active = true; + explosion[explosionIndex].frame = 0; + explosionIndex++; + if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0; + + break; + } + } + } + + // CHeck collision with explosions + for (int j = 0; j < MAX_EXPLOSIONS; j++) + { + if (explosion[j].active) + { + if (CheckCollisionPointCircle(missile[i].position, explosion[j].position, EXPLOSION_RADIUS*explosion[j].radiusMultiplier)) + { + // Missile dissapears and we earn 100 points + missile[i].active = false; + score += 100; + + explosion[explosionIndex].position = missile[i].position; + explosion[explosionIndex].active = true; + explosion[explosionIndex].frame = 0; + explosionIndex++; + if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0; + + break; + } + } + } + } + } + } + + // Explosions update + for (int i = 0; i < MAX_EXPLOSIONS; i++) + { + if (explosion[i].active) + { + explosion[i].frame++; + + if (explosion[i].frame <= EXPLOSION_INCREASE_TIME) explosion[i].radiusMultiplier = explosion[i].frame/(float)EXPLOSION_INCREASE_TIME; + else if (explosion[i].frame <= EXPLOSION_TOTAL_TIME) explosion[i].radiusMultiplier = 1 - (explosion[i].frame - (float)EXPLOSION_INCREASE_TIME)/(float)EXPLOSION_TOTAL_TIME; + else + { + explosion[i].frame = 0; + explosion[i].active = false; + } + } + } + + // Fire logic + UpdateOutgoingFire(); + UpdateIncomingFire(); + + // Game over logic + int checker = 0; + + for (int i = 0; i < LAUNCHERS_AMOUNT; i++) + { + if (!launcher[i].active) checker++; + if (checker == LAUNCHERS_AMOUNT) gameOver = true; + } + + checker = 0; + for (int i = 0; i < BUILDINGS_AMOUNT; i++) + { + if (!building[i].active) checker++; + if (checker == BUILDINGS_AMOUNT) gameOver = true; + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // Draw missiles + for (int i = 0; i < MAX_MISSILES; i++) + { + if (missile[i].active) + { + DrawLine(missile[i].origin.x, missile[i].origin.y, missile[i].position.x, missile[i].position.y, RED); + + if (framesCounter % 16 < 8) DrawCircle(missile[i].position.x, missile[i].position.y, 3, YELLOW); + } + } + + // Draw interceptors + for (int i = 0; i < MAX_INTERCEPTORS; i++) + { + if (interceptor[i].active) + { + DrawLine(interceptor[i].origin.x, interceptor[i].origin.y, interceptor[i].position.x, interceptor[i].position.y, GREEN); + + if (framesCounter % 16 < 8) DrawCircle(interceptor[i].position.x, interceptor[i].position.y, 3, BLUE); + } + } + + // Draw explosions + for (int i = 0; i < MAX_EXPLOSIONS; i++) + { + if (explosion[i].active) DrawCircle(explosion[i].position.x, explosion[i].position.y, EXPLOSION_RADIUS*explosion[i].radiusMultiplier, EXPLOSION_COLOR); + } + + // Draw buildings and launchers + for (int i = 0; i < LAUNCHERS_AMOUNT; i++) + { + if (launcher[i].active) DrawRectangle(launcher[i].position.x - LAUNCHER_SIZE/2, launcher[i].position.y - LAUNCHER_SIZE/2, LAUNCHER_SIZE, LAUNCHER_SIZE, GRAY); + } + + for (int i = 0; i < BUILDINGS_AMOUNT; i++) + { + if (building[i].active) DrawRectangle(building[i].position.x - BUILDING_SIZE/2, building[i].position.y - BUILDING_SIZE/2, BUILDING_SIZE, BUILDING_SIZE, LIGHTGRAY); + } + + // Draw score + DrawText(FormatText("SCORE %4i", score), 20, 20, 40, LIGHTGRAY); + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} + +//-------------------------------------------------------------------------------------- +// Additional module functions +//-------------------------------------------------------------------------------------- +static void UpdateOutgoingFire() +{ + static int interceptorNumber = 0; + int launcherShooting = 0; + + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) launcherShooting = 1; + if (IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) launcherShooting = 2; + if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) launcherShooting = 3; + + if (launcherShooting > 0 && launcher[launcherShooting - 1].active) + { + float module; + float sideX; + float sideY; + + // Activate the interceptor + interceptor[interceptorNumber].active = true; + + // Assign start position + interceptor[interceptorNumber].origin = launcher[launcherShooting - 1].position; + interceptor[interceptorNumber].position = interceptor[interceptorNumber].origin; + interceptor[interceptorNumber].objective = GetMousePosition(); + + // Calculate speed + module = sqrt( pow(interceptor[interceptorNumber].objective.x - interceptor[interceptorNumber].origin.x, 2) + + pow(interceptor[interceptorNumber].objective.y - interceptor[interceptorNumber].origin.y, 2)); + + sideX = (interceptor[interceptorNumber].objective.x - interceptor[interceptorNumber].origin.x)*INTERCEPTOR_SPEED/module; + sideY = (interceptor[interceptorNumber].objective.y - interceptor[interceptorNumber].origin.y)*INTERCEPTOR_SPEED/module; + + interceptor[interceptorNumber].speed = (Vector2){ sideX, sideY }; + + // Update + interceptorNumber++; + if (interceptorNumber == MAX_INTERCEPTORS) interceptorNumber = 0; + } +} + +static void UpdateIncomingFire() +{ + static int missileIndex = 0; + + // Launch missile + if (framesCounter % MISSILE_LAUNCH_FRAMES == 0) + { + float module; + float sideX; + float sideY; + + // Activate the missile + missile[missileIndex].active = true; + + // Assign start position + missile[missileIndex].origin = (Vector2){ GetRandomValue(20, screenWidth - 20), -10 }; + missile[missileIndex].position = missile[missileIndex].origin; + missile[missileIndex].objective = (Vector2){ GetRandomValue(20, screenWidth - 20), screenHeight + 10 }; + + // Calculate speed + module = sqrt( pow(missile[missileIndex].objective.x - missile[missileIndex].origin.x, 2) + + pow(missile[missileIndex].objective.y - missile[missileIndex].origin.y, 2)); + + sideX = (missile[missileIndex].objective.x - missile[missileIndex].origin.x)*MISSILE_SPEED/module; + sideY = (missile[missileIndex].objective.y - missile[missileIndex].origin.y)*MISSILE_SPEED/module; + + missile[missileIndex].speed = (Vector2){ sideX, sideY }; + + // Update + missileIndex++; + if (missileIndex == MAX_MISSILES) missileIndex = 0; + } +} \ No newline at end of file diff --git a/games/pang.c b/games/pang.c new file mode 100644 index 00000000..fe1c3005 --- /dev/null +++ b/games/pang.c @@ -0,0 +1,630 @@ +/******************************************************************************************* +* +* raylib - sample game: pang +* +* Sample game developed by Ian Eito and Albert Martos and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define PLAYER_BASE_SIZE 20.0f +#define PLAYER_SPEED 5.0f +#define PLAYER_MAX_SHOOTS 1 + +#define MAX_BIG_BALLS 2 +#define BALLS_SPEED 2.0f + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- + +typedef struct Player { + Vector2 position; + Vector2 speed; + Vector3 collider; + float rotation; +} Player; + +typedef struct Shoot { + Vector2 position; + Vector2 speed; + float radius; + float rotation; + int lifeSpawn; + bool active; +} Shoot; + +typedef struct Ball { + Vector2 position; + Vector2 speed; + float radius; + int points; + bool active; +} Ball; + +typedef struct Points { + Vector2 position; + int value; + float alpha; +} Points; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter; +static bool gameOver; +static bool pause; +static int score; + +static Player player; +static Shoot shoot[PLAYER_MAX_SHOOTS]; +static Ball bigBalls[MAX_BIG_BALLS]; +static Ball mediumBalls[MAX_BIG_BALLS*2]; +static Ball smallBalls[MAX_BIG_BALLS*4]; +static Points points[5]; + +// NOTE: Defined triangle is isosceles with common angles of 70 degrees. +static float shipHeight; +static float gravity; + +static int countmediumBallss; +static int countsmallBallss; +static int meteorsDestroyed; +static Vector2 linePosition; + +static bool victory; +static bool lose; +static bool awake; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + InitWindow(screenWidth, screenHeight, "sample game: pang"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +static void InitGame(void) +{ + int posx, posy; + int velx = 0; + int vely = 0; + + framesCounter = 0; + gameOver = false; + pause = false; + score = 0; + + victory = false; + lose = false; + awake = true; + gravity = 0.25f; + + linePosition = (Vector2){ 0.0f , 0.0f }; + shipHeight = (PLAYER_BASE_SIZE/2)/tanf(20*DEG2RAD); + + // Initialization player + player.position = (Vector2){ screenWidth/2, screenHeight }; + player.speed = (Vector2){ PLAYER_SPEED, PLAYER_SPEED }; + player.rotation = 0; + player.collider = (Vector3){ player.position.x, player.position.y - shipHeight/2.0f, 12.0f }; + + meteorsDestroyed = 0; + + // Initialize shoots + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) + { + shoot[i].position = (Vector2){ 0, 0 }; + shoot[i].speed = (Vector2){ 0, 0 }; + shoot[i].radius = 2; + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + } + + // Initialize big meteors + for (int i = 0; i < MAX_BIG_BALLS; i++) + { + bigBalls[i].radius = 40.0f; + posx = GetRandomValue(0 + bigBalls[i].radius, screenWidth - bigBalls[i].radius); + posy = GetRandomValue(0 + bigBalls[i].radius, screenHeight/2); + + bigBalls[i].position = (Vector2){ posx, posy }; + + while ((velx == 0) || (vely == 0)) + { + velx = GetRandomValue(-BALLS_SPEED, BALLS_SPEED); + vely = GetRandomValue(-BALLS_SPEED, BALLS_SPEED); + } + + bigBalls[i].speed = (Vector2){ velx, vely }; + bigBalls[i].points = 200; + bigBalls[i].active = true; + } + + // Initialize medium meteors + for (int i = 0; i < MAX_BIG_BALLS*2; i++) + { + mediumBalls[i].position = (Vector2){-100, -100}; + mediumBalls[i].speed = (Vector2){0,0}; + mediumBalls[i].radius = 20.0f; + mediumBalls[i].points = 100; + mediumBalls[i].active = false; + } + + // Initialize small meteors + for (int i = 0; i < MAX_BIG_BALLS*4; i++) + { + smallBalls[i].position = (Vector2){ -100, -100 }; + smallBalls[i].speed = (Vector2){ 0, 0 }; + smallBalls[i].radius = 10.0f; + smallBalls[i].points = 50; + smallBalls[i].active = false; + } + + // Initialize animated points + for (int i = 0; i < 5; i++) + { + points[i].position = (Vector2){ 0, 0 }; + points[i].value = 0; + points[i].alpha = 0.0f; + } + + countmediumBallss = 0; + countsmallBallss = 0; +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver && !victory) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + // Player logic + if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x; + if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x; + + // Player vs wall collision logic + if (player.position.x + PLAYER_BASE_SIZE/2 > screenWidth) player.position.x = screenWidth - PLAYER_BASE_SIZE/2; + else if (player.position.x - PLAYER_BASE_SIZE/2 < 0) player.position.x = 0 + PLAYER_BASE_SIZE/2; + + // Player shot logic + if (IsKeyPressed(KEY_SPACE)) + { + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) + { + if (!shoot[i].active) + { + shoot[i].position = (Vector2){ player.position.x, player.position.y - shipHeight }; + shoot[i].speed.y = PLAYER_SPEED; + shoot[i].active = true; + + linePosition = (Vector2){ player.position.x, player.position.y}; + + break; + } + } + } + + // Shoot life timer + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) + { + if (shoot[i].active) shoot[i].lifeSpawn++; + } + + // Shot logic + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) + { + if (shoot[i].active) + { + shoot[i].position.y -= shoot[i].speed.y; + + // Shot vs walls collision logic + if ((shoot[i].position.x > screenWidth + shoot[i].radius) || (shoot[i].position.x < 0 - shoot[i].radius) || + (shoot[i].position.y > screenHeight + shoot[i].radius) || (shoot[i].position.y < 0 - shoot[i].radius)) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + } + + // Player shot life spawn + if (shoot[i].lifeSpawn >= 120) + { + shoot[i].position = (Vector2){ 0.0f, 0.0f }; + shoot[i].speed = (Vector2){ 0.0f, 0.0f }; + shoot[i].lifeSpawn = 0; + shoot[i].active = false; + } + } + } + + // Player vs meteors collision logic + player.collider = (Vector3){player.position.x, player.position.y - shipHeight/2, 12}; + + for (int i = 0; i < MAX_BIG_BALLS; i++) + { + if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, bigBalls[i].position, bigBalls[i].radius) && bigBalls[i].active) + { + gameOver = true; + } + } + + for (int i = 0; i < MAX_BIG_BALLS*2; i++) + { + if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, mediumBalls[i].position, mediumBalls[i].radius) && mediumBalls[i].active) + { + gameOver = true; + } + } + + for (int i = 0; i < MAX_BIG_BALLS*4; i++) + { + if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, smallBalls[i].position, smallBalls[i].radius) && smallBalls[i].active) + { + gameOver = true; + } + } + + // Meteors logic (big) + for (int i = 0; i < MAX_BIG_BALLS; i++) + { + if (bigBalls[i].active) + { + // Meteor movement logic + bigBalls[i].position.x += bigBalls[i].speed.x; + bigBalls[i].position.y += bigBalls[i].speed.y; + + // Meteor vs wall collision logic + if (((bigBalls[i].position.x + bigBalls[i].radius) >= screenWidth) || ((bigBalls[i].position.x - bigBalls[i].radius) <= 0)) bigBalls[i].speed.x *= -1; + if ((bigBalls[i].position.y - bigBalls[i].radius) <= 0) bigBalls[i].speed.y *= -1.5; + + if ((bigBalls[i].position.y + bigBalls[i].radius) >= screenHeight) + { + bigBalls[i].speed.y *= -1; + bigBalls[i].position.y = screenHeight - bigBalls[i].radius; + } + + bigBalls[i].speed.y += gravity; + } + } + + // Meteors logic (medium) + for (int i = 0; i < MAX_BIG_BALLS*2; i++) + { + if (mediumBalls[i].active) + { + // Meteor movement logic + mediumBalls[i].position.x += mediumBalls[i].speed.x; + mediumBalls[i].position.y += mediumBalls[i].speed.y; + + // Meteor vs wall collision logic + if (mediumBalls[i].position.x + mediumBalls[i].radius >= screenWidth || mediumBalls[i].position.x - mediumBalls[i].radius <= 0) mediumBalls[i].speed.x *= -1; + if (mediumBalls[i].position.y - mediumBalls[i].radius <= 0) mediumBalls[i].speed.y *= -1; + if (mediumBalls[i].position.y + mediumBalls[i].radius >= screenHeight) + { + mediumBalls[i].speed.y *= -1; + mediumBalls[i].position.y = screenHeight - mediumBalls[i].radius; + } + + mediumBalls[i].speed.y += gravity + 0.12f; + } + } + + // Meteors logic (small) + for (int i = 0; i < MAX_BIG_BALLS*4; i++) + { + if (smallBalls[i].active) + { + // Meteor movement logic + smallBalls[i].position.x += smallBalls[i].speed.x; + smallBalls[i].position.y += smallBalls[i].speed.y; + + // Meteor vs wall collision logic + if (smallBalls[i].position.x + smallBalls[i].radius >= screenWidth || smallBalls[i].position.x - smallBalls[i].radius <= 0) smallBalls[i].speed.x *= -1; + if (smallBalls[i].position.y - smallBalls[i].radius <= 0) smallBalls[i].speed.y *= -1; + if (smallBalls[i].position.y + smallBalls[i].radius >= screenHeight) + { + smallBalls[i].speed.y *= -1; + smallBalls[i].position.y = screenHeight - smallBalls[i].radius; + } + + smallBalls[i].speed.y += gravity + 0.25f; + } + } + + // Player-shot vs meteors logic + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) + { + if ((shoot[i].active)) + { + for (int a = 0; a < MAX_BIG_BALLS; a++) + { + if (bigBalls[a].active && (bigBalls[a].position.x - bigBalls[a].radius <= linePosition.x && bigBalls[a].position.x + bigBalls[a].radius >= linePosition.x) + && (bigBalls[a].position.y + bigBalls[a].radius >= shoot[i].position.y)) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + bigBalls[a].active = false; + meteorsDestroyed++; + score += bigBalls[a].points; + + for (int z = 0; z < 5; z++) + { + if (points[z].alpha == 0.0f) + { + points[z].position = bigBalls[a].position; + points[z].value = bigBalls[a].points; + points[z].alpha = 1.0f; + z = 5; + } + } + + for (int j = 0; j < 2; j ++) + { + if ((countmediumBallss%2) == 0) + { + mediumBalls[countmediumBallss].position = (Vector2){bigBalls[a].position.x, bigBalls[a].position.y}; + mediumBalls[countmediumBallss].speed = (Vector2){ -1*BALLS_SPEED, BALLS_SPEED }; + } + else + { + mediumBalls[countmediumBallss].position = (Vector2){bigBalls[a].position.x, bigBalls[a].position.y}; + mediumBalls[countmediumBallss].speed = (Vector2){ BALLS_SPEED, BALLS_SPEED }; + } + + mediumBalls[countmediumBallss].active = true; + countmediumBallss ++; + } + + a = MAX_BIG_BALLS; + } + } + } + + if ((shoot[i].active)) + { + for (int b = 0; b < MAX_BIG_BALLS*2; b++) + { + if (mediumBalls[b].active && (mediumBalls[b].position.x - mediumBalls[b].radius <= linePosition.x && mediumBalls[b].position.x + mediumBalls[b].radius >= linePosition.x) + && (mediumBalls[b].position.y + mediumBalls[b].radius >= shoot[i].position.y)) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + mediumBalls[b].active = false; + meteorsDestroyed++; + score += mediumBalls[b].points; + + for (int z = 0; z < 5; z++) + { + if (points[z].alpha == 0.0f) + { + points[z].position = mediumBalls[b].position; + points[z].value = mediumBalls[b].points; + points[z].alpha = 1.0f; + z = 5; + } + } + + for (int j = 0; j < 2; j ++) + { + if (countsmallBallss%2 == 0) + { + smallBalls[countsmallBallss].position = (Vector2){mediumBalls[b].position.x, mediumBalls[b].position.y}; + smallBalls[countsmallBallss].speed = (Vector2){ BALLS_SPEED*-1, BALLS_SPEED*-1}; + } + else + { + smallBalls[countsmallBallss].position = (Vector2){mediumBalls[b].position.x, mediumBalls[b].position.y}; + smallBalls[countsmallBallss].speed = (Vector2){ BALLS_SPEED, BALLS_SPEED*-1}; + } + + smallBalls[countsmallBallss].active = true; + countsmallBallss ++; + } + + b = MAX_BIG_BALLS*2; + } + } + } + + if ((shoot[i].active)) + { + for (int c = 0; c < MAX_BIG_BALLS*4; c++) + { + if (smallBalls[c].active && (smallBalls[c].position.x - smallBalls[c].radius <= linePosition.x && smallBalls[c].position.x + smallBalls[c].radius >= linePosition.x) + && (smallBalls[c].position.y + smallBalls[c].radius >= shoot[i].position.y)) + { + shoot[i].active = false; + shoot[i].lifeSpawn = 0; + smallBalls[c].active = false; + meteorsDestroyed++; + score += smallBalls[c].points; + + for (int z = 0; z < 5; z++) + { + if (points[z].alpha == 0.0f) + { + points[z].position = smallBalls[c].position; + points[z].value = smallBalls[c].points; + points[z].alpha = 1.0f; + z = 5; + } + } + + c = MAX_BIG_BALLS*4; + } + } + } + } + + if (meteorsDestroyed == (MAX_BIG_BALLS + MAX_BIG_BALLS*2 + MAX_BIG_BALLS*4)) victory = true; + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } + + // Points move-up and fade logic + for (int z = 0; z < 5; z++) + { + if (points[z].alpha > 0.0f) + { + points[z].position.y -= 2; + points[z].alpha -= 0.02f; + } + + if (points[z].alpha < 0.0f) points[z].alpha = 0.0f; + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // Draw player + Vector2 v1 = { player.position.x + sinf(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cosf(player.rotation*DEG2RAD)*(shipHeight) }; + Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; + Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; + DrawTriangle(v1, v2, v3, MAROON); + + // Draw meteors (big) + for (int i = 0;i < MAX_BIG_BALLS; i++) + { + if (bigBalls[i].active) DrawCircleV(bigBalls[i].position, bigBalls[i].radius, DARKGRAY); + else DrawCircleV(bigBalls[i].position, bigBalls[i].radius, Fade(LIGHTGRAY, 0.3f)); + } + + // Draw meteors (medium) + for (int i = 0;i < MAX_BIG_BALLS*2; i++) + { + if (mediumBalls[i].active) DrawCircleV(mediumBalls[i].position, mediumBalls[i].radius, GRAY); + else DrawCircleV(mediumBalls[i].position, mediumBalls[i].radius, Fade(LIGHTGRAY, 0.3f)); + } + + // Draw meteors (small) + for (int i = 0;i < MAX_BIG_BALLS*4; i++) + { + if (smallBalls[i].active) DrawCircleV(smallBalls[i].position, smallBalls[i].radius, GRAY); + else DrawCircleV(smallBalls[i].position, smallBalls[i].radius, Fade(LIGHTGRAY, 0.3f)); + } + + // Draw shoot + for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) + { + if (shoot[i].active) DrawLine(linePosition.x, linePosition.y, shoot[i].position.x, shoot[i].position.y, RED); + } + + // Draw score points + for (int z = 0; z < 5; z++) + { + if (points[z].alpha > 0.0f) + { + DrawText(FormatText("+%02i", points[z].value), points[z].position.x, points[z].position.y, 20, Fade(BLUE, points[z].alpha)); + } + } + + // Draw score (UI) + DrawText(FormatText("SCORE: %i", score), 10, 10, 20, LIGHTGRAY); + + if (victory) + { + DrawText("YOU WIN!", screenWidth/2 - MeasureText("YOU WIN!", 60)/2, 100, 60, LIGHTGRAY); + DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, LIGHTGRAY); + } + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, LIGHTGRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, LIGHTGRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} \ No newline at end of file diff --git a/games/samples/arkanoid.c b/games/samples/arkanoid.c deleted file mode 100644 index f10f9383..00000000 --- a/games/samples/arkanoid.c +++ /dev/null @@ -1,349 +0,0 @@ -/******************************************************************************************* -* -* raylib - sample game: arkanoid -* -* Sample game Marc Palau and Ramon Santamaria -* -* This game has been created using raylib v1.3 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Copyright (c) 2015 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#include -#include -#include -#include - -#if defined(PLATFORM_WEB) - #include -#endif - -//---------------------------------------------------------------------------------- -// Some Defines -//---------------------------------------------------------------------------------- - -#define PLAYER_MAX_LIFE 5 -#define LINES_OF_BRICKS 5 -#define BRICKS_PER_LINE 20 - -//---------------------------------------------------------------------------------- -// Types and Structures Definition -//---------------------------------------------------------------------------------- -typedef enum GameScreen { LOGO, TITLE, GAMEPLAY, ENDING } GameScreen; - -typedef struct Player { - Vector2 position; - Vector2 size; - int life; -} Player; - -typedef struct Ball { - Vector2 position; - Vector2 speed; - int radius; - bool active; -} Ball; - -typedef struct Brick { - Vector2 position; - bool active; -} Brick; - -//------------------------------------------------------------------------------------ -// Global Variables Declaration -//------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; - -static int framesCounter; -static bool gameOver; -static bool pause; - -static Player player; -static Ball ball; -static Brick brick[LINES_OF_BRICKS][BRICKS_PER_LINE]; -static Vector2 brickSize; - -//------------------------------------------------------------------------------------ -// Module Functions Declaration (local) -//------------------------------------------------------------------------------------ -static void InitGame(void); // Initialize game -static void UpdateGame(void); // Update game (one frame) -static void DrawGame(void); // Draw game (one frame) -static void UnloadGame(void); // Unload game -static void UpdateDrawFrame(void); // Update and Draw (one frame) - -// Additional module functions -static void UpdateBall(void); - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - InitWindow(screenWidth, screenHeight, "sample game: arkanoid"); - - InitGame(); - -#if defined(PLATFORM_WEB) - emscripten_set_main_loop(UpdateDrawFrame, 0, 1); -#else - - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - UpdateGame(); - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - DrawGame(); - //---------------------------------------------------------------------------------- - } -#endif - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadGame(); // Unload loaded data (textures, sounds, models...) - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} - -//------------------------------------------------------------------------------------ -// Module Functions Definitions (local) -//------------------------------------------------------------------------------------ - -// Initialize game variables -void InitGame(void) -{ - brickSize = (Vector2){ GetScreenWidth()/BRICKS_PER_LINE, 40 }; - - // Initialize player - player.position = (Vector2){ screenWidth/2, screenHeight*7/8 }; - player.size = (Vector2){ screenWidth/10, 20 }; - player.life = PLAYER_MAX_LIFE; - - // Initialize ball - ball.position = (Vector2){ screenWidth/2, screenHeight*7/8 - 30 }; - ball.speed = (Vector2){ 0, 0 }; - ball.radius = 7; - ball.active = false; - - // Initialize bricks - int initialDownPosition = 50; - - for (int i = 0; i < LINES_OF_BRICKS; i++) - { - for (int j = 0; j < BRICKS_PER_LINE; j++) - { - brick[i][j].position = (Vector2){ j*brickSize.x + brickSize.x/2, i*brickSize.y + initialDownPosition }; - brick[i][j].active = true; - } - } -} - -// Update game (one frame) -void UpdateGame(void) -{ - if (!gameOver) - { - if (IsKeyPressed('P')) pause = !pause; - - if (!pause) - { - // Player movement - if (IsKeyDown(KEY_LEFT)) player.position.x -= 5; - if ((player.position.x - player.size.x/2) <= 0) player.position.x = player.size.x/2; - if (IsKeyDown(KEY_RIGHT)) player.position.x += 5; - if ((player.position.x + player.size.x/2) >= screenWidth) player.position.x = screenWidth - player.size.x/2; - - // Launch ball - if (!ball.active) - { - if (IsKeyPressed(KEY_SPACE)) - { - ball.active = true; - ball.speed = (Vector2){ 0, -5 }; - } - } - - UpdateBall(); - - // Game over logic - if (player.life <= 0) gameOver = true; - else - { - gameOver = true; - - for (int i = 0; i < LINES_OF_BRICKS; i++) - { - for (int j = 0; j < BRICKS_PER_LINE; j++) - { - if (brick[i][j].active) gameOver = false; - } - } - } - } - } - else - { - if (IsKeyPressed(KEY_ENTER)) - { - InitGame(); - gameOver = false; - } - } - - -} - -// Draw game (one frame) -void DrawGame(void) -{ - BeginDrawing(); - - ClearBackground(RAYWHITE); - - if (!gameOver) - { - // Draw player bar - DrawRectangle(player.position.x - player.size.x/2, player.position.y - player.size.y/2, player.size.x, player.size.y, BLACK); - - // Draw player lives - for (int i = 0; i < player.life; i++) DrawRectangle(20 + 40*i, screenHeight - 30, 35, 10, LIGHTGRAY); - - // Draw ball - DrawCircleV(ball.position, ball.radius, MAROON); - - // Draw bricks - for (int i = 0; i < LINES_OF_BRICKS; i++) - { - for (int j = 0; j < BRICKS_PER_LINE; j++) - { - if (brick[i][j].active) - { - if ((i + j) % 2 == 0) DrawRectangle(brick[i][j].position.x - brickSize.x/2, brick[i][j].position.y - brickSize.y/2, brickSize.x, brickSize.y, GRAY); - else DrawRectangle(brick[i][j].position.x - brickSize.x/2, brick[i][j].position.y - brickSize.y/2, brickSize.x, brickSize.y, DARKGRAY); - } - } - } - - if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); - } - else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); - - EndDrawing(); -} - -// Unload game variables -void UnloadGame(void) -{ - // TODO: Unload all dynamic loaded data (textures, sounds, models...) -} - -// Update and Draw (one frame) -void UpdateDrawFrame(void) -{ - UpdateGame(); - DrawGame(); -} - -//-------------------------------------------------------------------------------------- -// Additional module functions -//-------------------------------------------------------------------------------------- -static void UpdateBall() -{ - // Update position - if (ball.active) - { - ball.position.x += ball.speed.x; - ball.position.y += ball.speed.y; - } - else - { - ball.position = (Vector2){ player.position.x, screenHeight*7/8 - 30 }; - } - - // Bounce in x - if (((ball.position.x + ball.radius) >= screenWidth) || ((ball.position.x - ball.radius) <= 0)) ball.speed.x *= -1; - - // Bounce in y - if ((ball.position.y - ball.radius) <= 0) ball.speed.y *= -1; - - // Ball reaches bottom of the screen - if ((ball.position.y + ball.radius) >= screenHeight) - { - ball.speed = (Vector2){ 0, 0 }; - ball.active = false; - - player.life--; - } - - // Collision logic: ball vs player - if (CheckCollisionCircleRec(ball.position, ball.radius, - (Rectangle){ player.position.x - player.size.x/2, player.position.y - player.size.y/2, player.size.x, player.size.y})) - { - if (ball.speed.y > 0) - { - ball.speed.y *= -1; - ball.speed.x = (ball.position.x - player.position.x)/(player.size.x/2)*5; - } - } - - // Collision logic: ball vs bricks - for (int i = 0; i < LINES_OF_BRICKS; i++) - { - for (int j = 0; j < BRICKS_PER_LINE; j++) - { - if (brick[i][j].active) - { - // Hit below - if (((ball.position.y - ball.radius) <= (brick[i][j].position.y + brickSize.y/2)) && - ((ball.position.y - ball.radius) > (brick[i][j].position.y + brickSize.y/2 + ball.speed.y)) && - ((fabs(ball.position.x - brick[i][j].position.x)) < (brickSize.x/2 + ball.radius*2/3)) && (ball.speed.y < 0)) - { - brick[i][j].active = false; - ball.speed.y *= -1; - } - // Hit above - else if (((ball.position.y + ball.radius) >= (brick[i][j].position.y - brickSize.y/2)) && - ((ball.position.y + ball.radius) < (brick[i][j].position.y - brickSize.y/2 + ball.speed.y)) && - ((fabs(ball.position.x - brick[i][j].position.x)) < (brickSize.x/2 + ball.radius*2/3)) && (ball.speed.y > 0)) - { - brick[i][j].active = false; - ball.speed.y *= -1; - } - // Hit left - else if (((ball.position.x + ball.radius) >= (brick[i][j].position.x - brickSize.x/2)) && - ((ball.position.x + ball.radius) < (brick[i][j].position.x - brickSize.x/2 + ball.speed.x)) && - ((fabs(ball.position.y - brick[i][j].position.y)) < (brickSize.y/2 + ball.radius*2/3)) && (ball.speed.x > 0)) - { - brick[i][j].active = false; - ball.speed.x *= -1; - } - // Hit right - else if (((ball.position.x - ball.radius) <= (brick[i][j].position.x + brickSize.x/2)) && - ((ball.position.x - ball.radius) > (brick[i][j].position.x + brickSize.x/2 + ball.speed.x)) && - ((fabs(ball.position.y - brick[i][j].position.y)) < (brickSize.y/2 + ball.radius*2/3)) && (ball.speed.x < 0)) - { - brick[i][j].active = false; - ball.speed.x *= -1; - } - } - } - } -} \ No newline at end of file diff --git a/games/samples/asteroids.c b/games/samples/asteroids.c deleted file mode 100644 index 53ebbd8e..00000000 --- a/games/samples/asteroids.c +++ /dev/null @@ -1,579 +0,0 @@ -/******************************************************************************************* -* -* raylib - sample game: asteroids -* -* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria -* -* This game has been created using raylib v1.3 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Copyright (c) 2015 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#include - -#if defined(PLATFORM_WEB) - #include -#endif - -//---------------------------------------------------------------------------------- -// Some Defines -//---------------------------------------------------------------------------------- -#define PLAYER_BASE_SIZE 20.0f -#define PLAYER_SPEED 6.0f -#define PLAYER_MAX_SHOOTS 10 - -#define METEORS_SPEED 2 -#define MAX_BIG_METEORS 4 -#define MAX_MEDIUM_METEORS 8 -#define MAX_SMALL_METEORS 16 - -//---------------------------------------------------------------------------------- -// Types and Structures Definition -//---------------------------------------------------------------------------------- - -typedef struct Player { - Vector2 position; - Vector2 speed; - float acceleration; - float rotation; - Vector3 collider; - Color color; -} Player; - -typedef struct Shoot { - Vector2 position; - Vector2 speed; - float radius; - float rotation; - int lifeSpawn; - bool active; - Color color; -} Shoot; - -typedef struct Meteor { - Vector2 position; - Vector2 speed; - float radius; - bool active; - Color color; -} Meteor; - -//------------------------------------------------------------------------------------ -// Global Variables Declaration -//------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; - -static int framesCounter; -static bool gameOver; -static bool pause; -static bool victory; - -// NOTE: Defined triangle is isosceles with common angles of 70 degrees. -static float shipHeight; - -static Player player; -static Shoot shoot[PLAYER_MAX_SHOOTS]; -static Meteor bigMeteor[MAX_BIG_METEORS]; -static Meteor mediumMeteor[MAX_MEDIUM_METEORS]; -static Meteor smallMeteor[MAX_SMALL_METEORS]; - -static int countMediumMeteors; -static int countSmallMeteors; -static int meteorsDestroyed; - -//------------------------------------------------------------------------------------ -// Module Functions Declaration (local) -//------------------------------------------------------------------------------------ -static void InitGame(void); // Initialize game -static void UpdateGame(void); // Update game (one frame) -static void DrawGame(void); // Draw game (one frame) -static void UnloadGame(void); // Unload game -static void UpdateDrawFrame(void); // Update and Draw (one frame) - -static void InitShoot(Shoot shoot); -static void DrawSpaceship(Vector2 position, float rotation, Color color); - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - InitWindow(screenWidth, screenHeight, "sample game: asteroids"); - - InitGame(); - -#if defined(PLATFORM_WEB) - emscripten_set_main_loop(UpdateDrawFrame, 0, 1); -#else - - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - UpdateGame(); - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - DrawGame(); - //---------------------------------------------------------------------------------- - } -#endif - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadGame(); // Unload loaded data (textures, sounds, models...) - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} - -//------------------------------------------------------------------------------------ -// Module Functions Definitions (local) -//------------------------------------------------------------------------------------ - -// Initialize game variables -void InitGame(void) -{ - int posx, posy; - int velx, vely; - bool correctRange = false; - victory = false; - pause = false; - - shipHeight = (PLAYER_BASE_SIZE/2)/tanf(20*DEG2RAD); - - // Initialization player - player.position = (Vector2){screenWidth/2, screenHeight/2 - shipHeight/2}; - player.speed = (Vector2){0, 0}; - player.acceleration = 0; - player.rotation = 0; - player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12}; - player.color = LIGHTGRAY; - - meteorsDestroyed = 0; - - // Initialization shoot - for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) - { - shoot[i].position = (Vector2){0, 0}; - shoot[i].speed = (Vector2){0, 0}; - shoot[i].radius = 2; - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - shoot[i].color = WHITE; - } - - for (int i = 0; i < MAX_BIG_METEORS; i++) - { - posx = GetRandomValue(0, screenWidth); - - while(!correctRange) - { - if (posx > screenWidth/2 - 150 && posx < screenWidth/2 + 150) posx = GetRandomValue(0, screenWidth); - else correctRange = true; - } - - correctRange = false; - - posy = GetRandomValue(0, screenHeight); - - while(!correctRange) - { - if (posy > screenHeight/2 - 150 && posy < screenHeight/2 + 150) posy = GetRandomValue(0, screenHeight); - else correctRange = true; - } - - bigMeteor[i].position = (Vector2){posx, posy}; - - correctRange = false; - velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); - vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); - - while(!correctRange) - { - if (velx == 0 && vely == 0) - { - velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); - vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); - } - else correctRange = true; - } - - bigMeteor[i].speed = (Vector2){velx, vely}; - bigMeteor[i].radius = 40; - bigMeteor[i].active = true; - bigMeteor[i].color = BLUE; - } - - for (int i = 0; i < MAX_MEDIUM_METEORS; i++) - { - mediumMeteor[i].position = (Vector2){-100, -100}; - mediumMeteor[i].speed = (Vector2){0,0}; - mediumMeteor[i].radius = 20; - mediumMeteor[i].active = false; - mediumMeteor[i].color = BLUE; - } - - for (int i = 0; i < MAX_SMALL_METEORS; i++) - { - smallMeteor[i].position = (Vector2){-100, -100}; - smallMeteor[i].speed = (Vector2){0,0}; - smallMeteor[i].radius = 10; - smallMeteor[i].active = false; - smallMeteor[i].color = BLUE; - } - - countMediumMeteors = 0; - countSmallMeteors = 0; -} - -// Update game (one frame) -void UpdateGame(void) -{ - if (!gameOver) - { - if (IsKeyPressed('P')) pause = !pause; - - if (!pause) - { - // Player logic - - // Rotation - if (IsKeyDown(KEY_LEFT)) player.rotation -= 5; - if (IsKeyDown(KEY_RIGHT)) player.rotation += 5; - - // Speed - player.speed.x = sin(player.rotation*DEG2RAD)*PLAYER_SPEED; - player.speed.y = cos(player.rotation*DEG2RAD)*PLAYER_SPEED; - - // Controller - if (IsKeyDown(KEY_UP)) - { - if (player.acceleration < 1) player.acceleration += 0.04f; - } - else - { - if (player.acceleration > 0) player.acceleration -= 0.02f; - else if (player.acceleration < 0) player.acceleration = 0; - } - if (IsKeyDown(KEY_DOWN)) - { - if (player.acceleration > 0) player.acceleration -= 0.04f; - else if (player.acceleration < 0) player.acceleration = 0; - } - - // Movement - player.position.x += (player.speed.x*player.acceleration); - player.position.y -= (player.speed.y*player.acceleration); - - // Wall behaviour for player - if (player.position.x > screenWidth + shipHeight) player.position.x = -(shipHeight); - else if (player.position.x < -(shipHeight)) player.position.x = screenWidth + shipHeight; - if (player.position.y > (screenHeight + shipHeight)) player.position.y = -(shipHeight); - else if (player.position.y < -(shipHeight)) player.position.y = screenHeight + shipHeight; - - // Activation of shoot - if (IsKeyPressed(KEY_SPACE)) - { - for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) - { - if (!shoot[i].active) - { - shoot[i].position = (Vector2){ player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight) }; - shoot[i].active = true; - shoot[i].speed.x = 1.5*sin(player.rotation*DEG2RAD)*PLAYER_SPEED; - shoot[i].speed.y = 1.5*cos(player.rotation*DEG2RAD)*PLAYER_SPEED; - shoot[i].rotation = player.rotation; - break; - } - } - } - - // Shoot life timer - for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) - { - if (shoot[i].active) shoot[i].lifeSpawn++; - } - - // Shot logic - for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) - { - if (shoot[i].active) - { - // Movement - shoot[i].position.x += shoot[i].speed.x; - shoot[i].position.y -= shoot[i].speed.y; - - // Wall behaviour for shoot - if (shoot[i].position.x > screenWidth + shoot[i].radius) - { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - } - else if (shoot[i].position.x < 0 - shoot[i].radius) - { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - } - if (shoot[i].position.y > screenHeight + shoot[i].radius) - { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - } - else if (shoot[i].position.y < 0 - shoot[i].radius) - { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - } - - // Life of shoot - if (shoot[i].lifeSpawn >= 60) - { - shoot[i].position = (Vector2){0, 0}; - shoot[i].speed = (Vector2){0, 0}; - shoot[i].lifeSpawn = 0; - shoot[i].active = false; - } - } - } - - // Collision Player to meteors - player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12}; - - for (int a = 0; a < MAX_BIG_METEORS; a++) - { - if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, bigMeteor[a].position, bigMeteor[a].radius) && bigMeteor[a].active) gameOver = true; - } - - for (int a = 0; a < MAX_MEDIUM_METEORS; a++) - { - if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, mediumMeteor[a].position, mediumMeteor[a].radius) && mediumMeteor[a].active) gameOver = true; - } - - for (int a = 0; a < MAX_SMALL_METEORS; a++) - { - if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, smallMeteor[a].position, smallMeteor[a].radius) && smallMeteor[a].active) gameOver = true; - } - - // Meteor logic - for (int i = 0; i < MAX_BIG_METEORS; i++) - { - if (bigMeteor[i].active) - { - // movement - bigMeteor[i].position.x += bigMeteor[i].speed.x; - bigMeteor[i].position.y += bigMeteor[i].speed.y; - - // wall behaviour - if (bigMeteor[i].position.x > screenWidth + bigMeteor[i].radius) bigMeteor[i].position.x = -(bigMeteor[i].radius); - else if (bigMeteor[i].position.x < 0 - bigMeteor[i].radius) bigMeteor[i].position.x = screenWidth + bigMeteor[i].radius; - if (bigMeteor[i].position.y > screenHeight + bigMeteor[i].radius) bigMeteor[i].position.y = -(bigMeteor[i].radius); - else if (bigMeteor[i].position.y < 0 - bigMeteor[i].radius) bigMeteor[i].position.y = screenHeight + bigMeteor[i].radius; - } - } - - for (int i = 0; i < MAX_MEDIUM_METEORS; i++) - { - if (mediumMeteor[i].active) - { - // movement - mediumMeteor[i].position.x += mediumMeteor[i].speed.x; - mediumMeteor[i].position.y += mediumMeteor[i].speed.y; - - // wall behaviour - if (mediumMeteor[i].position.x > screenWidth + mediumMeteor[i].radius) mediumMeteor[i].position.x = -(mediumMeteor[i].radius); - else if (mediumMeteor[i].position.x < 0 - mediumMeteor[i].radius) mediumMeteor[i].position.x = screenWidth + mediumMeteor[i].radius; - if (mediumMeteor[i].position.y > screenHeight + mediumMeteor[i].radius) mediumMeteor[i].position.y = -(mediumMeteor[i].radius); - else if (mediumMeteor[i].position.y < 0 - mediumMeteor[i].radius) mediumMeteor[i].position.y = screenHeight + mediumMeteor[i].radius; - } - } - - for (int i = 0; i < MAX_SMALL_METEORS; i++) - { - if (smallMeteor[i].active) - { - // movement - smallMeteor[i].position.x += smallMeteor[i].speed.x; - smallMeteor[i].position.y += smallMeteor[i].speed.y; - - // wall behaviour - if (smallMeteor[i].position.x > screenWidth + smallMeteor[i].radius) smallMeteor[i].position.x = -(smallMeteor[i].radius); - else if (smallMeteor[i].position.x < 0 - smallMeteor[i].radius) smallMeteor[i].position.x = screenWidth + smallMeteor[i].radius; - if (smallMeteor[i].position.y > screenHeight + smallMeteor[i].radius) smallMeteor[i].position.y = -(smallMeteor[i].radius); - else if (smallMeteor[i].position.y < 0 - smallMeteor[i].radius) smallMeteor[i].position.y = screenHeight + smallMeteor[i].radius; - } - } - - // Collision behaviour - for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) - { - if ((shoot[i].active)) - { - for (int a = 0; a < MAX_BIG_METEORS; a++) - { - if (bigMeteor[a].active && CheckCollisionCircles(shoot[i].position, shoot[i].radius, bigMeteor[a].position, bigMeteor[a].radius)) - { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - bigMeteor[a].active = false; - meteorsDestroyed++; - for (int j = 0; j < 2; j ++) - { - if (countMediumMeteors%2 == 0) - { - mediumMeteor[countMediumMeteors].position = (Vector2){bigMeteor[a].position.x, bigMeteor[a].position.y}; - mediumMeteor[countMediumMeteors].speed = (Vector2){cos(shoot[i].rotation*DEG2RAD)*METEORS_SPEED*-1, sin(shoot[i].rotation*DEG2RAD)*METEORS_SPEED*-1}; - } - else - { - mediumMeteor[countMediumMeteors].position = (Vector2){bigMeteor[a].position.x, bigMeteor[a].position.y}; - mediumMeteor[countMediumMeteors].speed = (Vector2){cos(shoot[i].rotation*DEG2RAD)*METEORS_SPEED, sin(shoot[i].rotation*DEG2RAD)*METEORS_SPEED}; - } - - mediumMeteor[countMediumMeteors].active = true; - countMediumMeteors ++; - } - //bigMeteor[a].position = (Vector2){-100, -100}; - bigMeteor[a].color = RED; - a = MAX_BIG_METEORS; - } - } - } - if ((shoot[i].active)) - { - for (int b = 0; b < MAX_MEDIUM_METEORS; b++) - { - if (mediumMeteor[b].active && CheckCollisionCircles(shoot[i].position, shoot[i].radius, mediumMeteor[b].position, mediumMeteor[b].radius)) - { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - mediumMeteor[b].active = false; - meteorsDestroyed++; - for (int j = 0; j < 2; j ++) - { - if (countSmallMeteors%2 == 0) - { - smallMeteor[countSmallMeteors].position = (Vector2){mediumMeteor[b].position.x, mediumMeteor[b].position.y}; - smallMeteor[countSmallMeteors].speed = (Vector2){cos(shoot[i].rotation*DEG2RAD)*METEORS_SPEED*-1, sin(shoot[i].rotation*DEG2RAD)*METEORS_SPEED*-1}; - } - else - { - smallMeteor[countSmallMeteors].position = (Vector2){mediumMeteor[b].position.x, mediumMeteor[b].position.y}; - smallMeteor[countSmallMeteors].speed = (Vector2){cos(shoot[i].rotation*DEG2RAD)*METEORS_SPEED, sin(shoot[i].rotation*DEG2RAD)*METEORS_SPEED}; - } - - smallMeteor[countSmallMeteors].active = true; - countSmallMeteors ++; - } - //mediumMeteor[b].position = (Vector2){-100, -100}; - mediumMeteor[b].color = GREEN; - b = MAX_MEDIUM_METEORS; - } - } - } - if ((shoot[i].active)) - { - for (int c = 0; c < MAX_SMALL_METEORS; c++) - { - if (smallMeteor[c].active && CheckCollisionCircles(shoot[i].position, shoot[i].radius, smallMeteor[c].position, smallMeteor[c].radius)) - { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - smallMeteor[c].active = false; - meteorsDestroyed++; - smallMeteor[c].color = YELLOW; - // smallMeteor[c].position = (Vector2){-100, -100}; - c = MAX_SMALL_METEORS; - } - } - } - } - } - - if (meteorsDestroyed == MAX_BIG_METEORS + MAX_MEDIUM_METEORS + MAX_SMALL_METEORS) victory = true; - } - else - { - if (IsKeyPressed(KEY_ENTER)) - { - InitGame(); - gameOver = false; - } - } -} - -// Draw game (one frame) -void DrawGame(void) -{ - BeginDrawing(); - - ClearBackground(RAYWHITE); - - if (!gameOver) - { - // Draw spaceship - Vector2 v1 = { player.position.x + sinf(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cosf(player.rotation*DEG2RAD)*(shipHeight) }; - Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; - Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; - DrawTriangle(v1, v2, v3, MAROON); - - // Draw meteors - for (int i = 0; i < MAX_BIG_METEORS; i++) - { - if (bigMeteor[i].active) DrawCircleV(bigMeteor[i].position, bigMeteor[i].radius, DARKGRAY); - else DrawCircleV(bigMeteor[i].position, bigMeteor[i].radius, Fade(LIGHTGRAY, 0.3f)); - } - - for (int i = 0; i < MAX_MEDIUM_METEORS; i++) - { - if (mediumMeteor[i].active) DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, GRAY); - else DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, Fade(LIGHTGRAY, 0.3f)); - } - - for (int i = 0; i < MAX_SMALL_METEORS; i++) - { - if (smallMeteor[i].active) DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, GRAY); - else DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, Fade(LIGHTGRAY, 0.3f)); - } - - // Draw shoot - for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) - { - if (shoot[i].active) DrawCircleV(shoot[i].position, shoot[i].radius, BLACK); - } - - if (victory) DrawText("VICTORY", screenWidth/2 - MeasureText("VICTORY", 20)/2, screenHeight/2, 20, LIGHTGRAY); - - if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); - } - else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); - - EndDrawing(); -} - -// Unload game variables -void UnloadGame(void) -{ - // TODO: Unload all dynamic loaded data (textures, sounds, models...) -} - -// Update and Draw (one frame) -void UpdateDrawFrame(void) -{ - UpdateGame(); - DrawGame(); -} \ No newline at end of file diff --git a/games/samples/asteroids_survival.c b/games/samples/asteroids_survival.c deleted file mode 100644 index aa21112d..00000000 --- a/games/samples/asteroids_survival.c +++ /dev/null @@ -1,383 +0,0 @@ -/******************************************************************************************* -* -* raylib - sample game: asteroids survival -* -* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria -* -* This game has been created using raylib v1.3 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Copyright (c) 2015 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#include - -#if defined(PLATFORM_WEB) - #include -#endif - -//---------------------------------------------------------------------------------- -// Some Defines -//---------------------------------------------------------------------------------- -#define PLAYER_BASE_SIZE 20.0f -#define PLAYER_SPEED 6.0f -#define PLAYER_MAX_SHOOTS 10 - -#define METEORS_SPEED 2 -#define MAX_MEDIUM_METEORS 8 -#define MAX_SMALL_METEORS 16 - -//---------------------------------------------------------------------------------- -// Types and Structures Definition -//---------------------------------------------------------------------------------- - -typedef struct Player { - Vector2 position; - Vector2 speed; - float acceleration; - float rotation; - Vector3 collider; - Color color; -} Player; - -typedef struct Meteor { - Vector2 position; - Vector2 speed; - float radius; - bool active; - Color color; -} Meteor; - -//------------------------------------------------------------------------------------ -// Global Variables Declaration -//------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; - -static int framesCounter; -static bool gameOver; -static bool pause; - -// NOTE: Defined triangle is isosceles with common angles of 70 degrees. -static float shipHeight; - -static Player player; -static Meteor mediumMeteor[MAX_MEDIUM_METEORS]; -static Meteor smallMeteor[MAX_SMALL_METEORS]; - -//------------------------------------------------------------------------------------ -// Module Functions Declaration (local) -//------------------------------------------------------------------------------------ -static void InitGame(void); // Initialize game -static void UpdateGame(void); // Update game (one frame) -static void DrawGame(void); // Draw game (one frame) -static void UnloadGame(void); // Unload game -static void UpdateDrawFrame(void); // Update and Draw (one frame) - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - InitWindow(screenWidth, screenHeight, "sample game: asteroids survival"); - - InitGame(); - -#if defined(PLATFORM_WEB) - emscripten_set_main_loop(UpdateDrawFrame, 0, 1); -#else - - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - UpdateGame(); - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - DrawGame(); - //---------------------------------------------------------------------------------- - } -#endif - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadGame(); // Unload loaded data (textures, sounds, models...) - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} - -//------------------------------------------------------------------------------------ -// Module Functions Definitions (local) -//------------------------------------------------------------------------------------ - -// Initialize game variables -void InitGame(void) -{ - int posx, posy; - int velx, vely; - bool correctRange = false; - - pause = false; - - framesCounter = 0; - - shipHeight = (PLAYER_BASE_SIZE/2)/tanf(20*DEG2RAD); - - // Initialization player - player.position = (Vector2){screenWidth/2, screenHeight/2 - shipHeight/2}; - player.speed = (Vector2){0, 0}; - player.acceleration = 0; - player.rotation = 0; - player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12}; - player.color = LIGHTGRAY; - - for (int i = 0; i < MAX_MEDIUM_METEORS; i++) - { - posx = GetRandomValue(0, screenWidth); - - while(!correctRange) - { - if (posx > screenWidth/2 - 150 && posx < screenWidth/2 + 150) posx = GetRandomValue(0, screenWidth); - else correctRange = true; - } - - correctRange = false; - - posy = GetRandomValue(0, screenHeight); - - while(!correctRange) - { - if (posy > screenHeight/2 - 150 && posy < screenHeight/2 + 150) posy = GetRandomValue(0, screenHeight); - else correctRange = true; - } - - correctRange = false; - velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); - vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); - - while(!correctRange) - { - if (velx == 0 && vely == 0) - { - velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); - vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); - } - else correctRange = true; - } - mediumMeteor[i].position = (Vector2){posx, posy}; - mediumMeteor[i].speed = (Vector2){velx, vely}; - mediumMeteor[i].radius = 20; - mediumMeteor[i].active = true; - mediumMeteor[i].color = GREEN; - } - - for (int i = 0; i < MAX_SMALL_METEORS; i++) - { - posx = GetRandomValue(0, screenWidth); - - while(!correctRange) - { - if (posx > screenWidth/2 - 150 && posx < screenWidth/2 + 150) posx = GetRandomValue(0, screenWidth); - else correctRange = true; - } - - correctRange = false; - - posy = GetRandomValue(0, screenHeight); - - while(!correctRange) - { - if (posy > screenHeight/2 - 150 && posy < screenHeight/2 + 150) posy = GetRandomValue(0, screenHeight); - else correctRange = true; - } - - correctRange = false; - velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); - vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); - - while(!correctRange) - { - if (velx == 0 && vely == 0) - { - velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); - vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED); - } - else correctRange = true; - } - smallMeteor[i].position = (Vector2){posx, posy}; - smallMeteor[i].speed = (Vector2){velx, vely}; - smallMeteor[i].radius = 10; - smallMeteor[i].active = true; - smallMeteor[i].color = YELLOW; - } -} - -// Update game (one frame) -void UpdateGame(void) -{ - if (!gameOver) - { - if (IsKeyPressed('P')) pause = !pause; - - if (!pause) - { - framesCounter++; - - // Player logic - - // Rotation - if (IsKeyDown(KEY_LEFT)) player.rotation -= 5; - if (IsKeyDown(KEY_RIGHT)) player.rotation += 5; - - // Speed - player.speed.x = sin(player.rotation*DEG2RAD)*PLAYER_SPEED; - player.speed.y = cos(player.rotation*DEG2RAD)*PLAYER_SPEED; - - // Controller - if (IsKeyDown(KEY_UP)) - { - if (player.acceleration < 1) player.acceleration += 0.04f; - } - else - { - if (player.acceleration > 0) player.acceleration -= 0.02f; - else if (player.acceleration < 0) player.acceleration = 0; - } - if (IsKeyDown(KEY_DOWN)) - { - if (player.acceleration > 0) player.acceleration -= 0.04f; - else if (player.acceleration < 0) player.acceleration = 0; - } - - // Movement - player.position.x += (player.speed.x*player.acceleration); - player.position.y -= (player.speed.y*player.acceleration); - - // Wall behaviour for player - if (player.position.x > screenWidth + shipHeight) player.position.x = -(shipHeight); - else if (player.position.x < -(shipHeight)) player.position.x = screenWidth + shipHeight; - if (player.position.y > (screenHeight + shipHeight)) player.position.y = -(shipHeight); - else if (player.position.y < -(shipHeight)) player.position.y = screenHeight + shipHeight; - - // Collision Player to meteors - player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12}; - - for (int a = 0; a < MAX_MEDIUM_METEORS; a++) - { - if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, mediumMeteor[a].position, mediumMeteor[a].radius) && mediumMeteor[a].active) gameOver = true; - } - - for (int a = 0; a < MAX_SMALL_METEORS; a++) - { - if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, smallMeteor[a].position, smallMeteor[a].radius) && smallMeteor[a].active) gameOver = true; - } - - // Meteor logic - - for (int i = 0; i < MAX_MEDIUM_METEORS; i++) - { - if (mediumMeteor[i].active) - { - // movement - mediumMeteor[i].position.x += mediumMeteor[i].speed.x; - mediumMeteor[i].position.y += mediumMeteor[i].speed.y; - - // wall behaviour - if (mediumMeteor[i].position.x > screenWidth + mediumMeteor[i].radius) mediumMeteor[i].position.x = -(mediumMeteor[i].radius); - else if (mediumMeteor[i].position.x < 0 - mediumMeteor[i].radius) mediumMeteor[i].position.x = screenWidth + mediumMeteor[i].radius; - if (mediumMeteor[i].position.y > screenHeight + mediumMeteor[i].radius) mediumMeteor[i].position.y = -(mediumMeteor[i].radius); - else if (mediumMeteor[i].position.y < 0 - mediumMeteor[i].radius) mediumMeteor[i].position.y = screenHeight + mediumMeteor[i].radius; - } - } - - for (int i = 0; i < MAX_SMALL_METEORS; i++) - { - if (smallMeteor[i].active) - { - // movement - smallMeteor[i].position.x += smallMeteor[i].speed.x; - smallMeteor[i].position.y += smallMeteor[i].speed.y; - - // wall behaviour - if (smallMeteor[i].position.x > screenWidth + smallMeteor[i].radius) smallMeteor[i].position.x = -(smallMeteor[i].radius); - else if (smallMeteor[i].position.x < 0 - smallMeteor[i].radius) smallMeteor[i].position.x = screenWidth + smallMeteor[i].radius; - if (smallMeteor[i].position.y > screenHeight + smallMeteor[i].radius) smallMeteor[i].position.y = -(smallMeteor[i].radius); - else if (smallMeteor[i].position.y < 0 - smallMeteor[i].radius) smallMeteor[i].position.y = screenHeight + smallMeteor[i].radius; - } - } - } - } - else - { - if (IsKeyPressed(KEY_ENTER)) - { - InitGame(); - gameOver = false; - } - } -} - -// Draw game (one frame) -void DrawGame(void) -{ - BeginDrawing(); - - ClearBackground(RAYWHITE); - - if (!gameOver) - { - // Draw spaceship - Vector2 v1 = { player.position.x + sinf(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cosf(player.rotation*DEG2RAD)*(shipHeight) }; - Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; - Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; - DrawTriangle(v1, v2, v3, MAROON); - - // Draw meteor - for (int i = 0;i < MAX_MEDIUM_METEORS; i++) - { - if (mediumMeteor[i].active) DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, GRAY); - else DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, Fade(LIGHTGRAY, 0.3f)); - } - - for (int i = 0;i < MAX_SMALL_METEORS; i++) - { - if (smallMeteor[i].active) DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, DARKGRAY); - else DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, Fade(LIGHTGRAY, 0.3f)); - } - - DrawText(FormatText("TIME: %.02f", (float)framesCounter/60), 10, 10, 20, BLACK); - - if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); - } - else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); - - EndDrawing(); - //---------------------------------------------------------------------------------- -} - -// Unload game variables -void UnloadGame(void) -{ - // TODO: Unload all dynamic loaded data (textures, sounds, models...) -} - -// Update and Draw (one frame) -void UpdateDrawFrame(void) -{ - UpdateGame(); - DrawGame(); -} \ No newline at end of file diff --git a/games/samples/floppy.c b/games/samples/floppy.c deleted file mode 100644 index f48ea235..00000000 --- a/games/samples/floppy.c +++ /dev/null @@ -1,246 +0,0 @@ -/******************************************************************************************* -* -* raylib - sample game: floppy -* -* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria -* -* This game has been created using raylib v1.3 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Copyright (c) 2015 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#if defined(PLATFORM_WEB) - #include -#endif - -//---------------------------------------------------------------------------------- -// Some Defines -//---------------------------------------------------------------------------------- -#define MAX_TUBES 100 -#define FLOPPY_RADIUS 24 -#define TUBES_WIDTH 80 - -//---------------------------------------------------------------------------------- -// Types and Structures Definition -//---------------------------------------------------------------------------------- -typedef struct Floppy { - Vector2 position; - int radius; - Color color; -} Floppy; - -typedef struct Tubes { - Rectangle rec; - Color color; - bool active; -} Tubes; - -//------------------------------------------------------------------------------------ -// Global Variables Declaration -//------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; - -static int framesCounter; -static bool gameOver; -static bool pause; -static int score; -static int hiScore = 0; - -static Floppy floppy; -static Tubes tubes[MAX_TUBES*2]; -static Vector2 tubesPos[MAX_TUBES]; -static int tubesSpeedX; -static bool superfx; - -//------------------------------------------------------------------------------------ -// Module Functions Declaration (local) -//------------------------------------------------------------------------------------ -static void InitGame(void); // Initialize game -static void UpdateGame(void); // Update game (one frame) -static void DrawGame(void); // Draw game (one frame) -static void UnloadGame(void); // Unload game -static void UpdateDrawFrame(void); // Update and Draw (one frame) - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - InitWindow(screenWidth, screenHeight, "sample game: floppy"); - - InitGame(); - -#if defined(PLATFORM_WEB) - emscripten_set_main_loop(UpdateDrawFrame, 0, 1); -#else - - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - UpdateGame(); - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - DrawGame(); - //---------------------------------------------------------------------------------- - } -#endif - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadGame(); // Unload loaded data (textures, sounds, models...) - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} -//------------------------------------------------------------------------------------ -// Module Functions Definitions (local) -//------------------------------------------------------------------------------------ - -// Initialize game variables -void InitGame(void) -{ - floppy.radius = FLOPPY_RADIUS; - floppy.position = (Vector2){80, screenHeight/2 - floppy.radius}; - tubesSpeedX = 2; - - for (int i = 0; i < MAX_TUBES; i++) - { - tubesPos[i].x = 400 + 280*i; - tubesPos[i].y = -GetRandomValue(0, 120); - } - - for (int i = 0; i < MAX_TUBES*2; i += 2) - { - tubes[i].rec.x = tubesPos[i/2].x; - tubes[i].rec.y = tubesPos[i/2].y; - tubes[i].rec.width = TUBES_WIDTH; - tubes[i].rec.height = 255; - - tubes[i+1].rec.x = tubesPos[i/2].x; - tubes[i+1].rec.y = 600 + tubesPos[i/2].y - 255; - tubes[i+1].rec.width = TUBES_WIDTH; - tubes[i+1].rec.height = 255; - - tubes[i/2].active = true; - } - - score = 0; - - gameOver = false; - superfx = false; - pause = false; -} - -// Update game (one frame) -void UpdateGame(void) -{ - if (!gameOver) - { - if (IsKeyPressed('P')) pause = !pause; - - if (!pause) - { - for (int i = 0; i < MAX_TUBES; i++) tubesPos[i].x -= tubesSpeedX; - - for (int i = 0; i < MAX_TUBES*2; i += 2) - { - tubes[i].rec.x = tubesPos[i/2].x; - tubes[i+1].rec.x = tubesPos[i/2].x; - } - - if (IsKeyDown(KEY_SPACE) && !gameOver) floppy.position.y -= 3; - else floppy.position.y += 1; - - // Check Collisions - for (int i = 0; i < MAX_TUBES*2; i++) - { - if (CheckCollisionCircleRec(floppy.position, floppy.radius, tubes[i].rec)) - { - gameOver = true; - pause = false; - } - else if ((tubesPos[i/2].x < floppy.position.x) && tubes[i/2].active && !gameOver) - { - score += 100; - tubes[i/2].active = false; - - superfx = true; - - if (score > hiScore) hiScore = score; - } - } - } - } - else - { - if (IsKeyPressed(KEY_ENTER)) - { - InitGame(); - gameOver = false; - } - } -} - -// Draw game (one frame) -void DrawGame(void) -{ - BeginDrawing(); - - ClearBackground(RAYWHITE); - - if (!gameOver) - { - DrawCircle(floppy.position.x, floppy.position.y, floppy.radius, DARKGRAY); - - // Draw tubes - for (int i = 0; i < MAX_TUBES; i++) - { - DrawRectangle(tubes[i*2].rec.x, tubes[i*2].rec.y, tubes[i*2].rec.width, tubes[i*2].rec.height, GRAY); - DrawRectangle(tubes[i*2 + 1].rec.x, tubes[i*2 + 1].rec.y, tubes[i*2 + 1].rec.width, tubes[i*2 + 1].rec.height, GRAY); - } - - // Draw flashing fx (one frame only) - if (superfx) - { - DrawRectangle(0, 0, screenWidth, screenHeight, WHITE); - superfx = false; - } - - DrawText(FormatText("%04i", score), 20, 20, 40, GRAY); - DrawText(FormatText("HI-SCORE: %04i", hiScore), 20, 70, 20, LIGHTGRAY); - - if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); - } - else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); - - EndDrawing(); -} - -// Unload game variables -void UnloadGame(void) -{ - // TODO: Unload all dynamic loaded data (textures, sounds, models...) -} - -// Update and Draw (one frame) -void UpdateDrawFrame(void) -{ - UpdateGame(); - DrawGame(); -} \ No newline at end of file diff --git a/games/samples/gold_fever.c b/games/samples/gold_fever.c deleted file mode 100644 index 5a435027..00000000 --- a/games/samples/gold_fever.c +++ /dev/null @@ -1,288 +0,0 @@ -/******************************************************************************************* -* -* raylib - sample game: gold fever -* -* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria -* -* This game has been created using raylib v1.3 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Copyright (c) 2015 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#if defined(PLATFORM_WEB) - #include -#endif - -//---------------------------------------------------------------------------------- -// Types and Structures Definition -//---------------------------------------------------------------------------------- -typedef struct Player { - Vector2 position; - Vector2 speed; - int radius; -} Player; - -typedef struct Enemy { - Vector2 position; - Vector2 speed; - int radius; - int radiusBounds; - bool moveRight; // RAY: o__O -} Enemy; - -typedef struct Points { - Vector2 position; - int radius; - int value; - bool active; -} Points; - -typedef struct Home { - Rectangle rec; - bool active; - bool save; - Color color; -} Home; - -//------------------------------------------------------------------------------------ -// Global Variables Declaration -//------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; - -static int framesCounter; -static bool gameOver; -static bool pause; -static int score; -static int hiScore = 0; - -static Player player; -static Enemy enemy; -static Points points; -static Home home; -static bool follow; - -//------------------------------------------------------------------------------------ -// Module Functions Declaration (local) -//------------------------------------------------------------------------------------ -static void InitGame(void); // Initialize game -static void UpdateGame(void); // Update game (one frame) -static void DrawGame(void); // Draw game (one frame) -static void UnloadGame(void); // Unload game -static void UpdateDrawFrame(void); // Update and Draw (one frame) - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - - InitWindow(screenWidth, screenHeight, "sample game: gold fever"); - - InitGame(); - -#if defined(PLATFORM_WEB) - emscripten_set_main_loop(UpdateDrawFrame, 0, 1); -#else - - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - UpdateGame(); - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - DrawGame(); - //---------------------------------------------------------------------------------- - } -#endif - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadGame(); // Unload loaded data (textures, sounds, models...) - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} - -//------------------------------------------------------------------------------------ -// Module Functions Definitions (local) -//------------------------------------------------------------------------------------ - -// Initialize game variables -void InitGame(void) -{ - pause = false; - score = 0; - - player.position = (Vector2){50, 50}; - player.radius = 20; - player.speed = (Vector2){5, 5}; - - enemy.position = (Vector2){screenWidth - 50, screenHeight/2}; - enemy.radius = 20; - enemy.radiusBounds = 150; - enemy.speed = (Vector2){3, 3}; - enemy.moveRight = true; - follow = false; - - points.radius = 10; - points.position = (Vector2){GetRandomValue(points.radius, screenWidth - points.radius), GetRandomValue(points.radius, screenHeight - points.radius)}; - points.value = 100; - points.active = true; - - home.rec.width = 50; - home.rec.height = 50; - home.rec.x = GetRandomValue(0, screenWidth - home.rec.width); - home.rec.y = GetRandomValue(0, screenHeight - home.rec.height); - home.active = false; - home.save = false; -} - -// Update game (one frame) -void UpdateGame(void) -{ - if (!gameOver) - { - if (IsKeyPressed('P')) pause = !pause; - - if (!pause) - { - //Control player - if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x; - if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x; - if (IsKeyDown(KEY_UP)) player.position.y -= player.speed.y; - if (IsKeyDown(KEY_DOWN)) player.position.y += player.speed.y; - - //wall behaviour player - if (player.position.x - player.radius <= 0) player.position.x = player.radius; - if (player.position.x + player.radius >= screenWidth) player.position.x = screenWidth - player.radius; - if (player.position.y - player.radius <= 0) player.position.y = player.radius; - if (player.position.y + player.radius >= screenHeight) player.position.y = screenHeight - player.radius; - - //IA Enemy - if ( (follow || CheckCollisionCircles(player.position, player.radius, enemy.position, enemy.radiusBounds)) && !home.save) - { - if (player.position.x > enemy.position.x) enemy.position.x += enemy.speed.x; - if (player.position.x < enemy.position.x) enemy.position.x -= enemy.speed.x; - - if (player.position.y > enemy.position.y) enemy.position.y += enemy.speed.y; - if (player.position.y < enemy.position.y) enemy.position.y -= enemy.speed.y; - } - else - { - if (enemy.moveRight) enemy.position.x += enemy.speed.x; - else enemy.position.x -= enemy.speed.x; - } - - //wall behaviour enemy - if (enemy.position.x - enemy.radius <= 0) enemy.moveRight = true; - if (enemy.position.x + enemy.radius >= screenWidth) enemy.moveRight = false; - - if (enemy.position.x - enemy.radius <= 0) enemy.position.x = enemy.radius; - if (enemy.position.x + enemy.radius >= screenWidth) enemy.position.x = screenWidth - enemy.radius; - if (enemy.position.y - enemy.radius <= 0) enemy.position.y = enemy.radius; - if (enemy.position.y + enemy.radius >= screenHeight) enemy.position.y = screenHeight - enemy.radius; - - //Collisions - if (CheckCollisionCircles(player.position, player.radius, points.position, points.radius) && points.active) - { - follow = true; - points.active = false; - home.active = true; - } - - if (CheckCollisionCircles(player.position, player.radius, enemy.position, enemy.radius) && !home.save) - { - gameOver = true; - - if (hiScore < score) hiScore = score; - } - - if (CheckCollisionCircleRec(player.position, player.radius, home.rec)) - { - follow = false; - - if (!points.active) - { - score += points.value; - points.active = true; - enemy.speed.x += 0.5; - enemy.speed.y += 0.5; - points.position = (Vector2){GetRandomValue(points.radius, screenWidth - points.radius), GetRandomValue(points.radius, screenHeight - points.radius)}; - } - - home.save = true; - } - else home.save = false; - } - } - else - { - if (IsKeyPressed(KEY_ENTER)) - { - InitGame(); - gameOver = false; - } - } -} - -// Draw game (one frame) -void DrawGame(void) -{ - BeginDrawing(); - - ClearBackground(RAYWHITE); - - if (!gameOver) - { - if (follow) - { - DrawRectangle(0, 0, screenWidth, screenHeight, RED); - DrawRectangle(10, 10, screenWidth - 20, screenHeight - 20, RAYWHITE); - } - - DrawRectangleLines(home.rec.x, home.rec.y, home.rec.width, home.rec.height, BLUE); - - DrawCircleLines(enemy.position.x, enemy.position.y, enemy.radiusBounds, RED); - DrawCircleV(enemy.position, enemy.radius, MAROON); - - DrawCircleV(player.position, player.radius, GRAY); - if (points.active) DrawCircleV(points.position, points.radius, GOLD); - - DrawText(FormatText("SCORE: %04i", score), 20, 15, 20, GRAY); - DrawText(FormatText("HI-SCORE: %04i", hiScore), 300, 15, 20, GRAY); - - if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); - } - else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); - - EndDrawing(); -} - -// Unload game variables -void UnloadGame(void) -{ - // TODO: Unload all dynamic loaded data (textures, sounds, models...) -} - -// Update and Draw (one frame) -void UpdateDrawFrame(void) -{ - UpdateGame(); - DrawGame(); -} \ No newline at end of file diff --git a/games/samples/gorilas.c b/games/samples/gorilas.c deleted file mode 100644 index 86fd3f5b..00000000 --- a/games/samples/gorilas.c +++ /dev/null @@ -1,571 +0,0 @@ -/******************************************************************************************* -* -* raylib - sample game: gorilas -* -* Sample game Marc Palau and Ramon Santamaria -* -* This game has been created using raylib v1.3 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Copyright (c) 2015 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#include -#include -#include -#include - -#if defined(PLATFORM_WEB) - #include -#endif - -//---------------------------------------------------------------------------------- -// Some Defines -//---------------------------------------------------------------------------------- -#define MAX_BUILDINGS 15 -#define MAX_EXPLOSIONS 200 -#define MAX_PLAYERS 2 - -#define BUILDING_RELATIVE_ERROR 30 // Building size random range % -#define BUILDING_MIN_RELATIVE_HEIGHT 20 // Minimum height in % of the screenHeight -#define BUILDING_MAX_RELATIVE_HEIGHT 60 // Maximum height in % of the screenHeight -#define BUILDING_MIN_GRAYSCALE_COLOR 120 // Minimum gray color for the buildings -#define BUILDING_MAX_GRAYSCALE_COLOR 200 // Maximum gray color for the buildings - -#define MIN_PLAYER_POSITION 5 // Minimum x position % -#define MAX_PLAYER_POSITION 20 // Maximum x position % - -#define GRAVITY 9.81f -#define DELTA_FPS 60 - -//---------------------------------------------------------------------------------- -// Types and Structures Definition -//---------------------------------------------------------------------------------- -typedef struct Player { - Vector2 position; - Vector2 size; - - Vector2 aimingPoint; - int aimingAngle; - int aimingPower; - - Vector2 previousPoint; - int previousAngle; - int previousPower; - - Vector2 impactPoint; - - bool isLeftTeam; // This player belongs to the left or to the right team - bool isPlayer; // If is a player or an AI - bool isAlive; -} Player; - -typedef struct Building { - Rectangle rectangle; - Color color; -} Building; - -typedef struct Explosion { - Vector2 position; - int radius; - bool active; -} Explosion; - -typedef struct Ball { - Vector2 position; - Vector2 speed; - int radius; - bool active; -} Ball; - -//------------------------------------------------------------------------------------ -// Global Variables Declaration -//------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; - -static bool gameOver = false; -static bool pause = false; - -static Player player[MAX_PLAYERS]; -static Building building[MAX_BUILDINGS]; -static Explosion explosion[MAX_EXPLOSIONS]; -static Ball ball; - -static int playerTurn = 0; -static bool ballOnAir = false; - -//------------------------------------------------------------------------------------ -// Module Functions Declaration (local) -//------------------------------------------------------------------------------------ -static void InitGame(void); // Initialize game -static void UpdateGame(void); // Update game (one frame) -static void DrawGame(void); // Draw game (one frame) -static void UnloadGame(void); // Unload game -static void UpdateDrawFrame(void); // Update and Draw (one frame) - -// Additional module functions -static void InitBuildings(void); -static void InitPlayers(void); -static bool UpdatePlayer(int playerTurn); -static bool UpdateBall(int playerTurn); - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - InitWindow(screenWidth, screenHeight, "sample game: gorilas"); - - InitGame(); - -#if defined(PLATFORM_WEB) - emscripten_set_main_loop(UpdateDrawFrame, 0, 1); -#else - - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - UpdateGame(); - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - DrawGame(); - //---------------------------------------------------------------------------------- - } -#endif - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadGame(); // Unload loaded data (textures, sounds, models...) - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} - -//------------------------------------------------------------------------------------ -// Module Functions Definitions (local) -//------------------------------------------------------------------------------------ - -// Initialize game variables -void InitGame(void) -{ - // Init shoot - ball.radius = 10; - ballOnAir = false; - ball.active = false; - - InitBuildings(); - InitPlayers(); - - // Init explosions - for (int i = 0; i < MAX_EXPLOSIONS; i++) - { - explosion[i].position = (Vector2){ 0.0f, 0.0f }; - explosion[i].radius = 30; - explosion[i].active = false; - } -} - -// Update game (one frame) -void UpdateGame(void) -{ - if (!gameOver) - { - if (IsKeyPressed('P')) pause = !pause; - - if (!pause) - { - if (!ballOnAir) ballOnAir = UpdatePlayer(playerTurn); // If we are aiming - else - { - if (UpdateBall(playerTurn)) // If collision - { - // Game over logic - bool leftTeamAlive = false; - bool rightTeamAlive = false; - - for (int i = 0; i < MAX_PLAYERS; i++) - { - if (player[i].isAlive) - { - if (player[i].isLeftTeam) leftTeamAlive = true; - if (!player[i].isLeftTeam) rightTeamAlive = true; - } - } - - if (leftTeamAlive && rightTeamAlive) - { - ballOnAir = false; - ball.active = false; - - playerTurn++; - - if (playerTurn == MAX_PLAYERS) playerTurn = 0; - } - else - { - gameOver = true; - - // if (leftTeamAlive) left team wins - // if (rightTeamAlive) right team wins - } - } - } - } - } - else - { - if (IsKeyPressed(KEY_ENTER)) - { - InitGame(); - gameOver = false; - } - } -} - -// Draw game (one frame) -void DrawGame(void) -{ - BeginDrawing(); - - ClearBackground(RAYWHITE); - - if (!gameOver) - { - // Draw buildings - for (int i = 0; i < MAX_BUILDINGS; i++) DrawRectangleRec(building[i].rectangle, building[i].color); - - // Draw explosions - for (int i = 0; i < MAX_EXPLOSIONS; i++) - { - if (explosion[i].active) DrawCircle(explosion[i].position.x, explosion[i].position.y, explosion[i].radius, RAYWHITE); - } - - // Draw players - for (int i = 0; i < MAX_PLAYERS; i++) - { - if (player[i].isAlive) - { - if (player[i].isLeftTeam) DrawRectangle(player[i].position.x - player[i].size.x/2, player[i].position.y - player[i].size.y/2, - player[i].size.x, player[i].size.y, BLUE); - else DrawRectangle(player[i].position.x - player[i].size.x/2, player[i].position.y - player[i].size.y/2, - player[i].size.x, player[i].size.y, RED); - } - } - - // Draw ball - if (ball.active) DrawCircle(ball.position.x, ball.position.y, ball.radius, MAROON); - - // Draw the angle and the power of the aim, and the previous ones - if (!ballOnAir) - { - // Draw shot information - /* - if (player[playerTurn].isLeftTeam) - { - DrawText(FormatText("Previous Point %i, %i", (int)player[playerTurn].previousPoint.x, (int)player[playerTurn].previousPoint.y), 20, 20, 20, DARKBLUE); - DrawText(FormatText("Previous Angle %i", player[playerTurn].previousAngle), 20, 50, 20, DARKBLUE); - DrawText(FormatText("Previous Power %i", player[playerTurn].previousPower), 20, 80, 20, DARKBLUE); - DrawText(FormatText("Aiming Point %i, %i", (int)player[playerTurn].aimingPoint.x, (int)player[playerTurn].aimingPoint.y), 20, 110, 20, DARKBLUE); - DrawText(FormatText("Aiming Angle %i", player[playerTurn].aimingAngle), 20, 140, 20, DARKBLUE); - DrawText(FormatText("Aiming Power %i", player[playerTurn].aimingPower), 20, 170, 20, DARKBLUE); - } - else - { - DrawText(FormatText("Previous Point %i, %i", (int)player[playerTurn].previousPoint.x, (int)player[playerTurn].previousPoint.y), screenWidth*3/4, 20, 20, DARKBLUE); - DrawText(FormatText("Previous Angle %i", player[playerTurn].previousAngle), screenWidth*3/4, 50, 20, DARKBLUE); - DrawText(FormatText("Previous Power %i", player[playerTurn].previousPower), screenWidth*3/4, 80, 20, DARKBLUE); - DrawText(FormatText("Aiming Point %i, %i", (int)player[playerTurn].aimingPoint.x, (int)player[playerTurn].aimingPoint.y), screenWidth*3/4, 110, 20, DARKBLUE); - DrawText(FormatText("Aiming Angle %i", player[playerTurn].aimingAngle), screenWidth*3/4, 140, 20, DARKBLUE); - DrawText(FormatText("Aiming Power %i", player[playerTurn].aimingPower), screenWidth*3/4, 170, 20, DARKBLUE); - } - */ - - // Draw aim - if (player[playerTurn].isLeftTeam) - { - // Previous aiming - DrawTriangle((Vector2){ player[playerTurn].position.x - player[playerTurn].size.x/4, player[playerTurn].position.y - player[playerTurn].size.y/4 }, - (Vector2){ player[playerTurn].position.x + player[playerTurn].size.x/4, player[playerTurn].position.y + player[playerTurn].size.y/4 }, - player[playerTurn].previousPoint, GRAY); - - // Actual aiming - DrawTriangle((Vector2){ player[playerTurn].position.x - player[playerTurn].size.x/4, player[playerTurn].position.y - player[playerTurn].size.y/4 }, - (Vector2){ player[playerTurn].position.x + player[playerTurn].size.x/4, player[playerTurn].position.y + player[playerTurn].size.y/4 }, - player[playerTurn].aimingPoint, DARKBLUE); - } - else - { - // Previous aiming - DrawTriangle((Vector2){ player[playerTurn].position.x - player[playerTurn].size.x/4, player[playerTurn].position.y + player[playerTurn].size.y/4 }, - (Vector2){ player[playerTurn].position.x + player[playerTurn].size.x/4, player[playerTurn].position.y - player[playerTurn].size.y/4 }, - player[playerTurn].previousPoint, GRAY); - - // Actual aiming - DrawTriangle((Vector2){ player[playerTurn].position.x - player[playerTurn].size.x/4, player[playerTurn].position.y + player[playerTurn].size.y/4 }, - (Vector2){ player[playerTurn].position.x + player[playerTurn].size.x/4, player[playerTurn].position.y - player[playerTurn].size.y/4 }, - player[playerTurn].aimingPoint, MAROON); - } - } - - if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); - } - else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); - - EndDrawing(); -} - -// Unload game variables -void UnloadGame(void) -{ - // TODO: Unload all dynamic loaded data (textures, sounds, models...) -} - -// Update and Draw (one frame) -void UpdateDrawFrame(void) -{ - UpdateGame(); - DrawGame(); -} - -//-------------------------------------------------------------------------------------- -// Additional module functions -//-------------------------------------------------------------------------------------- -static void InitBuildings(void) -{ - // Horizontal generation - int currentWidth = 0; - - // We make sure the absolute error randomly generated for each building, has as a minimum value the screenWidth. - // This way all the screen will be filled with buildings. Each building will have a different, random width. - - float relativeWidth = 100/(100 - BUILDING_RELATIVE_ERROR); - float buildingWidthMean = (screenWidth*relativeWidth/MAX_BUILDINGS) + 1; // We add one to make sure we will cover the whole screen. - - // Vertical generation - int currentHeighth = 0; - int grayLevel; - - // Creation - for (int i = 0; i < MAX_BUILDINGS; i++) - { - // Horizontal - building[i].rectangle.x = currentWidth; - building[i].rectangle.width = GetRandomValue(buildingWidthMean*(100 - BUILDING_RELATIVE_ERROR/2)/100 + 1, buildingWidthMean*(100 + BUILDING_RELATIVE_ERROR)/100); - - currentWidth += building[i].rectangle.width; - - // Vertical - currentHeighth = GetRandomValue(BUILDING_MIN_RELATIVE_HEIGHT, BUILDING_MAX_RELATIVE_HEIGHT); - building[i].rectangle.y = screenHeight - (screenHeight*currentHeighth/100); - building[i].rectangle.height = screenHeight*currentHeighth/100 + 1; - - // Color - grayLevel = GetRandomValue(BUILDING_MIN_GRAYSCALE_COLOR, BUILDING_MAX_GRAYSCALE_COLOR); - building[i].color = (Color){ grayLevel, grayLevel, grayLevel, 255 }; - } -} - -static void InitPlayers(void) -{ - for (int i = 0; i < MAX_PLAYERS; i++) - { - player[i].isAlive = true; - - // Decide the team of this player - if (i % 2 == 0) player[i].isLeftTeam = true; - else player[i].isLeftTeam = false; - - // Now there is no AI - player[i].isPlayer = true; - - // Set size, by default by now - player[i].size = (Vector2){ 40, 40 }; - - // Set position - if (player[i].isLeftTeam) player[i].position.x = GetRandomValue(screenWidth*MIN_PLAYER_POSITION/100, screenWidth*MAX_PLAYER_POSITION/100); - else player[i].position.x = screenWidth - GetRandomValue(screenWidth*MIN_PLAYER_POSITION/100, screenWidth*MAX_PLAYER_POSITION/100); - - for (int j = 0; j < MAX_BUILDINGS; j++) - { - if (building[j].rectangle.x > player[i].position.x) - { - // Set the player in the center of the building - player[i].position.x = building[j-1].rectangle.x + building[j-1].rectangle.width/2; - // Set the player at the top of the building - player[i].position.y = building[j-1].rectangle.y - player[i].size.y/2; - break; - } - } - - // Set statistics to 0 - player[i].aimingPoint = player[i].position; - player[i].previousAngle = 0; - player[i].previousPower = 0; - player[i].previousPoint = player[i].position; - player[i].aimingAngle = 0; - player[i].aimingPower = 0; - - player[i].impactPoint = (Vector2){ -100, -100 }; - } -} - -static bool UpdatePlayer(int playerTurn) -{ - // If we are aiming at the firing quadrant, we calculate the angle - if (GetMousePosition().y <= player[playerTurn].position.y) - { - // Left team - if (player[playerTurn].isLeftTeam && GetMousePosition().x >= player[playerTurn].position.x) - { - // Distance (calculating the fire power) - player[playerTurn].aimingPower = sqrt(pow(player[playerTurn].position.x - GetMousePosition().x, 2) + pow(player[playerTurn].position.y - GetMousePosition().y, 2)); - // Calculates the angle via arcsin - player[playerTurn].aimingAngle = asin((player[playerTurn].position.y - GetMousePosition().y)/player[playerTurn].aimingPower)*RAD2DEG; - // Point of the screen we are aiming at - player[playerTurn].aimingPoint = GetMousePosition(); - - // Ball fired - if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) - { - player[playerTurn].previousPoint = player[playerTurn].aimingPoint; - player[playerTurn].previousPower = player[playerTurn].aimingPower; - player[playerTurn].previousAngle = player[playerTurn].aimingAngle; - ball.position = player[playerTurn].position; - - return true; - } - } - // Right team - else if (!player[playerTurn].isLeftTeam && GetMousePosition().x <= player[playerTurn].position.x) - { - // Distance (calculating the fire power) - player[playerTurn].aimingPower = sqrt(pow(player[playerTurn].position.x - GetMousePosition().x, 2) + pow(player[playerTurn].position.y - GetMousePosition().y, 2)); - // Calculates the angle via arcsin - player[playerTurn].aimingAngle = asin((player[playerTurn].position.y - GetMousePosition().y)/player[playerTurn].aimingPower)*RAD2DEG; - // Point of the screen we are aiming at - player[playerTurn].aimingPoint = GetMousePosition(); - - // Ball fired - if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) - { - player[playerTurn].previousPoint = player[playerTurn].aimingPoint; - player[playerTurn].previousPower = player[playerTurn].aimingPower; - player[playerTurn].previousAngle = player[playerTurn].aimingAngle; - ball.position = player[playerTurn].position; - - return true; - } - } - else - { - player[playerTurn].aimingPoint = player[playerTurn].position; - player[playerTurn].aimingPower = 0; - player[playerTurn].aimingAngle = 0; - } - } - else - { - player[playerTurn].aimingPoint = player[playerTurn].position; - player[playerTurn].aimingPower = 0; - player[playerTurn].aimingAngle = 0; - } - - return false; -} - -static bool UpdateBall(int playerTurn) -{ - static int explosionNumber = 0; - - // Activate ball - if (!ball.active) - { - if (player[playerTurn].isLeftTeam) - { - ball.speed.x = cos(player[playerTurn].previousAngle*DEG2RAD)*player[playerTurn].previousPower*3/DELTA_FPS; - ball.speed.y = -sin(player[playerTurn].previousAngle*DEG2RAD)*player[playerTurn].previousPower*3/DELTA_FPS; - ball.active = true; - } - else - { - ball.speed.x = -cos(player[playerTurn].previousAngle*DEG2RAD)*player[playerTurn].previousPower*3/DELTA_FPS; - ball.speed.y = -sin(player[playerTurn].previousAngle*DEG2RAD)*player[playerTurn].previousPower*3/DELTA_FPS; - ball.active = true; - } - } - - ball.position.x += ball.speed.x; - ball.position.y += ball.speed.y; - ball.speed.y += GRAVITY/DELTA_FPS; - - // Collision - if (ball.position.x + ball.radius < 0) return true; - else if (ball.position.x - ball.radius > screenWidth) return true; - else - { - // Player collision - for (int i = 0; i < MAX_PLAYERS; i++) - { - if (CheckCollisionCircleRec(ball.position, ball.radius, (Rectangle){ player[i].position.x - player[i].size.x/2, player[i].position.y - player[i].size.y/2, - player[i].size.x, player[i].size.y })) - { - // We can't hit ourselves - if (i == playerTurn) return false; - else - { - // We set the impact point - player[playerTurn].impactPoint.x = ball.position.x; - player[playerTurn].impactPoint.y = ball.position.y + ball.radius; - - // We destroy the player - player[i].isAlive = false; - return true; - } - } - } - - // Building collision - // NOTE: We only check building collision if we are not inside an explosion - for (int i = 0; i < MAX_BUILDINGS; i++) - { - if (CheckCollisionCircles(ball.position, ball.radius, explosion[i].position, explosion[i].radius - ball.radius)) - { - return false; - } - } - - for (int i = 0; i < MAX_BUILDINGS; i++) - { - if (CheckCollisionCircleRec(ball.position, ball.radius, building[i].rectangle)) - { - // We set the impact point - player[playerTurn].impactPoint.x = ball.position.x; - player[playerTurn].impactPoint.y = ball.position.y + ball.radius; - - // We create an explosion - explosion[explosionNumber].position = player[playerTurn].impactPoint; - explosion[explosionNumber].active = true; - explosionNumber++; - - return true; - } - } - } - - return false; -} \ No newline at end of file diff --git a/games/samples/missile_commander.c b/games/samples/missile_commander.c deleted file mode 100644 index 6317c41a..00000000 --- a/games/samples/missile_commander.c +++ /dev/null @@ -1,539 +0,0 @@ -/******************************************************************************************* -* -* raylib - sample game: missile commander -* -* Sample game Marc Palau and Ramon Santamaria -* -* This game has been created using raylib v1.3 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Copyright (c) 2015 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#include -#include -#include -#include - -#if defined(PLATFORM_WEB) - #include -#endif - -//---------------------------------------------------------------------------------- -// Some Defines -//---------------------------------------------------------------------------------- -#define MAX_MISSILES 100 -#define MAX_INTERCEPTORS 30 -#define MAX_EXPLOSIONS 100 -#define LAUNCHERS_AMOUNT 3 // Not a variable, should not be changed -#define BUILDINGS_AMOUNT 6 // Not a variable, should not be changed - -#define LAUNCHER_SIZE 80 -#define BUILDING_SIZE 60 -#define EXPLOSION_RADIUS 40 - -#define MISSILE_SPEED 1 -#define MISSILE_LAUNCH_FRAMES 80 -#define INTERCEPTOR_SPEED 10 -#define EXPLOSION_INCREASE_TIME 90 // In frames -#define EXPLOSION_TOTAL_TIME 210 // In frames - -#define EXPLOSION_COLOR (Color){ 125, 125, 125, 125 } - -//---------------------------------------------------------------------------------- -// Types and Structures Definition -//---------------------------------------------------------------------------------- -typedef struct Missile { - Vector2 origin; - Vector2 position; - Vector2 objective; - Vector2 speed; - - bool active; -} Missile; - -typedef struct Interceptor { - Vector2 origin; - Vector2 position; - Vector2 objective; - Vector2 speed; - - bool active; -} Interceptor; - -typedef struct Explosion { - Vector2 position; - float radiusMultiplier; - int frame; - bool active; -} Explosion; - -typedef struct Launcher { - Vector2 position; - bool active; -} Launcher; - -typedef struct Building { - Vector2 position; - bool active; -} Building; - -//------------------------------------------------------------------------------------ -// Global Variables Declaration -//------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; - -static int framesCounter = 0; -static bool gameOver = false; -static bool pause = false; -static int score = 0; - -static Missile missile[MAX_MISSILES]; -static Interceptor interceptor[MAX_INTERCEPTORS]; -static Explosion explosion[MAX_EXPLOSIONS]; -static Launcher launcher[LAUNCHERS_AMOUNT]; -static Building building[BUILDINGS_AMOUNT]; -static int explosionIndex = 0; - -//------------------------------------------------------------------------------------ -// Module Functions Declaration (local) -//------------------------------------------------------------------------------------ -static void InitGame(void); // Initialize game -static void UpdateGame(void); // Update game (one frame) -static void DrawGame(void); // Draw game (one frame) -static void UnloadGame(void); // Unload game -static void UpdateDrawFrame(void); // Update and Draw (one frame) - -// Additional module functions -static void UpdateOutgoingFire(); -static void UpdateIncomingFire(); - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - InitWindow(screenWidth, screenHeight, "sample game: missile commander"); - - InitGame(); - -#if defined(PLATFORM_WEB) - emscripten_set_main_loop(UpdateDrawFrame, 0, 1); -#else - - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - UpdateGame(); - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - DrawGame(); - //---------------------------------------------------------------------------------- - } -#endif - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadGame(); // Unload loaded data (textures, sounds, models...) - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} - -//-------------------------------------------------------------------------------------- -// Game Module Functions Definition -//-------------------------------------------------------------------------------------- - -// Initialize game variables -void InitGame(void) -{ - // Initialize missiles - for (int i = 0; i < MAX_MISSILES; i++) - { - missile[i].origin = (Vector2){ 0, 0 }; - missile[i].speed = (Vector2){ 0, 0 }; - missile[i].position = (Vector2){ 0, 0 }; - - missile[i].active = false; - } - - // Initialize interceptors - for (int i = 0; i < MAX_INTERCEPTORS; i++) - { - interceptor[i].origin = (Vector2){ 0, 0 }; - interceptor[i].speed = (Vector2){ 0, 0 }; - interceptor[i].position = (Vector2){ 0, 0 }; - - interceptor[i].active = false; - } - - // Initialize explosions - for (int i = 0; i < MAX_EXPLOSIONS; i++) - { - explosion[i].position = (Vector2){ 0, 0 }; - explosion[i].frame = 0; - explosion[i].active = false; - } - - // Initialize buildings and launchers - int sparcing = screenWidth/(LAUNCHERS_AMOUNT + BUILDINGS_AMOUNT + 1); - - // Buildings and launchers placing - launcher[0].position = (Vector2){ 1*sparcing, screenHeight - LAUNCHER_SIZE/2 }; - building[0].position = (Vector2){ 2*sparcing, screenHeight - BUILDING_SIZE/2 }; - building[1].position = (Vector2){ 3*sparcing, screenHeight - BUILDING_SIZE/2 }; - building[2].position = (Vector2){ 4*sparcing, screenHeight - BUILDING_SIZE/2 }; - launcher[1].position = (Vector2){ 5*sparcing, screenHeight - LAUNCHER_SIZE/2 }; - building[3].position = (Vector2){ 6*sparcing, screenHeight - BUILDING_SIZE/2 }; - building[4].position = (Vector2){ 7*sparcing, screenHeight - BUILDING_SIZE/2 }; - building[5].position = (Vector2){ 8*sparcing, screenHeight - BUILDING_SIZE/2 }; - launcher[2].position = (Vector2){ 9*sparcing, screenHeight - LAUNCHER_SIZE/2 }; - - // Buildings and launchers activation - for (int i = 0; i < LAUNCHERS_AMOUNT; i++) launcher[i].active = true; - for (int i = 0; i < BUILDINGS_AMOUNT; i++) building[i].active = true; - - // Initialize game variables - score = 0; -} - -// Update game (one frame) -void UpdateGame(void) -{ - if (!gameOver) - { - if (IsKeyPressed('P')) pause = !pause; - - if (!pause) - { - framesCounter++; - - static - float distance; - - // Interceptors update - for (int i = 0; i < MAX_INTERCEPTORS; i++) - { - if (interceptor[i].active) - { - // Update position - interceptor[i].position.x += interceptor[i].speed.x; - interceptor[i].position.y += interceptor[i].speed.y; - - // Distance to objective - distance = sqrt( pow(interceptor[i].position.x - interceptor[i].objective.x, 2) + - pow(interceptor[i].position.y - interceptor[i].objective.y, 2)); - - if (distance < INTERCEPTOR_SPEED) - { - // Interceptor dissapears - interceptor[i].active = false; - - // Explosion - explosion[explosionIndex].position = interceptor[i].position; - explosion[explosionIndex].active = true; - explosion[explosionIndex].frame = 0; - explosionIndex++; - if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0; - - break; - } - } - } - - // Missiles update - for (int i = 0; i < MAX_MISSILES; i++) - { - if (missile[i].active) - { - // Update position - missile[i].position.x += missile[i].speed.x; - missile[i].position.y += missile[i].speed.y; - - // Collision and missile out of bounds - if (missile[i].position.y > screenHeight) missile[i].active = false; - else - { - // CHeck collision with launchers - for (int j = 0; j < LAUNCHERS_AMOUNT; j++) - { - if (launcher[j].active) - { - if (CheckCollisionPointRec(missile[i].position, (Rectangle){ launcher[j].position.x - LAUNCHER_SIZE/2, launcher[j].position.y - LAUNCHER_SIZE/2, - LAUNCHER_SIZE, LAUNCHER_SIZE })) - { - // Missile dissapears - missile[i].active = false; - - // Explosion and destroy building - launcher[j].active = false; - - explosion[explosionIndex].position = missile[i].position; - explosion[explosionIndex].active = true; - explosion[explosionIndex].frame = 0; - explosionIndex++; - if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0; - - break; - } - } - } - - // CHeck collision with buildings - for (int j = 0; j < BUILDINGS_AMOUNT; j++) - { - if (building[j].active) - { - if (CheckCollisionPointRec(missile[i].position, (Rectangle){ building[j].position.x - BUILDING_SIZE/2, building[j].position.y - BUILDING_SIZE/2, - BUILDING_SIZE, BUILDING_SIZE })) - { - // Missile dissapears - missile[i].active = false; - - // Explosion and destroy building - building[j].active = false; - - explosion[explosionIndex].position = missile[i].position; - explosion[explosionIndex].active = true; - explosion[explosionIndex].frame = 0; - explosionIndex++; - if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0; - - break; - } - } - } - - // CHeck collision with explosions - for (int j = 0; j < MAX_EXPLOSIONS; j++) - { - if (explosion[j].active) - { - if (CheckCollisionPointCircle(missile[i].position, explosion[j].position, EXPLOSION_RADIUS*explosion[j].radiusMultiplier)) - { - // Missile dissapears and we earn 100 points - missile[i].active = false; - score += 100; - - explosion[explosionIndex].position = missile[i].position; - explosion[explosionIndex].active = true; - explosion[explosionIndex].frame = 0; - explosionIndex++; - if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0; - - break; - } - } - } - } - } - } - - // Explosions update - for (int i = 0; i < MAX_EXPLOSIONS; i++) - { - if (explosion[i].active) - { - explosion[i].frame++; - - if (explosion[i].frame <= EXPLOSION_INCREASE_TIME) explosion[i].radiusMultiplier = explosion[i].frame/(float)EXPLOSION_INCREASE_TIME; - else if (explosion[i].frame <= EXPLOSION_TOTAL_TIME) explosion[i].radiusMultiplier = 1 - (explosion[i].frame - (float)EXPLOSION_INCREASE_TIME)/(float)EXPLOSION_TOTAL_TIME; - else - { - explosion[i].frame = 0; - explosion[i].active = false; - } - } - } - - // Fire logic - UpdateOutgoingFire(); - UpdateIncomingFire(); - - // Game over logic - int checker = 0; - - for (int i = 0; i < LAUNCHERS_AMOUNT; i++) - { - if (!launcher[i].active) checker++; - if (checker == LAUNCHERS_AMOUNT) gameOver = true; - } - - checker = 0; - for (int i = 0; i < BUILDINGS_AMOUNT; i++) - { - if (!building[i].active) checker++; - if (checker == BUILDINGS_AMOUNT) gameOver = true; - } - } - } - else - { - if (IsKeyPressed(KEY_ENTER)) - { - InitGame(); - gameOver = false; - } - } -} - -// Draw game (one frame) -void DrawGame(void) -{ - BeginDrawing(); - - ClearBackground(RAYWHITE); - - if (!gameOver) - { - // Draw missiles - for (int i = 0; i < MAX_MISSILES; i++) - { - if (missile[i].active) - { - DrawLine(missile[i].origin.x, missile[i].origin.y, missile[i].position.x, missile[i].position.y, RED); - - if (framesCounter % 16 < 8) DrawCircle(missile[i].position.x, missile[i].position.y, 3, YELLOW); - } - } - - // Draw interceptors - for (int i = 0; i < MAX_INTERCEPTORS; i++) - { - if (interceptor[i].active) - { - DrawLine(interceptor[i].origin.x, interceptor[i].origin.y, interceptor[i].position.x, interceptor[i].position.y, GREEN); - - if (framesCounter % 16 < 8) DrawCircle(interceptor[i].position.x, interceptor[i].position.y, 3, BLUE); - } - } - - // Draw explosions - for (int i = 0; i < MAX_EXPLOSIONS; i++) - { - if (explosion[i].active) DrawCircle(explosion[i].position.x, explosion[i].position.y, EXPLOSION_RADIUS*explosion[i].radiusMultiplier, EXPLOSION_COLOR); - } - - // Draw buildings and launchers - for (int i = 0; i < LAUNCHERS_AMOUNT; i++) - { - if (launcher[i].active) DrawRectangle(launcher[i].position.x - LAUNCHER_SIZE/2, launcher[i].position.y - LAUNCHER_SIZE/2, LAUNCHER_SIZE, LAUNCHER_SIZE, GRAY); - } - - for (int i = 0; i < BUILDINGS_AMOUNT; i++) - { - if (building[i].active) DrawRectangle(building[i].position.x - BUILDING_SIZE/2, building[i].position.y - BUILDING_SIZE/2, BUILDING_SIZE, BUILDING_SIZE, LIGHTGRAY); - } - - // Draw score - DrawText(FormatText("SCORE %4i", score), 20, 20, 40, LIGHTGRAY); - - if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); - } - else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); - - EndDrawing(); -} - -// Unload game variables -void UnloadGame(void) -{ - // TODO: Unload all dynamic loaded data (textures, sounds, models...) -} - -// Update and Draw (one frame) -void UpdateDrawFrame(void) -{ - UpdateGame(); - DrawGame(); -} - -//-------------------------------------------------------------------------------------- -// Additional module functions -//-------------------------------------------------------------------------------------- -static void UpdateOutgoingFire() -{ - static int interceptorNumber = 0; - int launcherShooting = 0; - - if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) launcherShooting = 1; - if (IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) launcherShooting = 2; - if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) launcherShooting = 3; - - if (launcherShooting > 0 && launcher[launcherShooting - 1].active) - { - float module; - float sideX; - float sideY; - - // Activate the interceptor - interceptor[interceptorNumber].active = true; - - // Assign start position - interceptor[interceptorNumber].origin = launcher[launcherShooting - 1].position; - interceptor[interceptorNumber].position = interceptor[interceptorNumber].origin; - interceptor[interceptorNumber].objective = GetMousePosition(); - - // Calculate speed - module = sqrt( pow(interceptor[interceptorNumber].objective.x - interceptor[interceptorNumber].origin.x, 2) + - pow(interceptor[interceptorNumber].objective.y - interceptor[interceptorNumber].origin.y, 2)); - - sideX = (interceptor[interceptorNumber].objective.x - interceptor[interceptorNumber].origin.x)*INTERCEPTOR_SPEED/module; - sideY = (interceptor[interceptorNumber].objective.y - interceptor[interceptorNumber].origin.y)*INTERCEPTOR_SPEED/module; - - interceptor[interceptorNumber].speed = (Vector2){ sideX, sideY }; - - // Update - interceptorNumber++; - if (interceptorNumber == MAX_INTERCEPTORS) interceptorNumber = 0; - } -} - -static void UpdateIncomingFire() -{ - static int missileIndex = 0; - - // Launch missile - if (framesCounter % MISSILE_LAUNCH_FRAMES == 0) - { - float module; - float sideX; - float sideY; - - // Activate the missile - missile[missileIndex].active = true; - - // Assign start position - missile[missileIndex].origin = (Vector2){ GetRandomValue(20, screenWidth - 20), -10 }; - missile[missileIndex].position = missile[missileIndex].origin; - missile[missileIndex].objective = (Vector2){ GetRandomValue(20, screenWidth - 20), screenHeight + 10 }; - - // Calculate speed - module = sqrt( pow(missile[missileIndex].objective.x - missile[missileIndex].origin.x, 2) + - pow(missile[missileIndex].objective.y - missile[missileIndex].origin.y, 2)); - - sideX = (missile[missileIndex].objective.x - missile[missileIndex].origin.x)*MISSILE_SPEED/module; - sideY = (missile[missileIndex].objective.y - missile[missileIndex].origin.y)*MISSILE_SPEED/module; - - missile[missileIndex].speed = (Vector2){ sideX, sideY }; - - // Update - missileIndex++; - if (missileIndex == MAX_MISSILES) missileIndex = 0; - } -} \ No newline at end of file diff --git a/games/samples/pang.c b/games/samples/pang.c deleted file mode 100644 index fe1c3005..00000000 --- a/games/samples/pang.c +++ /dev/null @@ -1,630 +0,0 @@ -/******************************************************************************************* -* -* raylib - sample game: pang -* -* Sample game developed by Ian Eito and Albert Martos and Ramon Santamaria -* -* This game has been created using raylib v1.3 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Copyright (c) 2015 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#include - -#if defined(PLATFORM_WEB) - #include -#endif - -//---------------------------------------------------------------------------------- -// Some Defines -//---------------------------------------------------------------------------------- -#define PLAYER_BASE_SIZE 20.0f -#define PLAYER_SPEED 5.0f -#define PLAYER_MAX_SHOOTS 1 - -#define MAX_BIG_BALLS 2 -#define BALLS_SPEED 2.0f - -//---------------------------------------------------------------------------------- -// Types and Structures Definition -//---------------------------------------------------------------------------------- - -typedef struct Player { - Vector2 position; - Vector2 speed; - Vector3 collider; - float rotation; -} Player; - -typedef struct Shoot { - Vector2 position; - Vector2 speed; - float radius; - float rotation; - int lifeSpawn; - bool active; -} Shoot; - -typedef struct Ball { - Vector2 position; - Vector2 speed; - float radius; - int points; - bool active; -} Ball; - -typedef struct Points { - Vector2 position; - int value; - float alpha; -} Points; - -//------------------------------------------------------------------------------------ -// Global Variables Declaration -//------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; - -static int framesCounter; -static bool gameOver; -static bool pause; -static int score; - -static Player player; -static Shoot shoot[PLAYER_MAX_SHOOTS]; -static Ball bigBalls[MAX_BIG_BALLS]; -static Ball mediumBalls[MAX_BIG_BALLS*2]; -static Ball smallBalls[MAX_BIG_BALLS*4]; -static Points points[5]; - -// NOTE: Defined triangle is isosceles with common angles of 70 degrees. -static float shipHeight; -static float gravity; - -static int countmediumBallss; -static int countsmallBallss; -static int meteorsDestroyed; -static Vector2 linePosition; - -static bool victory; -static bool lose; -static bool awake; - -//------------------------------------------------------------------------------------ -// Module Functions Declaration (local) -//------------------------------------------------------------------------------------ -static void InitGame(void); // Initialize game -static void UpdateGame(void); // Update game (one frame) -static void DrawGame(void); // Draw game (one frame) -static void UnloadGame(void); // Unload game -static void UpdateDrawFrame(void); // Update and Draw (one frame) - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main() -{ - InitWindow(screenWidth, screenHeight, "sample game: pang"); - - InitGame(); - -#if defined(PLATFORM_WEB) - emscripten_set_main_loop(UpdateDrawFrame, 0, 1); -#else - - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - UpdateGame(); - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - DrawGame(); - //---------------------------------------------------------------------------------- - } -#endif - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadGame(); // Unload loaded data (textures, sounds, models...) - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} - -//------------------------------------------------------------------------------------ -// Module Functions Definitions (local) -//------------------------------------------------------------------------------------ - -// Initialize game variables -static void InitGame(void) -{ - int posx, posy; - int velx = 0; - int vely = 0; - - framesCounter = 0; - gameOver = false; - pause = false; - score = 0; - - victory = false; - lose = false; - awake = true; - gravity = 0.25f; - - linePosition = (Vector2){ 0.0f , 0.0f }; - shipHeight = (PLAYER_BASE_SIZE/2)/tanf(20*DEG2RAD); - - // Initialization player - player.position = (Vector2){ screenWidth/2, screenHeight }; - player.speed = (Vector2){ PLAYER_SPEED, PLAYER_SPEED }; - player.rotation = 0; - player.collider = (Vector3){ player.position.x, player.position.y - shipHeight/2.0f, 12.0f }; - - meteorsDestroyed = 0; - - // Initialize shoots - for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) - { - shoot[i].position = (Vector2){ 0, 0 }; - shoot[i].speed = (Vector2){ 0, 0 }; - shoot[i].radius = 2; - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - } - - // Initialize big meteors - for (int i = 0; i < MAX_BIG_BALLS; i++) - { - bigBalls[i].radius = 40.0f; - posx = GetRandomValue(0 + bigBalls[i].radius, screenWidth - bigBalls[i].radius); - posy = GetRandomValue(0 + bigBalls[i].radius, screenHeight/2); - - bigBalls[i].position = (Vector2){ posx, posy }; - - while ((velx == 0) || (vely == 0)) - { - velx = GetRandomValue(-BALLS_SPEED, BALLS_SPEED); - vely = GetRandomValue(-BALLS_SPEED, BALLS_SPEED); - } - - bigBalls[i].speed = (Vector2){ velx, vely }; - bigBalls[i].points = 200; - bigBalls[i].active = true; - } - - // Initialize medium meteors - for (int i = 0; i < MAX_BIG_BALLS*2; i++) - { - mediumBalls[i].position = (Vector2){-100, -100}; - mediumBalls[i].speed = (Vector2){0,0}; - mediumBalls[i].radius = 20.0f; - mediumBalls[i].points = 100; - mediumBalls[i].active = false; - } - - // Initialize small meteors - for (int i = 0; i < MAX_BIG_BALLS*4; i++) - { - smallBalls[i].position = (Vector2){ -100, -100 }; - smallBalls[i].speed = (Vector2){ 0, 0 }; - smallBalls[i].radius = 10.0f; - smallBalls[i].points = 50; - smallBalls[i].active = false; - } - - // Initialize animated points - for (int i = 0; i < 5; i++) - { - points[i].position = (Vector2){ 0, 0 }; - points[i].value = 0; - points[i].alpha = 0.0f; - } - - countmediumBallss = 0; - countsmallBallss = 0; -} - -// Update game (one frame) -void UpdateGame(void) -{ - if (!gameOver && !victory) - { - if (IsKeyPressed('P')) pause = !pause; - - if (!pause) - { - // Player logic - if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x; - if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x; - - // Player vs wall collision logic - if (player.position.x + PLAYER_BASE_SIZE/2 > screenWidth) player.position.x = screenWidth - PLAYER_BASE_SIZE/2; - else if (player.position.x - PLAYER_BASE_SIZE/2 < 0) player.position.x = 0 + PLAYER_BASE_SIZE/2; - - // Player shot logic - if (IsKeyPressed(KEY_SPACE)) - { - for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) - { - if (!shoot[i].active) - { - shoot[i].position = (Vector2){ player.position.x, player.position.y - shipHeight }; - shoot[i].speed.y = PLAYER_SPEED; - shoot[i].active = true; - - linePosition = (Vector2){ player.position.x, player.position.y}; - - break; - } - } - } - - // Shoot life timer - for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) - { - if (shoot[i].active) shoot[i].lifeSpawn++; - } - - // Shot logic - for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) - { - if (shoot[i].active) - { - shoot[i].position.y -= shoot[i].speed.y; - - // Shot vs walls collision logic - if ((shoot[i].position.x > screenWidth + shoot[i].radius) || (shoot[i].position.x < 0 - shoot[i].radius) || - (shoot[i].position.y > screenHeight + shoot[i].radius) || (shoot[i].position.y < 0 - shoot[i].radius)) - { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - } - - // Player shot life spawn - if (shoot[i].lifeSpawn >= 120) - { - shoot[i].position = (Vector2){ 0.0f, 0.0f }; - shoot[i].speed = (Vector2){ 0.0f, 0.0f }; - shoot[i].lifeSpawn = 0; - shoot[i].active = false; - } - } - } - - // Player vs meteors collision logic - player.collider = (Vector3){player.position.x, player.position.y - shipHeight/2, 12}; - - for (int i = 0; i < MAX_BIG_BALLS; i++) - { - if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, bigBalls[i].position, bigBalls[i].radius) && bigBalls[i].active) - { - gameOver = true; - } - } - - for (int i = 0; i < MAX_BIG_BALLS*2; i++) - { - if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, mediumBalls[i].position, mediumBalls[i].radius) && mediumBalls[i].active) - { - gameOver = true; - } - } - - for (int i = 0; i < MAX_BIG_BALLS*4; i++) - { - if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, smallBalls[i].position, smallBalls[i].radius) && smallBalls[i].active) - { - gameOver = true; - } - } - - // Meteors logic (big) - for (int i = 0; i < MAX_BIG_BALLS; i++) - { - if (bigBalls[i].active) - { - // Meteor movement logic - bigBalls[i].position.x += bigBalls[i].speed.x; - bigBalls[i].position.y += bigBalls[i].speed.y; - - // Meteor vs wall collision logic - if (((bigBalls[i].position.x + bigBalls[i].radius) >= screenWidth) || ((bigBalls[i].position.x - bigBalls[i].radius) <= 0)) bigBalls[i].speed.x *= -1; - if ((bigBalls[i].position.y - bigBalls[i].radius) <= 0) bigBalls[i].speed.y *= -1.5; - - if ((bigBalls[i].position.y + bigBalls[i].radius) >= screenHeight) - { - bigBalls[i].speed.y *= -1; - bigBalls[i].position.y = screenHeight - bigBalls[i].radius; - } - - bigBalls[i].speed.y += gravity; - } - } - - // Meteors logic (medium) - for (int i = 0; i < MAX_BIG_BALLS*2; i++) - { - if (mediumBalls[i].active) - { - // Meteor movement logic - mediumBalls[i].position.x += mediumBalls[i].speed.x; - mediumBalls[i].position.y += mediumBalls[i].speed.y; - - // Meteor vs wall collision logic - if (mediumBalls[i].position.x + mediumBalls[i].radius >= screenWidth || mediumBalls[i].position.x - mediumBalls[i].radius <= 0) mediumBalls[i].speed.x *= -1; - if (mediumBalls[i].position.y - mediumBalls[i].radius <= 0) mediumBalls[i].speed.y *= -1; - if (mediumBalls[i].position.y + mediumBalls[i].radius >= screenHeight) - { - mediumBalls[i].speed.y *= -1; - mediumBalls[i].position.y = screenHeight - mediumBalls[i].radius; - } - - mediumBalls[i].speed.y += gravity + 0.12f; - } - } - - // Meteors logic (small) - for (int i = 0; i < MAX_BIG_BALLS*4; i++) - { - if (smallBalls[i].active) - { - // Meteor movement logic - smallBalls[i].position.x += smallBalls[i].speed.x; - smallBalls[i].position.y += smallBalls[i].speed.y; - - // Meteor vs wall collision logic - if (smallBalls[i].position.x + smallBalls[i].radius >= screenWidth || smallBalls[i].position.x - smallBalls[i].radius <= 0) smallBalls[i].speed.x *= -1; - if (smallBalls[i].position.y - smallBalls[i].radius <= 0) smallBalls[i].speed.y *= -1; - if (smallBalls[i].position.y + smallBalls[i].radius >= screenHeight) - { - smallBalls[i].speed.y *= -1; - smallBalls[i].position.y = screenHeight - smallBalls[i].radius; - } - - smallBalls[i].speed.y += gravity + 0.25f; - } - } - - // Player-shot vs meteors logic - for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) - { - if ((shoot[i].active)) - { - for (int a = 0; a < MAX_BIG_BALLS; a++) - { - if (bigBalls[a].active && (bigBalls[a].position.x - bigBalls[a].radius <= linePosition.x && bigBalls[a].position.x + bigBalls[a].radius >= linePosition.x) - && (bigBalls[a].position.y + bigBalls[a].radius >= shoot[i].position.y)) - { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - bigBalls[a].active = false; - meteorsDestroyed++; - score += bigBalls[a].points; - - for (int z = 0; z < 5; z++) - { - if (points[z].alpha == 0.0f) - { - points[z].position = bigBalls[a].position; - points[z].value = bigBalls[a].points; - points[z].alpha = 1.0f; - z = 5; - } - } - - for (int j = 0; j < 2; j ++) - { - if ((countmediumBallss%2) == 0) - { - mediumBalls[countmediumBallss].position = (Vector2){bigBalls[a].position.x, bigBalls[a].position.y}; - mediumBalls[countmediumBallss].speed = (Vector2){ -1*BALLS_SPEED, BALLS_SPEED }; - } - else - { - mediumBalls[countmediumBallss].position = (Vector2){bigBalls[a].position.x, bigBalls[a].position.y}; - mediumBalls[countmediumBallss].speed = (Vector2){ BALLS_SPEED, BALLS_SPEED }; - } - - mediumBalls[countmediumBallss].active = true; - countmediumBallss ++; - } - - a = MAX_BIG_BALLS; - } - } - } - - if ((shoot[i].active)) - { - for (int b = 0; b < MAX_BIG_BALLS*2; b++) - { - if (mediumBalls[b].active && (mediumBalls[b].position.x - mediumBalls[b].radius <= linePosition.x && mediumBalls[b].position.x + mediumBalls[b].radius >= linePosition.x) - && (mediumBalls[b].position.y + mediumBalls[b].radius >= shoot[i].position.y)) - { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - mediumBalls[b].active = false; - meteorsDestroyed++; - score += mediumBalls[b].points; - - for (int z = 0; z < 5; z++) - { - if (points[z].alpha == 0.0f) - { - points[z].position = mediumBalls[b].position; - points[z].value = mediumBalls[b].points; - points[z].alpha = 1.0f; - z = 5; - } - } - - for (int j = 0; j < 2; j ++) - { - if (countsmallBallss%2 == 0) - { - smallBalls[countsmallBallss].position = (Vector2){mediumBalls[b].position.x, mediumBalls[b].position.y}; - smallBalls[countsmallBallss].speed = (Vector2){ BALLS_SPEED*-1, BALLS_SPEED*-1}; - } - else - { - smallBalls[countsmallBallss].position = (Vector2){mediumBalls[b].position.x, mediumBalls[b].position.y}; - smallBalls[countsmallBallss].speed = (Vector2){ BALLS_SPEED, BALLS_SPEED*-1}; - } - - smallBalls[countsmallBallss].active = true; - countsmallBallss ++; - } - - b = MAX_BIG_BALLS*2; - } - } - } - - if ((shoot[i].active)) - { - for (int c = 0; c < MAX_BIG_BALLS*4; c++) - { - if (smallBalls[c].active && (smallBalls[c].position.x - smallBalls[c].radius <= linePosition.x && smallBalls[c].position.x + smallBalls[c].radius >= linePosition.x) - && (smallBalls[c].position.y + smallBalls[c].radius >= shoot[i].position.y)) - { - shoot[i].active = false; - shoot[i].lifeSpawn = 0; - smallBalls[c].active = false; - meteorsDestroyed++; - score += smallBalls[c].points; - - for (int z = 0; z < 5; z++) - { - if (points[z].alpha == 0.0f) - { - points[z].position = smallBalls[c].position; - points[z].value = smallBalls[c].points; - points[z].alpha = 1.0f; - z = 5; - } - } - - c = MAX_BIG_BALLS*4; - } - } - } - } - - if (meteorsDestroyed == (MAX_BIG_BALLS + MAX_BIG_BALLS*2 + MAX_BIG_BALLS*4)) victory = true; - } - } - else - { - if (IsKeyPressed(KEY_ENTER)) - { - InitGame(); - gameOver = false; - } - } - - // Points move-up and fade logic - for (int z = 0; z < 5; z++) - { - if (points[z].alpha > 0.0f) - { - points[z].position.y -= 2; - points[z].alpha -= 0.02f; - } - - if (points[z].alpha < 0.0f) points[z].alpha = 0.0f; - } -} - -// Draw game (one frame) -void DrawGame(void) -{ - BeginDrawing(); - - ClearBackground(RAYWHITE); - - if (!gameOver) - { - // Draw player - Vector2 v1 = { player.position.x + sinf(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cosf(player.rotation*DEG2RAD)*(shipHeight) }; - Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; - Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; - DrawTriangle(v1, v2, v3, MAROON); - - // Draw meteors (big) - for (int i = 0;i < MAX_BIG_BALLS; i++) - { - if (bigBalls[i].active) DrawCircleV(bigBalls[i].position, bigBalls[i].radius, DARKGRAY); - else DrawCircleV(bigBalls[i].position, bigBalls[i].radius, Fade(LIGHTGRAY, 0.3f)); - } - - // Draw meteors (medium) - for (int i = 0;i < MAX_BIG_BALLS*2; i++) - { - if (mediumBalls[i].active) DrawCircleV(mediumBalls[i].position, mediumBalls[i].radius, GRAY); - else DrawCircleV(mediumBalls[i].position, mediumBalls[i].radius, Fade(LIGHTGRAY, 0.3f)); - } - - // Draw meteors (small) - for (int i = 0;i < MAX_BIG_BALLS*4; i++) - { - if (smallBalls[i].active) DrawCircleV(smallBalls[i].position, smallBalls[i].radius, GRAY); - else DrawCircleV(smallBalls[i].position, smallBalls[i].radius, Fade(LIGHTGRAY, 0.3f)); - } - - // Draw shoot - for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) - { - if (shoot[i].active) DrawLine(linePosition.x, linePosition.y, shoot[i].position.x, shoot[i].position.y, RED); - } - - // Draw score points - for (int z = 0; z < 5; z++) - { - if (points[z].alpha > 0.0f) - { - DrawText(FormatText("+%02i", points[z].value), points[z].position.x, points[z].position.y, 20, Fade(BLUE, points[z].alpha)); - } - } - - // Draw score (UI) - DrawText(FormatText("SCORE: %i", score), 10, 10, 20, LIGHTGRAY); - - if (victory) - { - DrawText("YOU WIN!", screenWidth/2 - MeasureText("YOU WIN!", 60)/2, 100, 60, LIGHTGRAY); - DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, LIGHTGRAY); - } - - if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, LIGHTGRAY); - } - else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, LIGHTGRAY); - - EndDrawing(); -} - -// Unload game variables -void UnloadGame(void) -{ - // TODO: Unload all dynamic loaded data (textures, sounds, models...) -} - -// Update and Draw (one frame) -void UpdateDrawFrame(void) -{ - UpdateGame(); - DrawGame(); -} \ No newline at end of file diff --git a/games/samples/snake.c b/games/samples/snake.c deleted file mode 100644 index ac2f6132..00000000 --- a/games/samples/snake.c +++ /dev/null @@ -1,293 +0,0 @@ -/******************************************************************************************* -* -* raylib - sample game: snake -* -* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria -* -* This game has been created using raylib v1.3 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Copyright (c) 2015 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#if defined(PLATFORM_WEB) - #include -#endif - -//---------------------------------------------------------------------------------- -// Some Defines -//---------------------------------------------------------------------------------- -#define SNAKE_LENGTH 256 -#define SQUARE_SIZE 31 - -//---------------------------------------------------------------------------------- -// Types and Structures Definition -//---------------------------------------------------------------------------------- -typedef struct Snake { - Vector2 position; - Vector2 size; - Vector2 speed; - Color color; -} Snake; - -typedef struct Food { - Vector2 position; - Vector2 size; - bool active; - Color color; -} Food; - -//------------------------------------------------------------------------------------ -// Global Variables Declaration -//------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; - -static int framesCounter; -static bool gameOver; -static bool pause; - -static Food fruit; -static Snake snake[SNAKE_LENGTH]; -static Vector2 snakePosition[SNAKE_LENGTH]; -static bool allowMove; -static Vector2 offset; -static int counterTail; - -//------------------------------------------------------------------------------------ -// Module Functions Declaration (local) -//------------------------------------------------------------------------------------ -static void InitGame(void); // Initialize game -static void UpdateGame(void); // Update game (one frame) -static void DrawGame(void); // Draw game (one frame) -static void UnloadGame(void); // Unload game -static void UpdateDrawFrame(void); // Update and Draw (one frame) - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - InitWindow(screenWidth, screenHeight, "sample game: snake"); - - InitGame(); - -#if defined(PLATFORM_WEB) - emscripten_set_main_loop(UpdateDrawFrame, 0, 1); -#else - - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - UpdateGame(); - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - DrawGame(); - //---------------------------------------------------------------------------------- - } -#endif - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadGame(); // Unload loaded data (textures, sounds, models...) - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} - -//------------------------------------------------------------------------------------ -// Module Functions Definitions (local) -//------------------------------------------------------------------------------------ - -// Initialize game variables -void InitGame(void) -{ - framesCounter = 0; - gameOver = false; - pause = false; - - counterTail = 1; - allowMove = false; - - offset.x = screenWidth%SQUARE_SIZE; - offset.y = screenHeight%SQUARE_SIZE; - - for (int i = 0; i < SNAKE_LENGTH; i++) - { - snake[i].position = (Vector2){ offset.x/2, offset.y/2 }; - snake[i].size = (Vector2){ SQUARE_SIZE, SQUARE_SIZE }; - snake[i].speed = (Vector2){ SQUARE_SIZE, 0 }; - - if (i == 0) snake[i].color = DARKBLUE; - else snake[i].color = BLUE; - } - - for (int i = 0; i < SNAKE_LENGTH; i++) - { - snakePosition[i] = (Vector2){ 0.0f, 0.0f }; - } - - fruit.size = (Vector2){ SQUARE_SIZE, SQUARE_SIZE }; - fruit.color = SKYBLUE; - fruit.active = false; -} - -// Update game (one frame) -void UpdateGame(void) -{ - if (!gameOver) - { - if (IsKeyPressed('P')) pause = !pause; - - if (!pause) - { - // control - if (IsKeyPressed(KEY_RIGHT) && (snake[0].speed.x == 0) && allowMove) - { - snake[0].speed = (Vector2){ SQUARE_SIZE, 0 }; - allowMove = false; - } - if (IsKeyPressed(KEY_LEFT) && (snake[0].speed.x == 0) && allowMove) - { - snake[0].speed = (Vector2){ -SQUARE_SIZE, 0 }; - allowMove = false; - } - if (IsKeyPressed(KEY_UP) && (snake[0].speed.y == 0) && allowMove) - { - snake[0].speed = (Vector2){ 0, -SQUARE_SIZE }; - allowMove = false; - } - if (IsKeyPressed(KEY_DOWN) && (snake[0].speed.y == 0) && allowMove) - { - snake[0].speed = (Vector2){ 0, SQUARE_SIZE }; - allowMove = false; - } - - // movement - for (int i = 0; i < counterTail; i++) snakePosition[i] = snake[i].position; - - if ((framesCounter%5) == 0) - { - for (int i = 0; i < counterTail; i++) - { - if (i == 0) - { - snake[0].position.x += snake[0].speed.x; - snake[0].position.y += snake[0].speed.y; - allowMove = true; - } - else snake[i].position = snakePosition[i-1]; - } - } - - // wall behaviour - if (((snake[0].position.x) > (screenWidth - offset.x)) || - ((snake[0].position.y) > (screenHeight - offset.y)) || - (snake[0].position.x < 0) || (snake[0].position.y < 0)) - { - gameOver = true; - } - - // collision with yourself - for (int i = 1; i < counterTail; i++) - { - if ((snake[0].position.x == snake[i].position.x) && (snake[0].position.y == snake[i].position.y)) gameOver = true; - } - - // TODO: review logic: fruit.position calculation - if (!fruit.active) - { - fruit.active = true; - fruit.position = (Vector2){ GetRandomValue(0, (screenWidth/SQUARE_SIZE) - 1)*SQUARE_SIZE + offset.x/2, GetRandomValue(0, (screenHeight/SQUARE_SIZE) - 1)*SQUARE_SIZE + offset.y/2 }; - - for (int i = 0; i < counterTail; i++) - { - while ((fruit.position.x == snake[i].position.x) && (fruit.position.y == snake[i].position.y)) - { - fruit.position = (Vector2){ GetRandomValue(0, (screenWidth/SQUARE_SIZE) - 1)*SQUARE_SIZE, GetRandomValue(0, (screenHeight/SQUARE_SIZE) - 1)*SQUARE_SIZE }; - i = 0; - } - } - } - - // collision - if (CheckCollisionRecs((Rectangle){(int)snake[0].position.x, (int)snake[0].position.y, (int)snake[0].size.x, (int)snake[0].size.y}, - (Rectangle){(int)fruit.position.x, (int)fruit.position.y, (int)fruit.size.x, (int)fruit.size.y})) - { - snake[counterTail].position = snakePosition[counterTail - 1]; - counterTail += 1; - fruit.active = false; - } - - framesCounter++; - } - } - else - { - if (IsKeyPressed(KEY_ENTER)) - { - InitGame(); - gameOver = false; - } - } -} - -// Draw game (one frame) -void DrawGame(void) -{ - BeginDrawing(); - - ClearBackground(RAYWHITE); - - if (!gameOver) - { - // Draw grid lines - for (int i = 0; i < screenWidth/SQUARE_SIZE + 1; i++) - { - DrawLineV((Vector2){SQUARE_SIZE*i + offset.x/2, offset.y/2}, (Vector2){SQUARE_SIZE*i + offset.x/2, screenHeight - offset.y/2}, LIGHTGRAY); - } - - for (int i = 0; i < screenHeight/SQUARE_SIZE + 1; i++) - { - DrawLineV((Vector2){offset.x/2, SQUARE_SIZE*i + offset.y/2}, (Vector2){screenWidth - offset.x/2, SQUARE_SIZE*i + offset.y/2}, LIGHTGRAY); - } - - // Draw snake - for (int i = 0; i < counterTail; i++) DrawRectangleV(snake[i].position, snake[i].size, snake[i].color); - - // Draw fruit to pick - DrawRectangleV(fruit.position, fruit.size, fruit.color); - - if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); - } - else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); - - EndDrawing(); -} - -// Unload game variables -void UnloadGame(void) -{ - // TODO: Unload all dynamic loaded data (textures, sounds, models...) -} - -// Update and Draw (one frame) -void UpdateDrawFrame(void) -{ - UpdateGame(); - DrawGame(); -} \ No newline at end of file diff --git a/games/samples/space_invaders.c b/games/samples/space_invaders.c deleted file mode 100644 index c2dd0c61..00000000 --- a/games/samples/space_invaders.c +++ /dev/null @@ -1,406 +0,0 @@ -/******************************************************************************************* -* -* raylib - sample game: space invaders -* -* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria -* -* This game has been created using raylib v1.3 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Copyright (c) 2015 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#if defined(PLATFORM_WEB) - #include -#endif - -//---------------------------------------------------------------------------------- -// Some Defines -//---------------------------------------------------------------------------------- -#define NUM_SHOOTS 50 -#define NUM_MAX_ENEMIES 50 -#define FIRST_WAVE 10 -#define SECOND_WAVE 20 -#define THIRD_WAVE 50 - -//---------------------------------------------------------------------------------- -// Types and Structures Definition -//---------------------------------------------------------------------------------- -typedef enum { FIRST = 0, SECOND, THIRD } EnemyWave; - -typedef struct Player{ - Rectangle rec; - Vector2 speed; - Color color; -} Player; - -typedef struct Enemy{ - Rectangle rec; - Vector2 speed; - bool active; - Color color; -} Enemy; - -typedef struct Shoot{ - Rectangle rec; - Vector2 speed; - bool active; - Color color; -} Shoot; - -//------------------------------------------------------------------------------------ -// Global Variables Declaration -//------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; - -static int framesCounter; -static bool gameOver; -static bool pause; -static int score; -static bool victory; - -static Player player; -static Enemy enemy[NUM_MAX_ENEMIES]; -static Shoot shoot[NUM_SHOOTS]; -static EnemyWave wave; - -static int shootRate; -static float alpha; - -static int activeEnemies; -static int enemiesKill; -static bool smooth; - -//------------------------------------------------------------------------------------ -// Module Functions Declaration (local) -//------------------------------------------------------------------------------------ -static void InitGame(void); // Initialize game -static void UpdateGame(void); // Update game (one frame) -static void DrawGame(void); // Draw game (one frame) -static void UnloadGame(void); // Unload game -static void UpdateDrawFrame(void); // Update and Draw (one frame) - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - InitWindow(screenWidth, screenHeight, "sample game: space invaders"); - - InitGame(); - -#if defined(PLATFORM_WEB) - emscripten_set_main_loop(UpdateDrawFrame, 0, 1); -#else - - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - UpdateGame(); - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - DrawGame(); - //---------------------------------------------------------------------------------- - } -#endif - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadGame(); // Unload loaded data (textures, sounds, models...) - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} - -//------------------------------------------------------------------------------------ -// Module Functions Definitions (local) -//------------------------------------------------------------------------------------ - -// Initialize game variables -void InitGame(void) -{ - // Initialize game variables - shootRate = 0; - pause = false; - gameOver = false; - victory = false; - smooth = false; - wave = FIRST; - activeEnemies = FIRST_WAVE; - enemiesKill = 0; - score = 0; - alpha = 0; - - // Initialize player - player.rec.x = 20; - player.rec.y = 50; - player.rec.width = 20; - player.rec.height = 20; - player.speed.x = 5; - player.speed.y = 5; - player.color = BLACK; - - // Initialize enemies - for (int i = 0; i < NUM_MAX_ENEMIES; i++) - { - enemy[i].rec.width = 10; - enemy[i].rec.height = 10; - enemy[i].rec.x = GetRandomValue(screenWidth, screenWidth + 1000); - enemy[i].rec.y = GetRandomValue(0, screenHeight - enemy[i].rec.height); - enemy[i].speed.x = 5; - enemy[i].speed.y = 5; - enemy[i].active = true; - enemy[i].color = GRAY; - } - - // Initialize shoots - for (int i = 0; i < NUM_SHOOTS; i++) - { - shoot[i].rec.x = player.rec.x; - shoot[i].rec.y = player.rec.y + player.rec.height/4; - shoot[i].rec.width = 10; - shoot[i].rec.height = 5; - shoot[i].speed.x = 7; - shoot[i].speed.y = 0; - shoot[i].active = false; - shoot[i].color = MAROON; - } -} - -// Update game (one frame) -void UpdateGame(void) -{ - if (!gameOver) - { - if (IsKeyPressed('P')) pause = !pause; - - if (!pause) - { - switch (wave) - { - case FIRST: - { - if (!smooth) - { - alpha += 0.02f; - - if (alpha >= 1.0f) smooth = true; - } - - if (smooth) alpha -= 0.02f; - - if (enemiesKill == activeEnemies) - { - enemiesKill = 0; - - for (int i = 0; i < activeEnemies; i++) - { - if (!enemy[i].active) enemy[i].active = true; - } - - activeEnemies = SECOND_WAVE; - wave = SECOND; - smooth = false; - alpha = 0.0f; - } - } break; - case SECOND: - { - if (!smooth) - { - alpha += 0.02f; - - if (alpha >= 1.0f) smooth = true; - } - - if (smooth) alpha -= 0.02f; - - if (enemiesKill == activeEnemies) - { - enemiesKill = 0; - - for (int i = 0; i < activeEnemies; i++) - { - if (!enemy[i].active) enemy[i].active = true; - } - - activeEnemies = THIRD_WAVE; - wave = THIRD; - smooth = false; - alpha = 0.0f; - } - } break; - case THIRD: - { - if (!smooth) - { - alpha += 0.02f; - - if (alpha >= 1.0f) smooth = true; - } - - if (smooth) alpha -= 0.02f; - - if (enemiesKill == activeEnemies) victory = true; - - } break; - default: break; - } - - // Player movement - if (IsKeyDown(KEY_RIGHT)) player.rec.x += player.speed.x; - if (IsKeyDown(KEY_LEFT)) player.rec.x -= player.speed.x; - if (IsKeyDown(KEY_UP)) player.rec.y -= player.speed.y; - if (IsKeyDown(KEY_DOWN)) player.rec.y += player.speed.y; - - // Player collision with enemy - for (int i = 0; i < activeEnemies; i++) - { - if (CheckCollisionRecs(player.rec, enemy[i].rec)) gameOver = true; - } - - // Enemy behaviour - for (int i = 0; i < activeEnemies; i++) - { - if (enemy[i].active) - { - enemy[i].rec.x -= enemy[i].speed.x; - - if (enemy[i].rec.x < 0) - { - enemy[i].rec.x = GetRandomValue(screenWidth, screenWidth + 1000); - enemy[i].rec.y = GetRandomValue(0, screenHeight - enemy[i].rec.height); - } - } - } - - // Wall behaviour - if (player.rec.x <= 0) player.rec.x = 0; - if (player.rec.x + player.rec.width >= screenWidth) player.rec.x = screenWidth - player.rec.width; - if (player.rec.y <= 0) player.rec.y = 0; - if (player.rec.y + player.rec.height >= screenHeight) player.rec.y = screenHeight - player.rec.height; - - //Shoot initialization - if (IsKeyDown(KEY_SPACE)) - { - shootRate += 5; - - for (int i = 0; i < NUM_SHOOTS; i++) - { - if (!shoot[i].active && shootRate%20 == 0) - { - shoot[i].rec.x = player.rec.x; - shoot[i].rec.y = player.rec.y + player.rec.height/4; - shoot[i].active = true; - break; - } - } - } - - // Shoot logic - for (int i = 0; i < NUM_SHOOTS; i++) - { - if (shoot[i].active) - { - // Movement - shoot[i].rec.x += shoot[i].speed.x; - - // Collision with enemy - for (int j = 0; j < activeEnemies; j++) - { - if (enemy[j].active) - { - if (CheckCollisionRecs(shoot[i].rec, enemy[j].rec)) - { - shoot[i].active = false; - enemy[j].rec.x = GetRandomValue(screenWidth, screenWidth + 1000); - enemy[j].rec.y = GetRandomValue(0, screenHeight - enemy[j].rec.height); - shootRate = 0; - enemiesKill++; - score += 100; - } - - if (shoot[i].rec.x + shoot[i].rec.width >= screenWidth) - { - shoot[i].active = false; - shootRate = 0; - } - } - } - } - } - } - } - else - { - if (IsKeyPressed(KEY_ENTER)) - { - InitGame(); - gameOver = false; - } - } -} - -// Draw game (one frame) -void DrawGame(void) -{ - BeginDrawing(); - - ClearBackground(RAYWHITE); - - if (!gameOver) - { - DrawRectangleRec(player.rec, player.color); - - if (wave == FIRST) DrawText("FIRST WAVE", screenWidth/2 - MeasureText("FIRST WAVE", 40)/2, screenHeight/2 - 40, 40, Fade(BLACK, alpha)); - else if (wave == SECOND) DrawText("SECOND WAVE", screenWidth/2 - MeasureText("SECOND WAVE", 40)/2, screenHeight/2 - 40, 40, Fade(BLACK, alpha)); - else if (wave == THIRD) DrawText("THIRD WAVE", screenWidth/2 - MeasureText("THIRD WAVE", 40)/2, screenHeight/2 - 40, 40, Fade(BLACK, alpha)); - - for (int i = 0; i < activeEnemies; i++) - { - if (enemy[i].active) DrawRectangleRec(enemy[i].rec, enemy[i].color); - } - - for (int i = 0; i < NUM_SHOOTS; i++) - { - if (shoot[i].active) DrawRectangleRec(shoot[i].rec, shoot[i].color); - } - - DrawText(FormatText("%04i", score), 20, 20, 40, GRAY); - - if (victory) DrawText("YOU WIN", screenWidth/2 - MeasureText("YOU WIN", 40)/2, screenHeight/2 - 40, 40, BLACK); - - if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); - } - else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); - - EndDrawing(); -} - -// Unload game variables -void UnloadGame(void) -{ - // TODO: Unload all dynamic loaded data (textures, sounds, models...) -} - -// Update and Draw (one frame) -void UpdateDrawFrame(void) -{ - UpdateGame(); - DrawGame(); -} \ No newline at end of file diff --git a/games/samples/tetris.c b/games/samples/tetris.c deleted file mode 100644 index 62400201..00000000 --- a/games/samples/tetris.c +++ /dev/null @@ -1,836 +0,0 @@ -/******************************************************************************************* -* -* raylib - sample game: tetris -* -* Sample game Marc Palau and Ramon Santamaria -* -* This game has been created using raylib v1.3 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Copyright (c) 2015 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#include -#include -#include -#include - -#if defined(PLATFORM_WEB) - #include -#endif - -//---------------------------------------------------------------------------------- -// Some Defines -//---------------------------------------------------------------------------------- -#define SQUARE_SIZE 20 - -#define GRID_HORIZONTAL_SIZE 12 -#define GRID_VERTICAL_SIZE 20 - -#define LATERAL_SPEED 10 -#define TURNING_SPEED 12 -#define FAST_FALL_AWAIT_COUNTER 30 - -#define FADING_TIME 33 - -//---------------------------------------------------------------------------------- -// Types and Structures Definition -//---------------------------------------------------------------------------------- -typedef enum GridSquare { EMPTY, MOVING, FULL, BLOCK, FADING } GridSquare; - -//------------------------------------------------------------------------------------ -// Global Variables Declaration -//------------------------------------------------------------------------------------ -static int screenWidth = 800; -static int screenHeight = 450; - -static bool gameOver = false; -static bool pause = false; - -// Matrices -static GridSquare grid [GRID_HORIZONTAL_SIZE][GRID_VERTICAL_SIZE]; -static GridSquare piece [4][4]; -static GridSquare incomingPiece [4][4]; - -// Theese variables keep track of the active piece position -static int piecePositionX = 0; -static int piecePositionY = 0; - -// Game parameters -static Color fadingColor; -//static int fallingSpeed; // In frames - -static bool beginPlay = true; // This var is only true at the begining of the game, used for the first matrix creations -static bool pieceActive = false; -static bool detection = false; -static bool lineToDelete = false; - -// Statistics -static int level = 1; -static int lines = 0; - -// Counters -static int gravityMovementCounter = 0; -static int lateralMovementCounter = 0; -static int turnMovementCounter = 0; -static int fastFallMovementCounter = 0; - -static int fadeLineCounter = 0; - -// Based on level -static int gravitySpeed = 30; - -//------------------------------------------------------------------------------------ -// Module Functions Declaration (local) -//------------------------------------------------------------------------------------ -static void InitGame(void); // Initialize game -static void UpdateGame(void); // Update game (one frame) -static void DrawGame(void); // Draw game (one frame) -static void UnloadGame(void); // Unload game -static void UpdateDrawFrame(void); // Update and Draw (one frame) - -// Additional module functions -static bool Createpiece(); -static void GetRandompiece(); -static void ResolveFallingMovement(); -static bool ResolveLateralMovement(); -static bool ResolveTurnMovement(); -static void CheckDetection(); -static void CheckCompletition(); -static void DeleteCompleteLines(); - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - InitWindow(screenWidth, screenHeight, "sample game: tetris"); - - InitGame(); - -#if defined(PLATFORM_WEB) - emscripten_set_main_loop(UpdateDrawFrame, 0, 1); -#else - - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - UpdateGame(); - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - DrawGame(); - //---------------------------------------------------------------------------------- - } -#endif - - // De-Initialization - //-------------------------------------------------------------------------------------- - UnloadGame(); // Unload loaded data (textures, sounds, models...) - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} - -//-------------------------------------------------------------------------------------- -// Game Module Functions Definition -//-------------------------------------------------------------------------------------- - -// Initialize game variables -void InitGame(void) -{ - // Initialize game statistics - level = 1; - lines = 0; - - fadingColor = GRAY; - - piecePositionX = 0; - piecePositionY = 0; - - pause = false; - - beginPlay = true; - pieceActive = false; - detection = false; - lineToDelete = false; - - // Counters - gravityMovementCounter = 0; - lateralMovementCounter = 0; - turnMovementCounter = 0; - fastFallMovementCounter = 0; - - fadeLineCounter = 0; - gravitySpeed = 30; - - // Initialize grid matrices - for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++) - { - for (int j = 0; j < GRID_VERTICAL_SIZE; j++) - { - if ((j == GRID_VERTICAL_SIZE - 1) || (i == 0) || (i == GRID_HORIZONTAL_SIZE - 1)) grid[i][j] = BLOCK; - else grid[i][j] = EMPTY; - } - } - - // Initialize incoming piece matrices - for (int i = 0; i < 4; i++) - { - for (int j = 0; j< 4; j++) - { - incomingPiece[i][j] = EMPTY; - } - } -} - -// Update game (one frame) -void UpdateGame(void) -{ - if (!gameOver) - { - if (IsKeyPressed('P')) pause = !pause; - - if (!pause) - { - if (!lineToDelete) - { - if (!pieceActive) - { - // Get another piece - pieceActive = Createpiece(); - - // We leave a little time before starting the fast falling down - fastFallMovementCounter = 0; - } - else // Piece falling - { - // Counters update - fastFallMovementCounter++; - gravityMovementCounter++; - lateralMovementCounter++; - turnMovementCounter++; - - // We make sure to move if we've pressed the key this frame - if (IsKeyPressed(KEY_LEFT) || IsKeyPressed(KEY_RIGHT)) lateralMovementCounter = LATERAL_SPEED; - if (IsKeyPressed(KEY_UP)) turnMovementCounter = TURNING_SPEED; - - // Fall down - if (IsKeyDown(KEY_DOWN) && (fastFallMovementCounter >= FAST_FALL_AWAIT_COUNTER)) - { - // We make sure the piece is going to fall this frame - gravityMovementCounter += gravitySpeed; - } - - if (gravityMovementCounter >= gravitySpeed) - { - // Basic falling movement - CheckDetection(&detection); - - // Check if the piece has collided with another piece or with the boundings - ResolveFallingMovement(&detection, &pieceActive); - - // Check if we fullfilled a line and if so, erase the line and pull down the the lines above - CheckCompletition(&lineToDelete); - - gravityMovementCounter = 0; - } - - // Move laterally at player's will - if (lateralMovementCounter >= LATERAL_SPEED) - { - // Update the lateral movement and if success, reset the lateral counter - if (!ResolveLateralMovement()) lateralMovementCounter = 0; - } - - // Turn the piece at player's will - if (turnMovementCounter >= TURNING_SPEED) - { - // Update the turning movement and reset the turning counter - if (ResolveTurnMovement()) turnMovementCounter = 0; - } - } - - // Game over logic - for (int j = 0; j < 2; j++) - { - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) - { - if (grid[i][j] == FULL) - { - gameOver = true; - } - } - } - } - else - { - // Animation when deleting lines - fadeLineCounter++; - - if (fadeLineCounter%8 < 4) fadingColor = MAROON; - else fadingColor = GRAY; - - if (fadeLineCounter >= FADING_TIME) - { - DeleteCompleteLines(); - fadeLineCounter = 0; - lineToDelete = false; - - lines++; - } - } - } - } - else - { - if (IsKeyPressed(KEY_ENTER)) - { - InitGame(); - gameOver = false; - } - } -} - -// Draw game (one frame) -void DrawGame(void) -{ - BeginDrawing(); - - ClearBackground(RAYWHITE); - - if (!gameOver) - { - // Draw gameplay area - Vector2 offset; - offset.x = screenWidth/2 - (GRID_HORIZONTAL_SIZE*SQUARE_SIZE/2) - 50; - offset.y = screenHeight/2 - ((GRID_VERTICAL_SIZE - 1)*SQUARE_SIZE/2) + SQUARE_SIZE*2; - - offset.y -= 50; // NOTE: Harcoded position! - - int controller = offset.x; - - for (int j = 0; j < GRID_VERTICAL_SIZE; j++) - { - for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++) - { - // Draw each square of the grid - if (grid[i][j] == EMPTY) - { - DrawLine(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, LIGHTGRAY ); - DrawLine(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, LIGHTGRAY ); - DrawLine(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY ); - DrawLine(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY ); - offset.x += SQUARE_SIZE; - } - else if (grid[i][j] == FULL) - { - DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, GRAY); - offset.x += SQUARE_SIZE; - } - else if (grid[i][j] == MOVING) - { - DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, DARKGRAY); - offset.x += SQUARE_SIZE; - } - else if (grid[i][j] == BLOCK) - { - DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, LIGHTGRAY); - offset.x += SQUARE_SIZE; - } - else if (grid[i][j] == FADING) - { - DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, fadingColor); - offset.x += SQUARE_SIZE; - } - } - - offset.x = controller; - offset.y += SQUARE_SIZE; - } - - // Draw incoming piece (hardcoded) - offset.x = 500; - offset.y = 45; - - int controler = offset.x; - - for (int j = 0; j < 4; j++) - { - for (int i = 0; i < 4; i++) - { - if (incomingPiece[i][j] == EMPTY) - { - DrawLine(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, LIGHTGRAY ); - DrawLine(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, LIGHTGRAY ); - DrawLine(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY ); - DrawLine(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY ); - offset.x += SQUARE_SIZE; - } - else if (incomingPiece[i][j] == MOVING) - { - DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, GRAY); - offset.x += SQUARE_SIZE; - } - } - - offset.x = controler; - offset.y += SQUARE_SIZE; - } - - DrawText("INCOMING:", offset.x, offset.y - 100, 10, GRAY); - DrawText(FormatText("LINES: %04i", lines), offset.x, offset.y + 20, 10, GRAY); - - if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); - } - else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); - - EndDrawing(); -} - -// Unload game variables -void UnloadGame(void) -{ - // TODO: Unload all dynamic loaded data (textures, sounds, models...) -} - -// Update and Draw (one frame) -void UpdateDrawFrame(void) -{ - UpdateGame(); - DrawGame(); -} - -//-------------------------------------------------------------------------------------- -// Additional module functions -//-------------------------------------------------------------------------------------- -static bool Createpiece() -{ - piecePositionX = (int)((GRID_HORIZONTAL_SIZE - 4)/2); - piecePositionY = 0; - - // If the game is starting and you are going to create the first piece, we create an extra one - if (beginPlay) - { - GetRandompiece(); - beginPlay = false; - } - - // We assign the incoming piece to the actual piece - for (int i = 0; i < 4; i++) - { - for (int j = 0; j< 4; j++) - { - piece[i][j] = incomingPiece[i][j]; - } - } - - // We assign a random piece to the incoming one - GetRandompiece(); - - // Assign the piece to the grid - for (int i = piecePositionX; i < piecePositionX + 4; i++) - { - for (int j = 0; j < 4; j++) - { - if (piece[i - (int)piecePositionX][j] == MOVING) grid[i][j] = MOVING; - } - } - - return true; -} - -static void GetRandompiece() -{ - srand(time(NULL)); - int random = rand() % 7; - - for (int i = 0; i < 4; i++) - { - for (int j = 0; j < 4; j++) - { - incomingPiece[i][j] = EMPTY; - } - } - - switch(random) - { - case 0: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //Cube - case 1: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //L - case 2: { incomingPiece[1][2] = MOVING; incomingPiece[2][0] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; } break; //L inversa - case 3: { incomingPiece[0][1] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //Recta - case 4: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][1] = MOVING; } break; //Creu tallada - case 5: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[3][2] = MOVING; } break; //S - case 6: { incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //S inversa - } -} - -static void ResolveFallingMovement(bool *detection, bool *pieceActive) -{ - // If we finished moving this piece, we stop it - if (*detection) - { - for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) - { - if (grid[i][j] == MOVING) - { - grid[i][j] = FULL; - *detection = false; - *pieceActive = false; - } - } - } - } - // We move down the piece - else - { - for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) - { - if (grid[i][j] == MOVING) - { - grid[i][j+1] = MOVING; - grid[i][j] = EMPTY; - } - } - } - piecePositionY++; - } -} - -static bool ResolveLateralMovement() -{ - bool collision = false; - - // Move left - if (IsKeyDown(KEY_LEFT)) - { - // Check if is possible to move to left - for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) - { - if (grid[i][j] == MOVING) - { - // Check if we are touching the left wall or we have a full square at the left - if ((i-1 == 0) || (grid[i-1][j] == FULL)) collision = true; - } - } - } - // If able, move left - if (!collision) - { - for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) // We check the matrix from left to right - { - // Move everything to the left - if (grid[i][j] == MOVING) - { - grid[i-1][j] = MOVING; - grid[i][j] = EMPTY; - } - } - } - - piecePositionX--; - } - } - - // Move right - else if (IsKeyDown(KEY_RIGHT)) - { - // Check if is possible to move to right - for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) - { - if (grid[i][j] == MOVING) - { - // Check if we are touching the right wall or we have a full square at the right - if ((i+1 == GRID_HORIZONTAL_SIZE - 1) || (grid[i+1][j] == FULL)) - { - collision = true; - - } - } - } - } - // If able move right - if (!collision) - { - for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - for (int i = GRID_HORIZONTAL_SIZE - 1; i >= 1; i--) // We check the matrix from right to left - { - // Move everything to the right - if (grid[i][j] == MOVING) - { - grid[i+1][j] = MOVING; - grid[i][j] = EMPTY; - } - } - } - - piecePositionX++; - } - } - - return collision; -} - -static bool ResolveTurnMovement() -{ - // Input for turning the piece - if (IsKeyDown(KEY_UP)) - { - int aux; - bool checker = false; - - // Check all turning possibilities - if ((grid[piecePositionX + 3][piecePositionY] == MOVING) && - (grid[piecePositionX][piecePositionY] != EMPTY) && - (grid[piecePositionX][piecePositionY] != MOVING)) - { - checker = true; - } - if ((grid[piecePositionX + 3][piecePositionY + 3] == MOVING) && - (grid[piecePositionX + 3][piecePositionY] != EMPTY) && - (grid[piecePositionX + 3][piecePositionY] != MOVING)) - { - checker = true; - } - if ((grid[piecePositionX][piecePositionY + 3] == MOVING) && - (grid[piecePositionX + 3][piecePositionY + 3] != EMPTY) && - (grid[piecePositionX + 3][piecePositionY + 3] != MOVING)) - { - checker = true; - } - if ((grid[piecePositionX][piecePositionY] == MOVING) && - (grid[piecePositionX][piecePositionY + 3] != EMPTY) && - (grid[piecePositionX][piecePositionY + 3] != MOVING)) - { - checker = true; - } - - - if ((grid[piecePositionX + 1][piecePositionY] == MOVING) && - (grid[piecePositionX][piecePositionY + 2] != EMPTY) && - (grid[piecePositionX][piecePositionY + 2] != MOVING)) - { - checker = true; - } - if ((grid[piecePositionX + 3][piecePositionY + 1] == MOVING) && - (grid[piecePositionX + 1][piecePositionY] != EMPTY) && - (grid[piecePositionX + 1][piecePositionY] != MOVING)) - { - checker = true; - } - if ((grid[piecePositionX + 2][piecePositionY + 3] == MOVING) && - (grid[piecePositionX + 3][piecePositionY + 1] != EMPTY) && - (grid[piecePositionX + 3][piecePositionY + 1] != MOVING)) - { - checker = true; - } - if ((grid[piecePositionX][piecePositionY + 2] == MOVING) && - (grid[piecePositionX + 2][piecePositionY + 3] != EMPTY) && - (grid[piecePositionX + 2][piecePositionY + 3] != MOVING)) - { - checker = true; - } - - - if ((grid[piecePositionX + 2][piecePositionY] == MOVING) && - (grid[piecePositionX][piecePositionY + 1] != EMPTY) && - (grid[piecePositionX][piecePositionY + 1] != MOVING)) - { - checker = true; - } - if ((grid[piecePositionX + 3][piecePositionY + 2] == MOVING) && - (grid[piecePositionX + 2][piecePositionY] != EMPTY) && - (grid[piecePositionX + 2][piecePositionY] != MOVING)) - { - checker = true; - } - if ((grid[piecePositionX + 1][piecePositionY + 3] == MOVING) && - (grid[piecePositionX + 3][piecePositionY + 2] != EMPTY) && - (grid[piecePositionX + 3][piecePositionY + 2] != MOVING)) - { - checker = true; - } - if ((grid[piecePositionX][piecePositionY + 1] == MOVING) && - (grid[piecePositionX + 1][piecePositionY + 3] != EMPTY) && - (grid[piecePositionX + 1][piecePositionY + 3] != MOVING)) - { - checker = true; - } - - if ((grid[piecePositionX + 1][piecePositionY + 1] == MOVING) && - (grid[piecePositionX + 1][piecePositionY + 2] != EMPTY) && - (grid[piecePositionX + 1][piecePositionY + 2] != MOVING)) - { - checker = true; - } - - if ((grid[piecePositionX + 2][piecePositionY + 1] == MOVING) && - (grid[piecePositionX + 1][piecePositionY + 1] != EMPTY) && - (grid[piecePositionX + 1][piecePositionY + 1] != MOVING)) - { - checker = true; - } - if ((grid[piecePositionX + 2][piecePositionY + 2] == MOVING) && - (grid[piecePositionX + 2][piecePositionY + 1] != EMPTY) && - (grid[piecePositionX + 2][piecePositionY + 1] != MOVING)) - { - checker = true; - } - if ((grid[piecePositionX + 1][piecePositionY + 2] == MOVING) && - (grid[piecePositionX + 2][piecePositionY + 2] != EMPTY) && - (grid[piecePositionX + 2][piecePositionY + 2] != MOVING)) - { - checker = true; - } - - if (!checker) - { - aux = piece[0][0]; - piece[0][0] = piece[3][0]; - piece[3][0] = piece[3][3]; - piece[3][3] = piece[0][3]; - piece[0][3] = aux; - - aux = piece[1][0]; - piece[1][0] = piece[3][1]; - piece[3][1] = piece[2][3]; - piece[2][3] = piece[0][2]; - piece[0][2] = aux; - - aux = piece[2][0]; - piece[2][0] = piece[3][2]; - piece[3][2] = piece[1][3]; - piece[1][3] = piece[0][1]; - piece[0][1] = aux; - - aux = piece[1][1]; - piece[1][1] = piece[2][1]; - piece[2][1] = piece[2][2]; - piece[2][2] = piece[1][2]; - piece[1][2] = aux; - } - - for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) - { - if (grid[i][j] == MOVING) - { - grid[i][j] = EMPTY; - } - } - } - - for (int i = piecePositionX; i < piecePositionX + 4; i++) - { - for (int j = piecePositionY; j < piecePositionY + 4; j++) - { - if (piece[i - piecePositionX][j - piecePositionY] == MOVING) - { - grid[i][j] = MOVING; - } - } - } - return true; - } - - return false; -} - -static void CheckDetection(bool *detection) -{ - for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) - { - if ((grid[i][j] == MOVING) && ((grid[i][j+1] == FULL) || (grid[i][j+1] == BLOCK))) *detection = true; - } - } -} - -static void CheckCompletition(bool *lineToDelete) -{ - int calculator; - - for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - calculator = 0; - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) - { - // Count each square of the line - if (grid[i][j] == FULL) - { - calculator++; - } - - // Check if we completed the whole line - if (calculator == GRID_HORIZONTAL_SIZE - 2) - { - *lineToDelete = true; - calculator = 0; - // points++; - - // Mark the completed line - for (int z = 1; z < GRID_HORIZONTAL_SIZE - 1; z++) - { - grid[z][j] = FADING; - } - } - } - } -} - -static void DeleteCompleteLines() -{ - // erase the completed line - for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - while (grid[1][j] == FADING) - { - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) - { - grid[i][j] = EMPTY; - } - for (int j2 = j-1; j2 >= 0; j2--) - { - for (int i2 = 1; i2 < GRID_HORIZONTAL_SIZE - 1; i2++) - { - if (grid[i2][j2] == FULL) - { - grid[i2][j2+1] = FULL; - grid[i2][j2] = EMPTY; - } - else if (grid[i2][j2] == FADING) - { - grid[i2][j2+1] = FADING; - grid[i2][j2] = EMPTY; - } - } - } - } - } -} \ No newline at end of file diff --git a/games/snake.c b/games/snake.c new file mode 100644 index 00000000..ac2f6132 --- /dev/null +++ b/games/snake.c @@ -0,0 +1,293 @@ +/******************************************************************************************* +* +* raylib - sample game: snake +* +* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define SNAKE_LENGTH 256 +#define SQUARE_SIZE 31 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct Snake { + Vector2 position; + Vector2 size; + Vector2 speed; + Color color; +} Snake; + +typedef struct Food { + Vector2 position; + Vector2 size; + bool active; + Color color; +} Food; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter; +static bool gameOver; +static bool pause; + +static Food fruit; +static Snake snake[SNAKE_LENGTH]; +static Vector2 snakePosition[SNAKE_LENGTH]; +static bool allowMove; +static Vector2 offset; +static int counterTail; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: snake"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + framesCounter = 0; + gameOver = false; + pause = false; + + counterTail = 1; + allowMove = false; + + offset.x = screenWidth%SQUARE_SIZE; + offset.y = screenHeight%SQUARE_SIZE; + + for (int i = 0; i < SNAKE_LENGTH; i++) + { + snake[i].position = (Vector2){ offset.x/2, offset.y/2 }; + snake[i].size = (Vector2){ SQUARE_SIZE, SQUARE_SIZE }; + snake[i].speed = (Vector2){ SQUARE_SIZE, 0 }; + + if (i == 0) snake[i].color = DARKBLUE; + else snake[i].color = BLUE; + } + + for (int i = 0; i < SNAKE_LENGTH; i++) + { + snakePosition[i] = (Vector2){ 0.0f, 0.0f }; + } + + fruit.size = (Vector2){ SQUARE_SIZE, SQUARE_SIZE }; + fruit.color = SKYBLUE; + fruit.active = false; +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + // control + if (IsKeyPressed(KEY_RIGHT) && (snake[0].speed.x == 0) && allowMove) + { + snake[0].speed = (Vector2){ SQUARE_SIZE, 0 }; + allowMove = false; + } + if (IsKeyPressed(KEY_LEFT) && (snake[0].speed.x == 0) && allowMove) + { + snake[0].speed = (Vector2){ -SQUARE_SIZE, 0 }; + allowMove = false; + } + if (IsKeyPressed(KEY_UP) && (snake[0].speed.y == 0) && allowMove) + { + snake[0].speed = (Vector2){ 0, -SQUARE_SIZE }; + allowMove = false; + } + if (IsKeyPressed(KEY_DOWN) && (snake[0].speed.y == 0) && allowMove) + { + snake[0].speed = (Vector2){ 0, SQUARE_SIZE }; + allowMove = false; + } + + // movement + for (int i = 0; i < counterTail; i++) snakePosition[i] = snake[i].position; + + if ((framesCounter%5) == 0) + { + for (int i = 0; i < counterTail; i++) + { + if (i == 0) + { + snake[0].position.x += snake[0].speed.x; + snake[0].position.y += snake[0].speed.y; + allowMove = true; + } + else snake[i].position = snakePosition[i-1]; + } + } + + // wall behaviour + if (((snake[0].position.x) > (screenWidth - offset.x)) || + ((snake[0].position.y) > (screenHeight - offset.y)) || + (snake[0].position.x < 0) || (snake[0].position.y < 0)) + { + gameOver = true; + } + + // collision with yourself + for (int i = 1; i < counterTail; i++) + { + if ((snake[0].position.x == snake[i].position.x) && (snake[0].position.y == snake[i].position.y)) gameOver = true; + } + + // TODO: review logic: fruit.position calculation + if (!fruit.active) + { + fruit.active = true; + fruit.position = (Vector2){ GetRandomValue(0, (screenWidth/SQUARE_SIZE) - 1)*SQUARE_SIZE + offset.x/2, GetRandomValue(0, (screenHeight/SQUARE_SIZE) - 1)*SQUARE_SIZE + offset.y/2 }; + + for (int i = 0; i < counterTail; i++) + { + while ((fruit.position.x == snake[i].position.x) && (fruit.position.y == snake[i].position.y)) + { + fruit.position = (Vector2){ GetRandomValue(0, (screenWidth/SQUARE_SIZE) - 1)*SQUARE_SIZE, GetRandomValue(0, (screenHeight/SQUARE_SIZE) - 1)*SQUARE_SIZE }; + i = 0; + } + } + } + + // collision + if (CheckCollisionRecs((Rectangle){(int)snake[0].position.x, (int)snake[0].position.y, (int)snake[0].size.x, (int)snake[0].size.y}, + (Rectangle){(int)fruit.position.x, (int)fruit.position.y, (int)fruit.size.x, (int)fruit.size.y})) + { + snake[counterTail].position = snakePosition[counterTail - 1]; + counterTail += 1; + fruit.active = false; + } + + framesCounter++; + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // Draw grid lines + for (int i = 0; i < screenWidth/SQUARE_SIZE + 1; i++) + { + DrawLineV((Vector2){SQUARE_SIZE*i + offset.x/2, offset.y/2}, (Vector2){SQUARE_SIZE*i + offset.x/2, screenHeight - offset.y/2}, LIGHTGRAY); + } + + for (int i = 0; i < screenHeight/SQUARE_SIZE + 1; i++) + { + DrawLineV((Vector2){offset.x/2, SQUARE_SIZE*i + offset.y/2}, (Vector2){screenWidth - offset.x/2, SQUARE_SIZE*i + offset.y/2}, LIGHTGRAY); + } + + // Draw snake + for (int i = 0; i < counterTail; i++) DrawRectangleV(snake[i].position, snake[i].size, snake[i].color); + + // Draw fruit to pick + DrawRectangleV(fruit.position, fruit.size, fruit.color); + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} \ No newline at end of file diff --git a/games/space_invaders.c b/games/space_invaders.c new file mode 100644 index 00000000..c2dd0c61 --- /dev/null +++ b/games/space_invaders.c @@ -0,0 +1,406 @@ +/******************************************************************************************* +* +* raylib - sample game: space invaders +* +* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define NUM_SHOOTS 50 +#define NUM_MAX_ENEMIES 50 +#define FIRST_WAVE 10 +#define SECOND_WAVE 20 +#define THIRD_WAVE 50 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum { FIRST = 0, SECOND, THIRD } EnemyWave; + +typedef struct Player{ + Rectangle rec; + Vector2 speed; + Color color; +} Player; + +typedef struct Enemy{ + Rectangle rec; + Vector2 speed; + bool active; + Color color; +} Enemy; + +typedef struct Shoot{ + Rectangle rec; + Vector2 speed; + bool active; + Color color; +} Shoot; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter; +static bool gameOver; +static bool pause; +static int score; +static bool victory; + +static Player player; +static Enemy enemy[NUM_MAX_ENEMIES]; +static Shoot shoot[NUM_SHOOTS]; +static EnemyWave wave; + +static int shootRate; +static float alpha; + +static int activeEnemies; +static int enemiesKill; +static bool smooth; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: space invaders"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + // Initialize game variables + shootRate = 0; + pause = false; + gameOver = false; + victory = false; + smooth = false; + wave = FIRST; + activeEnemies = FIRST_WAVE; + enemiesKill = 0; + score = 0; + alpha = 0; + + // Initialize player + player.rec.x = 20; + player.rec.y = 50; + player.rec.width = 20; + player.rec.height = 20; + player.speed.x = 5; + player.speed.y = 5; + player.color = BLACK; + + // Initialize enemies + for (int i = 0; i < NUM_MAX_ENEMIES; i++) + { + enemy[i].rec.width = 10; + enemy[i].rec.height = 10; + enemy[i].rec.x = GetRandomValue(screenWidth, screenWidth + 1000); + enemy[i].rec.y = GetRandomValue(0, screenHeight - enemy[i].rec.height); + enemy[i].speed.x = 5; + enemy[i].speed.y = 5; + enemy[i].active = true; + enemy[i].color = GRAY; + } + + // Initialize shoots + for (int i = 0; i < NUM_SHOOTS; i++) + { + shoot[i].rec.x = player.rec.x; + shoot[i].rec.y = player.rec.y + player.rec.height/4; + shoot[i].rec.width = 10; + shoot[i].rec.height = 5; + shoot[i].speed.x = 7; + shoot[i].speed.y = 0; + shoot[i].active = false; + shoot[i].color = MAROON; + } +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + switch (wave) + { + case FIRST: + { + if (!smooth) + { + alpha += 0.02f; + + if (alpha >= 1.0f) smooth = true; + } + + if (smooth) alpha -= 0.02f; + + if (enemiesKill == activeEnemies) + { + enemiesKill = 0; + + for (int i = 0; i < activeEnemies; i++) + { + if (!enemy[i].active) enemy[i].active = true; + } + + activeEnemies = SECOND_WAVE; + wave = SECOND; + smooth = false; + alpha = 0.0f; + } + } break; + case SECOND: + { + if (!smooth) + { + alpha += 0.02f; + + if (alpha >= 1.0f) smooth = true; + } + + if (smooth) alpha -= 0.02f; + + if (enemiesKill == activeEnemies) + { + enemiesKill = 0; + + for (int i = 0; i < activeEnemies; i++) + { + if (!enemy[i].active) enemy[i].active = true; + } + + activeEnemies = THIRD_WAVE; + wave = THIRD; + smooth = false; + alpha = 0.0f; + } + } break; + case THIRD: + { + if (!smooth) + { + alpha += 0.02f; + + if (alpha >= 1.0f) smooth = true; + } + + if (smooth) alpha -= 0.02f; + + if (enemiesKill == activeEnemies) victory = true; + + } break; + default: break; + } + + // Player movement + if (IsKeyDown(KEY_RIGHT)) player.rec.x += player.speed.x; + if (IsKeyDown(KEY_LEFT)) player.rec.x -= player.speed.x; + if (IsKeyDown(KEY_UP)) player.rec.y -= player.speed.y; + if (IsKeyDown(KEY_DOWN)) player.rec.y += player.speed.y; + + // Player collision with enemy + for (int i = 0; i < activeEnemies; i++) + { + if (CheckCollisionRecs(player.rec, enemy[i].rec)) gameOver = true; + } + + // Enemy behaviour + for (int i = 0; i < activeEnemies; i++) + { + if (enemy[i].active) + { + enemy[i].rec.x -= enemy[i].speed.x; + + if (enemy[i].rec.x < 0) + { + enemy[i].rec.x = GetRandomValue(screenWidth, screenWidth + 1000); + enemy[i].rec.y = GetRandomValue(0, screenHeight - enemy[i].rec.height); + } + } + } + + // Wall behaviour + if (player.rec.x <= 0) player.rec.x = 0; + if (player.rec.x + player.rec.width >= screenWidth) player.rec.x = screenWidth - player.rec.width; + if (player.rec.y <= 0) player.rec.y = 0; + if (player.rec.y + player.rec.height >= screenHeight) player.rec.y = screenHeight - player.rec.height; + + //Shoot initialization + if (IsKeyDown(KEY_SPACE)) + { + shootRate += 5; + + for (int i = 0; i < NUM_SHOOTS; i++) + { + if (!shoot[i].active && shootRate%20 == 0) + { + shoot[i].rec.x = player.rec.x; + shoot[i].rec.y = player.rec.y + player.rec.height/4; + shoot[i].active = true; + break; + } + } + } + + // Shoot logic + for (int i = 0; i < NUM_SHOOTS; i++) + { + if (shoot[i].active) + { + // Movement + shoot[i].rec.x += shoot[i].speed.x; + + // Collision with enemy + for (int j = 0; j < activeEnemies; j++) + { + if (enemy[j].active) + { + if (CheckCollisionRecs(shoot[i].rec, enemy[j].rec)) + { + shoot[i].active = false; + enemy[j].rec.x = GetRandomValue(screenWidth, screenWidth + 1000); + enemy[j].rec.y = GetRandomValue(0, screenHeight - enemy[j].rec.height); + shootRate = 0; + enemiesKill++; + score += 100; + } + + if (shoot[i].rec.x + shoot[i].rec.width >= screenWidth) + { + shoot[i].active = false; + shootRate = 0; + } + } + } + } + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + DrawRectangleRec(player.rec, player.color); + + if (wave == FIRST) DrawText("FIRST WAVE", screenWidth/2 - MeasureText("FIRST WAVE", 40)/2, screenHeight/2 - 40, 40, Fade(BLACK, alpha)); + else if (wave == SECOND) DrawText("SECOND WAVE", screenWidth/2 - MeasureText("SECOND WAVE", 40)/2, screenHeight/2 - 40, 40, Fade(BLACK, alpha)); + else if (wave == THIRD) DrawText("THIRD WAVE", screenWidth/2 - MeasureText("THIRD WAVE", 40)/2, screenHeight/2 - 40, 40, Fade(BLACK, alpha)); + + for (int i = 0; i < activeEnemies; i++) + { + if (enemy[i].active) DrawRectangleRec(enemy[i].rec, enemy[i].color); + } + + for (int i = 0; i < NUM_SHOOTS; i++) + { + if (shoot[i].active) DrawRectangleRec(shoot[i].rec, shoot[i].color); + } + + DrawText(FormatText("%04i", score), 20, 20, 40, GRAY); + + if (victory) DrawText("YOU WIN", screenWidth/2 - MeasureText("YOU WIN", 40)/2, screenHeight/2 - 40, 40, BLACK); + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} \ No newline at end of file diff --git a/games/tetris.c b/games/tetris.c new file mode 100644 index 00000000..62400201 --- /dev/null +++ b/games/tetris.c @@ -0,0 +1,836 @@ +/******************************************************************************************* +* +* raylib - sample game: tetris +* +* Sample game Marc Palau and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include +#include +#include +#include + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define SQUARE_SIZE 20 + +#define GRID_HORIZONTAL_SIZE 12 +#define GRID_VERTICAL_SIZE 20 + +#define LATERAL_SPEED 10 +#define TURNING_SPEED 12 +#define FAST_FALL_AWAIT_COUNTER 30 + +#define FADING_TIME 33 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum GridSquare { EMPTY, MOVING, FULL, BLOCK, FADING } GridSquare; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static bool gameOver = false; +static bool pause = false; + +// Matrices +static GridSquare grid [GRID_HORIZONTAL_SIZE][GRID_VERTICAL_SIZE]; +static GridSquare piece [4][4]; +static GridSquare incomingPiece [4][4]; + +// Theese variables keep track of the active piece position +static int piecePositionX = 0; +static int piecePositionY = 0; + +// Game parameters +static Color fadingColor; +//static int fallingSpeed; // In frames + +static bool beginPlay = true; // This var is only true at the begining of the game, used for the first matrix creations +static bool pieceActive = false; +static bool detection = false; +static bool lineToDelete = false; + +// Statistics +static int level = 1; +static int lines = 0; + +// Counters +static int gravityMovementCounter = 0; +static int lateralMovementCounter = 0; +static int turnMovementCounter = 0; +static int fastFallMovementCounter = 0; + +static int fadeLineCounter = 0; + +// Based on level +static int gravitySpeed = 30; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +// Additional module functions +static bool Createpiece(); +static void GetRandompiece(); +static void ResolveFallingMovement(); +static bool ResolveLateralMovement(); +static bool ResolveTurnMovement(); +static void CheckDetection(); +static void CheckCompletition(); +static void DeleteCompleteLines(); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: tetris"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//-------------------------------------------------------------------------------------- +// Game Module Functions Definition +//-------------------------------------------------------------------------------------- + +// Initialize game variables +void InitGame(void) +{ + // Initialize game statistics + level = 1; + lines = 0; + + fadingColor = GRAY; + + piecePositionX = 0; + piecePositionY = 0; + + pause = false; + + beginPlay = true; + pieceActive = false; + detection = false; + lineToDelete = false; + + // Counters + gravityMovementCounter = 0; + lateralMovementCounter = 0; + turnMovementCounter = 0; + fastFallMovementCounter = 0; + + fadeLineCounter = 0; + gravitySpeed = 30; + + // Initialize grid matrices + for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++) + { + for (int j = 0; j < GRID_VERTICAL_SIZE; j++) + { + if ((j == GRID_VERTICAL_SIZE - 1) || (i == 0) || (i == GRID_HORIZONTAL_SIZE - 1)) grid[i][j] = BLOCK; + else grid[i][j] = EMPTY; + } + } + + // Initialize incoming piece matrices + for (int i = 0; i < 4; i++) + { + for (int j = 0; j< 4; j++) + { + incomingPiece[i][j] = EMPTY; + } + } +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + if (!lineToDelete) + { + if (!pieceActive) + { + // Get another piece + pieceActive = Createpiece(); + + // We leave a little time before starting the fast falling down + fastFallMovementCounter = 0; + } + else // Piece falling + { + // Counters update + fastFallMovementCounter++; + gravityMovementCounter++; + lateralMovementCounter++; + turnMovementCounter++; + + // We make sure to move if we've pressed the key this frame + if (IsKeyPressed(KEY_LEFT) || IsKeyPressed(KEY_RIGHT)) lateralMovementCounter = LATERAL_SPEED; + if (IsKeyPressed(KEY_UP)) turnMovementCounter = TURNING_SPEED; + + // Fall down + if (IsKeyDown(KEY_DOWN) && (fastFallMovementCounter >= FAST_FALL_AWAIT_COUNTER)) + { + // We make sure the piece is going to fall this frame + gravityMovementCounter += gravitySpeed; + } + + if (gravityMovementCounter >= gravitySpeed) + { + // Basic falling movement + CheckDetection(&detection); + + // Check if the piece has collided with another piece or with the boundings + ResolveFallingMovement(&detection, &pieceActive); + + // Check if we fullfilled a line and if so, erase the line and pull down the the lines above + CheckCompletition(&lineToDelete); + + gravityMovementCounter = 0; + } + + // Move laterally at player's will + if (lateralMovementCounter >= LATERAL_SPEED) + { + // Update the lateral movement and if success, reset the lateral counter + if (!ResolveLateralMovement()) lateralMovementCounter = 0; + } + + // Turn the piece at player's will + if (turnMovementCounter >= TURNING_SPEED) + { + // Update the turning movement and reset the turning counter + if (ResolveTurnMovement()) turnMovementCounter = 0; + } + } + + // Game over logic + for (int j = 0; j < 2; j++) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if (grid[i][j] == FULL) + { + gameOver = true; + } + } + } + } + else + { + // Animation when deleting lines + fadeLineCounter++; + + if (fadeLineCounter%8 < 4) fadingColor = MAROON; + else fadingColor = GRAY; + + if (fadeLineCounter >= FADING_TIME) + { + DeleteCompleteLines(); + fadeLineCounter = 0; + lineToDelete = false; + + lines++; + } + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // Draw gameplay area + Vector2 offset; + offset.x = screenWidth/2 - (GRID_HORIZONTAL_SIZE*SQUARE_SIZE/2) - 50; + offset.y = screenHeight/2 - ((GRID_VERTICAL_SIZE - 1)*SQUARE_SIZE/2) + SQUARE_SIZE*2; + + offset.y -= 50; // NOTE: Harcoded position! + + int controller = offset.x; + + for (int j = 0; j < GRID_VERTICAL_SIZE; j++) + { + for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++) + { + // Draw each square of the grid + if (grid[i][j] == EMPTY) + { + DrawLine(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, LIGHTGRAY ); + DrawLine(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, LIGHTGRAY ); + DrawLine(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY ); + DrawLine(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY ); + offset.x += SQUARE_SIZE; + } + else if (grid[i][j] == FULL) + { + DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, GRAY); + offset.x += SQUARE_SIZE; + } + else if (grid[i][j] == MOVING) + { + DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, DARKGRAY); + offset.x += SQUARE_SIZE; + } + else if (grid[i][j] == BLOCK) + { + DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, LIGHTGRAY); + offset.x += SQUARE_SIZE; + } + else if (grid[i][j] == FADING) + { + DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, fadingColor); + offset.x += SQUARE_SIZE; + } + } + + offset.x = controller; + offset.y += SQUARE_SIZE; + } + + // Draw incoming piece (hardcoded) + offset.x = 500; + offset.y = 45; + + int controler = offset.x; + + for (int j = 0; j < 4; j++) + { + for (int i = 0; i < 4; i++) + { + if (incomingPiece[i][j] == EMPTY) + { + DrawLine(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, LIGHTGRAY ); + DrawLine(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, LIGHTGRAY ); + DrawLine(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY ); + DrawLine(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY ); + offset.x += SQUARE_SIZE; + } + else if (incomingPiece[i][j] == MOVING) + { + DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, GRAY); + offset.x += SQUARE_SIZE; + } + } + + offset.x = controler; + offset.y += SQUARE_SIZE; + } + + DrawText("INCOMING:", offset.x, offset.y - 100, 10, GRAY); + DrawText(FormatText("LINES: %04i", lines), offset.x, offset.y + 20, 10, GRAY); + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} + +//-------------------------------------------------------------------------------------- +// Additional module functions +//-------------------------------------------------------------------------------------- +static bool Createpiece() +{ + piecePositionX = (int)((GRID_HORIZONTAL_SIZE - 4)/2); + piecePositionY = 0; + + // If the game is starting and you are going to create the first piece, we create an extra one + if (beginPlay) + { + GetRandompiece(); + beginPlay = false; + } + + // We assign the incoming piece to the actual piece + for (int i = 0; i < 4; i++) + { + for (int j = 0; j< 4; j++) + { + piece[i][j] = incomingPiece[i][j]; + } + } + + // We assign a random piece to the incoming one + GetRandompiece(); + + // Assign the piece to the grid + for (int i = piecePositionX; i < piecePositionX + 4; i++) + { + for (int j = 0; j < 4; j++) + { + if (piece[i - (int)piecePositionX][j] == MOVING) grid[i][j] = MOVING; + } + } + + return true; +} + +static void GetRandompiece() +{ + srand(time(NULL)); + int random = rand() % 7; + + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 4; j++) + { + incomingPiece[i][j] = EMPTY; + } + } + + switch(random) + { + case 0: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //Cube + case 1: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //L + case 2: { incomingPiece[1][2] = MOVING; incomingPiece[2][0] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; } break; //L inversa + case 3: { incomingPiece[0][1] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //Recta + case 4: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][1] = MOVING; } break; //Creu tallada + case 5: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[3][2] = MOVING; } break; //S + case 6: { incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //S inversa + } +} + +static void ResolveFallingMovement(bool *detection, bool *pieceActive) +{ + // If we finished moving this piece, we stop it + if (*detection) + { + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if (grid[i][j] == MOVING) + { + grid[i][j] = FULL; + *detection = false; + *pieceActive = false; + } + } + } + } + // We move down the piece + else + { + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if (grid[i][j] == MOVING) + { + grid[i][j+1] = MOVING; + grid[i][j] = EMPTY; + } + } + } + piecePositionY++; + } +} + +static bool ResolveLateralMovement() +{ + bool collision = false; + + // Move left + if (IsKeyDown(KEY_LEFT)) + { + // Check if is possible to move to left + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if (grid[i][j] == MOVING) + { + // Check if we are touching the left wall or we have a full square at the left + if ((i-1 == 0) || (grid[i-1][j] == FULL)) collision = true; + } + } + } + // If able, move left + if (!collision) + { + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) // We check the matrix from left to right + { + // Move everything to the left + if (grid[i][j] == MOVING) + { + grid[i-1][j] = MOVING; + grid[i][j] = EMPTY; + } + } + } + + piecePositionX--; + } + } + + // Move right + else if (IsKeyDown(KEY_RIGHT)) + { + // Check if is possible to move to right + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if (grid[i][j] == MOVING) + { + // Check if we are touching the right wall or we have a full square at the right + if ((i+1 == GRID_HORIZONTAL_SIZE - 1) || (grid[i+1][j] == FULL)) + { + collision = true; + + } + } + } + } + // If able move right + if (!collision) + { + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = GRID_HORIZONTAL_SIZE - 1; i >= 1; i--) // We check the matrix from right to left + { + // Move everything to the right + if (grid[i][j] == MOVING) + { + grid[i+1][j] = MOVING; + grid[i][j] = EMPTY; + } + } + } + + piecePositionX++; + } + } + + return collision; +} + +static bool ResolveTurnMovement() +{ + // Input for turning the piece + if (IsKeyDown(KEY_UP)) + { + int aux; + bool checker = false; + + // Check all turning possibilities + if ((grid[piecePositionX + 3][piecePositionY] == MOVING) && + (grid[piecePositionX][piecePositionY] != EMPTY) && + (grid[piecePositionX][piecePositionY] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX + 3][piecePositionY + 3] == MOVING) && + (grid[piecePositionX + 3][piecePositionY] != EMPTY) && + (grid[piecePositionX + 3][piecePositionY] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX][piecePositionY + 3] == MOVING) && + (grid[piecePositionX + 3][piecePositionY + 3] != EMPTY) && + (grid[piecePositionX + 3][piecePositionY + 3] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX][piecePositionY] == MOVING) && + (grid[piecePositionX][piecePositionY + 3] != EMPTY) && + (grid[piecePositionX][piecePositionY + 3] != MOVING)) + { + checker = true; + } + + + if ((grid[piecePositionX + 1][piecePositionY] == MOVING) && + (grid[piecePositionX][piecePositionY + 2] != EMPTY) && + (grid[piecePositionX][piecePositionY + 2] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX + 3][piecePositionY + 1] == MOVING) && + (grid[piecePositionX + 1][piecePositionY] != EMPTY) && + (grid[piecePositionX + 1][piecePositionY] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX + 2][piecePositionY + 3] == MOVING) && + (grid[piecePositionX + 3][piecePositionY + 1] != EMPTY) && + (grid[piecePositionX + 3][piecePositionY + 1] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX][piecePositionY + 2] == MOVING) && + (grid[piecePositionX + 2][piecePositionY + 3] != EMPTY) && + (grid[piecePositionX + 2][piecePositionY + 3] != MOVING)) + { + checker = true; + } + + + if ((grid[piecePositionX + 2][piecePositionY] == MOVING) && + (grid[piecePositionX][piecePositionY + 1] != EMPTY) && + (grid[piecePositionX][piecePositionY + 1] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX + 3][piecePositionY + 2] == MOVING) && + (grid[piecePositionX + 2][piecePositionY] != EMPTY) && + (grid[piecePositionX + 2][piecePositionY] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX + 1][piecePositionY + 3] == MOVING) && + (grid[piecePositionX + 3][piecePositionY + 2] != EMPTY) && + (grid[piecePositionX + 3][piecePositionY + 2] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX][piecePositionY + 1] == MOVING) && + (grid[piecePositionX + 1][piecePositionY + 3] != EMPTY) && + (grid[piecePositionX + 1][piecePositionY + 3] != MOVING)) + { + checker = true; + } + + if ((grid[piecePositionX + 1][piecePositionY + 1] == MOVING) && + (grid[piecePositionX + 1][piecePositionY + 2] != EMPTY) && + (grid[piecePositionX + 1][piecePositionY + 2] != MOVING)) + { + checker = true; + } + + if ((grid[piecePositionX + 2][piecePositionY + 1] == MOVING) && + (grid[piecePositionX + 1][piecePositionY + 1] != EMPTY) && + (grid[piecePositionX + 1][piecePositionY + 1] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX + 2][piecePositionY + 2] == MOVING) && + (grid[piecePositionX + 2][piecePositionY + 1] != EMPTY) && + (grid[piecePositionX + 2][piecePositionY + 1] != MOVING)) + { + checker = true; + } + if ((grid[piecePositionX + 1][piecePositionY + 2] == MOVING) && + (grid[piecePositionX + 2][piecePositionY + 2] != EMPTY) && + (grid[piecePositionX + 2][piecePositionY + 2] != MOVING)) + { + checker = true; + } + + if (!checker) + { + aux = piece[0][0]; + piece[0][0] = piece[3][0]; + piece[3][0] = piece[3][3]; + piece[3][3] = piece[0][3]; + piece[0][3] = aux; + + aux = piece[1][0]; + piece[1][0] = piece[3][1]; + piece[3][1] = piece[2][3]; + piece[2][3] = piece[0][2]; + piece[0][2] = aux; + + aux = piece[2][0]; + piece[2][0] = piece[3][2]; + piece[3][2] = piece[1][3]; + piece[1][3] = piece[0][1]; + piece[0][1] = aux; + + aux = piece[1][1]; + piece[1][1] = piece[2][1]; + piece[2][1] = piece[2][2]; + piece[2][2] = piece[1][2]; + piece[1][2] = aux; + } + + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if (grid[i][j] == MOVING) + { + grid[i][j] = EMPTY; + } + } + } + + for (int i = piecePositionX; i < piecePositionX + 4; i++) + { + for (int j = piecePositionY; j < piecePositionY + 4; j++) + { + if (piece[i - piecePositionX][j - piecePositionY] == MOVING) + { + grid[i][j] = MOVING; + } + } + } + return true; + } + + return false; +} + +static void CheckDetection(bool *detection) +{ + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if ((grid[i][j] == MOVING) && ((grid[i][j+1] == FULL) || (grid[i][j+1] == BLOCK))) *detection = true; + } + } +} + +static void CheckCompletition(bool *lineToDelete) +{ + int calculator; + + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + calculator = 0; + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + // Count each square of the line + if (grid[i][j] == FULL) + { + calculator++; + } + + // Check if we completed the whole line + if (calculator == GRID_HORIZONTAL_SIZE - 2) + { + *lineToDelete = true; + calculator = 0; + // points++; + + // Mark the completed line + for (int z = 1; z < GRID_HORIZONTAL_SIZE - 1; z++) + { + grid[z][j] = FADING; + } + } + } + } +} + +static void DeleteCompleteLines() +{ + // erase the completed line + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + while (grid[1][j] == FADING) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + grid[i][j] = EMPTY; + } + for (int j2 = j-1; j2 >= 0; j2--) + { + for (int i2 = 1; i2 < GRID_HORIZONTAL_SIZE - 1; i2++) + { + if (grid[i2][j2] == FULL) + { + grid[i2][j2+1] = FULL; + grid[i2][j2] = EMPTY; + } + else if (grid[i2][j2] == FADING) + { + grid[i2][j2+1] = FADING; + grid[i2][j2] = EMPTY; + } + } + } + } + } +} \ No newline at end of file -- cgit v1.2.3 From 89409817b5c2ce85c0c73d8d866b842fd11b96c1 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 20 Feb 2016 20:25:10 +0100 Subject: Games makefile --- games/makefile | 254 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 games/makefile diff --git a/games/makefile b/games/makefile new file mode 100644 index 00000000..792642ce --- /dev/null +++ b/games/makefile @@ -0,0 +1,254 @@ +#************************************************************************************************** +# +# raylib makefile for desktop platforms, Raspberry Pi and HTML5 (emscripten) +# +# Copyright (c) 2015 Ramon Santamaria (@raysan5) +# +# 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 = -O1 -Wall -std=c99 -s USE_GLFW=3 + #-s ASSERTIONS=1 # to check for memory allocation errors (-O1 disables it) + #-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 +# external libraries headers +# GLFW3 + INCLUDES += -I../external/glfw3/include +# GLEW - Not required any more, replaced by GLAD + #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 +# 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 - Not required any more, replaced by GLAD + #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 -lglfw3 -lGLEW -lGL -lopenal -lm -pthread + # on XWindow could require also below libraries, just uncomment + #LIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor + 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 -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 +endif +ifeq ($(PLATFORM),PLATFORM_WEB) + # just adjust the correct path to libraylib.bc + 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 object files required +SAMPLES = \ + arkanoid \ + asteroids \ + asteroids_survival \ + floppy \ + gold_fever \ + gorilas \ + missile_commander \ + pang \ + snake \ + space_invaders \ + tetris \ + fix_dylib \ + + +# typing 'make' will invoke the first target entry in the file, +# in this case, the 'default' target entry is raylib +default: samples + +# compile all game samples +samples: $(SAMPLES) + +# compile game sample - arkanoid +arkanoid: arkanoid.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + +# compile game sample - steroids +asteroids: asteroids.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + +# compile game sample - asteroids_survival +asteroids_survival: asteroids_survival.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + +# compile game sample - floppy +floppy: floppy.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + +# compile game sample - gold_fever +gold_fever: gold_fever.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + +# compile game sample - gorilas +gorilas: gorilas.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + +# compile game sample - missile_commander +missile_commander: missile_commander.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + +# compile game sample - pang +pang: pang.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + +# compile game sample - snake +snake: snake.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + +# compile game sample - space_invaders +space_invaders: space_invaders.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + +# compile game sample - tetris +tetris: tetris.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + +# fix dylib install path name for each executable (MAC) +fix_dylib: +ifeq ($(PLATFORM_OS),OSX) + find . -type f -perm +ugo+x -print0 | xargs -t -0 -R 1 -I file install_name_tool -change libglfw.3.0.dylib ../external/glfw3/lib/osx/libglfw.3.0.dylib file +endif + +# 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 +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) -- cgit v1.2.3 From 84252f9b708fca64ceaf5fb3ea4b92b884570843 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 20 Feb 2016 20:29:20 +0100 Subject: Uploaded raylib bitcode library (PLATFORM_WEB) --- src/libraylib.bc | Bin 0 -> 603552 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/libraylib.bc diff --git a/src/libraylib.bc b/src/libraylib.bc new file mode 100644 index 00000000..21039250 Binary files /dev/null and b/src/libraylib.bc differ -- cgit v1.2.3 From a8bb9b6b19424b9499765996e8aa40904ffd41ce Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 20 Feb 2016 22:43:10 +0100 Subject: Updated image to POT --- examples/resources/cat.png | Bin 663451 -> 388532 bytes examples/textures_image_drawing.c | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/resources/cat.png b/examples/resources/cat.png index 9b5c08d2..d023aa21 100644 Binary files a/examples/resources/cat.png and b/examples/resources/cat.png differ diff --git a/examples/textures_image_drawing.c b/examples/textures_image_drawing.c index e09828d5..1c6a1fb9 100644 --- a/examples/textures_image_drawing.c +++ b/examples/textures_image_drawing.c @@ -25,14 +25,14 @@ int main() // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Image cat = LoadImage("resources/cat.png"); // Load image in CPU memory (RAM) - ImageCrop(&cat, (Rectangle){ 170, 120, 280, 380 }); // Crop an image piece + ImageCrop(&cat, (Rectangle){ 100, 10, 280, 380 }); // Crop an image piece ImageFlipHorizontal(&cat); // Flip cropped image horizontally ImageResize(&cat, 150, 200); // Resize flipped-cropped image Image parrots = LoadImage("resources/parrots.png"); // Load image in CPU memory (RAM) // Draw one image over the other with a scaling of 1.5f - ImageDraw(&parrots, cat, (Rectangle){ 0, 0, cat.width, cat.height}, (Rectangle){ 30, 40, cat.width*1.5f, cat.height*1.5f }); + ImageDraw(&parrots, cat, (Rectangle){ 0, 0, cat.width, cat.height }, (Rectangle){ 30, 40, cat.width*1.5f, cat.height*1.5f }); ImageCrop(&parrots, (Rectangle){ 0, 50, parrots.width, parrots.height - 100 }); // Crop resulting image UnloadImage(cat); // Unload image from RAM -- cgit v1.2.3 From 182054b6620302ba7a3ce857cf6bd403408d01db Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 20 Feb 2016 23:49:21 +0100 Subject: Updated for web --- games/drturtle/04_drturtle_gui.c | 18 +- games/drturtle/05_drturtle_audio.c | 18 +- games/drturtle/06_drturtle_final.c | 22 +- games/drturtle/drturtle_final_web.c | 541 ++++++++++++++++++++++++++++++++++++ games/drturtle/makefile | 186 +++++++++++++ games/light_my_ritual/makefile | 8 +- 6 files changed, 761 insertions(+), 32 deletions(-) create mode 100644 games/drturtle/drturtle_final_web.c create mode 100644 games/drturtle/makefile diff --git a/games/drturtle/04_drturtle_gui.c b/games/drturtle/04_drturtle_gui.c index 0e648b5d..bbfd3492 100644 --- a/games/drturtle/04_drturtle_gui.c +++ b/games/drturtle/04_drturtle_gui.c @@ -338,7 +338,7 @@ int main() DrawTexture(title, screenWidth/2 - title.width/2, screenHeight/2 - title.height/2 - 80, WHITE); // Draw blinking text - if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER", (Vector2){ screenWidth/2 - 150, 480 }, GetFontBaseSize(font), 0, WHITE); + if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER", (Vector2){ screenWidth/2 - 150, 480 }, font.size, 0, WHITE); } break; case GAMEPLAY: @@ -388,8 +388,8 @@ int main() DrawRectangle(20, 20, foodBar, 40, ORANGE); DrawRectangleLines(20, 20, 400, 40, BLACK); - DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ screenWidth - 300, 20 }, GetFontBaseSize(font), -2, ORANGE); - DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 550, 20 }, GetFontBaseSize(font), -2, ORANGE); + DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ screenWidth - 300, 20 }, font.size, -2, ORANGE); + DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 550, 20 }, font.size, -2, ORANGE); if (gameraMode) { @@ -403,15 +403,15 @@ int main() // Draw a transparent black rectangle that covers all screen DrawRectangle(0, 0, screenWidth, screenHeight, Fade(BLACK, 0.4f)); - DrawTextEx(font, "GAME OVER", (Vector2){ 300, 160 }, GetFontBaseSize(font)*3, -2, MAROON); + DrawTextEx(font, "GAME OVER", (Vector2){ 300, 160 }, font.size*3, -2, MAROON); - DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ 680, 350 }, GetFontBaseSize(font), -2, GOLD); - DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 290, 350 }, GetFontBaseSize(font), -2, GOLD); - DrawTextEx(font, FormatText("HISCORE: %04i", hiscore), (Vector2){ 665, 400 }, GetFontBaseSize(font), -2, ORANGE); - DrawTextEx(font, FormatText("HIDISTANCE: %04i", (int)hidistance), (Vector2){ 270, 400 }, GetFontBaseSize(font), -2, ORANGE); + DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ 680, 350 }, font.size, -2, GOLD); + DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 290, 350 }, font.size, -2, GOLD); + DrawTextEx(font, FormatText("HISCORE: %04i", hiscore), (Vector2){ 665, 400 }, font.size, -2, ORANGE); + DrawTextEx(font, FormatText("HIDISTANCE: %04i", (int)hidistance), (Vector2){ 270, 400 }, font.size, -2, ORANGE); // Draw blinking text - if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER to REPLAY", (Vector2){ screenWidth/2 - 250, 520 }, GetFontBaseSize(font), -2, LIGHTGRAY); + if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER to REPLAY", (Vector2){ screenWidth/2 - 250, 520 }, font.size, -2, LIGHTGRAY); } break; default: break; diff --git a/games/drturtle/05_drturtle_audio.c b/games/drturtle/05_drturtle_audio.c index 7e8cac70..4a36d015 100644 --- a/games/drturtle/05_drturtle_audio.c +++ b/games/drturtle/05_drturtle_audio.c @@ -351,7 +351,7 @@ int main() DrawTexture(title, screenWidth/2 - title.width/2, screenHeight/2 - title.height/2 - 80, WHITE); // Draw blinking text - if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER", (Vector2){ screenWidth/2 - 150, 480 }, GetFontBaseSize(font), 0, WHITE); + if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER", (Vector2){ screenWidth/2 - 150, 480 }, font.size, 0, WHITE); } break; case GAMEPLAY: @@ -401,8 +401,8 @@ int main() DrawRectangle(20, 20, foodBar, 40, ORANGE); DrawRectangleLines(20, 20, 400, 40, BLACK); - DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ screenWidth - 300, 20 }, GetFontBaseSize(font), -2, ORANGE); - DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 550, 20 }, GetFontBaseSize(font), -2, ORANGE); + DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ screenWidth - 300, 20 }, font.size, -2, ORANGE); + DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 550, 20 }, font.size, -2, ORANGE); if (gameraMode) { @@ -416,15 +416,15 @@ int main() // Draw a transparent black rectangle that covers all screen DrawRectangle(0, 0, screenWidth, screenHeight, Fade(BLACK, 0.4f)); - DrawTextEx(font, "GAME OVER", (Vector2){ 300, 160 }, GetFontBaseSize(font)*3, -2, MAROON); + DrawTextEx(font, "GAME OVER", (Vector2){ 300, 160 }, font.size*3, -2, MAROON); - DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ 680, 350 }, GetFontBaseSize(font), -2, GOLD); - DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 290, 350 }, GetFontBaseSize(font), -2, GOLD); - DrawTextEx(font, FormatText("HISCORE: %04i", hiscore), (Vector2){ 665, 400 }, GetFontBaseSize(font), -2, ORANGE); - DrawTextEx(font, FormatText("HIDISTANCE: %04i", (int)hidistance), (Vector2){ 270, 400 }, GetFontBaseSize(font), -2, ORANGE); + DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ 680, 350 }, font.size, -2, GOLD); + DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 290, 350 }, font.size, -2, GOLD); + DrawTextEx(font, FormatText("HISCORE: %04i", hiscore), (Vector2){ 665, 400 }, font.size, -2, ORANGE); + DrawTextEx(font, FormatText("HIDISTANCE: %04i", (int)hidistance), (Vector2){ 270, 400 }, font.size, -2, ORANGE); // Draw blinking text - if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER to REPLAY", (Vector2){ screenWidth/2 - 250, 520 }, GetFontBaseSize(font), -2, LIGHTGRAY); + if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER to REPLAY", (Vector2){ screenWidth/2 - 250, 520 }, font.size, -2, LIGHTGRAY); } break; default: break; diff --git a/games/drturtle/06_drturtle_final.c b/games/drturtle/06_drturtle_final.c index a3475de4..128b23a5 100644 --- a/games/drturtle/06_drturtle_final.c +++ b/games/drturtle/06_drturtle_final.c @@ -21,6 +21,8 @@ #include "raylib.h" +#include // Used for sinf() + #define MAX_ENEMIES 10 typedef enum { TITLE, GAMEPLAY, ENDING } GameScreen; @@ -128,7 +130,7 @@ int main() framesCounter++; // Sea color tint effect - blue = 210 + 25 * sin(timeCounter); + blue = 210 + 25 * sinf(timeCounter); timeCounter += 0.01; // Game screens management @@ -374,7 +376,7 @@ int main() DrawTexture(title, screenWidth/2 - title.width/2, screenHeight/2 - title.height/2 - 80, WHITE); // Draw blinking text - if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER", (Vector2){ screenWidth/2 - 150, 480 }, GetFontBaseSize(font), 0, WHITE); + if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER", (Vector2){ screenWidth/2 - 150, 480 }, font.size, 0, WHITE); } break; case GAMEPLAY: @@ -424,8 +426,8 @@ int main() DrawRectangle(20, 20, foodBar, 40, ORANGE); DrawRectangleLines(20, 20, 400, 40, BLACK); - DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ screenWidth - 300, 20 }, GetFontBaseSize(font), -2, ORANGE); - DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 550, 20 }, GetFontBaseSize(font), -2, ORANGE); + DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ screenWidth - 300, 20 }, font.size, -2, ORANGE); + DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 550, 20 }, font.size, -2, ORANGE); if (gameraMode) { @@ -439,15 +441,15 @@ int main() // Draw a transparent black rectangle that covers all screen DrawRectangle(0, 0, screenWidth, screenHeight, Fade(BLACK, 0.4f)); - DrawTextEx(font, "GAME OVER", (Vector2){ 300, 160 }, GetFontBaseSize(font)*3, -2, MAROON); + DrawTextEx(font, "GAME OVER", (Vector2){ 300, 160 }, font.size*3, -2, MAROON); - DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ 680, 350 }, GetFontBaseSize(font), -2, GOLD); - DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 290, 350 }, GetFontBaseSize(font), -2, GOLD); - DrawTextEx(font, FormatText("HISCORE: %04i", hiscore), (Vector2){ 665, 400 }, GetFontBaseSize(font), -2, ORANGE); - DrawTextEx(font, FormatText("HIDISTANCE: %04i", (int)hidistance), (Vector2){ 270, 400 }, GetFontBaseSize(font), -2, ORANGE); + DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ 680, 350 }, font.size, -2, GOLD); + DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 290, 350 }, font.size, -2, GOLD); + DrawTextEx(font, FormatText("HISCORE: %04i", hiscore), (Vector2){ 665, 400 }, font.size, -2, ORANGE); + DrawTextEx(font, FormatText("HIDISTANCE: %04i", (int)hidistance), (Vector2){ 270, 400 }, font.size, -2, ORANGE); // Draw blinking text - if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER to REPLAY", (Vector2){ screenWidth/2 - 250, 520 }, GetFontBaseSize(font), -2, LIGHTGRAY); + if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER to REPLAY", (Vector2){ screenWidth/2 - 250, 520 }, font.size, -2, LIGHTGRAY); } break; default: break; diff --git a/games/drturtle/drturtle_final_web.c b/games/drturtle/drturtle_final_web.c new file mode 100644 index 00000000..25f4074b --- /dev/null +++ b/games/drturtle/drturtle_final_web.c @@ -0,0 +1,541 @@ +/******************************************************************************************* +* +* raylib game - Dr. Turtle & Mr. Gamera +* +* Welcome to raylib! +* +* To test examples, just press F6 and execute raylib_compile_execute script +* Note that compiled executable is placed in the same folder as .c file +* +* You can find all basic examples on C:\raylib\raylib\examples folder or +* raylib official webpage: www.raylib.com +* +* Enjoy using raylib. :) +* +* This game has been created using raylib 1.1 (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" +#include // Used for sinf() + +#if defined(PLATFORM_WEB) + #include +#endif + +#define MAX_ENEMIES 10 + +typedef enum { TITLE = 0, GAMEPLAY, ENDING } GameScreen; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +const int screenWidth = 1280; +const int screenHeight = 720; + +Texture2D sky; +Texture2D mountains; +Texture2D sea; +Texture2D title; +Texture2D turtle; +Texture2D gamera; +Texture2D shark; +Texture2D orca; +Texture2D swhale; +Texture2D fish; +Texture2D gframe; + +SpriteFont font; + +Sound eat; +Sound die; +Sound growl; + +// Define scrolling variables +int backScrolling = 0; +int seaScrolling = 0; + +// Define current screen +GameScreen currentScreen = 0; + +// Define player variables +int playerRail = 1; +Rectangle playerBounds; +bool gameraMode = false; + +// Define enemies variables +Rectangle enemyBounds[MAX_ENEMIES]; +int enemyRail[MAX_ENEMIES]; +int enemyType[MAX_ENEMIES]; +bool enemyActive[MAX_ENEMIES]; +float enemySpeed = 10; + +// Define additional game variables +int score = 0; +float distance = 0.0f; +int hiscore = 0; +float hidistance = 0.0f; +int foodBar = 0; +int framesCounter = 0; + +unsigned char blue = 200; +float timeCounter = 0; + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- +void UpdateDrawFrame(void); // Update and Draw one frame + +//---------------------------------------------------------------------------------- +// Main Enry Point +//---------------------------------------------------------------------------------- +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + + // Init window + InitWindow(screenWidth, screenHeight, "Dr. Turtle & Mr. GAMERA"); + + // Initialize audio device + InitAudioDevice(); + + // Load game resources: textures + sky = LoadTexture("resources/sky.png"); + mountains = LoadTexture("resources/mountains.png"); + sea = LoadTexture("resources/sea.png"); + title = LoadTexture("resources/title.png"); + turtle = LoadTexture("resources/turtle.png"); + gamera = LoadTexture("resources/gamera.png"); + shark = LoadTexture("resources/shark.png"); + orca = LoadTexture("resources/orca.png"); + swhale = LoadTexture("resources/swhale.png"); + fish = LoadTexture("resources/fish.png"); + gframe = LoadTexture("resources/gframe.png"); + + // Load game resources: fonts + font = LoadSpriteFont("resources/komika.png"); + + // Load game resources: sounds + eat = LoadSound("resources/eat.wav"); + die = LoadSound("resources/die.wav"); + growl = LoadSound("resources/gamera.wav"); + + // Start playing streaming music + PlayMusicStream("resources/speeding.ogg"); + + playerBounds = (Rectangle){ 30 + 14, playerRail*120 + 90 + 14, 100, 100 }; + + // Init enemies variables + for (int i = 0; i < MAX_ENEMIES; i++) + { + // Define enemy type (all same probability) + //enemyType[i] = GetRandomValue(0, 3); + + // Probability system for enemies type + int enemyProb = GetRandomValue(0, 100); + + if (enemyProb < 30) enemyType[i] = 0; + else if (enemyProb < 60) enemyType[i] = 1; + else if (enemyProb < 90) enemyType[i] = 2; + else enemyType[i] = 3; + + // define enemy rail + enemyRail[i] = GetRandomValue(0, 4); + + // Make sure not two consecutive enemies in the same row + if (i > 0) while (enemyRail[i] == enemyRail[i - 1]) enemyRail[i] = GetRandomValue(0, 4); + + enemyBounds[i] = (Rectangle){ screenWidth + 14, 120*enemyRail[i] + 90 + 14, 100, 100 }; + enemyActive[i] = false; + } + +#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 + { + UpdateDrawFrame(); + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + + // Unload textures + UnloadTexture(sky); + UnloadTexture(mountains); + UnloadTexture(sea); + UnloadTexture(gframe); + UnloadTexture(title); + UnloadTexture(turtle); + UnloadTexture(shark); + UnloadTexture(orca); + UnloadTexture(swhale); + UnloadTexture(fish); + UnloadTexture(gamera); + + // Unload font texture + UnloadSpriteFont(font); + + // Unload sounds + UnloadSound(eat); + UnloadSound(die); + UnloadSound(growl); + + StopMusicStream(); // Stop music + CloseAudioDevice(); // Close audio device + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//---------------------------------------------------------------------------------- +// Module Functions Definition +//---------------------------------------------------------------------------------- +void UpdateDrawFrame(void) +{ + // Update + //---------------------------------------------------------------------------------- + UpdateMusicStream(); + + framesCounter++; + + // Sea color tint effect + blue = 210 + 25 * sinf(timeCounter); + timeCounter += 0.01; + + // Game screens management + switch (currentScreen) + { + case TITLE: + { + // Sea scrolling + seaScrolling -= 2; + if (seaScrolling <= -screenWidth) seaScrolling = 0; + + // Press enter to change to gameplay screen + if (IsKeyPressed(KEY_ENTER)) + { + currentScreen = GAMEPLAY; + framesCounter = 0; + } + + } break; + case GAMEPLAY: + { + // Background scrolling logic + backScrolling--; + if (backScrolling <= -screenWidth) backScrolling = 0; + + // Sea scrolling logic + seaScrolling -= (enemySpeed - 2); + if (seaScrolling <= -screenWidth) seaScrolling = 0; + + // Player movement logic + if (IsKeyPressed(KEY_DOWN)) playerRail++; + else if (IsKeyPressed(KEY_UP)) playerRail--; + + // Check player not out of rails + if (playerRail > 4) playerRail = 4; + else if (playerRail < 0) playerRail = 0; + + // Update player bounds + playerBounds = (Rectangle){ 30 + 14, playerRail*120 + 90 + 14, 100, 100 }; + + // Enemies activation logic (every 40 frames) + if (framesCounter > 40) + { + for (int i = 0; i < MAX_ENEMIES; i++) + { + if (enemyActive[i] == false) + { + enemyActive[i] = true; + i = MAX_ENEMIES; + } + } + + framesCounter = 0; + } + + // Enemies logic + for (int i = 0; i < MAX_ENEMIES; i++) + { + if (enemyActive[i]) + { + enemyBounds[i].x -= enemySpeed; + } + + // Check enemies out of screen + if (enemyBounds[i].x <= 0 - 128) + { + enemyActive[i] = false; + enemyType[i] = GetRandomValue(0, 3); + enemyRail[i] = GetRandomValue(0, 4); + + // Make sure not two consecutive enemies in the same row + if (i > 0) while (enemyRail[i] == enemyRail[i - 1]) enemyRail[i] = GetRandomValue(0, 4); + + enemyBounds[i] = (Rectangle){ screenWidth + 14, 120*enemyRail[i] + 90 + 14, 100, 100 }; + } + } + + if (!gameraMode) enemySpeed += 0.005; + + // Check collision player vs enemies + for (int i = 0; i < MAX_ENEMIES; i++) + { + if (enemyActive[i]) + { + if (CheckCollisionRecs(playerBounds, enemyBounds[i])) + { + if (enemyType[i] < 3) // Bad enemies + { + if (gameraMode) + { + if (enemyType[i] == 0) score += 50; + else if (enemyType[i] == 1) score += 150; + else if (enemyType[i] == 2) score += 300; + + foodBar += 15; + + enemyActive[i] = false; + + // After enemy deactivation, reset enemy parameters to be reused + enemyType[i] = GetRandomValue(0, 3); + enemyRail[i] = GetRandomValue(0, 4); + + // Make sure not two consecutive enemies in the same row + if (i > 0) while (enemyRail[i] == enemyRail[i - 1]) enemyRail[i] = GetRandomValue(0, 4); + + enemyBounds[i] = (Rectangle){ screenWidth + 14, 120*enemyRail[i] + 90 + 14, 100, 100 }; + + PlaySound(eat); + } + else + { + // Player die logic + PlaySound(die); + + currentScreen = ENDING; + framesCounter = 0; + + // Save hiscore and hidistance for next game + if (score > hiscore) hiscore = score; + if (distance > hidistance) hidistance = distance; + } + } + else // Sweet fish + { + enemyActive[i] = false; + enemyType[i] = GetRandomValue(0, 3); + enemyRail[i] = GetRandomValue(0, 4); + + // Make sure not two consecutive enemies in the same row + if (i > 0) while (enemyRail[i] == enemyRail[i - 1]) enemyRail[i] = GetRandomValue(0, 4); + + enemyBounds[i] = (Rectangle){ screenWidth + 14, 120*enemyRail[i] + 90 + 14, 100, 100 }; + + if (!gameraMode) foodBar += 80; + else foodBar += 25; + + score += 10; + + if (foodBar == 400) + { + gameraMode = true; + + PlaySound(growl); + } + + PlaySound(eat); + } + } + } + } + + // Gamera mode logic + if (gameraMode) + { + foodBar--; + + if (foodBar <= 0) + { + gameraMode = false; + enemySpeed -= 2; + if (enemySpeed < 10) enemySpeed = 10; + } + } + + // Update distance counter + distance += 0.5f; + + } break; + case ENDING: + { + // Press enter to play again + if (IsKeyPressed(KEY_ENTER)) + { + currentScreen = GAMEPLAY; + + // Reset player + playerRail = 1; + playerBounds = (Rectangle){ 30 + 14, playerRail*120 + 90 + 14, 100, 100 }; + gameraMode = false; + + // Reset enemies data + for (int i = 0; i < MAX_ENEMIES; i++) + { + int enemyProb = GetRandomValue(0, 100); + + if (enemyProb < 30) enemyType[i] = 0; + else if (enemyProb < 60) enemyType[i] = 1; + else if (enemyProb < 90) enemyType[i] = 2; + else enemyType[i] = 3; + + //enemyType[i] = GetRandomValue(0, 3); + enemyRail[i] = GetRandomValue(0, 4); + + // Make sure not two consecutive enemies in the same row + if (i > 0) while (enemyRail[i] == enemyRail[i - 1]) enemyRail[i] = GetRandomValue(0, 4); + + enemyBounds[i] = (Rectangle){ screenWidth + 14, 120*enemyRail[i] + 90 + 14, 100, 100 }; + enemyActive[i] = false; + } + + enemySpeed = 10; + + // Reset game variables + score = 0; + distance = 0.0; + foodBar = 0; + framesCounter = 0; + } + + } break; + default: break; + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + // Draw background (common to all screens) + DrawTexture(sky, 0, 0, WHITE); + + DrawTexture(mountains, backScrolling, 0, WHITE); + DrawTexture(mountains, screenWidth + backScrolling, 0, WHITE); + + if (!gameraMode) + { + DrawTexture(sea, seaScrolling, 0, (Color){ 16, 189, blue, 255}); + DrawTexture(sea, screenWidth + seaScrolling, 0, (Color){ 16, 189, blue, 255}); + } + else + { + DrawTexture(sea, seaScrolling, 0, (Color){ 255, 113, 66, 255}); + DrawTexture(sea, screenWidth + seaScrolling, 0, (Color){ 255, 113, 66, 255}); + } + + switch (currentScreen) + { + case TITLE: + { + // Draw title + DrawTexture(title, screenWidth/2 - title.width/2, screenHeight/2 - title.height/2 - 80, WHITE); + + // Draw blinking text + if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER", (Vector2){ screenWidth/2 - 150, 480 }, font.size, 1, WHITE); + + } break; + case GAMEPLAY: + { + // Draw water lines + for (int i = 0; i < 5; i++) DrawRectangle(0, i*120 + 120, screenWidth, 110, Fade(SKYBLUE, 0.1f)); + + // Draw player + if (!gameraMode) DrawTexture(turtle, playerBounds.x - 14, playerBounds.y - 14, WHITE); + else DrawTexture(gamera, playerBounds.x - 64, playerBounds.y - 64, WHITE); + + // Draw player bounding box + //if (!gameraMode) DrawRectangleRec(playerBounds, Fade(GREEN, 0.4f)); + //else DrawRectangleRec(playerBounds, Fade(ORANGE, 0.4f)); + + // Draw enemies + for (int i = 0; i < MAX_ENEMIES; i++) + { + if (enemyActive[i]) + { + // Draw enemies + switch(enemyType[i]) + { + case 0: DrawTexture(shark, enemyBounds[i].x - 14, enemyBounds[i].y - 14, WHITE); break; + case 1: DrawTexture(orca, enemyBounds[i].x - 14, enemyBounds[i].y - 14, WHITE); break; + case 2: DrawTexture(swhale, enemyBounds[i].x - 14, enemyBounds[i].y - 14, WHITE); break; + case 3: DrawTexture(fish, enemyBounds[i].x - 14, enemyBounds[i].y - 14, WHITE); break; + default: break; + } + + // Draw enemies bounding boxes + /* + switch(enemyType[i]) + { + case 0: DrawRectangleRec(enemyBounds[i], Fade(RED, 0.5f)); break; + case 1: DrawRectangleRec(enemyBounds[i], Fade(RED, 0.5f)); break; + case 2: DrawRectangleRec(enemyBounds[i], Fade(RED, 0.5f)); break; + case 3: DrawRectangleRec(enemyBounds[i], Fade(GREEN, 0.5f)); break; + default: break; + } + */ + } + } + + // Draw gameplay interface + DrawRectangle(20, 20, 400, 40, Fade(GRAY, 0.4f)); + DrawRectangle(20, 20, foodBar, 40, ORANGE); + DrawRectangleLines(20, 20, 400, 40, BLACK); + + DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ screenWidth - 300, 20 }, font.size, -2, ORANGE); + DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 550, 20 }, font.size, -2, ORANGE); + + if (gameraMode) + { + DrawText("GAMERA MODE", 60, 22, 40, GRAY); + DrawTexture(gframe, 0, 0, Fade(WHITE, 0.5f)); + } + + } break; + case ENDING: + { + // Draw a transparent black rectangle that covers all screen + DrawRectangle(0, 0, screenWidth, screenHeight, Fade(BLACK, 0.4f)); + + DrawTextEx(font, "GAME OVER", (Vector2){ 300, 160 }, font.size*3, -2, MAROON); + + DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ 680, 350 }, font.size, -2, GOLD); + DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 290, 350 }, font.size, -2, GOLD); + DrawTextEx(font, FormatText("HISCORE: %04i", hiscore), (Vector2){ 665, 400 }, font.size, -2, ORANGE); + DrawTextEx(font, FormatText("HIDISTANCE: %04i", (int)hidistance), (Vector2){ 270, 400 }, font.size, -2, ORANGE); + + // Draw blinking text + if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER to REPLAY", (Vector2){ screenWidth/2 - 250, 520 }, font.size, -2, LIGHTGRAY); + + } break; + default: break; + } + + EndDrawing(); + //---------------------------------------------------------------------------------- +} \ No newline at end of file diff --git a/games/drturtle/makefile b/games/drturtle/makefile new file mode 100644 index 00000000..6641a5fd --- /dev/null +++ b/games/drturtle/makefile @@ -0,0 +1,186 @@ +#************************************************************************************************** +# +# raylib - makefile to compile Dr.Turtle game +# +# 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 if not defined (by default, compile for RPI) +# Other possible platform: PLATFORM_DESKTOP +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 = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources -s ALLOW_MEMORY_GROWTH=1 + #-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 + +# 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. -IC:/raylib/raylib/src -IC:/raylib/raylib/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. -LC:/raylib/raylib/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 = \ + +# typing 'make' will invoke the first target entry in the file, +# in this case, the 'default' target entry is advance_game +default: drturtle + +# compile template - advance_game +drturtle: drturtle_final_web.c $(SCREENS) + $(CC) -o $@$(EXT) $< $(SCREENS) $(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 -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) diff --git a/games/light_my_ritual/makefile b/games/light_my_ritual/makefile index b7e1bb58..90a02278 100644 --- a/games/light_my_ritual/makefile +++ b/games/light_my_ritual/makefile @@ -81,7 +81,7 @@ endif ifeq ($(PLATFORM),PLATFORM_RPI) INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads else - INCLUDES = -I. -IC:/raylib/raylib/src -IC:/raylib/raylib/src + INCLUDES = -I. -I../../src # external libraries headers # GLFW3 INCLUDES += -I../../external/glfw3/include @@ -95,7 +95,7 @@ endif ifeq ($(PLATFORM),PLATFORM_RPI) LFLAGS = -L. -L../../src -L/opt/vc/lib else - LFLAGS = -L. -LC:/raylib/raylib/src -L../../../src + LFLAGS = -L. -L../../src # external libraries to link with # GLFW3 LFLAGS += -L../../external/glfw3/lib/$(LIBPATH) @@ -133,14 +133,14 @@ ifeq ($(PLATFORM),PLATFORM_RPI) LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal endif ifeq ($(PLATFORM),PLATFORM_WEB) - LIBS = C:/raylib/raylib/src/libraylib.bc + 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 = C:/raylib/raylib/src/resources -Wl,--subsystem,windows + WINFLAGS = ../../src/resources -Wl,--subsystem,windows endif ifeq ($(PLATFORM),PLATFORM_WEB) -- cgit v1.2.3 From 9f5efeb309e15999a2b057dc7670169cf8d7d1b8 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 21 Feb 2016 00:44:55 +0100 Subject: Update makefiles --- games/drturtle/makefile | 6 +- games/just_do/makefile | 2 +- games/light_my_ritual/makefile | 4 +- games/makefile | 12 ++-- games/raylib_demo/makefile | 116 +++++++++++++++++++++++++++++++-------- games/raylib_demo/raylib_demo.c | 64 +++++++++++---------- games/skully_escape/makefile | 10 ++-- templates/advance_game/makefile | 19 ++++--- templates/basic_game/makefile | 11 ++-- templates/simple_game/makefile | 11 ++-- templates/standard_game/makefile | 11 ++-- 11 files changed, 168 insertions(+), 98 deletions(-) diff --git a/games/drturtle/makefile b/games/drturtle/makefile index 6641a5fd..f9efd3e8 100644 --- a/games/drturtle/makefile +++ b/games/drturtle/makefile @@ -69,7 +69,7 @@ else CFLAGS = -O2 -Wall -std=c99 endif ifeq ($(PLATFORM),PLATFORM_WEB) - CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources -s ALLOW_MEMORY_GROWTH=1 + CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources -s ALLOW_MEMORY_GROWTH=1 --shell-file ../../templates/web_shell/shell.html #-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) @@ -79,7 +79,7 @@ endif ifeq ($(PLATFORM),PLATFORM_RPI) INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads else - INCLUDES = -I. -IC:/raylib/raylib/src -IC:/raylib/raylib/src + INCLUDES = -I. -I../../src # external libraries headers # GLFW3 INCLUDES += -I../../external/glfw3/include @@ -93,7 +93,7 @@ endif ifeq ($(PLATFORM),PLATFORM_RPI) LFLAGS = -L. -L../../src -L/opt/vc/lib else - LFLAGS = -L. -LC:/raylib/raylib/src -L../../../src + LFLAGS = -L. -L../../src # external libraries to link with # GLFW3 LFLAGS += -L../../external/glfw3/lib/$(LIBPATH) diff --git a/games/just_do/makefile b/games/just_do/makefile index 4c36b154..5cca9df5 100644 --- a/games/just_do/makefile +++ b/games/just_do/makefile @@ -72,7 +72,7 @@ else CFLAGS = -O2 -Wall -std=c99 endif ifeq ($(PLATFORM),PLATFORM_WEB) - CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 + CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --shell-file ../../templates/web_shell/shell.html #-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) diff --git a/games/light_my_ritual/makefile b/games/light_my_ritual/makefile index 90a02278..84d7e994 100644 --- a/games/light_my_ritual/makefile +++ b/games/light_my_ritual/makefile @@ -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) # @@ -71,7 +71,7 @@ else CFLAGS = -O2 -Wall -std=c99 endif ifeq ($(PLATFORM),PLATFORM_WEB) - CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources -s ALLOW_MEMORY_GROWTH=1 + CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources -s ALLOW_MEMORY_GROWTH=1 --shell-file ../../templates/web_shell/shell.html #-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) diff --git a/games/makefile b/games/makefile index 792642ce..2d992896 100644 --- a/games/makefile +++ b/games/makefile @@ -70,7 +70,7 @@ else CFLAGS = -O2 -Wall -std=c99 endif ifeq ($(PLATFORM),PLATFORM_WEB) - CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 + CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --shell-file ../../templates/web_shell/shell.html #-s ASSERTIONS=1 # to check for memory allocation errors (-O1 disables it) #-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing #-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) @@ -98,13 +98,13 @@ ifeq ($(PLATFORM),PLATFORM_RPI) else LFLAGS = -L. -L../src # external libraries to link with -# GLFW3 - LFLAGS += -L../external/glfw3/lib/$(LIBPATH) + # GLFW3 + LFLAGS += -L../external/glfw3/lib/$(LIBPATH) ifneq ($(PLATFORM_OS),OSX) # OpenAL Soft LFLAGS += -L../external/openal_soft/lib/$(LIBPATH) - # GLEW - Not required any more, replaced by GLAD - #LFLAGS += -L../external/glew/lib/$(LIBPATH) + # GLEW: Not used, replaced by GLAD + #LFLAGS += -L../../external/glew/lib/$(LIBPATH) endif endif @@ -137,7 +137,7 @@ ifeq ($(PLATFORM),PLATFORM_RPI) LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal endif ifeq ($(PLATFORM),PLATFORM_WEB) - # just adjust the correct path to libraylib.bc + # NOTE: Set the correct path to libraylib.bc LIBS = ../src/libraylib.bc endif diff --git a/games/raylib_demo/makefile b/games/raylib_demo/makefile index 3e2fe614..a4435bb0 100644 --- a/games/raylib_demo/makefile +++ b/games/raylib_demo/makefile @@ -2,7 +2,7 @@ # # raylib - Basic Game # -# makefile to compile basic 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,31 +23,57 @@ # #************************************************************************************************** -# define raylib platform (by default, compile for RPI) -# Other possible platform: PLATFORM_DESKTOP, PLATFORM_WEB, PLATFORM_RPI -PLATFORM ?= PLATFORM_WEB +# 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 = -O1 -Wall -std=gnu99 -fgnu89-inline + CFLAGS = -O2 -Wall -std=gnu99 -fgnu89-inline else - CFLAGS = -O1 -Wall -std=c99 + 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 + CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources --shell-file ../../templates/web_shell/shell.html + #-s ASSERTIONS=1 # to check for memory allocation errors (-O1 disables it) #-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing #-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) endif @@ -59,33 +85,66 @@ 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 - Not required any more, replaced by GLAD + #INCLUDES += -I../external/glew/include +# OpenAL Soft + INCLUDES += -I../../external/openal_soft/include endif # define library paths containing required libs -ifeq ($(PLATFORM),PLATFORM_WEB) - LFLAGS = -L. -else +ifeq ($(PLATFORM),PLATFORM_RPI) LFLAGS = -L. -L../../src -L/opt/vc/lib +else + LFLAGS = -L. -L../../src -LC:/raylib/raylib/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: Not used, replaced by GLAD + #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 -lglfw3 -lGLEW -lGL -lopenal -lm -pthread + # on XWindow could require also below libraries, just uncomment + #LIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor + 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 -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) + # NOTE: Set the correct path to libraylib.bc 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 @@ -99,21 +158,30 @@ endif # in this case, the 'default' target entry is qidv_raylib default: raylib_demo -# compile qidv_raylib +# compile raylib demo raylib_demo: raylib_demo.c $(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 -ifeq ($(PLATFORM),PLATFORM_WEB) - del *.html *.js -else - del *.o *.exe endif +ifeq ($(PLATFORM),PLATFORM_WEB) + del *.o *.html *.js endif @echo Cleaning done diff --git a/games/raylib_demo/raylib_demo.c b/games/raylib_demo/raylib_demo.c index 5bbccbe8..7f6f291a 100644 --- a/games/raylib_demo/raylib_demo.c +++ b/games/raylib_demo/raylib_demo.c @@ -1,10 +1,8 @@ /******************************************************************************************* * -* raylib - Talk: QIDV raylib (Learn Videogames Programming) +* raylib - Features demo 01 (Learn Videogames Programming) * -* Aprende a Programar Videojuegos con raylib -* -* This talk has been created using raylib v1.2 (www.raylib.com) +* This show has been created using raylib v1.4 (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) @@ -703,11 +701,11 @@ void UpdateDrawOneFrame(void) { DrawText("This module give you functions to:", 48, 200, 10, GetColor(0x5c5a5aff)); - DrawTextEx(fontRomulus, "Open-Close Window", (Vector2){ 48, 230 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x5c5a5aff)); - DrawTextEx(fontRomulus, "Manage Drawing Area", (Vector2){ 48, 260 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x5c5a5aff)); - DrawTextEx(fontRomulus, "Manage Inputs", (Vector2){ 48, 290 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x5c5a5aff)); - DrawTextEx(fontRomulus, "Manage Timming", (Vector2){ 48, 320 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x5c5a5aff)); - DrawTextEx(fontRomulus, "Auxiliar Functions", (Vector2){ 48, 350 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x5c5a5aff)); + DrawTextEx(fontRomulus, "Open-Close Window", (Vector2){ 48, 230 }, fontRomulus.size*2, 4, GetColor(0x5c5a5aff)); + DrawTextEx(fontRomulus, "Manage Drawing Area", (Vector2){ 48, 260 }, fontRomulus.size*2, 4, GetColor(0x5c5a5aff)); + DrawTextEx(fontRomulus, "Manage Inputs", (Vector2){ 48, 290 }, fontRomulus.size*2, 4, GetColor(0x5c5a5aff)); + DrawTextEx(fontRomulus, "Manage Timming", (Vector2){ 48, 320 }, fontRomulus.size*2, 4, GetColor(0x5c5a5aff)); + DrawTextEx(fontRomulus, "Auxiliar Functions", (Vector2){ 48, 350 }, fontRomulus.size*2, 4, GetColor(0x5c5a5aff)); switch (coreWindow) { @@ -733,16 +731,16 @@ void UpdateDrawOneFrame(void) if (framesCounter > 140) { - DrawTextEx(fontMecha, "MOVE ME", (Vector2){ ballPosition.x - 26, ballPosition.y - 20 }, GetFontBaseSize(fontMecha), 2, BLACK); - DrawTextEx(fontMecha, "[ W A S D ]", (Vector2){ ballPosition.x - 36, ballPosition.y }, GetFontBaseSize(fontMecha), 2, BLACK); + DrawTextEx(fontMecha, "MOVE ME", (Vector2){ ballPosition.x - 26, ballPosition.y - 20 }, fontMecha.size, 2, BLACK); + DrawTextEx(fontMecha, "[ W A S D ]", (Vector2){ ballPosition.x - 36, ballPosition.y }, fontMecha.size, 2, BLACK); } } break; case SHAPES: { DrawText("This module give you functions to:", 48, 200, 10, GetColor(0xcd5757ff)); - DrawTextEx(fontRomulus, "Draw Basic Shapes", (Vector2){ 48, 230 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0xcd5757ff)); - DrawTextEx(fontRomulus, "Basic Collision Detection", (Vector2){ 48, 260 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0xcd5757ff)); + DrawTextEx(fontRomulus, "Draw Basic Shapes", (Vector2){ 48, 230 }, fontRomulus.size*2, 4, GetColor(0xcd5757ff)); + DrawTextEx(fontRomulus, "Basic Collision Detection", (Vector2){ 48, 260 }, fontRomulus.size*2, 4, GetColor(0xcd5757ff)); DrawCircle(screenWidth/4, 120 + 240, 35, DARKBLUE); DrawCircleGradient(screenWidth/4, 220 + 240, 60, GREEN, SKYBLUE); @@ -763,8 +761,8 @@ void UpdateDrawOneFrame(void) { DrawText("This module give you functions to:", 48, 200, 10, GetColor(0x60815aff)); - DrawTextEx(fontRomulus, "Load Images and Textures", (Vector2){ 48, 230 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x60815aff)); - DrawTextEx(fontRomulus, "Draw Textures", (Vector2){ 48, 260 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x60815aff)); + DrawTextEx(fontRomulus, "Load Images and Textures", (Vector2){ 48, 230 }, fontRomulus.size*2, 4, GetColor(0x60815aff)); + DrawTextEx(fontRomulus, "Draw Textures", (Vector2){ 48, 260 }, fontRomulus.size*2, 4, GetColor(0x60815aff)); DrawRectangle(138, 348, 260, 260, GRAY); DrawTexturePro(lena, (Rectangle){ 0, 0, lena.width, lena.height }, (Rectangle){ 140 + 128, 350 + 128, lena.width/2*scaleFactor, lena.height/2*scaleFactor }, (Vector2){ lena.width/4*scaleFactor, lena.height/4*scaleFactor }, 0.0f, WHITE); @@ -780,21 +778,21 @@ void UpdateDrawOneFrame(void) { DrawText("This module give you functions to:", 48, 200, 10, GetColor(0x377764ff)); - DrawTextEx(fontRomulus, "Load SpriteFonts", (Vector2){ 48, 230 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x377764ff)); - DrawTextEx(fontRomulus, "Draw Text", (Vector2){ 48, 260 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x377764ff)); - DrawTextEx(fontRomulus, "Text Formatting", (Vector2){ 48, 290 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x377764ff)); + DrawTextEx(fontRomulus, "Load SpriteFonts", (Vector2){ 48, 230 }, fontRomulus.size*2, 4, GetColor(0x377764ff)); + DrawTextEx(fontRomulus, "Draw Text", (Vector2){ 48, 260 }, fontRomulus.size*2, 4, GetColor(0x377764ff)); + DrawTextEx(fontRomulus, "Text Formatting", (Vector2){ 48, 290 }, fontRomulus.size*2, 4, GetColor(0x377764ff)); DrawTexture(texAlagard, 60, 360, WHITE); - DrawTextEx(fontMechaC, msg1, (Vector2){ 540 + 168, 210 }, GetFontBaseSize(fontMechaC), -3, WHITE); - DrawTextEx(fontAlagardC, msg2, (Vector2){ 460 + 140, 260 }, GetFontBaseSize(fontAlagardC), -2, WHITE); - DrawTextEx(fontJupiterC, msg3, (Vector2){ 640 + 70, 300 }, GetFontBaseSize(fontJupiterC), 2, WHITE); + DrawTextEx(fontMechaC, msg1, (Vector2){ 540 + 168, 210 }, fontMechaC.size, -3, WHITE); + DrawTextEx(fontAlagardC, msg2, (Vector2){ 460 + 140, 260 }, fontAlagardC.size, -2, WHITE); + DrawTextEx(fontJupiterC, msg3, (Vector2){ 640 + 70, 300 }, fontJupiterC.size, 2, WHITE); - DrawTextEx(fontAlagard, "It also includes some...", (Vector2){ 650 + 70, 400 }, GetFontBaseSize(fontAlagard)*2, 2, MAROON); - DrawTextEx(fontPixelplay, "...free fonts in rBMF format...", (Vector2){ 705 - 26, 450 }, GetFontBaseSize(fontPixelplay)*2, 4, ORANGE); - DrawTextEx(fontMecha, "...to be used even in...", (Vector2){ 700 + 40, 500 }, GetFontBaseSize(fontMecha)*2, 4, DARKGREEN); - DrawTextEx(fontSetback, "...comercial projects...", (Vector2){ 710, 550 }, GetFontBaseSize(fontSetback)*2, 4, DARKBLUE); - DrawTextEx(fontRomulus, "...completely for free!", (Vector2){ 710 + 17, 600 }, GetFontBaseSize(fontRomulus)*2, 3, DARKPURPLE); + DrawTextEx(fontAlagard, "It also includes some...", (Vector2){ 650 + 70, 400 }, fontAlagard.size*2, 2, MAROON); + DrawTextEx(fontPixelplay, "...free fonts in rBMF format...", (Vector2){ 705 - 26, 450 }, fontPixelplay.size*2, 4, ORANGE); + DrawTextEx(fontMecha, "...to be used even in...", (Vector2){ 700 + 40, 500 }, fontMecha.size*2, 4, DARKGREEN); + DrawTextEx(fontSetback, "...comercial projects...", (Vector2){ 710, 550 }, fontSetback.size*2, 4, DARKBLUE); + DrawTextEx(fontRomulus, "...completely for free!", (Vector2){ 710 + 17, 600 }, fontRomulus.size*2, 3, DARKPURPLE); DrawText("This is a custom font spritesheet, raylib can load it automatically!", 228, 360 + 295, 10, GRAY); @@ -803,9 +801,9 @@ void UpdateDrawOneFrame(void) { DrawText("This module give you functions to:", 48, 200, 10, GetColor(0x417794ff)); - DrawTextEx(fontRomulus, "Draw Geometric Models", (Vector2){ 48, 230 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x417794ff)); - DrawTextEx(fontRomulus, "Load 3D Models", (Vector2){ 48, 260 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x417794ff)); - DrawTextEx(fontRomulus, "Draw 3D Models", (Vector2){ 48, 290 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x417794ff)); + DrawTextEx(fontRomulus, "Draw Geometric Models", (Vector2){ 48, 230 }, fontRomulus.size*2, 4, GetColor(0x417794ff)); + DrawTextEx(fontRomulus, "Load 3D Models", (Vector2){ 48, 260 }, fontRomulus.size*2, 4, GetColor(0x417794ff)); + DrawTextEx(fontRomulus, "Draw 3D Models", (Vector2){ 48, 290 }, fontRomulus.size*2, 4, GetColor(0x417794ff)); Begin3dMode(camera); @@ -823,7 +821,7 @@ void UpdateDrawOneFrame(void) DrawCylinder((Vector3){1, 0, -4}, 0, 1.5, 3, 8, GOLD); DrawCylinderWires((Vector3){1, 0, -4}, 0, 1.5, 3, 8, PINK); - DrawModelEx(cat, (Vector3){ 8.0f, 0.0f, 2.0f }, (Vector3){ 0.0f, 0.5f*framesCounter, 0.0f }, (Vector3){ 0.1f, 0.1f, 0.1f }, WHITE); + DrawModelEx(cat, (Vector3){ 8.0f, 0.0f, 2.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, 0.5f*framesCounter, (Vector3){ 0.1f, 0.1f, 0.1f }, WHITE); DrawGizmo((Vector3){ 8.0f, 0.0f, 2.0f }); DrawGrid(10.0, 1.0); // Draw a grid @@ -837,8 +835,8 @@ void UpdateDrawOneFrame(void) { DrawText("This module give you functions to:", 48, 200, 10, GetColor(0x8c7539ff)); - DrawTextEx(fontRomulus, "Load and Play Sounds", (Vector2){ 48, 230 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x8c7539ff)); - DrawTextEx(fontRomulus, "Play Music (streaming)", (Vector2){ 48, 260 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x8c7539ff)); + DrawTextEx(fontRomulus, "Load and Play Sounds", (Vector2){ 48, 230 }, fontRomulus.size*2, 4, GetColor(0x8c7539ff)); + DrawTextEx(fontRomulus, "Play Music (streaming)", (Vector2){ 48, 260 }, fontRomulus.size*2, 4, GetColor(0x8c7539ff)); DrawText("PRESS SPACE to START PLAYING MUSIC", 135, 350, 20, GRAY); DrawRectangle(150, 390, 400, 12, LIGHTGRAY); @@ -891,7 +889,7 @@ void UpdateDrawOneFrame(void) case ENDING: { // Draw ENDING screen - DrawTextEx(fontAlagard, "LEARN VIDEOGAMES PROGRAMMING", (Vector2){ screenWidth/2 - MeasureTextEx(fontAlagard, "LEARN VIDEOGAMES PROGRAMMING", GetFontBaseSize(fontAlagard)*4, 4).x/2, 80 }, GetFontBaseSize(fontAlagard)*4, 4, MAROON); + DrawTextEx(fontAlagard, "LEARN VIDEOGAMES PROGRAMMING", (Vector2){ screenWidth/2 - MeasureTextEx(fontAlagard, "LEARN VIDEOGAMES PROGRAMMING", fontAlagard.size*4, 4).x/2, 80 }, fontAlagard.size*4, 4, MAROON); DrawTexture(raylibLogoA, logoPositionX, logoPositionY - 40, WHITE); diff --git a/games/skully_escape/makefile b/games/skully_escape/makefile index 0a343037..d47760d3 100644 --- a/games/skully_escape/makefile +++ b/games/skully_escape/makefile @@ -71,7 +71,7 @@ else CFLAGS = -O2 -Wall -std=c99 endif ifeq ($(PLATFORM),PLATFORM_WEB) - CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources -s ALLOW_MEMORY_GROWTH=1 + CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources -s ALLOW_MEMORY_GROWTH=1 --shell-file ../../templates/web_shell/shell.html #-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) @@ -81,7 +81,7 @@ endif ifeq ($(PLATFORM),PLATFORM_RPI) INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads else - INCLUDES = -I. -IC:/raylib/raylib/src -IC:/raylib/raylib/src + INCLUDES = -I. -I../../src # external libraries headers # GLFW3 INCLUDES += -I../../external/glfw3/include @@ -95,7 +95,7 @@ endif ifeq ($(PLATFORM),PLATFORM_RPI) LFLAGS = -L. -L../../src -L/opt/vc/lib else - LFLAGS = -L. -LC:/raylib/raylib/src -L../../../src + LFLAGS = -L. -L../../src -L../../../src # external libraries to link with # GLFW3 LFLAGS += -L../../external/glfw3/lib/$(LIBPATH) @@ -133,14 +133,14 @@ ifeq ($(PLATFORM),PLATFORM_RPI) LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal endif ifeq ($(PLATFORM),PLATFORM_WEB) - LIBS = C:/raylib/raylib/src/libraylib.bc + 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 = C:/raylib/raylib/src/resources + WINFLAGS = ../../src/resources #-Wl,--subsystem,windows endif diff --git a/templates/advance_game/makefile b/templates/advance_game/makefile index b6dfc534..e19eb746 100644 --- a/templates/advance_game/makefile +++ b/templates/advance_game/makefile @@ -72,7 +72,8 @@ 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 + CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources --shell-file ../../templates/web_shell/shell.html + #-s ASSERTIONS=1 # to check for memory allocation errors (-O1 disables it) #-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing #-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) endif @@ -87,8 +88,8 @@ else # external libraries headers # GLFW3 INCLUDES += -I../../external/glfw3/include -# GLEW - INCLUDES += -I../../external/glew/include +# GLEW - Not required any more, replaced by GLAD + #INCLUDES += -I../external/glew/include # OpenAL Soft INCLUDES += -I../../external/openal_soft/include endif @@ -100,12 +101,12 @@ else LFLAGS = -L. -L../../src -LC:/raylib/raylib/src # external libraries to link with # GLFW3 - LFLAGS += -L../../external/glfw3/lib/$(LIBPATH) + 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) + # GLEW: Not used, replaced by GLAD + #LFLAGS += -L../../external/glew/lib/$(LIBPATH) endif endif @@ -128,7 +129,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) else # libraries for Windows desktop compiling # NOTE: GLFW3 and OpenAL Soft libraries should be installed - LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32 + LIBS = -lraylib -lglfw3 -lopengl32 -lopenal32 -lgdi32 endif endif endif @@ -138,8 +139,8 @@ ifeq ($(PLATFORM),PLATFORM_RPI) LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal endif ifeq ($(PLATFORM),PLATFORM_WEB) - # just adjust the correct path to libraylib.bc - LIBS = C:/raylib/raylib/src/libraylib.bc + # NOTE: Set the correct path to libraylib.bc + LIBS = ../../src/libraylib.bc endif # define additional parameters and flags for windows diff --git a/templates/basic_game/makefile b/templates/basic_game/makefile index 9a52c4eb..05732040 100644 --- a/templates/basic_game/makefile +++ b/templates/basic_game/makefile @@ -72,7 +72,8 @@ 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 + CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources --shell-file ../../templates/web_shell/shell.html + #-s ASSERTIONS=1 # to check for memory allocation errors (-O1 disables it) #-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing #-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) endif @@ -104,8 +105,8 @@ else ifneq ($(PLATFORM_OS),OSX) # OpenAL Soft LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH) - # GLEW - LFLAGS += -L../../external/glew/lib/$(LIBPATH) + # GLEW: Not used, replaced by GLAD + #LFLAGS += -L../../external/glew/lib/$(LIBPATH) endif endif @@ -138,8 +139,8 @@ ifeq ($(PLATFORM),PLATFORM_RPI) LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal endif ifeq ($(PLATFORM),PLATFORM_WEB) - # just adjust the correct path to libraylib.bc - LIBS = C:/raylib/raylib/src/libraylib.bc + # NOTE: Set the correct path to libraylib.bc + LIBS = ../../src/libraylib.bc endif # define additional parameters and flags for windows diff --git a/templates/simple_game/makefile b/templates/simple_game/makefile index 30216e5d..41fef740 100644 --- a/templates/simple_game/makefile +++ b/templates/simple_game/makefile @@ -72,7 +72,8 @@ 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 + CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources --shell-file ../../templates/web_shell/shell.html + #-s ASSERTIONS=1 # to check for memory allocation errors (-O1 disables it) #-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing #-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) endif @@ -104,8 +105,8 @@ else ifneq ($(PLATFORM_OS),OSX) # OpenAL Soft LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH) - # GLEW - LFLAGS += -L../../external/glew/lib/$(LIBPATH) + # GLEW: Not used, replaced by GLAD + #LFLAGS += -L../../external/glew/lib/$(LIBPATH) endif endif @@ -138,8 +139,8 @@ ifeq ($(PLATFORM),PLATFORM_RPI) LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal endif ifeq ($(PLATFORM),PLATFORM_WEB) - # just adjust the correct path to libraylib.bc - LIBS = C:/raylib/raylib/src/libraylib.bc + # NOTE: Set the correct path to libraylib.bc + LIBS = ../../src/libraylib.bc endif # define additional parameters and flags for windows diff --git a/templates/standard_game/makefile b/templates/standard_game/makefile index ec847b0e..90f0e6f2 100644 --- a/templates/standard_game/makefile +++ b/templates/standard_game/makefile @@ -72,7 +72,8 @@ 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 + CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources --shell-file ../../templates/web_shell/shell.html + #-s ASSERTIONS=1 # to check for memory allocation errors (-O1 disables it) #-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing #-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) endif @@ -104,8 +105,8 @@ else ifneq ($(PLATFORM_OS),OSX) # OpenAL Soft LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH) - # GLEW - LFLAGS += -L../../external/glew/lib/$(LIBPATH) + # GLEW: Not used, replaced by GLAD + #LFLAGS += -L../../external/glew/lib/$(LIBPATH) endif endif @@ -138,8 +139,8 @@ ifeq ($(PLATFORM),PLATFORM_RPI) LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal endif ifeq ($(PLATFORM),PLATFORM_WEB) - # just adjust the correct path to libraylib.bc - LIBS = C:/raylib/raylib/src/libraylib.bc + # NOTE: Set the correct path to libraylib.bc + LIBS = ../../src/libraylib.bc endif # define additional parameters and flags for windows -- cgit v1.2.3 From 2f08845d1ef32b767726eb96a38a909419aa19fd Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 21 Feb 2016 02:27:34 +0100 Subject: Updated docs --- CHANGELOG | 39 ++++++++++++++++++++++++++++++++++++++- HELPME.md | 6 ++++-- README.md | 31 ++++++++++++++++++------------- ROADMAP.md | 51 ++++++++++++++++++++++++++++++--------------------- 4 files changed, 90 insertions(+), 37 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 2af57c2c..66556ff8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,11 +1,48 @@ changelog --------- -Current Release: raylib 1.3.0 (03 September 2015) +Current Release: raylib 1.4.0 (22 February 2016) NOTE: Only versions marked as 'Release' are available in installer, updates are only available as source. NOTE: Current Release includes all previous updates. +----------------------------------------------- +Release: raylib 1.4.0 (22 February 2016) +----------------------------------------------- +NOTE: + This version supposed another big improvement for raylib, inlcuding new modules and new features. + More than 30 new functions have been added to previous raylib version. + Around 8 new examples and +10 new game samples have been added. + +BIG changes: +[textures] IMAGE MANIPULATION: Functions to crop, resize, colorize, flip, dither and even draw image-to-image or text-to-image. +[text] SPRITEFONT SUPPORT: Added support for AngelCode fonts (.fnt) and TrueType fonts (.ttf). +[gestures] REDESIGN: Gestures system simplified and prepared to process generic touch events, including mouse events (multiplatform). +[physac] NEW MODULE: Basic 2D physics support, use colliders and rigit bodies; apply forces to physic objects. + +other changes: +[rlgl] Removed GLEW library dependency, now using GLAD +[rlgl] Implemented alternative to glGetTexImage() on OpenGL ES +[rlgl] Using depth data on batch drawing +[rlgl] Reviewed glReadPixels() function +[core][rlgl] Reviewed raycast system, now 3D picking works +[core] Android: Reviewed Android App cycle, paused if inactive +[shaders] Implemented Blinn-Phong lighting shading model +[textures] Implemented Floyd-Steinberg dithering - ImageDither() +[text] Added line-break support to DrawText() +[text] Added TrueType Fonts support (using stb_truetype) +[models] Implement function: CalculateBoundingBox(Mesh mesh) +[models] Added functions to check Ray collisions +[models] Improve map resolution control on LoadHeightmap() +[camera] Corrected small-glitch on zoom-in with mouse-wheel +[gestures] Implemented SetGesturesEnabled() to enable only some gestures +[gestures] Implemented GetElapsedTime() on Windows system +[gestures] Support mouse gestures for desktop platforms +[raymath] Complete review of the module and converted to header-only +[easings] Added new module for easing animations +[stb] Updated to latest headers versions +[*] Lots of tweaks around + ----------------------------------------------- Release: raylib 1.3.0 (01 September 2015) ----------------------------------------------- diff --git a/HELPME.md b/HELPME.md index 8a0ada18..b4f0219f 100644 --- a/HELPME.md +++ b/HELPME.md @@ -32,6 +32,8 @@ contact * Webpage: [http://www.raylib.com](http://www.raylib.com) * Twitter: [http://www.twitter.com/raysan5](http://www.twitter.com/raysan5) * Facebook: [http://www.facebook.com/raylibgames](http://www.facebook.com/raylibgames) - + * Reddit: [https://www.reddit.com/r/raylib](https://www.reddit.com/r/raylib) + * Twitch: [http://www.twitch.tv/raysan5](http://www.twitch.tv/raysan5) + * Patreon: [https://www.patreon.com/raysan5](https://www.patreon.com/raysan5) -[raysan5]: mailto:raysan@raysanweb.com "Ramon Santamaria - Ray San" +[raysan5]: mailto:raysan5@gmail.com "Ramon Santamaria - Ray San" diff --git a/README.md b/README.md index f9a5a0e2..fab198bd 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,6 @@ about raylib is a simple and easy-to-use library to learn videogames programming. raylib is highly inspired by Borland BGI graphics lib and by XNA framework. -Allegro and SDL have also been analyzed for reference. NOTE for ADVENTURERS: raylib is a programming library to learn videogames programming; no fancy interface, no visual helpers, no auto-debugging... just coding in the most @@ -15,7 +14,7 @@ pure spartan-programmers way. Are you ready to learn? Jump to [code examples!](h history ------- -I've developed videogames for some years and last year I had to taught videogames development +I've developed videogames for some years and 4 year ago I started teaching videogames development to young people with artistic profile, most of them had never written a single line of code. I started with C language basis and, after searching for the most simple and easy-to-use library to teach @@ -102,25 +101,28 @@ Lots of code changes and lot of testing have concluded in this amazing new rayli notes on raylib 1.4 ------------------- -On February 2016, after 4 months of raylib 1.3 release, it comes raylib 1.4. +On February 2016, after 4 months of raylib 1.3 release, it comes raylib 1.4. For this new version, lots of parts of the library have been reviewed to better accomodate the shaders system. +Lots of bugs have been solved and some missing features have been added to the library. -Lots of parts of the library have been reviewed to better accomodate to shaders systems and multiple new features have been added. +SpriteFonts system has been improved, adding support for AngelCode fonts (.fnt) and TTF fonts (using stb_truetype helper library). -SpriteFonts system has been improved, adding support for AngelCode fonts (.fnt) and TTF fonts (using stb_truetype). +A set of Image manipulation functions have been added to crop, resize, colorize, flip, dither and even draw image-to-image or text-to-image. -Finally, raycast system for 3D picking is working, including some ray collision-detection functions. +[raymath](https://github.com/raysan5/raylib/blob/develop/src/raymath.h) module has been reviewed and converted to a header-only file for easier portability, functions can also be used as inline. -A set of Image manipulation functions have been added to crop, resize, colorize, dither and even draw image-to-image or text-to-image. +Raycast system for 3D picking is now fully functional, including some ray collision-detection functions. -Two new functions added for persistent data storage. +[raymath](https://github.com/raysan5/raylib/blob/develop/src/gestures.c) module has redesigned and simplified, now it can process touch events from any source, including mouse. This way, gestures system can be used for any platform. -New [physac](https://github.com/raysan5/raylib/blob/develop/src/physac.h) physics module! +Raspberry Pi input system has been redesigned to better read raw inputs using generic Linux event handlers (keyboard:`stdin`, mouse:`/dev/input/mouse0`, gamepad:`/dev/input/js0`). Gamepad support has been added. -Complete LUA scripting support to allow raylib usage from LUA and LUA scripts support within raylib. +Two new functions added for persistent data storage. Now raylib user can save and load game data in a file. -Up to 8 new examples have been added to show the new raylib features. +[physac](https://github.com/raysan5/raylib/blob/develop/src/physac.h) physics module added. Basic 2D physics support. -Lots of code changes and lot of testing have concluded in this amazing new raylib 1.4. +Up to 8 new examples have been added to show the new raylib features... and +10 game samples to learn how to create some classic games like Arkanoid, Asteroids, Missile Commander, Snake or Tetris. + +Lots of code changes and lots of hours of hard work have concluded in this amazing new raylib 1.4. features -------- @@ -130,7 +132,7 @@ features * Hardware accelerated with OpenGL (1.1, 3.3 or ES2) * Unique OpenGL abstraction layer (usable as standalone module): [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.c) * Powerful fonts module with multiple SpriteFonts formats support (XNA bitmap fonts, AngelCode fonts, TTF) - * Outstanding texture formats support, including compressed formats + * Outstanding texture formats support, including compressed formats (DXT, ETC, PVRT, ASTC) * Basic 3d support for Shapes, Models, Billboards, Heightmaps and Cubicmaps * Powerful math module for Vector and Matrix operations: [raymath](https://github.com/raysan5/raylib/blob/master/src/raymath.c) * Audio loading and playing with streaming support (WAV and OGG) @@ -181,6 +183,9 @@ contact * Webpage: [http://www.raylib.com](http://www.raylib.com) * Twitter: [http://www.twitter.com/raysan5](http://www.twitter.com/raysan5) * Facebook: [http://www.facebook.com/raylibgames](http://www.facebook.com/raylibgames) + * Reddit: [https://www.reddit.com/r/raylib](https://www.reddit.com/r/raylib) + * Twitch: [http://www.twitch.tv/raysan5](http://www.twitch.tv/raysan5) + * Patreon: [https://www.patreon.com/raysan5](https://www.patreon.com/raysan5) If you are using raylib and you enjoy it, please, [let me know][raysan5]. diff --git a/ROADMAP.md b/ROADMAP.md index e0d0c825..0481aaf2 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,28 +1,37 @@ roadmap ------- -Current version of raylib is quite complete and functional but there is still a lot of things I would like to improve. -Here it is a list of features I would like to add and functions to improve. - -Around the source code there are multiple TODO points with pending revisions/bugs and here it is a list of desired features. - -raylib v1.4 - - [DONE] TTF fonts support (using stb_truetype) - [DONE] Raycast system for 3D picking (including collisions detection) - [DONE] Floyd-Steinberg dithering on 16bit image format conversion - [DONE] Basic image manipulation functions (crop, resize, draw...) - [DONE] Storage load/save data functionality - [DONE] Physics module - [IN PROGRESS] LUA scripting support (wrapper to lua lib) - - Remove GLEW dependency (use another solution... glad?) - - Basic image procedural generation (spot, gradient, noise...) - - Basic GPU stats sytem (memory, draws, time...) - - -Check [GITHUB ISSUES][issues] for further details on implementation status for this features! +Current version of raylib is quite complete and functional but there is still a lot of things to add and improve. +Here it is a wish list of features I would like to add and functions to improve. + +Note that around the raylib source code there are multiple TODO points with pending revisions/bugs. Check [GITHUB ISSUES][issues] for further details! + +raylib 1.5 + + Redesign Shaders/Textures system, use Materials + Redesign physics module (physac) + Basic GPU stats sytem (memory, draws, time...) + Procedural image generation functions (spot, gradient, noise...) + Procedural mesh generation functions (cube, cone, sphere...) + Touch-based camera controls for Android + Skybox and Fog support + [IN PROGRESS] LUA scripting support (wrapper to lua lib) + +raylib 1.4 + + [DONE] TTF fonts support (using stb_truetype) + [DONE] Raycast system for 3D picking (including collisions detection) + [DONE] Floyd-Steinberg dithering on 16bit image format conversion + [DONE] Basic image manipulation functions (crop, resize, draw...) + [DONE] Storage load/save data functionality + [DONE] Add Physics module (physac) + [DONE] Remove GLEW dependency -> Replaced by GLAD + [DONE] Redesign Raspberry PI inputs system + [DONE] Redesign gestures module to be multiplatform + [DONE] Module raymath as header-only and functions inline + [DONE] Add Easings module (easings.h) Any feature missing? Do you have a request? [Let me know!][raysan5] -[raysan5]: mailto:raysan@raysanweb.com "Ramon Santamaria - Ray San" +[raysan5]: mailto:raysan5@gmail.com "Ramon Santamaria - Ray San" [isssues]: https://github.com/raysan5/raylib/issues -- cgit v1.2.3 From 9ec47768121766cf12fef5d1bab8c8302cdac3a6 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 21 Feb 2016 02:29:11 +0100 Subject: Corrected typo --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 66556ff8..795a2ee5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -18,7 +18,7 @@ BIG changes: [textures] IMAGE MANIPULATION: Functions to crop, resize, colorize, flip, dither and even draw image-to-image or text-to-image. [text] SPRITEFONT SUPPORT: Added support for AngelCode fonts (.fnt) and TrueType fonts (.ttf). [gestures] REDESIGN: Gestures system simplified and prepared to process generic touch events, including mouse events (multiplatform). -[physac] NEW MODULE: Basic 2D physics support, use colliders and rigit bodies; apply forces to physic objects. +[physac] NEW MODULE: Basic 2D physics support, use colliders and rigidbodies; apply forces to physic objects. other changes: [rlgl] Removed GLEW library dependency, now using GLAD -- cgit v1.2.3 From c86b3d0c05df9cb246f7838a0e2561bdce37063f Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 21 Feb 2016 02:34:07 +0100 Subject: Updated --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index fab198bd..49653a85 100644 --- a/README.md +++ b/README.md @@ -108,11 +108,9 @@ SpriteFonts system has been improved, adding support for AngelCode fonts (.fnt) A set of Image manipulation functions have been added to crop, resize, colorize, flip, dither and even draw image-to-image or text-to-image. -[raymath](https://github.com/raysan5/raylib/blob/develop/src/raymath.h) module has been reviewed and converted to a header-only file for easier portability, functions can also be used as inline. +[raymath](https://github.com/raysan5/raylib/blob/develop/src/raymath.h) module has been reviewed and converted to a header-only file for easier portability, functions can also be used as inline. Raycast system for 3D picking is now fully functional, including some ray collision-detection functions. -Raycast system for 3D picking is now fully functional, including some ray collision-detection functions. - -[raymath](https://github.com/raysan5/raylib/blob/develop/src/gestures.c) module has redesigned and simplified, now it can process touch events from any source, including mouse. This way, gestures system can be used for any platform. +[gestures](https://github.com/raysan5/raylib/blob/develop/src/gestures.c) module has redesigned and simplified, now it can process touch events from any source, including mouse. This way, gestures system can be used for any platform. Raspberry Pi input system has been redesigned to better read raw inputs using generic Linux event handlers (keyboard:`stdin`, mouse:`/dev/input/mouse0`, gamepad:`/dev/input/js0`). Gamepad support has been added. -- cgit v1.2.3 From c7486a0339d25fd5142746ad213eb001594fb649 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 21 Feb 2016 12:13:36 +0100 Subject: Update README.md --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 49653a85..c89c33cc 100644 --- a/README.md +++ b/README.md @@ -101,24 +101,24 @@ Lots of code changes and lot of testing have concluded in this amazing new rayli notes on raylib 1.4 ------------------- -On February 2016, after 4 months of raylib 1.3 release, it comes raylib 1.4. For this new version, lots of parts of the library have been reviewed to better accomodate the shaders system. -Lots of bugs have been solved and some missing features have been added to the library. +On February 2016, after 4 months of raylib 1.3 release, it comes raylib 1.4. For this new version, lots of parts of the library have been reviewed, lots of bugs have been solved and some interesting features have been added. -SpriteFonts system has been improved, adding support for AngelCode fonts (.fnt) and TTF fonts (using stb_truetype helper library). +First big addition is a set of [Image manipulation functions](https://github.com/raysan5/raylib/blob/develop/src/raylib.h#L673) have been added to crop, resize, colorize, flip, dither and even draw image-to-image or text-to-image. Now a basic image processing can be done before converting the image to texture for usage. -A set of Image manipulation functions have been added to crop, resize, colorize, flip, dither and even draw image-to-image or text-to-image. +SpriteFonts system has been improved, adding support for AngelCode fonts (.fnt) and TrueType Fonts (using [stb_truetype](https://github.com/nothings/stb/blob/master/stb_truetype.h) helper library). Now raylib can read standard .fnt font data and also generate at loading a SpriteFont from a TTF file. -[raymath](https://github.com/raysan5/raylib/blob/develop/src/raymath.h) module has been reviewed and converted to a header-only file for easier portability, functions can also be used as inline. Raycast system for 3D picking is now fully functional, including some ray collision-detection functions. +New [physac](https://github.com/raysan5/raylib/blob/develop/src/physac.h) physics module for basic 2D physics support. Still in development but already functional. Module comes with some usage examples for basic jump and level interaction and also force-based physic movements. -[gestures](https://github.com/raysan5/raylib/blob/develop/src/gestures.c) module has redesigned and simplified, now it can process touch events from any source, including mouse. This way, gestures system can be used for any platform. +[raymath](https://github.com/raysan5/raylib/blob/develop/src/raymath.h) module has been reviewed; some bugs have been solved and the module has been converted to a header-only file for easier portability, optionally, functions can also be used as inline. -Raspberry Pi input system has been redesigned to better read raw inputs using generic Linux event handlers (keyboard:`stdin`, mouse:`/dev/input/mouse0`, gamepad:`/dev/input/js0`). Gamepad support has been added. +[gestures](https://github.com/raysan5/raylib/blob/develop/src/gestures.c) module has redesigned and simplified, now it can process touch events from any source, including mouse. This way, gestures system can be used on any platform providing an unified way to work with inputs and allowing the user to create multiplatform games with only one source code. -Two new functions added for persistent data storage. Now raylib user can save and load game data in a file. +Raspberry Pi input system has been redesigned to better read raw inputs using generic Linux event handlers (keyboard:`stdin`, mouse:`/dev/input/mouse0`, gamepad:`/dev/input/js0`). Gamepad support has also been added (experimental). -[physac](https://github.com/raysan5/raylib/blob/develop/src/physac.h) physics module added. Basic 2D physics support. +Other important improvements are the functional raycast system for 3D picking, including some ray collision-detection functions, and the addition of two simple functions for persistent data storage. Now raylib user can save and load game data in a file (only some platforms supported). -Up to 8 new examples have been added to show the new raylib features... and +10 game samples to learn how to create some classic games like Arkanoid, Asteroids, Missile Commander, Snake or Tetris. + +Up to 8 new code examples have been added to show the new raylib features and +10 complete game samples have been provided to learn how to create some classic games like Arkanoid, Asteroids, Missile Commander, Snake or Tetris. Lots of code changes and lots of hours of hard work have concluded in this amazing new raylib 1.4. -- cgit v1.2.3 From 24ba22a43aa06e99a34fcb5c1b17c9d8c3ef5017 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 21 Feb 2016 12:18:36 +0100 Subject: Update ROADMAP.md --- ROADMAP.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index 0481aaf2..aaa1a256 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -4,7 +4,7 @@ roadmap Current version of raylib is quite complete and functional but there is still a lot of things to add and improve. Here it is a wish list of features I would like to add and functions to improve. -Note that around the raylib source code there are multiple TODO points with pending revisions/bugs. Check [GITHUB ISSUES][issues] for further details! +Note that around the raylib source code there are multiple TODO points with pending revisions/bugs. Check [GitHub Issues](https://github.com/raysan5/raylib/issues) for further details! raylib 1.5 -- cgit v1.2.3 From c70d8acb333ca2997ddd944aa1d4cd3c39dc1cac Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 21 Feb 2016 12:22:44 +0100 Subject: Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index c89c33cc..30ceeed5 100644 --- a/README.md +++ b/README.md @@ -115,8 +115,7 @@ New [physac](https://github.com/raysan5/raylib/blob/develop/src/physac.h) physic Raspberry Pi input system has been redesigned to better read raw inputs using generic Linux event handlers (keyboard:`stdin`, mouse:`/dev/input/mouse0`, gamepad:`/dev/input/js0`). Gamepad support has also been added (experimental). -Other important improvements are the functional raycast system for 3D picking, including some ray collision-detection functions, and the addition of two simple functions for persistent data storage. Now raylib user can save and load game data in a file (only some platforms supported). - +Other important improvements are the functional raycast system for 3D picking, including some ray collision-detection functions, and the addition of two simple functions for persistent data storage. Now raylib user can save and load game data in a file (only some platforms supported). A simple [easings](https://github.com/raysan5/raylib/blob/develop/src/easings.h) module has also been added for values animation. Up to 8 new code examples have been added to show the new raylib features and +10 complete game samples have been provided to learn how to create some classic games like Arkanoid, Asteroids, Missile Commander, Snake or Tetris. -- cgit v1.2.3 From 4d2b8471fa6f6f58d9dcf260d024b2de563c32db Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 21 Feb 2016 14:17:33 +0100 Subject: Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 30ceeed5..5f6fea7f 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ pure spartan-programmers way. Are you ready to learn? Jump to [code examples!](h history ------- -I've developed videogames for some years and 4 year ago I started teaching videogames development +I've developed videogames for some years and 4 years ago I started teaching videogames development to young people with artistic profile, most of them had never written a single line of code. I started with C language basis and, after searching for the most simple and easy-to-use library to teach -- cgit v1.2.3 From 2a058338f3489ce241d207b52ddf48c9cfc34b62 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 21 Feb 2016 14:34:11 +0100 Subject: Updated some files --- examples/core_3d_picking.png | Bin 23100 -> 24383 bytes templates/android_project/jni/include/raylib.h | 221 ++++++++++++------------- templates/android_project/jni/libs/libraylib.a | Bin 1617368 -> 1646046 bytes 3 files changed, 109 insertions(+), 112 deletions(-) diff --git a/examples/core_3d_picking.png b/examples/core_3d_picking.png index 828c41a8..bb7660b0 100644 Binary files a/examples/core_3d_picking.png and b/examples/core_3d_picking.png differ diff --git a/templates/android_project/jni/include/raylib.h b/templates/android_project/jni/include/raylib.h index 72211b59..c4d4392d 100644 --- a/templates/android_project/jni/include/raylib.h +++ b/templates/android_project/jni/include/raylib.h @@ -7,10 +7,10 @@ * Features: * Library written in plain C code (C99) * Uses C# PascalCase/camelCase notation -* Hardware accelerated with OpenGL (1.1, 3.3+ or ES2) +* Hardware accelerated with OpenGL (1.1, 3.3 or ES2) * Unique OpenGL abstraction layer [rlgl] -* Powerful fonts module with SpriteFonts support -* Multiple textures support, including DDS and mipmaps generation +* Powerful fonts module with SpriteFonts support (including AngelCode fonts and TTF) +* Multiple textures support, including compressed formats and mipmaps generation * Basic 3d support for Shapes, Models, Heightmaps and Billboards * Powerful math module for Vector and Matrix operations [raymath] * Audio loading and playing with streaming support (WAV and OGG) @@ -18,20 +18,21 @@ * * Used external libs: * GLFW3 (www.glfw.org) for window/context management and input -* GLEW for OpenGL extensions loading (3.3+ and ES2) +* GLAD for OpenGL extensions loading (3.3 Core profile, only PLATFORM_DESKTOP) * stb_image (Sean Barret) for images loading (JPEG, PNG, BMP, TGA, PSD, GIF, HDR, PIC) * stb_image_write (Sean Barret) for image writting (PNG) * stb_vorbis (Sean Barret) for ogg audio loading +* stb_truetype (Sean Barret) for ttf fonts loading * OpenAL Soft for audio device/context management * tinfl for data decompression (DEFLATE algorithm) * * Some design decisions: -* 32bit Colors - All defined color are always RGBA -* SpriteFonts - All loaded sprite-font images are converted to RGBA and POT textures +* 32bit Colors - All defined color are always RGBA (struct Color is 4 byte) * One custom default font is loaded automatically when InitWindow() -* If using OpenGL 3.3+ or ES2, one default shader is loaded automatically (internally defined) +* If using OpenGL 3.3 or ES2, several vertex buffers (VAO/VBO) are created to manage lines-triangles-quads +* If using OpenGL 3.3 or ES2, two default shaders are loaded automatically (internally defined) * -* -- LICENSE (raylib v1.2, September 2014) -- +* -- LICENSE -- * * raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software: @@ -80,8 +81,8 @@ #define PI 3.14159265358979323846 #endif -#define DEG2RAD (PI / 180.0f) -#define RAD2DEG (180.0f / PI) +#define DEG2RAD (PI/180.0f) +#define RAD2DEG (180.0f/PI) // raylib Config Flags #define FLAG_FULLSCREEN_MODE 1 @@ -110,6 +111,8 @@ #define KEY_F8 297 #define KEY_F9 298 #define KEY_F10 299 +#define KEY_F11 300 +#define KEY_F12 301 #define KEY_LEFT_SHIFT 340 #define KEY_LEFT_CONTROL 341 #define KEY_LEFT_ALT 342 @@ -117,7 +120,7 @@ #define KEY_RIGHT_CONTROL 345 #define KEY_RIGHT_ALT 346 -// Keyboard Alhpa Numeric Keys +// Keyboard Alpha Numeric Keys #define KEY_ZERO 48 #define KEY_ONE 49 #define KEY_TWO 50 @@ -165,6 +168,9 @@ #define MOUSE_MIDDLE_BUTTON 2 #endif +// Touch points registered +#define MAX_TOUCH_POINTS 2 + // Gamepad Number #define GAMEPAD_PLAYER1 0 #define GAMEPAD_PLAYER2 1 @@ -308,17 +314,27 @@ typedef struct Camera { Vector3 up; } Camera; +// Bounding box type +typedef struct BoundingBox { + Vector3 min; + Vector3 max; +} BoundingBox; + // 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 - unsigned int vaoId; - unsigned int vboId[4]; -} VertexData; +typedef struct Mesh { + int vertexCount; // num vertices + float *vertices; // vertex position (XYZ - 3 components per vertex) + float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) + float *texcoords2; // vertex second texture coordinates (useful for lightmaps) + float *normals; // vertex normals (XYZ - 3 components per vertex) + float *tangents; // vertex tangents (XYZ - 3 components per vertex) + unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) + + BoundingBox bounds; // mesh limits defined by min and max points + + unsigned int vaoId; // OpenGL Vertex Array Object id + unsigned int vboId[6]; // OpenGL Vertex Buffer Objects id (6 types of vertex data) +} Mesh; // Shader type (generic shader) typedef struct Shader { @@ -336,10 +352,7 @@ typedef struct Shader { int colorLoc; // Color attibute location point (vertex shader) // Uniforms - int projectionLoc; // Projection matrix uniform location point (vertex shader) - int modelviewLoc; // ModelView matrix uniform location point (vertex shader) - int modelLoc; // Model transformation matrix uniform location point (vertex shader) - int viewLoc; // View transformation matrix uniform location point (vertex shader) + int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) int tintColorLoc; // Color uniform location point (fragment shader) int mapDiffuseLoc; // Diffuse map texture uniform location point (fragment shader) @@ -347,12 +360,31 @@ typedef struct Shader { int mapSpecularLoc; // Specular map texture uniform location point (fragment shader) } Shader; +// Material type +// TODO: Redesign material-shaders-textures system +typedef struct Material { + //Shader shader; + + //Texture2D texDiffuse; // Diffuse texture + //Texture2D texNormal; // Normal texture + //Texture2D texSpecular; // Specular texture + + Color colDiffuse; + Color colAmbient; + Color colSpecular; + + float glossiness; + float normalDepth; +} Material; + // 3d Model type +// TODO: Replace shader/testure by material typedef struct Model { - VertexData mesh; + Mesh mesh; Matrix transform; Texture2D texture; // Only for OpenGL 1.1, on newer versions this should be in the shader Shader shader; + //Material material; } Model; // Ray type (useful for raycast) @@ -376,26 +408,6 @@ typedef struct Wave { short channels; } Wave; -// Light type -typedef struct Light { - float position[3]; - float rotation[3]; - float intensity[1]; - float ambientColor[3]; - float diffuseColor[3]; - float specularColor[3]; - float specularIntensity[1]; -} Light; - -// Material type -typedef struct Material { - float ambientColor[3]; - float diffuseColor[3]; - float specularColor[3]; - float glossiness[1]; - float normalDepth[1]; -} Material; - // Texture formats // NOTE: Support depends on OpenGL version and platform typedef enum { @@ -425,42 +437,36 @@ typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode; // Gestures type // NOTE: It could be used as flags to enable only some gestures typedef enum { - GESTURE_NONE = 1, - GESTURE_TAP = 2, - GESTURE_DOUBLETAP = 4, - GESTURE_HOLD = 8, - GESTURE_DRAG = 16, - GESTURE_SWIPE_RIGHT = 32, - GESTURE_SWIPE_LEFT = 64, - GESTURE_SWIPE_UP = 128, - GESTURE_SWIPE_DOWN = 256, - GESTURE_PINCH_IN = 512, - GESTURE_PINCH_OUT = 1024 + GESTURE_NONE = 0, + GESTURE_TAP = 1, + GESTURE_DOUBLETAP = 2, + GESTURE_HOLD = 4, + GESTURE_DRAG = 8, + GESTURE_SWIPE_RIGHT = 16, + GESTURE_SWIPE_LEFT = 32, + GESTURE_SWIPE_UP = 64, + GESTURE_SWIPE_DOWN = 128, + GESTURE_PINCH_IN = 256, + GESTURE_PINCH_OUT = 512 } Gestures; +// Touch action (fingers or mouse) typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction; // Gesture events -// NOTE: MAX_TOUCH_POINTS fixed to 4 +// NOTE: MAX_TOUCH_POINTS fixed to 2 typedef struct { int touchAction; int pointCount; - int pointerId[4]; - Vector2 position[4]; + int pointerId[MAX_TOUCH_POINTS]; + Vector2 position[MAX_TOUCH_POINTS]; } GestureEvent; // Camera system modes typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode; // Collider types -typedef enum { RectangleCollider, CircleCollider } ColliderType; - -// Physics struct -typedef struct Physics { - bool enabled; - bool debug; // Should be used by programmer for testing purposes - Vector2 gravity; -} Physics; +typedef enum { COLLIDER_CIRCLE, COLLIDER_RECTANGLE, COLLIDER_CAPSULE } ColliderType; // Transform struct typedef struct Transform { @@ -486,8 +492,8 @@ typedef struct Rigidbody { typedef struct Collider { bool enabled; ColliderType type; - Rectangle bounds; // Just used for RectangleCollider type - int radius; // Just used for CircleCollider type + Rectangle bounds; // Used for COLLIDER_RECTANGLE and COLLIDER_CAPSULE + int radius; // Used for COLLIDER_CIRCLE and COLLIDER_CAPSULE } Collider; #ifdef __cplusplus @@ -524,10 +530,12 @@ void BeginDrawing(void); // Setup drawing can void BeginDrawingEx(int blendMode, Shader shader, Matrix transform); // Setup drawing canvas with extended parameters void EndDrawing(void); // End canvas drawing and Swap Buffers (Double Buffering) -void Begin3dMode(Camera cam); // Initializes 3D mode for drawing (Camera setup) +void Begin3dMode(Camera camera); // Initializes 3D mode for drawing (Camera setup) void End3dMode(void); // Ends 3D mode and returns to default 2D orthographic mode -Ray GetMouseRay(Vector2 mousePosition, Camera camera); // TODO: Returns a ray trace from mouse position +Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position +Vector2 WorldToScreen(Vector3 position, Camera camera); // Returns the screen space position from a 3d world space position +Matrix GetCameraMatrix(Camera camera); // Returns camera transform matrix (view matrix) void SetTargetFPS(int fps); // Set target FPS (maximum) float GetFPS(void); // Returns current FPS @@ -535,6 +543,9 @@ float GetFrameTime(void); // Returns time in s Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value int GetHexValue(Color color); // Returns hexadecimal value for a Color +float *ColorToFloat(Color color); // Converts Color to float array and normalizes +float *VectorToFloat(Vector3 vec); // Converts Vector3 to float array +float *MatrixToFloat(Matrix mat); // Converts Matrix to float array 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 @@ -571,10 +582,10 @@ int GetMouseWheelMove(void); // Returns mouse wheel m void ShowCursor(void); // Shows cursor void HideCursor(void); // Hides cursor +void EnableCursor(void); // Enables cursor +void DisableCursor(void); // Disables cursor bool IsCursorHidden(void); // Returns true if cursor is not visible -#endif -#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 @@ -583,30 +594,31 @@ 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) || defined(PLATFORM_WEB) -int GetTouchX(void); // Returns touch position X (relative to screen size) -int GetTouchY(void); // Returns touch position Y (relative to screen size) -Vector2 GetTouchPosition(void); // Returns touch position XY (relative to screen size) +int GetTouchX(void); // Returns touch position X for touch point 0 (relative to screen size) +int GetTouchY(void); // Returns touch position Y for touch point 0 (relative to screen size) +Vector2 GetTouchPosition(int index); // Returns touch position XY for a touch point index (relative to screen size) + +#if defined(PLATFORM_ANDROID) bool IsButtonPressed(int button); // Detect if an android physic button has been pressed bool IsButtonDown(int button); // Detect if an android physic button is being pressed bool IsButtonReleased(int button); // Detect if an android physic button has been released +#endif //------------------------------------------------------------------------------------ // Gestures and Touch Handling Functions (Module: gestures) //------------------------------------------------------------------------------------ +void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures void UpdateGestures(void); // Update gestures detected (must be called every frame) bool IsGestureDetected(void); // Check if a gesture have been detected int GetGestureType(void); // Get latest detected gesture void SetGesturesEnabled(unsigned int gestureFlags); // Enable a set of gestures using flags -void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures +int GetTouchPointsCount(void); // Get touch points count -float GetGestureDragIntensity(void); // Get gesture drag intensity -float GetGestureDragAngle(void); // Get gesture drag angle +float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds Vector2 GetGestureDragVector(void); // Get gesture drag vector -int GetGestureHoldDuration(void); // Get gesture hold time in frames -float GetGesturePinchDelta(void); // Get gesture pinch delta +float GetGestureDragAngle(void); // Get gesture drag angle +Vector2 GetGesturePinchVector(void); // Get gesture pinch delta float GetGesturePinchAngle(void); // Get gesture pinch angle -#endif //------------------------------------------------------------------------------------ // Camera System Functions (Module: camera) @@ -738,27 +750,31 @@ void DrawGizmo(Vector3 position); // 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 LoadModelEx(Mesh 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 LoadHeightmap(Image heightmap, Vector3 size); // 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 DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) -void DrawModelEx(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color tint); // Draw a model with extended parameters +void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, 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 DrawModelWiresEx(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters +void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters +void DrawBoundingBox(BoundingBox box); // Draw bounding box (wires) 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 +BoundingBox CalculateBoundingBox(Mesh mesh); // Calculate mesh bounding box limits bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB); // Detect collision between two spheres bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, Vector3 maxBBox2); // Detect collision between two boxes bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSphere, float radiusSphere); // Detect collision between box and sphere +bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius); // Detect collision between ray and sphere +bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadius, Vector3 *collisionPoint); // Detect collision between ray and sphere with extended parameters and collision point detection +bool CheckCollisionRayBox(Ray ray, Vector3 minBBox, Vector3 maxBBox); // Detect collision between ray and box Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius); // Detect collision of player radius with cubicmap // NOTE: Return the normal vector of the impacted surface - //------------------------------------------------------------------------------------ // Shaders System Functions (Module: rlgl) // NOTE: This functions are useless when using OpenGL 1.1 @@ -775,6 +791,7 @@ bool IsPosproShaderEnabled(void); // Check if int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float) void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int) +void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4) void SetShaderMapDiffuse(Shader *shader, Texture2D texture); // Default diffuse shader map texture assignment void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture); // Normal map texture shader assignment void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture); // Specular map texture shader assignment @@ -783,30 +800,10 @@ void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textur void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied) //---------------------------------------------------------------------------------- -// Lighting System Functions (engine-module: lighting) -// NOTE: light and material structs uses float pointers instead of vectors to be compatible with SetShaderValue() -//---------------------------------------------------------------------------------- -// Lights functions -void SetLightPosition(Light *light, Vector3 position); // Set light position converting position vector to float pointer -void SetLightRotation(Light *light, Vector3 rotation); // Set light rotation converting rotation vector to float pointer -void SetLightIntensity(Light *light, float intensity); // Set light intensity value -void SetLightAmbientColor(Light *light, Vector3 color); // Set light ambient color value (it will be multiplied by material ambient color) -void SetLightDiffuseColor(Light *light, Vector3 color); // Set light diffuse color (light color) -void SetLightSpecularColor(Light *light, Vector3 color); // Set light specular color (it will be multiplied by material specular color) -void SetLightSpecIntensity(Light *light, float specIntensity); // Set light specular intensity (specular color scalar multiplier) - -// Materials functions -void SetMaterialAmbientColor(Material *material, Vector3 color); // Set material ambient color value (it will be multiplied by light ambient color) -void SetMaterialDiffuseColor(Material *material, Vector3 color); // Set material diffuse color (material color, should use DrawModel() tint parameter) -void SetMaterialSpecularColor(Material *material, Vector3 color); // Set material specular color (it will be multiplied by light specular color) -void SetMaterialGlossiness(Material *material, float glossiness); // Set material glossiness value (recommended values: 0 - 100) -void SetMaterialNormalDepth(Material *material, float depth); // Set normal map depth (B component from RGB type map scalar multiplier) - -//---------------------------------------------------------------------------------- -// Physics System Functions (engine-module: physics) +// Physics System Functions (engine-module: physac) //---------------------------------------------------------------------------------- -void InitPhysics(void); // Initialize all internal physics values -void SetPhysics(Physics settings); // Set physics settings values using Physics data type to overwrite internal physics settings +void InitPhysics(int maxPhysicElements); // Initialize all internal physics values +void UnloadPhysics(); // Unload physic elements arrays void AddRigidbody(int index, Rigidbody rigidbody); // Initialize a new rigidbody with parameters to internal index slot void AddCollider(int index, Collider collider); // Initialize a new Collider with parameters to internal index slot diff --git a/templates/android_project/jni/libs/libraylib.a b/templates/android_project/jni/libs/libraylib.a index 14e10ab7..2cda5843 100644 Binary files a/templates/android_project/jni/libs/libraylib.a and b/templates/android_project/jni/libs/libraylib.a differ -- cgit v1.2.3 From 2cc05e5e9243645aad810fee86465d4e84c81816 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 21 Feb 2016 16:19:31 +0100 Subject: Corrected typo --- src/raylib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raylib.h b/src/raylib.h index c4d4392d..c598ec30 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -697,7 +697,7 @@ void ImageFlipVertical(Image *image); void ImageFlipHorizontal(Image *image); // Flip image horizontally void ImageColorTint(Image *image, Color color); // Modify image color: tint void ImageColorInvert(Image *image); // Modify image color: invert -void ImageColorGrayscale(Image *image); // Modify bimage color: grayscale +void ImageColorGrayscale(Image *image); // Modify image color: grayscale void ImageColorContrast(Image *image, float contrast); // Modify image color: contrast (-100 to 100) void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255) void GenTextureMipmaps(Texture2D texture); // Generate GPU mipmaps for a texture -- cgit v1.2.3 From d042ed52fac5feac426f7aac1cc3e7c3e8c14b16 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 21 Feb 2016 16:19:40 +0100 Subject: Updated --- src/resources | Bin 107204 -> 107204 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/resources b/src/resources index b41637ff..6fc578e0 100644 Binary files a/src/resources and b/src/resources differ -- cgit v1.2.3 From 0dfc7fffff68b0bfafd30a86fb322073daf7fc0e Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 23 Feb 2016 00:57:50 +0100 Subject: Removed a couple of TODOs --- src/gestures.c | 2 -- src/rlgl.c | 1 - 2 files changed, 3 deletions(-) diff --git a/src/gestures.c b/src/gestures.c index 3638f23e..e615c06d 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -155,8 +155,6 @@ void ProcessGestureEvent(GestureEvent event) dragDistance = Vector2Distance(touchDownPosition, touchUpPosition); dragIntensity = dragDistance/(float)((GetCurrentTime() - swipeTime)); - // TODO: Make getures detection resolution independant - startMoving = false; // Detect GESTURE_SWIPE diff --git a/src/rlgl.c b/src/rlgl.c index 5f8a5ea1..8ea7d0f2 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1611,7 +1611,6 @@ void rlglInitGraphics(int offsetX, int offsetY, int width, int height) } // Get world coordinates from screen coordinates -// TODO: It doesn't work! It drives me crazy! // NOTE: Using global variables: screenWidth, screenHeight Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view) { -- cgit v1.2.3