Redesigned physics module (IN PROGRESS)
physac modules is being redesigned. Physics base behaviour is done and it is composed by three steps: apply physics, resolve collisions and fix overlapping. A basic example is currently in progress. The next steps are try to add torque and unoriented physic collisions and implement physics basic functions to add forces. Rigidbody grounding state is automatically calculated and has a perfect result. Rigidbodies interacts well with each others. To achieve physics accuracy, UpdatePhysics() is called a number of times per frame. In a future, it should be changed to another thread and call it without any target frame restriction. Basic physics example has been redone (not finished) using the new module functions. Forces examples will be redone so I removed it from branch.
This commit is contained in:
parent
68088bc5be
commit
305efcf5ad
6 changed files with 418 additions and 539 deletions
|
@ -1,8 +1,8 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [physac] physics example - Basic rigidbody
|
||||
* raylib [physac] example - Basic rigidbody
|
||||
*
|
||||
* This example has been created using raylib 1.4 (www.raylib.com)
|
||||
* This example has been created using raylib 1.5 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
*
|
||||
* Copyright (c) 2016 Victor Fisac and Ramon Santamaria (@raysan5)
|
||||
|
@ -11,8 +11,8 @@
|
|||
|
||||
#include "raylib.h"
|
||||
|
||||
#define OBJECT_SIZE 50
|
||||
#define PLAYER_INDEX 0
|
||||
#define MOVE_VELOCITY 5
|
||||
#define JUMP_VELOCITY 35
|
||||
|
||||
int main()
|
||||
{
|
||||
|
@ -20,28 +20,45 @@ int main()
|
|||
//--------------------------------------------------------------------------------------
|
||||
int screenWidth = 800;
|
||||
int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [physics] example - basic rigidbody");
|
||||
|
||||
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}};
|
||||
AddCollider(PLAYER_INDEX, (Collider){true, COLLIDER_RECTANGLE, (Rectangle){player.position.x, player.position.y, player.scale.x, player.scale.y}, 0});
|
||||
AddRigidbody(PLAYER_INDEX, (Rigidbody){true, 1.0f, (Vector2){0, 0}, (Vector2){0, 0}, false, false, true, 0.5f, 1.0f});
|
||||
|
||||
// Floor initialization
|
||||
// NOTE: floor doesn't need a rigidbody because it's a static physic object, just a collider to collide with other dynamic colliders (with rigidbody)
|
||||
Transform floor = (Transform){(Vector2){0, screenHeight * 0.8f}, 0.0f, (Vector2){screenWidth, screenHeight * 0.2f}};
|
||||
AddCollider(PLAYER_INDEX + 1, (Collider){true, COLLIDER_RECTANGLE, (Rectangle){floor.position.x, floor.position.y, floor.scale.x, floor.scale.y}, 0});
|
||||
|
||||
// Object properties initialization
|
||||
float moveSpeed = 6.0f;
|
||||
float jumpForce = 5.0f;
|
||||
|
||||
bool physicsDebug = false;
|
||||
InitWindow(screenWidth, screenHeight, "raylib [physac] example - basic rigidbody");
|
||||
InitPhysics(); // Initialize physics module
|
||||
|
||||
SetTargetFPS(60);
|
||||
|
||||
// Debug variables
|
||||
bool isDebug = false;
|
||||
|
||||
// Player physic object
|
||||
PhysicObject *player = CreatePhysicObject((Vector2){ screenWidth*0.25f, screenHeight/2 }, 0.0f, (Vector2){ 50, 50 });
|
||||
player->rigidbody.enabled = true; // Enable physic object rigidbody behaviour
|
||||
player->rigidbody.applyGravity = true;
|
||||
player->rigidbody.friction = 0.3f;
|
||||
player->collider.enabled = true; // Enable physic object collisions detection
|
||||
|
||||
// Player physic object
|
||||
PhysicObject *player2 = CreatePhysicObject((Vector2){ screenWidth*0.75f, screenHeight/2 }, 0.0f, (Vector2){ 50, 50 });
|
||||
player2->rigidbody.enabled = true;
|
||||
player2->rigidbody.applyGravity = true;
|
||||
player2->rigidbody.friction = 0.1f;
|
||||
player2->collider.enabled = true;
|
||||
|
||||
// Floor physic object
|
||||
PhysicObject *floor = CreatePhysicObject((Vector2){ screenWidth/2, screenHeight*0.95f }, 0.0f, (Vector2){ screenWidth*0.9f, 100 });
|
||||
floor->collider.enabled = true; // Enable just physic object collisions detection
|
||||
|
||||
// Left wall physic object
|
||||
PhysicObject *leftWall = CreatePhysicObject((Vector2){ 0.0f, screenHeight/2 }, 0.0f, (Vector2){ screenWidth*0.1f, screenHeight });
|
||||
leftWall->collider.enabled = true;
|
||||
|
||||
// Right wall physic object
|
||||
PhysicObject *rightWall = CreatePhysicObject((Vector2){ screenWidth, screenHeight/2 }, 0.0f, (Vector2){ screenWidth*0.1f, screenHeight });
|
||||
rightWall->collider.enabled = true;
|
||||
|
||||
// Platform physic objectdd
|
||||
PhysicObject *platform = CreatePhysicObject((Vector2){ screenWidth/2, screenHeight*0.7f }, 0.0f, (Vector2){ screenWidth*0.25f, 20 });
|
||||
platform->collider.enabled = true;
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
|
@ -49,35 +66,22 @@ int main()
|
|||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdatePhysics(); // Update all created physic objects
|
||||
|
||||
// Update object physics
|
||||
// NOTE: all physics detections and reactions are calculated in ApplyPhysics() function (You will live happier :D)
|
||||
ApplyPhysics(PLAYER_INDEX, &player.position);
|
||||
// Check debug switch input
|
||||
if (IsKeyPressed('P')) isDebug = !isDebug;
|
||||
|
||||
// Check jump button input
|
||||
if (IsKeyDown(KEY_SPACE) && GetRigidbody(PLAYER_INDEX).isGrounded)
|
||||
{
|
||||
// Reset object Y velocity to avoid double jumping cases but keep the same X velocity that it already has
|
||||
SetRigidbodyVelocity(PLAYER_INDEX, (Vector2){GetRigidbody(PLAYER_INDEX).velocity.x, 0});
|
||||
|
||||
// Add jumping force in Y axis
|
||||
AddRigidbodyForce(PLAYER_INDEX, (Vector2){0, jumpForce});
|
||||
}
|
||||
// Check player movement inputs
|
||||
if (IsKeyDown('W') && player->rigidbody.isGrounded) player->rigidbody.velocity.y = JUMP_VELOCITY;
|
||||
|
||||
// Check movement buttons input
|
||||
if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D))
|
||||
{
|
||||
// Set rigidbody velocity in X based on moveSpeed value and apply the same Y velocity that it already has
|
||||
SetRigidbodyVelocity(PLAYER_INDEX, (Vector2){moveSpeed, GetRigidbody(PLAYER_INDEX).velocity.y});
|
||||
}
|
||||
else if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A))
|
||||
{
|
||||
// Set rigidbody velocity in X based on moveSpeed negative value and apply the same Y velocity that it already has
|
||||
SetRigidbodyVelocity(PLAYER_INDEX, (Vector2){-moveSpeed, GetRigidbody(PLAYER_INDEX).velocity.y});
|
||||
}
|
||||
if (IsKeyDown('A')) player->rigidbody.velocity.x = -MOVE_VELOCITY;
|
||||
else if (IsKeyDown('D')) player->rigidbody.velocity.x = MOVE_VELOCITY;
|
||||
|
||||
// Check debug mode toggle button input
|
||||
if (IsKeyPressed(KEY_P)) physicsDebug = !physicsDebug;
|
||||
// Check player 2 movement inputs
|
||||
if (IsKeyDown(KEY_UP) && player2->rigidbody.isGrounded) player2->rigidbody.velocity.y = JUMP_VELOCITY;
|
||||
|
||||
if (IsKeyDown(KEY_LEFT)) player2->rigidbody.velocity.x = -MOVE_VELOCITY;
|
||||
else if (IsKeyDown(KEY_RIGHT)) player2->rigidbody.velocity.x = MOVE_VELOCITY;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
|
@ -86,28 +90,28 @@ int main()
|
|||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Draw information
|
||||
DrawText("Use LEFT / RIGHT to MOVE and SPACE to JUMP", (screenWidth - MeasureText("Use LEFT / RIGHT to MOVE and SPACE to JUMP", 20)) / 2, screenHeight * 0.20f, 20, LIGHTGRAY);
|
||||
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 (physicsDebug)
|
||||
if (isDebug)
|
||||
{
|
||||
// Draw every internal physics stored collider if it is active
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (GetCollider(i).enabled)
|
||||
{
|
||||
DrawRectangleLines(GetCollider(i).bounds.x, GetCollider(i).bounds.y, GetCollider(i).bounds.width, GetCollider(i).bounds.height, GREEN);
|
||||
}
|
||||
}
|
||||
DrawRectangleLines(floor->collider.bounds.x, floor->collider.bounds.y, floor->collider.bounds.width, floor->collider.bounds.height, GREEN);
|
||||
DrawRectangleLines(leftWall->collider.bounds.x, leftWall->collider.bounds.y, leftWall->collider.bounds.width, leftWall->collider.bounds.height, GREEN);
|
||||
DrawRectangleLines(rightWall->collider.bounds.x, rightWall->collider.bounds.y, rightWall->collider.bounds.width, rightWall->collider.bounds.height, GREEN);
|
||||
DrawRectangleLines(platform->collider.bounds.x, platform->collider.bounds.y, platform->collider.bounds.width, platform->collider.bounds.height, GREEN);
|
||||
DrawRectangleLines(player->collider.bounds.x, player->collider.bounds.y, player->collider.bounds.width, player->collider.bounds.height, GREEN);
|
||||
DrawRectangleLines(player2->collider.bounds.x, player2->collider.bounds.y, player2->collider.bounds.width, player2->collider.bounds.height, GREEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw player and floor
|
||||
DrawRectangleRec((Rectangle){player.position.x, player.position.y, player.scale.x, player.scale.y}, GRAY);
|
||||
DrawRectangleRec((Rectangle){floor.position.x, floor.position.y, floor.scale.x, floor.scale.y}, BLACK);
|
||||
// Convert transform values to rectangle data type variable
|
||||
DrawRectangleRec(TransformToRectangle(floor->transform), DARKGRAY);
|
||||
DrawRectangleRec(TransformToRectangle(leftWall->transform), DARKGRAY);
|
||||
DrawRectangleRec(TransformToRectangle(rightWall->transform), DARKGRAY);
|
||||
DrawRectangleRec(TransformToRectangle(platform->transform), DARKGRAY);
|
||||
DrawRectangleRec(TransformToRectangle(player->transform), RED);
|
||||
DrawRectangleRec(TransformToRectangle(player2->transform), BLUE);
|
||||
}
|
||||
|
||||
// Draw all physic object information in specific screen position and font size
|
||||
// DrawPhysicObjectInfo(player, (Vector2){ 10.0f, 10.0f }, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -115,8 +119,7 @@ int main()
|
|||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadPhysics(); // Unload physic objects
|
||||
|
||||
ClosePhysics(); // Unitialize physics module
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -1,135 +0,0 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [physac] physics example - Rigidbody forces
|
||||
*
|
||||
* 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 Victor Fisac and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define MAX_OBJECTS 5
|
||||
#define OBJECTS_OFFSET 150
|
||||
|
||||
#define FORCE_INTENSITY 250.0f // Customize by user
|
||||
#define FORCE_RADIUS 100 // Customize by user
|
||||
|
||||
int main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
int screenWidth = 800;
|
||||
int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [physics] example - rigidbodies forces");
|
||||
|
||||
InitPhysics(MAX_OBJECTS + 1); // Initialize physics system with maximum physic objects
|
||||
|
||||
// Physic Objects initialization
|
||||
Transform objects[MAX_OBJECTS];
|
||||
|
||||
for (int i = 0; i < MAX_OBJECTS; i++)
|
||||
{
|
||||
objects[i] = (Transform){(Vector2){75 + OBJECTS_OFFSET * i, (screenHeight - 50) / 2}, 0.0f, (Vector2){50, 50}};
|
||||
AddCollider(i, (Collider){true, COLLIDER_RECTANGLE, (Rectangle){objects[i].position.x, objects[i].position.y, objects[i].scale.x, objects[i].scale.y}, 0});
|
||||
AddRigidbody(i, (Rigidbody){true, 1.0f, (Vector2){0, 0}, (Vector2){0, 0}, false, false, true, 0.5f, 0.5f});
|
||||
}
|
||||
|
||||
// Floor initialization
|
||||
// NOTE: floor doesn't need a rigidbody because it's a static physic object, just a collider to collide with other dynamic colliders (with rigidbody)
|
||||
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);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Update object physics
|
||||
// NOTE: all physics detections and reactions are calculated in ApplyPhysics() function (You will live happier :D)
|
||||
for (int i = 0; i < MAX_OBJECTS; i++)
|
||||
{
|
||||
ApplyPhysics(i, &objects[i].position);
|
||||
}
|
||||
|
||||
// Check foce button input
|
||||
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
|
||||
{
|
||||
AddForceAtPosition(GetMousePosition(), FORCE_INTENSITY, FORCE_RADIUS);
|
||||
}
|
||||
|
||||
// Check debug mode toggle button input
|
||||
if (IsKeyPressed(KEY_P)) physicsDebug = !physicsDebug;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Check if debug mode is enabled
|
||||
if (physicsDebug)
|
||||
{
|
||||
// Draw every internal physics stored collider if it is active (floor included)
|
||||
for (int i = 0; i < MAX_OBJECTS; i++)
|
||||
{
|
||||
if (GetCollider(i).enabled)
|
||||
{
|
||||
// Draw collider bounds
|
||||
DrawRectangleLines(GetCollider(i).bounds.x, GetCollider(i).bounds.y, GetCollider(i).bounds.width, GetCollider(i).bounds.height, GREEN);
|
||||
|
||||
// Check if current collider is not floor
|
||||
if (i < MAX_OBJECTS)
|
||||
{
|
||||
// Draw lines between mouse position and objects if they are in force range
|
||||
if (CheckCollisionPointCircle(GetMousePosition(), (Vector2){GetCollider(i).bounds.x + GetCollider(i).bounds.width / 2, GetCollider(i).bounds.y + GetCollider(i).bounds.height / 2}, FORCE_RADIUS))
|
||||
{
|
||||
DrawLineV(GetMousePosition(), (Vector2){GetCollider(i).bounds.x + GetCollider(i).bounds.width / 2, GetCollider(i).bounds.y + GetCollider(i).bounds.height / 2}, RED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw radius circle
|
||||
DrawCircleLines(GetMousePosition().x, GetMousePosition().y, FORCE_RADIUS, RED);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw objects
|
||||
for (int i = 0; i < MAX_OBJECTS; i++)
|
||||
{
|
||||
DrawRectangleRec((Rectangle){objects[i].position.x, objects[i].position.y, objects[i].scale.x, objects[i].scale.y}, GRAY);
|
||||
}
|
||||
|
||||
// Draw floor
|
||||
DrawRectangleRec((Rectangle){floor.position.x, floor.position.y, floor.scale.x, floor.scale.y}, BLACK);
|
||||
}
|
||||
|
||||
|
||||
// Draw help messages
|
||||
DrawText("Use LEFT MOUSE BUTTON to create a force in mouse position", (screenWidth - MeasureText("Use LEFT MOUSE BUTTON to create a force in mouse position", 20)) / 2, screenHeight * 0.20f, 20, LIGHTGRAY);
|
||||
DrawText("Use P to switch DEBUG MODE", (screenWidth - MeasureText("Use P to switch DEBUG MODE", 20)) / 2, screenHeight * 0.3f, 20, LIGHTGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadPhysics(); // Unload physic objects
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 18 KiB |
Loading…
Add table
Add a link
Reference in a new issue