Physac redesign (3/3)
Finally, physics update is handled in main thread using steps to get accuracy in collisions detection instead of moving it to a new thread. Examples are finished as simple and clear as I could. Finally, physac module is MORE simpler than in the first version, calculation everything by the same way for both types of physic objects. I tryed to add rotated physics a couple of times but I didn't get anything good to get a base to improve it. Maybe for the next version... No bugs or strange behaviours found during testing.
This commit is contained in:
parent
c453ac8265
commit
60223a358b
@ -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);
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 15 KiB |
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
BIN
examples/physics_forces.png
Normal file
BIN
examples/physics_forces.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
49
src/physac.c
49
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]->rigidbody.enabled)
|
||||
{
|
||||
// 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);
|
||||
|
||||
// Check if physic object is in force range
|
||||
if(distanceLength <= radius)
|
||||
{
|
||||
// Normalize force direction
|
||||
distance.x /= distanceLength;
|
||||
distance.y /= -distanceLength;
|
||||
if(physicObjects[i]->collider.type == COLLIDER_RECTANGLE)
|
||||
{
|
||||
distance.x += physicObjects[i]->transform.scale.x/2;
|
||||
distance.y += physicObjects[i]->transform.scale.y/2;
|
||||
}
|
||||
|
||||
// Apply force to the physic object
|
||||
ApplyForce(physicObjects[i], (Vector2){ distance.x*force, distance.y*force });
|
||||
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 final force
|
||||
Vector2 finalForce = { distance.x*force, distance.y*force };
|
||||
|
||||
// Apply force to the physic object
|
||||
ApplyForce(physicObjects[i], finalForce);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user