diff options
-rw-r--r-- | .idea/misc.xml | 3 | ||||
-rw-r--r-- | src/main.c | 213 |
2 files changed, 91 insertions, 125 deletions
diff --git a/.idea/misc.xml b/.idea/misc.xml index 79b3c94..0b76fe5 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> + <component name="CMakePythonSetting"> + <option name="pythonIntegrationState" value="YES" /> + </component> <component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" /> </project>
\ No newline at end of file @@ -1,100 +1,78 @@ -#include <stdlib.h> -#include <stdio.h> - #include "raylib.h" #include "raymath.h" -typedef struct Config { +typedef struct InitConfig { int SCREEN_WIDTH; int SCREEN_HEIGHT; - int ORIGIN_X; - int ORIGIN_Y; - char TITLE[50]; + char TITLE[20]; int TARGET_FPS; -} Config; - -typedef struct Line { - Vector2 start; - Vector2 end; - Color color; -} Line; +} InitConfig; -typedef struct Object { - float posX; - float posY; +typedef struct Ball { + Vector2 pos; float radius; + float mass; + Vector2 velocity; + Vector2 force; Color color; - float charge; -} Object; +} Ball; -typedef struct VectorField { - int colSize; - int rowSize; - int spacing; - Line **lines; -} VectorField; +typedef struct Physics { + float gravityConstant; +} Physics; -void Initialize(Config config); -void InitializeVectorField(VectorField *vectorField, int colSize, int rowSize); -void doDrawing(VectorField *vectorField, int colSize, int rowSize, Object *objects, int objectNum); -void doUpdate(VectorField *vectorField, Object *objects, int objectNum); +void doInitialization(InitConfig config); +void doDrawing(Ball **balls, int totalBalls); +void doUpdate(Ball **balls, int totalBalls, Physics physics); int main(void) { - Config config = { + InitConfig config = { 1500, 900, - 1500 / 2, - 900 / 2, - "Force Field Simulator", + "Just a fucking test", 60 }; - Initialize(config); - - int spacing = 20; - int colSize = config.SCREEN_WIDTH / spacing - 1; - int rowSize = config.SCREEN_HEIGHT / spacing - 1; - Line **lines = NULL; - VectorField vectorField = { - .colSize = colSize, - .rowSize = rowSize, - .spacing = spacing, - .lines = lines + doInitialization(config); + + Physics physics = { + .gravityConstant = 70.0f, }; - InitializeVectorField(&vectorField, colSize, rowSize); - Object object0 = { - .posX = (float)config.ORIGIN_X - 200, - .posY = (float)config.ORIGIN_Y, - .radius = 20, - .color = RED, - .charge = 100 + Ball luna = { + .pos = {(float)config.SCREEN_WIDTH / 2, 0.0f + 100}, + .radius = 5, + .mass = 200, + .velocity = { 50.0f, 0.0f }, + .force = {0.0f, 0.0f}, + WHITE }; - Object object1 = { - .posX = (float)config.ORIGIN_X + 200, - .posY = (float)config.ORIGIN_Y, - .radius = 20, - .color = BLUE, - .charge = -100 + Ball potato = { + .pos = {(float)config.SCREEN_WIDTH / 2, (float)config.SCREEN_HEIGHT - 320}, + .radius = 5, + .mass = 200, + .velocity = { -80.0f, 0.0f }, + .force = {0.0f, 0.0f}, + YELLOW }; -// Object object2 = { -// .posX = (float)config.ORIGIN_X + 200, -// .posY = (float)config.ORIGIN_Y - 100, -// .radius = 20, -// .color = BLUE, -// .charge = -100 -// }; + Ball earth = { + .pos = {(float)config.SCREEN_WIDTH / 2, (float)config.SCREEN_HEIGHT / 2 }, + .radius = 20, + .mass = 15000, + .velocity = { 0.0f, 0.0f }, + .force = {0.0f, 0.0f}, + BLUE + }; - Object objects[] = {object0, object1}; - int objectNum = sizeof(objects) / sizeof(Object); + Ball *balls[] = {&earth, &luna, &potato}; while (!WindowShouldClose()) { - doUpdate(&vectorField, objects, objectNum); - doDrawing(&vectorField, colSize, rowSize, objects, objectNum); + doUpdate(balls, 3, physics); + doDrawing(balls, 3); } CloseWindow(); @@ -102,81 +80,66 @@ int main(void) return 0; } -void Initialize(Config config) { +void doInitialization(InitConfig config) { InitWindow(config.SCREEN_WIDTH, config.SCREEN_HEIGHT, config.TITLE); SetTargetFPS(config.TARGET_FPS); } -void MemAllocFailed(char *source) { - printf("Memory allocation for %s failed", source); - exit(42); -} - -//float getRndAngle() { -// float nMax = 360; -// return (float)rand() / ((float)RAND_MAX / nMax); // NOLINT(cert-msc30-c, cert-msc50-cpp) +//float pix2m(int pixels) { +// // Pixel to meter conversion, 1 pixel = 1 cm +// return 0.01f * (float)pixels; +//} +// +//int m2pix(float metres) { +// return (int)floorf(metres / 0.01f); //} -void InitializeVectorField(VectorField *vectorField, int colSize, int rowSize) { - vectorField->lines = malloc(rowSize * sizeof(Line*)); - for (int i = 0; i < rowSize; i++) { - vectorField->lines[i] = malloc(colSize * sizeof(Line)); - for (int j = 0; j < colSize; j++) { - Vector2 start = { - (float)((j + 1) * vectorField->spacing), - (float)((i + 1) * vectorField->spacing) - }; - Vector2 end = {start.x + 5, start.y - 5}; - Line line = { - .start = start, - .end = end, - .color = WHITE - }; - vectorField->lines[i][j] = line; - } - } +Vector2 computeGravity(Ball *ball1, Ball *ball2, Physics physics) { + // Gravity felt by ball2 + Vector2 displacement = Vector2Subtract(ball1->pos, ball2->pos); + float gravityMag = (physics.gravityConstant * ball1->mass * ball2->mass) / Vector2LengthSqr(displacement); + return Vector2Scale(Vector2Normalize(displacement), gravityMag); } -void doUpdate(VectorField *vectorField, Object *objects, int objectNum) { - float forceConstant = 5000.0f; +Vector2 computeGravityNDimension(Ball *ball1, Ball *ball2, Physics physics, int dimension) { + // Generalisasi. Nyoba kalo ada N-dimensi ruang + Vector2 displacement = Vector2Subtract(ball1->pos, ball2->pos); + float distance = Vector2Length(displacement); + float distanceFactor = (float)pow(distance, dimension - 1); + float gravityMag = (physics.gravityConstant * ball1->mass * ball2->mass) / distanceFactor; + return Vector2Scale(Vector2Normalize(displacement), gravityMag); +} + +void doUpdate(Ball **balls, int totalBalls, Physics physics) { float dt = GetFrameTime(); - for (int i = 0; i < vectorField->rowSize; i++) { - for (int j = 0; j < vectorField->colSize; j++) { - Vector2 resultant = Vector2Zero(); - for (int k = 0; k < objectNum; k++) { - Object object = objects[k]; - Vector2 distanceVector = Vector2Subtract(vectorField->lines[i][j].start, (Vector2){object.posX, object.posY}); - float fieldStrength = forceConstant * object.charge / Vector2LengthSqr(distanceVector); - Vector2 force = Vector2Normalize(distanceVector); - force = Vector2Scale(force, fieldStrength); - resultant = Vector2Add(force, resultant); - } - float resultantMag = Clamp(Vector2Length(resultant), -20.0f, 20.0f); - if (fabsf(resultantMag) < 2.0f) { - resultantMag = resultantMag >= 0 ? 2.0f : -2.0f; + for (int i = 0; i < totalBalls; i++) { + Ball *ball = balls[i]; + // Sum over gravity felt from all other balls + Vector2 gravityTotal = {0.0f, 0.0f}; + for (int j = 0; j < totalBalls; j++) { + if (i != j) { + Ball *otherBall = balls[j]; + Vector2 gravity = computeGravity(otherBall, ball, physics); + gravityTotal = Vector2Add(gravityTotal, gravity); } - resultant = Vector2Normalize(resultant); - resultant = Vector2Scale(resultant, resultantMag); - vectorField->lines[i][j].end = Vector2Add(vectorField->lines[i][j].start, resultant); } + // Update position from last velocity + ball->pos = Vector2Add(ball->pos, Vector2Scale(ball->velocity, dt)); + // a = F / m + Vector2 acceleration = Vector2Scale(gravityTotal, 1.0f / ball->mass); + // Update velocity for next frame + ball->velocity = Vector2Add(ball->velocity, Vector2Scale(acceleration, dt)); } -// objects[0].posX += 10 * dt; -// objects[1].posX -= 10 * dt; } -void doDrawing(VectorField *vectorField, int colSize, int rowSize, Object *objects, int objectNum) { +void doDrawing(Ball **balls, int totalBalls) { BeginDrawing(); ClearBackground(BLACK); - for (int i = 0; i < rowSize; i++) { - for (int j = 0; j < colSize; j++) { - DrawLineV(vectorField->lines[i][j].start, vectorField->lines[i][j].end, vectorField->lines[i][j].color); - } - } - for (int i = 0; i < objectNum; i++) { - Object object = objects[i]; - DrawCircle((int)object.posX, (int)object.posY, object.radius, object.color); + for (int i = 0; i < totalBalls; i++) { + Ball *ball = balls[i]; + DrawCircleV(ball->pos, ball->radius, ball->color); } EndDrawing(); |