From e8630c78d069a1cba50b1a78108663ebc19e5b9b Mon Sep 17 00:00:00 2001 From: victorfisac Date: Mon, 21 Nov 2016 20:31:30 +0100 Subject: [PATCH] Added new Physac examples --- examples/physics_demo.c | 122 +++++++++++++++++++++++++++ examples/physics_demo.png | Bin 0 -> 23466 bytes examples/physics_friction.c | 136 +++++++++++++++++++++++++++++++ examples/physics_friction.png | Bin 0 -> 18150 bytes examples/physics_movement.c | 122 +++++++++++++++++++++++++++ examples/physics_movement.png | Bin 0 -> 15947 bytes examples/physics_restitution.c | 115 ++++++++++++++++++++++++++ examples/physics_restitution.png | Bin 0 -> 17833 bytes examples/physics_shatter.c | 107 ++++++++++++++++++++++++ examples/physics_shatter.png | Bin 0 -> 23197 bytes 10 files changed, 602 insertions(+) create mode 100644 examples/physics_demo.c create mode 100644 examples/physics_demo.png create mode 100644 examples/physics_friction.c create mode 100644 examples/physics_friction.png create mode 100644 examples/physics_movement.c create mode 100644 examples/physics_movement.png create mode 100644 examples/physics_restitution.c create mode 100644 examples/physics_restitution.png create mode 100644 examples/physics_shatter.c create mode 100644 examples/physics_shatter.png diff --git a/examples/physics_demo.c b/examples/physics_demo.c new file mode 100644 index 00000000..bed7c94d --- /dev/null +++ b/examples/physics_demo.c @@ -0,0 +1,122 @@ +/******************************************************************************************* +* +* Physac - Physics demo +* +* NOTE: Physac requires multi-threading, when InitPhysics() a second thread is created to manage physics calculations. +* The file pthreadGC2.dll is required to run the program; you can find it in 'src\external' +* +* Copyright (c) 2016 Victor Fisac +* +********************************************************************************************/ + +#include "raylib.h" + +#define PHYSAC_IMPLEMENTATION +#include "..\src\physac.h" + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + SetConfigFlags(FLAG_MSAA_4X_HINT); + InitWindow(screenWidth, screenHeight, "Physac [raylib] - Physics demo"); + SetTargetFPS(60); + + // Physac logo drawing position + int logoX = screenWidth - MeasureText("Physac", 30) - 10; + int logoY = 15; + + // Initialize physics and default physics bodies + InitPhysics(); + + // Create floor rectangle physics body + PhysicsBody floor = CreatePhysicsBodyRectangle((Vector2){ screenWidth/2, screenHeight }, 500, 100, 10); + floor->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) + + // Create obstacle circle physics body + PhysicsBody circle = CreatePhysicsBodyCircle((Vector2){ screenWidth/2, screenHeight/2 }, 45, 10); + circle->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + if (IsKeyPressed('R')) // Reset physics input + { + ResetPhysics(); + + floor = CreatePhysicsBodyRectangle((Vector2){ screenWidth/2, screenHeight }, 500, 100, 10); + floor->enabled = false; + + circle = CreatePhysicsBodyCircle((Vector2){ screenWidth/2, screenHeight/2 }, 45, 10); + circle->enabled = false; + } + + // Physics body creation inputs + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) CreatePhysicsBodyPolygon(GetMousePosition(), GetRandomValue(20, 80), GetRandomValue(3, 8), 10); + else if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) CreatePhysicsBodyCircle(GetMousePosition(), GetRandomValue(10, 45), 10); + + // Destroy falling physics bodies + int bodiesCount = GetPhysicsBodiesCount(); + for (int i = bodiesCount - 1; i >= 0; i--) + { + PhysicsBody body = GetPhysicsBody(i); + if (body != NULL && (body->position.y > screenHeight*2)) DestroyPhysicsBody(body); + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(BLACK); + + DrawFPS(screenWidth - 90, screenHeight - 30); + + // Draw created physics bodies + bodiesCount = GetPhysicsBodiesCount(); + for (int i = 0; i < bodiesCount; i++) + { + PhysicsBody body = GetPhysicsBody(i); + + if (body != NULL) + { + int vertexCount = GetPhysicsShapeVerticesCount(i); + for (int j = 0; j < vertexCount; j++) + { + // Get physics bodies shape vertices to draw lines + // Note: GetPhysicsShapeVertex() already calculates rotation transformations + Vector2 vertexA = GetPhysicsShapeVertex(body, j); + + int jj = (((j + 1) < vertexCount) ? (j + 1) : 0); // Get next vertex or first to close the shape + Vector2 vertexB = GetPhysicsShapeVertex(body, jj); + + DrawLineV(vertexA, vertexB, GREEN); // Draw a line between two vertex positions + } + } + } + + DrawText("Left mouse button to create a polygon", 10, 10, 10, WHITE); + DrawText("Right mouse button to create a circle", 10, 25, 10, WHITE); + DrawText("Press 'R' to reset example", 10, 40, 10, WHITE); + + DrawText("Physac", logoX, logoY, 30, WHITE); + DrawText("Powered by", logoX + 50, logoY - 7, 10, WHITE); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + ClosePhysics(); // Unitialize physics + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/physics_demo.png b/examples/physics_demo.png new file mode 100644 index 0000000000000000000000000000000000000000..12dc7e724c52ec20a5310c24c856bb2aa5b58d6b GIT binary patch literal 23466 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 = false; // Disable body state to convert it to static (no dynamics, but collisions) + PhysicsBody wall = CreatePhysicsBodyRectangle((Vector2){ screenWidth/2, screenHeight*0.8f }, 10, 80, 10); + wall->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) + + // Create left ramp physics body + PhysicsBody rectLeft = CreatePhysicsBodyRectangle((Vector2){ 25, screenHeight - 5 }, 250, 250, 10); + rectLeft->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) + SetPhysicsBodyRotation(rectLeft, 30*DEG2RAD); + + // Create right ramp physics body + PhysicsBody rectRight = CreatePhysicsBodyRectangle((Vector2){ screenWidth - 25, screenHeight - 5 }, 250, 250, 10); + rectRight->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) + SetPhysicsBodyRotation(rectRight, 330*DEG2RAD); + + // Create dynamic physics bodies + PhysicsBody bodyA = CreatePhysicsBodyRectangle((Vector2){ 35, screenHeight*0.6f }, 40, 40, 10); + bodyA->staticFriction = 0.1f; + bodyA->dynamicFriction = 0.1f; + SetPhysicsBodyRotation(bodyA, 30*DEG2RAD); + + PhysicsBody bodyB = CreatePhysicsBodyRectangle((Vector2){ screenWidth - 35, screenHeight*0.6f }, 40, 40, 10); + bodyB->staticFriction = 1; + bodyB->dynamicFriction = 1; + SetPhysicsBodyRotation(bodyB, 330*DEG2RAD); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + if (IsKeyPressed('R')) // Reset physics input + { + // Reset dynamic physics bodies position, velocity and rotation + bodyA->position = (Vector2){ 35, screenHeight*0.6f }; + bodyA->velocity = (Vector2){ 0, 0 }; + bodyA->angularVelocity = 0; + SetPhysicsBodyRotation(bodyA, 30*DEG2RAD); + + bodyB->position = (Vector2){ screenWidth - 35, screenHeight*0.6f }; + bodyB->velocity = (Vector2){ 0, 0 }; + bodyB->angularVelocity = 0; + SetPhysicsBodyRotation(bodyB, 330*DEG2RAD); + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(BLACK); + + DrawFPS(screenWidth - 90, screenHeight - 30); + + // Draw created physics bodies + int bodiesCount = GetPhysicsBodiesCount(); + for (int i = 0; i < bodiesCount; i++) + { + PhysicsBody body = GetPhysicsBody(i); + + if (body != NULL) + { + int vertexCount = GetPhysicsShapeVerticesCount(i); + for (int j = 0; j < vertexCount; j++) + { + // Get physics bodies shape vertices to draw lines + // Note: GetPhysicsShapeVertex() already calculates rotation transformations + Vector2 vertexA = GetPhysicsShapeVertex(body, j); + + int jj = (((j + 1) < vertexCount) ? (j + 1) : 0); // Get next vertex or first to close the shape + Vector2 vertexB = GetPhysicsShapeVertex(body, jj); + + DrawLineV(vertexA, vertexB, GREEN); // Draw a line between two vertex positions + } + } + } + + DrawRectangle(0, screenHeight - 49, screenWidth, 49, BLACK); + + DrawText("Friction amount", (screenWidth - MeasureText("Friction amount", 30))/2, 75, 30, WHITE); + DrawText("0.1", bodyA->position.x - MeasureText("0.1", 20)/2, bodyA->position.y - 7, 20, WHITE); + DrawText("1", bodyB->position.x - MeasureText("1", 20)/2, bodyB->position.y - 7, 20, WHITE); + + DrawText("Press 'R' to reset example", 10, 10, 10, WHITE); + + DrawText("Physac", logoX, logoY, 30, WHITE); + DrawText("Powered by", logoX + 50, logoY - 7, 10, WHITE); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + ClosePhysics(); // Unitialize physics + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/physics_friction.png b/examples/physics_friction.png new file mode 100644 index 0000000000000000000000000000000000000000..e791ec2b901486fb5b5d49de1d93f7ba3c92bd3e GIT binary patch literal 18150 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 M**+ep-5Cl019djzkpKVy literal 0 HcmV?d00001 diff --git a/examples/physics_movement.c b/examples/physics_movement.c new file mode 100644 index 00000000..ca18f3df --- /dev/null +++ b/examples/physics_movement.c @@ -0,0 +1,122 @@ +/******************************************************************************************* +* +* Physac - Physics movement +* +* NOTE: Physac requires multi-threading, when InitPhysics() a second thread is created to manage physics calculations. +* The file pthreadGC2.dll is required to run the program; you can find it in 'src\external' +* +* Copyright (c) 2016 Victor Fisac +* +********************************************************************************************/ + +#include "raylib.h" + +#define PHYSAC_IMPLEMENTATION +#include "..\src\physac.h" + +#define VELOCITY 0.5f + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + SetConfigFlags(FLAG_MSAA_4X_HINT); + InitWindow(screenWidth, screenHeight, "Physac [raylib] - Physics movement"); + SetTargetFPS(60); + + // Physac logo drawing position + int logoX = screenWidth - MeasureText("Physac", 30) - 10; + int logoY = 15; + + // Initialize physics and default physics bodies + InitPhysics(); + + // Create floor and walls rectangle physics body + PhysicsBody floor = CreatePhysicsBodyRectangle((Vector2){ screenWidth/2, screenHeight }, screenWidth, 100, 10); + PhysicsBody platformLeft = CreatePhysicsBodyRectangle((Vector2){ screenWidth*0.25f, screenHeight*0.6f }, screenWidth*0.25f, 10, 10); + PhysicsBody platformRight = CreatePhysicsBodyRectangle((Vector2){ screenWidth*0.75f, screenHeight*0.6f }, screenWidth*0.25f, 10, 10); + PhysicsBody wallLeft = CreatePhysicsBodyRectangle((Vector2){ -5, screenHeight/2 }, 10, screenHeight, 10); + PhysicsBody wallRight = CreatePhysicsBodyRectangle((Vector2){ screenWidth + 5, screenHeight/2 }, 10, screenHeight, 10); + + // Disable dynamics to floor and walls physics bodies + floor->enabled = false; + platformLeft->enabled = false; + platformRight->enabled = false; + wallLeft->enabled = false; + wallRight->enabled = false; + + // Create movement physics body + PhysicsBody body = CreatePhysicsBodyRectangle((Vector2){ screenWidth/2, screenHeight/2 }, 50, 50, 1); + body->freezeOrient = true; // Constrain body rotation to avoid little collision torque amounts + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + if (IsKeyPressed('R')) // Reset physics input + { + // Reset movement physics body position, velocity and rotation + body->position = (Vector2){ screenWidth/2, screenHeight/2 }; + body->velocity = (Vector2){ 0, 0 }; + SetPhysicsBodyRotation(body, 0); + } + + // Horizontal movement input + if (IsKeyDown(KEY_RIGHT)) body->velocity.x = VELOCITY; + else if (IsKeyDown(KEY_LEFT)) body->velocity.x = -VELOCITY; + + // Vertical movement input checking if player physics body is grounded + if (IsKeyDown(KEY_UP) && body->isGrounded) body->velocity.y = -VELOCITY*4; + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(BLACK); + + DrawFPS(screenWidth - 90, screenHeight - 30); + + // Draw created physics bodies + int bodiesCount = GetPhysicsBodiesCount(); + for (int i = 0; i < bodiesCount; i++) + { + PhysicsBody body = GetPhysicsBody(i); + + int vertexCount = GetPhysicsShapeVerticesCount(i); + for (int j = 0; j < vertexCount; j++) + { + // Get physics bodies shape vertices to draw lines + // Note: GetPhysicsShapeVertex() already calculates rotation transformations + Vector2 vertexA = GetPhysicsShapeVertex(body, j); + + int jj = (((j + 1) < vertexCount) ? (j + 1) : 0); // Get next vertex or first to close the shape + Vector2 vertexB = GetPhysicsShapeVertex(body, jj); + + DrawLineV(vertexA, vertexB, GREEN); // Draw a line between two vertex positions + } + } + + DrawText("Use 'ARROWS' to move player", 10, 10, 10, WHITE); + DrawText("Press 'R' to reset example", 10, 30, 10, WHITE); + + DrawText("Physac", logoX, logoY, 30, WHITE); + DrawText("Powered by", logoX + 50, logoY - 7, 10, WHITE); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + ClosePhysics(); // Unitialize physics + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/physics_movement.png b/examples/physics_movement.png new file mode 100644 index 0000000000000000000000000000000000000000..a88a7d79facfbfb5ca1a91b74cf02ebfd3f11847 GIT binary patch literal 15947 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 aJYcu*6}QKoNq|J+z_O)Y9v9r`iT?wVkXms7 literal 0 HcmV?d00001 diff --git a/examples/physics_restitution.c b/examples/physics_restitution.c new file mode 100644 index 00000000..3543db69 --- /dev/null +++ b/examples/physics_restitution.c @@ -0,0 +1,115 @@ +/******************************************************************************************* +* +* Physac - Physics restitution +* +* NOTE: Physac requires multi-threading, when InitPhysics() a second thread is created to manage physics calculations. +* The file pthreadGC2.dll is required to run the program; you can find it in 'src\external' +* +* Copyright (c) 2016 Victor Fisac +* +********************************************************************************************/ + +#include "raylib.h" + +#define PHYSAC_IMPLEMENTATION +#include "..\src\physac.h" + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + SetConfigFlags(FLAG_MSAA_4X_HINT); + InitWindow(screenWidth, screenHeight, "Physac [raylib] - Physics restitution"); + SetTargetFPS(60); + + // Physac logo drawing position + int logoX = screenWidth - MeasureText("Physac", 30) - 10; + int logoY = 15; + + // Initialize physics and default physics bodies + InitPhysics(); + + // Create floor rectangle physics body + PhysicsBody floor = CreatePhysicsBodyRectangle((Vector2){ screenWidth/2, screenHeight }, screenWidth, 100, 10); + floor->enabled = false; // Disable body state to convert it to static (no dynamics, but collisions) + floor->restitution = 1; + + // Create circles physics body + PhysicsBody circleA = CreatePhysicsBodyCircle((Vector2){ screenWidth*0.25f, screenHeight/2 }, 30, 10); + circleA->restitution = 0; + PhysicsBody circleB = CreatePhysicsBodyCircle((Vector2){ screenWidth*0.5f, screenHeight/2 }, 30, 10); + circleB->restitution = 0.5f; + PhysicsBody circleC = CreatePhysicsBodyCircle((Vector2){ screenWidth*0.75f, screenHeight/2 }, 30, 10); + circleC->restitution = 1; + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + if (IsKeyPressed('R')) // Reset physics input + { + // Reset circles physics bodies position and velocity + circleA->position = (Vector2){ screenWidth*0.25f, screenHeight/2 }; + circleA->velocity = (Vector2){ 0, 0 }; + circleB->position = (Vector2){ screenWidth*0.5f, screenHeight/2 }; + circleB->velocity = (Vector2){ 0, 0 }; + circleC->position = (Vector2){ screenWidth*0.75f, screenHeight/2 }; + circleC->velocity = (Vector2){ 0, 0 }; + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(BLACK); + + DrawFPS(screenWidth - 90, screenHeight - 30); + + // Draw created physics bodies + int bodiesCount = GetPhysicsBodiesCount(); + for (int i = 0; i < bodiesCount; i++) + { + PhysicsBody body = GetPhysicsBody(i); + + int vertexCount = GetPhysicsShapeVerticesCount(i); + for (int j = 0; j < vertexCount; j++) + { + // Get physics bodies shape vertices to draw lines + // Note: GetPhysicsShapeVertex() already calculates rotation transformations + Vector2 vertexA = GetPhysicsShapeVertex(body, j); + + int jj = (((j + 1) < vertexCount) ? (j + 1) : 0); // Get next vertex or first to close the shape + Vector2 vertexB = GetPhysicsShapeVertex(body, jj); + + DrawLineV(vertexA, vertexB, GREEN); // Draw a line between two vertex positions + } + } + + DrawText("Restitution amount", (screenWidth - MeasureText("Restitution amount", 30))/2, 75, 30, WHITE); + DrawText("0", circleA->position.x - MeasureText("0", 20)/2, circleA->position.y - 7, 20, WHITE); + DrawText("0.5", circleB->position.x - MeasureText("0.5", 20)/2, circleB->position.y - 7, 20, WHITE); + DrawText("1", circleC->position.x - MeasureText("1", 20)/2, circleC->position.y - 7, 20, WHITE); + + DrawText("Press 'R' to reset example", 10, 10, 10, WHITE); + + DrawText("Physac", logoX, logoY, 30, WHITE); + DrawText("Powered by", logoX + 50, logoY - 7, 10, WHITE); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + ClosePhysics(); // Unitialize physics + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/physics_restitution.png b/examples/physics_restitution.png new file mode 100644 index 0000000000000000000000000000000000000000..8ec4b3f3270063659472bd5e21ffb39f29af6303 GIT binary patch literal 17833 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 0; i--) + { + PhysicsBody currentBody = GetPhysicsBody(i); + if (currentBody != NULL) PhysicsShatter(currentBody, GetMousePosition(), 10/currentBody->inverseMass); + } + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(BLACK); + + // Draw created physics bodies + int bodiesCount = GetPhysicsBodiesCount(); + for (int i = 0; i < bodiesCount; i++) + { + PhysicsBody currentBody = GetPhysicsBody(i); + + int vertexCount = GetPhysicsShapeVerticesCount(i); + for (int j = 0; j < vertexCount; j++) + { + // Get physics bodies shape vertices to draw lines + // Note: GetPhysicsShapeVertex() already calculates rotation transformations + Vector2 vertexA = GetPhysicsShapeVertex(currentBody, j); + + int jj = (((j + 1) < vertexCount) ? (j + 1) : 0); // Get next vertex or first to close the shape + Vector2 vertexB = GetPhysicsShapeVertex(currentBody, jj); + + DrawLineV(vertexA, vertexB, GREEN); // Draw a line between two vertex positions + } + } + + DrawText("Left mouse button in polygon area to shatter body\nPress 'R' to reset example", 10, 10, 10, WHITE); + + DrawText("Physac", logoX, logoY, 30, WHITE); + DrawText("Powered by", logoX + 50, logoY - 7, 10, WHITE); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + ClosePhysics(); // Unitialize physics + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/physics_shatter.png b/examples/physics_shatter.png new file mode 100644 index 0000000000000000000000000000000000000000..68f9a1b7d2ea6a0043828131342c6e2f641e858e GIT binary patch literal 23197 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 literal 0 HcmV?d00001