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 000000000..bed7c94d3 --- /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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 literal 0 HcmV?d00001 diff --git a/examples/physics_friction.c b/examples/physics_friction.c new file mode 100644 index 000000000..28d3c4b8c --- /dev/null +++ b/examples/physics_friction.c @@ -0,0 +1,136 @@ +/******************************************************************************************* +* +* Physac - Physics friction +* +* 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 friction"); + 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) + 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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 = 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 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYU_8XZ#=yWJp1k%11B0EAr;B4qMO<=9#KI5r z6(2Dk){x+ByeNR3V4T%JCMQAgM~2YDRXcWK8Rhi zr|rN7?#7Ff6E3>gN--@~G{8bQY!{Gt+t8!74W~nQLENwrryD>{xQxSnJ#7a*K%5YQ z&j|^VysvRO;8yE_|NsAQlsb3fghfV^>=U<~cL!DdIuE;BD=glbYr^8@oPa@O$S}R= zt&W*HX`+CjOS!{_uXQVKDmTq+UEl7ZZCSI|*2y-k>YLchxeA#VAIs|A#b$(nV#C_C zoLRFMZ9n{B>(s2d+HiQZKRgw@LCcsN$t>ea{{7Wa5^Do|*`5wj;3-zr?WdFZ)#gtFXT!~T0W)Su`l zT@?;$e))$(8f5p?VqBD|S4^5)x^kF1ehgODlX2L!)v2x+NrKkTcT&ccot=oy( zC2i87RtiT-Bv!~SRIqkzY+T#i;GbuarknDAQ9Gw;^_~-Hf|C>2qw}k`M95-fmqrf8 znp~xrB4*V-IlCjfnx{0TPqI>Y@}?ZSzZG(29mJm3~du`DTF!lJh8_QbD;l=_7} zJ3RY;ytvQAgD*Z^V2OOV(joEfEqDBKb|uKTq{sG)?Z=i|p0qQl=0+{DR=DzJ=flrh zX4MHvSEe-YYz$aDnL5`_Mgh!`8&c$NZBMmObEK#1t7qR7710$z|EzCxn&o2Rm(hJ2UQ;$994O({bj~SMd0cQ6XuEvXeCo-a> zF#;Z%V;4ko^ynRw^3B2K3S}b}kJx3cdw6=TT;5W!a(T*13BB(Vq-Jh0V4pATmhRxj zJqKzGMxtXRSn^!ZWpSIH(2KqBa+GJf$jFoxEFTnE18?lAKqcpbx)$rvO(hO5w(z_^rQ_t8K+lY zyz9jMU+H)AjF#rJYZVNi__6!&?y7uImiT&wfUww+w(A)Sjj<=F1p*5)IK>PdJ60Dr z=<#KrcqDW@U3^nqlGM8`Jyl+Ry}ND~+-$wW**McZPrY|Sbw=vDjBhg7qH3O^!{^`) z8%j9}dXGJpUaGG4W25Pwm$JD_euzIY^Rn{U@g-?CqvQ7ODB1SLcOQDid@$4I1w{wX z-CbhMJFgf`4k_-)6~DBHxhdDJ`9>sDk&v+FT!EDG157=aIFyg>SNNY8+^^TSesQCW z+lxB)=aXNV*L-Zz-s5JivUn;uRiF_J`veqrF*mJG?DX!7di2Al;VfU0)WIjOn0K~b z`=@&S?~OZb#@!QUZ(OM?;5$OriIb8fZUBA%@LzHVl+pL<_K8xd^9bLriIb80Pa4a5u-KbXiYgRrshdhlh*-AQ z$u#^4P_>#h4LylEHzaWMoNMS&n{-h?;)TGCA8m~b-+sN&#~$FGWul5P+sq)SXkf)` zG|LCW9FQMD(G40)mYs0%2=2+OTa1#v%$PF)&{6Qi`YfPf=3t0dkv#?-fCo+e;2+~1 zb;4*wj3!4|gJd)H=;Kcj<`5uFoL>=6%gA_*e$V13r)p4(Q*OYOhO|@OGjc$$A*aymprR)`+eWN zxdz-{$4+EOGj+}3S!}GZxD#_r6Lf5&Ay4rD)4abO6$VmIFoslM`&1SyI@}hBSO}gZ zI0n@S8-GJ^Uxk@0cbJ>>y{sgvt%b+G(kiSI_r;9 zLJ3=nNhrpyDA+~{(AFMng~gpX_V>9tgZDtOAtDxy)fNw)Tw3-DxgbaODdF8kwBFa4 zz;WiXx}L-&J*O)ZSIwL7^2jW9=hs5ymG13Z>_nr+)Xiplif-;x1^D3*LP)4HFYv57oDIurGGB z!!>wpAjPzWw^5XfaA`T3If>YG3@QY%ZykiBM7|Rl6b{5QnCgG*dF0$6!N9=4;OXk; Jvd$@?2>_CiT5$jX literal 0 HcmV?d00001 diff --git a/examples/physics_restitution.c b/examples/physics_restitution.c new file mode 100644 index 000000000..3543db69c --- /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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 NGwCotN2yYR@_jeQxM81{xm^G}J-8SL|x_+@{ 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