diff --git a/examples/physics_basic_rigidbody.c b/examples/physics_basic_rigidbody.c index f0edba723..917813ad8 100644 --- a/examples/physics_basic_rigidbody.c +++ b/examples/physics_basic_rigidbody.c @@ -65,7 +65,7 @@ int main() if (IsKeyDown('A')) rectangle->rigidbody.velocity.x = -MOVE_VELOCITY; else if (IsKeyDown('D')) rectangle->rigidbody.velocity.x = MOVE_VELOCITY; - // Check player 2 movement inputs + // Check square movement inputs if (IsKeyDown(KEY_UP) && square->rigidbody.isGrounded) square->rigidbody.velocity.y = JUMP_VELOCITY; if (IsKeyDown(KEY_LEFT)) square->rigidbody.velocity.x = -MOVE_VELOCITY; else if (IsKeyDown(KEY_RIGHT)) square->rigidbody.velocity.x = MOVE_VELOCITY; @@ -80,17 +80,20 @@ int main() ClearBackground(RAYWHITE); - // Convert transform values to rectangle data type variable - DrawRectangleRec(TransformToRectangle(floor->transform), DARKGRAY); + // Draw floor, roof and walls rectangles + DrawRectangleRec(TransformToRectangle(floor->transform), DARKGRAY); // Convert transform values to rectangle data type variable DrawRectangleRec(TransformToRectangle(leftWall->transform), DARKGRAY); DrawRectangleRec(TransformToRectangle(rightWall->transform), DARKGRAY); DrawRectangleRec(TransformToRectangle(roof->transform), DARKGRAY); + // Draw middle platform rectangle DrawRectangleRec(TransformToRectangle(platform->transform), DARKGRAY); + // Draw physic objects DrawRectangleRec(TransformToRectangle(rectangle->transform), RED); DrawRectangleRec(TransformToRectangle(square->transform), BLUE); + // Draw collider lines if debug is enabled if (isDebug) { DrawRectangleLines(floor->collider.bounds.x, floor->collider.bounds.y, floor->collider.bounds.width, floor->collider.bounds.height, GREEN); diff --git a/examples/physics_basic_rigidbody.png b/examples/physics_basic_rigidbody.png index 3d691637b..52f265acf 100644 Binary files a/examples/physics_basic_rigidbody.png and b/examples/physics_basic_rigidbody.png differ diff --git a/examples/physics_forces.c b/examples/physics_forces.c index 2afd14ee3..74b40d57e 100644 --- a/examples/physics_forces.c +++ b/examples/physics_forces.c @@ -12,9 +12,12 @@ #include "raylib.h" #include "math.h" -#define FORCE_AMOUNT 5.0f -#define FORCE_RADIUS 150 -#define LINE_LENGTH 100 +#define FORCE_AMOUNT 5.0f +#define FORCE_RADIUS 150 +#define LINE_LENGTH 75 +#define TRIANGLE_LENGTH 12 + +void DrawRigidbodyCircle(PhysicObject *obj, Color color); int main() { @@ -42,6 +45,7 @@ int main() } // Create circles physic objects + // NOTE: when creating circle physic objects, transform.scale must be { 0, 0 } and object radius must be defined in collider.radius and use this value to draw the circle. PhysicObject *circles[3]; for (int i = 0; i < 3; i++) { @@ -111,14 +115,23 @@ int main() // Draw force radius DrawCircleLines(mousePosition.x, mousePosition.y, FORCE_RADIUS, BLACK); - // Draw direction line + // Draw direction lines if (CheckCollisionPointCircle((Vector2){ rectangles[i]->transform.position.x + rectangles[i]->transform.scale.x/2, rectangles[i]->transform.position.y + rectangles[i]->transform.scale.y/2 }, mousePosition, FORCE_RADIUS)) { Vector2 direction = { rectangles[i]->transform.position.x + rectangles[i]->transform.scale.x/2 - mousePosition.x, rectangles[i]->transform.position.y + rectangles[i]->transform.scale.y/2 - mousePosition.y }; float angle = atan2l(direction.y, direction.x); - DrawLineV((Vector2){ rectangles[i]->transform.position.x + rectangles[i]->transform.scale.x/2, rectangles[i]->transform.position.y + rectangles[i]->transform.scale.y/2 }, - (Vector2){ rectangles[i]->transform.position.x + rectangles[i]->transform.scale.x/2 + (cos(angle)*LINE_LENGTH), rectangles[i]->transform.position.y + rectangles[i]->transform.scale.y/2 + (sin(angle)*LINE_LENGTH) }, BLACK); + // Calculate arrow start and end positions + Vector2 startPosition = { rectangles[i]->transform.position.x + rectangles[i]->transform.scale.x/2, rectangles[i]->transform.position.y + rectangles[i]->transform.scale.y/2 }; + Vector2 endPosition = { rectangles[i]->transform.position.x + rectangles[i]->transform.scale.x/2 + (cos(angle)*LINE_LENGTH), rectangles[i]->transform.position.y + rectangles[i]->transform.scale.y/2 + (sin(angle)*LINE_LENGTH) }; + + // Draw arrow line + DrawLineV(startPosition, endPosition, BLACK); + + // Draw arrow triangle + DrawTriangleLines((Vector2){ endPosition.x - cos(angle + 90*DEG2RAD)*LINE_LENGTH/TRIANGLE_LENGTH, endPosition.y - sin(angle + 90*DEG2RAD)*LINE_LENGTH/TRIANGLE_LENGTH }, + (Vector2){ endPosition.x + cos(angle + 90*DEG2RAD)*LINE_LENGTH/TRIANGLE_LENGTH, endPosition.y + sin(angle + 90*DEG2RAD)*LINE_LENGTH/TRIANGLE_LENGTH }, + (Vector2){ endPosition.x + cos(angle)*LINE_LENGTH/TRIANGLE_LENGTH*2, endPosition.y + sin(angle)*LINE_LENGTH/TRIANGLE_LENGTH*2 }, BLACK); } } @@ -131,14 +144,23 @@ int main() // Draw force radius DrawCircleLines(mousePosition.x, mousePosition.y, FORCE_RADIUS, BLACK); - // Draw direction line + // Draw direction lines if (CheckCollisionPointCircle((Vector2){ circles[i]->transform.position.x, circles[i]->transform.position.y }, mousePosition, FORCE_RADIUS)) { Vector2 direction = { circles[i]->transform.position.x - mousePosition.x, circles[i]->transform.position.y - mousePosition.y }; float angle = atan2l(direction.y, direction.x); - DrawLineV((Vector2){ circles[i]->transform.position.x, circles[i]->transform.position.y }, - (Vector2){ circles[i]->transform.position.x + (cos(angle)*LINE_LENGTH), circles[i]->transform.position.y + (sin(angle)*LINE_LENGTH) }, BLACK); + // Calculate arrow start and end positions + Vector2 startPosition = { circles[i]->transform.position.x, circles[i]->transform.position.y }; + Vector2 endPosition = { circles[i]->transform.position.x + (cos(angle)*LINE_LENGTH), circles[i]->transform.position.y + (sin(angle)*LINE_LENGTH) }; + + // Draw arrow line + DrawLineV(startPosition, endPosition, BLACK); + + // Draw arrow triangle + DrawTriangleLines((Vector2){ endPosition.x - cos(angle + 90*DEG2RAD)*LINE_LENGTH/TRIANGLE_LENGTH, endPosition.y - sin(angle + 90*DEG2RAD)*LINE_LENGTH/TRIANGLE_LENGTH }, + (Vector2){ endPosition.x + cos(angle + 90*DEG2RAD)*LINE_LENGTH/TRIANGLE_LENGTH, endPosition.y + sin(angle + 90*DEG2RAD)*LINE_LENGTH/TRIANGLE_LENGTH }, + (Vector2){ endPosition.x + cos(angle)*LINE_LENGTH/TRIANGLE_LENGTH*2, endPosition.y + sin(angle)*LINE_LENGTH/TRIANGLE_LENGTH*2 }, BLACK); } } diff --git a/examples/physics_forces.png b/examples/physics_forces.png new file mode 100644 index 000000000..832bdbd9e Binary files /dev/null and b/examples/physics_forces.png differ diff --git a/src/physac.c b/src/physac.c index 718a06bb4..e3f956bad 100644 --- a/src/physac.c +++ b/src/physac.c @@ -2,7 +2,7 @@ * * [physac] raylib physics module - Basic functions to apply physics to 2D objects * -* Copyright (c) 2015 Victor Fisac and Ramon Santamaria +* Copyright (c) 2016 Victor Fisac and Ramon Santamaria * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -75,10 +75,7 @@ void InitPhysics(Vector2 gravity) void UpdatePhysics() { // Reset all physic objects is grounded state - for (int i = 0; i < physicObjectsCount; i++) - { - if (physicObjects[i]->rigidbody.enabled) physicObjects[i]->rigidbody.isGrounded = false; - } + for (int i = 0; i < physicObjectsCount; i++) physicObjects[i]->rigidbody.isGrounded = false; for (int steps = 0; steps < PHYSICS_STEPS; steps++) { @@ -537,26 +534,32 @@ void ApplyForceAtPosition(Vector2 position, float force, float radius) { for(int i = 0; i < physicObjectsCount; i++) { - // Calculate direction and distance between force and physic object pposition - Vector2 distance = (Vector2){ physicObjects[i]->transform.position.x - position.x, physicObjects[i]->transform.position.y - position.y }; - - if(physicObjects[i]->collider.type == COLLIDER_RECTANGLE) + if(physicObjects[i]->rigidbody.enabled) { - distance.x += physicObjects[i]->transform.scale.x/2; - distance.y += physicObjects[i]->transform.scale.y/2; - } - - float distanceLength = Vector2Length(distance); - - // Check if physic object is in force range - if(distanceLength <= radius) - { - // Normalize force direction - distance.x /= distanceLength; - distance.y /= -distanceLength; + // Calculate direction and distance between force and physic object pposition + Vector2 distance = (Vector2){ physicObjects[i]->transform.position.x - position.x, physicObjects[i]->transform.position.y - position.y }; + + if(physicObjects[i]->collider.type == COLLIDER_RECTANGLE) + { + distance.x += physicObjects[i]->transform.scale.x/2; + distance.y += physicObjects[i]->transform.scale.y/2; + } + + float distanceLength = Vector2Length(distance); - // Apply force to the physic object - ApplyForce(physicObjects[i], (Vector2){ distance.x*force, distance.y*force }); + // Check if physic object is in force range + if(distanceLength <= radius) + { + // Normalize force direction + distance.x /= distanceLength; + distance.y /= -distanceLength; + + // Calculate final force + Vector2 finalForce = { distance.x*force, distance.y*force }; + + // Apply force to the physic object + ApplyForce(physicObjects[i], finalForce); + } } } } diff --git a/src/physac.h b/src/physac.h index c70dbbe21..37544686b 100644 --- a/src/physac.h +++ b/src/physac.h @@ -2,7 +2,7 @@ * * [physac] raylib physics module - Basic functions to apply physics to 2D objects * -* Copyright (c) 2015 Victor Fisac and Ramon Santamaria +* Copyright (c) 2016 Victor Fisac and Ramon Santamaria * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -44,8 +44,8 @@ typedef enum { COLLIDER_CIRCLE, COLLIDER_RECTANGLE } ColliderType; typedef struct Transform { Vector2 position; - float rotation; - Vector2 scale; + float rotation; // Radians (not used) + Vector2 scale; // Just for rectangle physic objects, for circle physic objects use collider radius and keep scale as { 0, 0 } } Transform; typedef struct Rigidbody { diff --git a/src/raylib.h b/src/raylib.h index a87b58da3..1782fef39 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -498,8 +498,8 @@ typedef enum { COLLIDER_CIRCLE, COLLIDER_RECTANGLE } ColliderType; typedef struct Transform { Vector2 position; - float rotation; - Vector2 scale; + float rotation; // Radians (not used) + Vector2 scale; // Just for rectangle physic objects, for circle physic objects use collider radius and keep scale as { 0, 0 } } Transform; typedef struct Rigidbody {