0

i have been trying to make a particle gravity simulation thing using sdl2 and c++ but even though i used the correct formula its the same. the particles are getting attracted to the top right corner of the screen, it seems to fix itself if i increase the value of the gravitational constant but if i do so everything becomes really fast.

this is my code:

#include "SDL.h"
#undef main
#include <iostream>
#include <vector>
#include <cmath>
#include <random>
double Gravity = 1;
const int NumberOfParticles = 100;
bool isRunning = true;
int ParticleIndex = 0;
int MouseX = NULL;
int MouseY = NULL;
//References
int  DistanceY;
int x;
int y;
int ScreenHeight = 700;
int ScreenWidth = 700;
Uint32 TicksCounter;
double DeltaTime;

double  DistanceX;
//
double InverseDistance;
//
double Distance;
double Force;
double ForceY;
double ForceX;


struct Particle {
    double Mass[NumberOfParticles];
    double AX[NumberOfParticles];
    double AY[NumberOfParticles];
    SDL_Rect Particle[NumberOfParticles];
};
Particle Particles;
Particle OO;
int main() {
    //Setup
    SDL_Window* GameWindow = SDL_CreateWindow("Gravity Simulation.", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, ScreenWidth, ScreenWidth, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_RENDERER_PRESENTVSYNC);
    SDL_Renderer* Renderer = SDL_CreateRenderer(GameWindow, -1, 0);
    SDL_Event Event;
    SDL_Surface* WindowSurface = SDL_GetWindowSurface(GameWindow);
    //GameLoop
    while (isRunning) {
        srand(time(0));
        //Calculate DeltaTime
        DeltaTime = (SDL_GetTicks() - TicksCounter) / 1000.0;
        TicksCounter = SDL_GetTicks();
        std::cout << "DeltaTime : " << DeltaTime << std::endl;
        SDL_GetMouseState(&MouseX, &MouseY);
        while (SDL_PollEvent(&Event)) {
            if (Event.type == SDL_QUIT) {
                isRunning = false;
            }
            if (Event.type == SDL_KEYDOWN) {
                //Keyboard Inputs
            }
            if (Event.type == SDL_MOUSEBUTTONDOWN) {
                //Mouse Inputs
                if (Event.button.button == SDL_BUTTON_LEFT) {
                    //Add Particle
                    Particles.Particle[ParticleIndex].x = MouseX;
                    Particles.Particle[ParticleIndex].y = MouseY;
                    Particles.Particle[ParticleIndex].w = 5;
                    Particles.Particle[ParticleIndex].h = 5;
                    Particles.Mass[ParticleIndex] = 10 + rand() & 10;
                    ParticleIndex++;

                }
                if (Event.button.button == SDL_BUTTON_RIGHT) {
                    //Add Particle
                    Particles.Particle[ParticleIndex].x = MouseX;
                    Particles.Particle[ParticleIndex].y = MouseY;
                    Particles.Particle[ParticleIndex].w = 25;
                    Particles.Particle[ParticleIndex].h = 25;
                    Particles.Mass[ParticleIndex] = 1000;
                    ParticleIndex++;
                }

            }
        }
    
        for (y = 0; y < ParticleIndex; y++) {
            for (x = 0; x < ParticleIndex; x++) {
                if (x != y) {
                    DistanceX = Particles.Particle[x].x - Particles.Particle[y].x;
                    DistanceY = Particles.Particle[x].y - Particles.Particle[y].y;
                    Distance = std::sqrt(DistanceX * DistanceX + DistanceY * DistanceY + 1);
                    InverseDistance = 1.0 / Distance;
                        //Calculat Forces
                    std::cout << "Particle Index :" << ParticleIndex << std::endl;
                    //Calculate Gravity 
                        std::cout << "Mass :" << Particles.Mass[x] << std::endl << "Distance :" << Distance << std::endl;
                        Force = ((Gravity * (Particles.Mass[x] * Particles.Mass[y])) / (Distance * Distance)) ;
                        Particles.AX[y] += (Force * DistanceX / Particles.Mass[x]) * DeltaTime;
                        Particles.AY[y] += (Force * DistanceY / Particles.Mass[x]) * DeltaTime ;
                }
            }
        }
        for (y = 0; y < ParticleIndex; y++) {
            Particles.Particle[y].x += Particles.AX[y];
            Particles.Particle[y].y += Particles.AY[y];
        }
        //Rendering
        SDL_SetRenderDrawColor(Renderer, 255, 255, 255, 255);
        SDL_RenderClear(Renderer);
        SDL_SetRenderDrawColor(Renderer, 0, 0, 0, 255);
        for (y = 0; y < ParticleIndex; ++y) {
            SDL_RenderFillRect(Renderer, &Particles.Particle[y]);
        }
        SDL_RenderPresent(Renderer);
    }
}

i have tried using other formulae, thought that maybe the initial positions of the other particles is at 0,0 (the top right corner), to check if the other ones were going there because of that i made the number of particles just 2, but they too were getting attracted to the corner.

genpfault
  • 51,148
  • 11
  • 85
  • 139
riyan
  • 1
  • 1
  • 1
    You should only call `srand` once. – molbdnilo Mar 08 '23 at 12:28
  • (seems unrelated) warning about the expression `10 + rand() & 10`: 1. Operator `+` has higher presence than operator `&`. 2. The number of possible result is 4, not 10 nor 11. – MikeCAT Mar 08 '23 at 12:28
  • sorry i used the '&' symbol instead of mod ('%') – riyan Mar 08 '23 at 12:32
  • 2
    The force equation, F = ma, gives a = F/m. You do a = (F * distance)/m, and use the acceleration as the velocity. – molbdnilo Mar 08 '23 at 12:39
  • oh, i was just messing around with the values to magically find some golden number that will fix all my problems – riyan Mar 08 '23 at 12:46
  • 1
    @riyan That method never works. If the math is wrong, you can't fix it by magic. – molbdnilo Mar 08 '23 at 12:48
  • yeah i know, i just saw a persons code on github while checking if my gravity calculation code was correct and saw that his one has a +1 thats why i wanted to check.. – riyan Mar 08 '23 at 12:49
  • If you also took the `InverseDistance` (which you don't use for anything) from the same place, it was probably a hack to avoid dividing by zero, and not a good one. – molbdnilo Mar 08 '23 at 13:19
  • yeah it was from there – riyan Mar 08 '23 at 13:39
  • 1
    I believe the main problem is that force has a direction (in F = ma, both F and a are vectors), but your force is directed along the positive axes; that is, towards a corner. You need to orient the force towards "the other" particle when determining the acceleration. – molbdnilo Mar 08 '23 at 13:56
  • how do i do that though? – riyan Mar 08 '23 at 14:04
  • 1
    Acceleration changes VELOCITY, not POSITION as you are doing currently. By multiplying acceleration by unnormalised displacement you are also creating a simple inverse-distance attraction law, not an inverse-squared-distance one. – lastchance Mar 08 '23 at 15:46
  • Use something like [GLM](https://github.com/g-truc/glm) for vector-wrangling, it beats the pants off of faffing around with component-wise math. [N-body gravity simulator using GLM](https://stackoverflow.com/a/23223423/44729). – genpfault Mar 08 '23 at 19:06
  • just curious.. how do you test your formula? – p._phidot_ Mar 09 '23 at 10:10
  • i see if the simulation looks okay or not. and btw i rewrote the entire thing in unity and it seems to work fine, i still dont know why it didn't work is sdl though.. so i wanna still know why – riyan Mar 09 '23 at 15:46

0 Answers0