problem with gravity

im trying to make a program that simulates gravity as if your mouse pointer was a large object, and particles were gravitating around it. but when i run it, it crashes instantly, and i can't figure out why. i am relatively new to c++.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#include <iostream>
#include <SDL/SDL.h>
#include <vector>
#include <math.h>
#include <stdio.h>
#include <time.h>

using namespace std;

//set important variables
int screenWidth = 640;
int screenHeight = 480;
int mouseX = screenWidth / 2;
int mouseY = screenHeight / 2;

//class for the mouse pointer that everything gravitates around
class foci
{
public:
    int x, y;   //x and y coordinates
    double mass;    //mass of the object
    foci(int X, int Y, int Mass);
    void move();    //track mouse movement and move object to that location
};

foci::foci(int X, int Y, int Mass)
{
    x = X;
    y = Y;
    mass = Mass;
}

void foci::move()
{
    x = mouseX;
    y = mouseY;
}

//particles
class particle
{
public:
    int x, y, mass;    //x and y locations, and mass
    float xvel, yvel, xacc, yacc, distance, theta, gravForce;   //speed, acceleration, distance from foci, angle between foci and particle, and the force of gravity
    Uint32 color;     //color of the particle
    particle(int X, int Y, float Xvel, float Yvel,int Mass, Uint32 Color);
    void calcDistance(foci b);     //calculate distance from foci
    void calcGravForce(foci a);    //calculate the gravitational force foci has on particle
    void calcTheta(foci c);        //calculate the angle between foci and particle
    void calcAcceleration();       //calculate the acceleration of the particle
    void calcVelocity();           //calculate the velocity of the particle
    void move();                   //move the particle
    void show();                   //show the particle
};

particle::particle(int X, int Y, float Xvel, float Yvel,int Mass, Uint32 Color)
{
    x = X;
    y = Y;
    xvel = Xvel;
    yvel = Yvel;
    mass = Mass;
    color = Color;
}

void particle::calcDistance(foci b)
{
    distance = hypot((b.x - x), (b.y - y));
}

void particle::calcGravForce(foci a)
{
    gravForce = ((a.mass * mass) / (distance * distance));   //ignored gravitational constant(assumed its 1, for simplicity sake)
}

void particle::calcTheta(foci c)
{
    theta = atan2((c.y - y), (c.x - x));
}

void particle::calcAcceleration()
{
    //A = F/M
    xacc = (gravForce * cos(theta))/mass;
    yacc = (gravForce * sin(theta))/mass;
}

void particle::calcVelocity()
{
    //Vf(velocity final) = A*time(which is each frame) - Vi(velocity initial)
    xvel = xacc - xvel;
    yvel = yacc - yvel;
}

void particle::move()
{
    //move the particle
    x += xvel;
    y += yvel;

    //check boundaries
    if(x == 0)
        xvel = xvel * -1;
    if(y == 0)
        yvel = yvel * -1;
    if(y > screenHeight)
        yvel = yvel * -1;
    if(x > screenWidth)
        xvel = xvel * -1;
}

void particle::show()
{
    //show the particle
    Uint8* pixels=(Uint8*)SDL_GetVideoSurface()->pixels;
    Uint8* pixel=pixels+(int)y*SDL_GetVideoSurface()->pitch+(int)x;
    *pixel=color;
}




int main (int argc, char** argv)
{
    //initialize
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_Surface* screen;
    screen = SDL_SetVideoMode(screenWidth, screenHeight, 8, SDL_SWSURFACE);
    Uint32 start;

    //seed random # generator
    srand(time(NULL));
    const int FPS = 30;
    bool running = true;

    //max particles on screen
    int maxParticles = 5000;

    //make the mouse pointer foci
    foci Luna(screenWidth / 2, screenHeight, 999);

    //make the vector
    vector<particle*> particles;

    //fill the vector
    for(int i = 0; i < maxParticles; ++i)
        particles.push_back(new particle((rand()%screenWidth) - 5, (rand()%screenHeight) - 5, 0, 0, 100, SDL_MapRGB(screen->format, rand()%255, rand()%255, rand()%255)));

    while(running)
    {
        start = SDL_GetTicks();
        SDL_Event event;
        while(SDL_PollEvent(&event))
        {
            switch(event.type)
            {
                case SDL_QUIT:
                    running = false;
                    break;
                case SDL_MOUSEMOTION:
                    mouseX = event.motion.x;
                    mouseY = event.motion.y;

            }
        }
        //check mouse pointer location
        Luna.move();

        //make screen black
        SDL_FillRect(screen, &screen->clip_rect, SDL_MapRGB(screen->format, 0, 0, 0));

        for(int j = 0; j < maxParticles; ++j)
        {
            //make all the calculations for the variables and move the particles
            particles[j]->calcDistance(Luna);
            particles[j]->calcGravForce(Luna);
            particles[j]->calcTheta(Luna);
            particles[j]->calcAcceleration();
            particles[j]->calcVelocity();
            particles[j]->move();
            particles[j]->show();
        }

        SDL_Flip(screen);


        //regulate fps
        if(1000/FPS>SDL_GetTicks()-start)
                SDL_Delay(1000/FPS-(SDL_GetTicks()-start));


    }
    SDL_Quit();
    return 0;
}
I would suggest perhaps adding a break to line 163.
Last edited on
Is that necessary Smac?

Um tatsu, would an arrow key controlled cursor be easier to handle? And what if particles spawn on each other?
$ gdb a.out
> run
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401432 in particle::show (this=0x71aff0) at foo.cpp:117
117 *pixel=color;

> print pixel
$1 = (Uint8 *) 0x77ee09 <Address 0x77ee09 out of bounds>



Also, you are leaking memory with your `particles' vector. ¿is there a good reason to use dynamic allocation there?
Last edited on
ne555,
as i said, im new to c++, the only way i learned to make something hold all the particles was to make the vector in that way. i was also told before that my way of printing the pixels to the screen was not the best, but i have never found a better way to do it. any help would be appreciated. also, i use codeblocks, which babys me very much in terms of error finding lol, so I cant understand the error message you posted. sorry X(

greenleaf800073,
i think that setting the x and y to the mouses x and y was pretty easy in itself, but if it would cause any disturbance to the program then i could easily make it keyboard controlled

thanks everyone :)
1
2
3
4
5
6
7
void particle::show()
{
    //show the particle
    Uint8* pixels=(Uint8*)SDL_GetVideoSurface()->pixels;
    Uint8* pixel=pixels+(int)y*SDL_GetVideoSurface()->pitch+(int)x;
    *pixel=color;
}
The values of `x' and `y' are referring to a point that it is outside the screen.
You try to access something that you don't own, producing the crash.


About the vector
1
2
3
4
5
6
7
    vector<particle> particles; //holding objects instead of pointers

    //fill the vector
    for(int i = 0; i < maxParticles; ++i)
        particles.push_back(particle(/**/));

    particles[j].calcDistance(Luna); //accessing 
When the vector goes out of scope (the function ends), all the particles will be destroyed.
I was playing a little.
1
2
3
4
5
6
void particle::show()
{
    if(x<0 or y<0 or x>=screenWidth or y>=screenHeight) //out of bounds
      return;
   //...
}
so you can see it.

It looks awful. I found two mistakes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void particle::calcVelocity()
{
    //Vf(velocity final) = A*time(which is each frame) - Vi(velocity initial)
    //nope, A = (Vf-Vi)/t so Vf = A*t + Vi

    xvel += xacc;
    yvel += yacc;
}

//particles
class particle
{
public:
    /*int*/double x, y;
The force is really small, by using integers for the coordinates, you'll have artifacts in the movements.
Of course, you'll need integers in `show()' as you use pointer arithmetic.


Another thing, `cos(theta)' is equivalent to `(f.x-x)/distance' where `f' is the foci
Can you use scroll wheel or up and down buttons to alter gravity?

and colored particles would be beautiful
Thanks ne555, I'll try it next time I can get to my computer. And I can't believe I got the formula wrong X(

And greenleaf, I could possibly use the scroll wheel, but I want to get this working first lol, and the particles are colored. The color is randomly generated :)
yay
Topic archived. No new replies allowed.