- #1
creativemfs
- 3
- 0
Hi everyone, I am new here, nice to meet you.
For fun I am trying to make a gravity simulator in c++ and using SDL.
I believe there is a problem in my merge function when I calculate the new velocity and trajectory of two colliding bodies.
Also, does my main code look accurate. The part where I calculate the gravitational force, determine acceleration, and sum the acceleration from one body to all the other bodies.
This is my first time attempting a project like this and my professors are gone for the summer so I am kind of in the dark.
I am using euler integration for now, it is all I know and can implement.
Thank you,
Michaela
if you want to run the code
the collision code is here
http://sdl-collide.sourceforge.net/
For fun I am trying to make a gravity simulator in c++ and using SDL.
I believe there is a problem in my merge function when I calculate the new velocity and trajectory of two colliding bodies.
Also, does my main code look accurate. The part where I calculate the gravitational force, determine acceleration, and sum the acceleration from one body to all the other bodies.
This is my first time attempting a project like this and my professors are gone for the summer so I am kind of in the dark.
I am using euler integration for now, it is all I know and can implement.
Thank you,
Michaela
if you want to run the code
the collision code is here
http://sdl-collide.sourceforge.net/
Code:
/*
* main.cpp
*
* Created on: Jul 28, 2012
* Author: michaela
* Fnet = (G * m1 * m2) / r^2
*/
#include "SDL_collide.h"
#include <SDL/SDL.h>
#include <SDL/SDL_gfxPrimitives.h>
#include <list>
#include <math.h>
#include <iostream>
const int SCREEN_HEIGHT = 600;
const int SCREEN_WIDTH = 800;
const int SCREEN_BPP = 32;
const double G = 6.67e-11;
const double DELTA_TIME = 0.1;
//Hardcoded number of bodies, used if no argument is specified
int bodies = 100;
struct celestial_body
{
int count;
double mass;
double radius;
double x, y;
double vX, vY;
double aX, aY;
SDL_Color color;
celestial_body(int newCount)
{
count = newCount;
//Random mass
mass = rand() % 100000000;
radius = 0.5;
//Random position on screen
x = fmod((double)rand(), (double)SCREEN_WIDTH);
y = fmod((double)rand(), (double)SCREEN_HEIGHT);
vX = vY = 0;
//Random color and avoid very dark colors
color.r = (int)mass % (rand() % 10000) % 255;
color.g = (int)mass % (rand() % 10000) % 255;
color.b = (int)mass % (rand() % 10000) % 255;
if(color.r <= 20 && color.g <= 20 && color.b <= 20)
{
color.r += 25;
color.g += 25;
color.b += 25;
}
}
void draw(SDL_Surface* screen)
{
filledCircleRGBA(screen, x, y, radius, color.r, color.g, color.b, 255);
}
void update()
{
vX = vX + (aX * DELTA_TIME);
vY = vY + (aY * DELTA_TIME);
x = x + (vX * DELTA_TIME);
y = y + (vY * DELTA_TIME);
}
void print()
{
std::cout << "Mass: " << mass << "\nX: " << x << "\nY: " << y <<
"\nVx : " << vX << " Vy: " << vY <<
"\nColor: " << (int)color.r << " " << (int)color.g << " " << (int)color.b << "\n\n";
}
};
void merge(celestial_body &a, celestial_body &b)
{
//Radius and color merge is arbitrary (for now)
a.radius += b.radius;
a.color.r = (a.color.r + b.color.r) / 2;
a.color.g = (a.color.g + b.color.g) / 2;
a.color.b = (a.color.b + b.color.b) / 2;
//Total velocity for a and b
double vA = sqrt((a.vX * a.vX) + (a.vY * a.vY));
double thetaA = atan2(a.vY, a.vX);
if(thetaA < 0)
vA *= -1.0;
double vB = sqrt((b.vX * b.vX) + (b.vY * b.vY));
double thetaB = atan2(b.vY, b.vX);
if(thetaB < 0)
vB *= -1.0;
//New velocity of collided bodies
double velocity = ((a.mass * vA) + (b.mass * vB)) / (a.mass + b.mass);
//Angle of trajectory
double theta = atan2(((a.mass * a.vY) + (b.mass * b.vY)), ((a.mass * a.vX) + (b.mass * b.vX)));
std::cout << "vA: " << vA << " vB: " << vB << "\n" << velocity << " : " << theta << std::endl;
//Vector components of velocity
a.vX = velocity * cos(theta);
a.vY = velocity * sin(theta);
//Masses are added together (mass final)
a.mass += b.mass;
a.print();
}
void cleanup(std::list<celestial_body> &cb)
{
cb.clear();
SDL_Quit();
}
int main(int argc, char** argv)
{
//Process arguments
if(argc == 2)
{
int tempBodies = atoi(argv[1]);
if(tempBodies > 0)
bodies = tempBodies;
}
SDL_Surface* screen;
SDL_Event event;
std::list<celestial_body> cb;
std::list<celestial_body>::iterator it;
std::list<celestial_body>::iterator ij;
double distance, diffX, diffY, tempAx, tempAy;
double Fnet; //Net Force on body
double theta; //Angle between two points in 2-D space
double accel; //Net acceleration of body
bool quit = false;
if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
quit = true;
SDL_WM_SetCaption("Gravity Simulator", NULL);
SDL_ShowCursor(1);
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_HWSURFACE | SDL_DOUBLEBUF);
if(screen == NULL)
quit = true;
for(int i = 0; i < bodies; ++i)
{
celestial_body newBody(i);
cb.push_back(newBody);
newBody.print();
}
std::cout << "Number of bodies: " << bodies << "\n\n";
while(!quit)
{
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
quit = true;
if(event.type == SDL_KEYDOWN)
if(event.key.keysym.sym == SDLK_ESCAPE)
quit = true;
}
// SDL_FillRect(screen, &screen->clip_rect, 0x000000);
for(it = cb.begin(); it != cb.end(); ++it)
(*it).draw(screen);
SDL_Flip(screen);
for(it = cb.begin(); it != cb.end(); ++it)
{
tempAx = tempAy = 0;
for(ij = cb.begin(); ij != cb.end(); ++ij)
{
//Simply makes sure a body is not calculated against itself
if((*it).count != (*ij).count)
{
diffX = (*it).x - (*ij).x;
diffY = (*it).y - (*ij).y;
if(!SDL_CollideBoundingCircle((*it).x, (*it).y, (*it).radius, (*ij).x, (*ij).y, (*ij).radius, 0))
{
//Determine the distance between two bodies
distance = sqrt( (diffX * diffX) + (diffY * diffY) );
//Determine the net gravitational force between the two
Fnet = ((G * (*it).mass * (*ij).mass)) / (distance * distance);
//Determine the angle from a to b in 2-Dimensional space
theta = atan2(diffY, diffX);
//Determine the total acceleration
accel = Fnet / (*it).mass;
//Find acceleration from vector components
//Add them together for each affecting body
tempAx += -(accel * cos(theta));
tempAy += -(accel * sin(theta));
}
else
{
if((*it).mass > (*ij).mass)
{
merge((*it), (*ij));
ij = cb.erase(ij);
}
else
{
merge((*ij), (*it));
it = cb.erase(it);
}
std::cout << "Number of bodies: " << cb.size() << "\n";
}
}
}
(*it).aX = tempAx;
(*it).aY = tempAy;
}
for(it = cb.begin(); it != cb.end(); ++it)
(*it).update();
}
cleanup(cb);
return 0;
}
Last edited: