(gravity) added radial, Newtonian (1/r^2) force field
This commit is contained in:
parent
dc0e5be086
commit
53e71fa27d
11
balls.c
11
balls.c
@ -48,11 +48,14 @@ void balls_init_state () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ball_update_state (struct ball * p) {
|
void ball_update_state (struct ball * p) {
|
||||||
p->x += delta*p->v_x + delta*delta*g_x/2.0;
|
struct gravity_vector g;
|
||||||
p->v_x += delta*g_x;
|
gravity_get_vector (&g, p);
|
||||||
|
|
||||||
p->y += delta*p->v_y + delta*delta*g_y/2.0;
|
p->x += delta*p->v_x + delta*delta*g.x/2.0;
|
||||||
p->v_y += delta*g_y;
|
p->v_x += delta*g.x;
|
||||||
|
|
||||||
|
p->y += delta*p->v_y + delta*delta*g.y/2.0;
|
||||||
|
p->v_y += delta*g.y;
|
||||||
|
|
||||||
if (p->x + p->radius > width) { /* right wall */
|
if (p->x + p->radius > width) { /* right wall */
|
||||||
if (p->v_x > 0) {
|
if (p->v_x > 0) {
|
||||||
|
80
gravity.c
80
gravity.c
@ -4,13 +4,31 @@
|
|||||||
#include "gravity.h"
|
#include "gravity.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
|
||||||
double g_y = 20;
|
static double g_y = 20;
|
||||||
double g_x = 0;
|
static double g_x = 0;
|
||||||
|
|
||||||
|
static double g_r = 50;
|
||||||
|
static double g_g = 10000000;
|
||||||
|
|
||||||
|
static int constant_field = 1;
|
||||||
|
|
||||||
static int gravity_vector_countdown = 0;
|
static int gravity_vector_countdown = 0;
|
||||||
static int gravity_vector_init = 300;
|
static int gravity_vector_init = 300;
|
||||||
|
|
||||||
|
void gravity_constant_field (double x, double y) {
|
||||||
|
constant_field = 1;
|
||||||
|
g_x = x;
|
||||||
|
g_y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gravity_newton_field (double r, double g) {
|
||||||
|
constant_field = 0;
|
||||||
|
g_r = r;
|
||||||
|
g_g = g;
|
||||||
|
}
|
||||||
|
|
||||||
void gravity_draw (cairo_t * cr) {
|
void gravity_draw (cairo_t * cr) {
|
||||||
|
if (constant_field) {
|
||||||
if (gravity_vector_countdown != 0) {
|
if (gravity_vector_countdown != 0) {
|
||||||
cairo_save(cr);
|
cairo_save(cr);
|
||||||
cairo_new_path(cr);
|
cairo_new_path(cr);
|
||||||
@ -25,15 +43,71 @@ void gravity_draw (cairo_t * cr) {
|
|||||||
--gravity_vector_countdown;
|
--gravity_vector_countdown;
|
||||||
cairo_restore(cr);
|
cairo_restore(cr);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
||||||
|
cairo_save (cr);
|
||||||
|
cairo_new_path (cr);
|
||||||
|
cairo_arc (cr, width/2, height/2, g_r, 0, 2*M_PI);
|
||||||
|
cairo_set_line_width(cr, 3.0);
|
||||||
|
cairo_stroke(cr);
|
||||||
|
cairo_restore(cr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gravity_show () {
|
void gravity_show () {
|
||||||
|
if (constant_field)
|
||||||
gravity_vector_countdown = gravity_vector_init;
|
gravity_vector_countdown = gravity_vector_init;
|
||||||
};
|
};
|
||||||
|
|
||||||
void gravity_change (double dx, double dy) {
|
void gravity_change (double dx, double dy) {
|
||||||
|
if (constant_field) {
|
||||||
g_x += dx;
|
g_x += dx;
|
||||||
g_y += dy;
|
g_y += dy;
|
||||||
gravity_show ();
|
gravity_show ();
|
||||||
};
|
} else {
|
||||||
|
g_r += dx;
|
||||||
|
g_g += dy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gravity_get_vector (struct gravity_vector * v, const struct ball * b) {
|
||||||
|
if (constant_field) {
|
||||||
|
v->x = g_x;
|
||||||
|
v->y = g_y;
|
||||||
|
} else {
|
||||||
|
double dx = width/2 - b->x;
|
||||||
|
double dy = height/2 - b->y;
|
||||||
|
double r2 = dx*dx+dy*dy;
|
||||||
|
if (r2 < g_r*g_r) {
|
||||||
|
v->x = 0;
|
||||||
|
v->y = 0;
|
||||||
|
} else {
|
||||||
|
double r = sqrt(r2);
|
||||||
|
v->x = g_g/r2/r*dx;
|
||||||
|
v->y = g_g/r2/r*dy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gravity_collisions (struct ball * begin, struct ball * end) {
|
||||||
|
if (constant_field)
|
||||||
|
return;
|
||||||
|
for (struct ball * b = begin; b != end; ++b) {
|
||||||
|
double dx = b->x - width/2;
|
||||||
|
double dy = b->y - height/2;
|
||||||
|
double d2 = dx*dx + dy*dy;
|
||||||
|
double r = b->radius + g_r;
|
||||||
|
if (d2 <= r*r) {
|
||||||
|
double dv_x = b->v_x;
|
||||||
|
double dv_y = b->v_y;
|
||||||
|
|
||||||
|
double f = dv_x*dx + dv_y*dy;
|
||||||
|
|
||||||
|
if (f < 0) {
|
||||||
|
f /= d2;
|
||||||
|
b->v_x -= 2*f*dx;
|
||||||
|
b->v_y -= 2*f*dy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
15
gravity.h
15
gravity.h
@ -1,11 +1,22 @@
|
|||||||
#ifndef GRAVITY_H_INCLUDED
|
#ifndef GRAVITY_H_INCLUDED
|
||||||
#define GRAVITY_H_INCLUDED
|
#define GRAVITY_H_INCLUDED
|
||||||
|
|
||||||
extern double g_y;
|
#include "balls.h"
|
||||||
extern double g_x;
|
|
||||||
|
struct gravity_vector {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void gravity_constant_field (double x, double y);
|
||||||
|
extern void gravity_newton_field (double r, double g);
|
||||||
|
|
||||||
|
extern void gravity_get_vector (struct gravity_vector * v, const struct ball * b);
|
||||||
|
|
||||||
extern void gravity_draw (cairo_t * cr);
|
extern void gravity_draw (cairo_t * cr);
|
||||||
extern void gravity_change (double dx, double dy);
|
extern void gravity_change (double dx, double dy);
|
||||||
extern void gravity_show ();
|
extern void gravity_show ();
|
||||||
|
|
||||||
|
extern void gravity_collisions (struct ball * begin, struct ball * end);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
16
main.c
16
main.c
@ -24,6 +24,8 @@ void check_collisions_simple () {
|
|||||||
ball_elastic_collision(balls + i, balls + j);
|
ball_elastic_collision(balls + i, balls + j);
|
||||||
for(int j = 0; j < n_balls; ++j)
|
for(int j = 0; j < n_balls; ++j)
|
||||||
ball_elastic_collision(&spaceship, balls + j);
|
ball_elastic_collision(&spaceship, balls + j);
|
||||||
|
gravity_collisions (balls, balls + n_balls);
|
||||||
|
gravity_collisions (&spaceship, &spaceship + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_collisions_with_index () {
|
void check_collisions_with_index () {
|
||||||
@ -31,6 +33,8 @@ void check_collisions_with_index () {
|
|||||||
c_index_check_collisions(ball_elastic_collision);
|
c_index_check_collisions(ball_elastic_collision);
|
||||||
for(int j = 0; j < n_balls; ++j)
|
for(int j = 0; j < n_balls; ++j)
|
||||||
ball_elastic_collision(&spaceship, balls + j);
|
ball_elastic_collision(&spaceship, balls + j);
|
||||||
|
gravity_collisions (balls, balls + n_balls);
|
||||||
|
gravity_collisions (&spaceship, &spaceship + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void (*check_collisions)() = 0;
|
void (*check_collisions)() = 0;
|
||||||
@ -137,7 +141,8 @@ void print_usage (const char * progname) {
|
|||||||
"options:\n"
|
"options:\n"
|
||||||
"\t<width>x<height>\n"
|
"\t<width>x<height>\n"
|
||||||
"\tn=<number of balls>\n"
|
"\tn=<number of balls>\n"
|
||||||
"\tfx=<x-force>\n"
|
"\tfconst=<x-force>,<y-force> :: constant force field\n"
|
||||||
|
"\tfnewt=<radius>,<g> :: radial, Newtonian force field\n"
|
||||||
"\tfy=<y-force>\n"
|
"\tfy=<y-force>\n"
|
||||||
"\tradius=<min-radius>-<max-radius>\n"
|
"\tradius=<min-radius>-<max-radius>\n"
|
||||||
"\tv=<min-velocity>-<max-velocity>\n"
|
"\tv=<min-velocity>-<max-velocity>\n"
|
||||||
@ -193,16 +198,21 @@ gboolean timeout (gpointer user_data) {
|
|||||||
int main (int argc, const char *argv[]) {
|
int main (int argc, const char *argv[]) {
|
||||||
int w = DEFAULT_WIDTH;
|
int w = DEFAULT_WIDTH;
|
||||||
int h = DEFAULT_HEIGHT;
|
int h = DEFAULT_HEIGHT;
|
||||||
|
double fa, fb;
|
||||||
|
|
||||||
for (int i = 1; i < argc; ++i) {
|
for (int i = 1; i < argc; ++i) {
|
||||||
if (sscanf(argv[i], "%dx%d", &w, &h) == 2)
|
if (sscanf(argv[i], "%dx%d", &w, &h) == 2)
|
||||||
continue;
|
continue;
|
||||||
if (sscanf(argv[i], "n=%u", &n_balls) == 1)
|
if (sscanf(argv[i], "n=%u", &n_balls) == 1)
|
||||||
continue;
|
continue;
|
||||||
if (sscanf(argv[i], "fx=%lf", &g_x) == 1)
|
if (sscanf(argv[i], "fconst=%lf,%lf", &fa, &fb) == 2) {
|
||||||
|
gravity_constant_field (fa,fb);
|
||||||
continue;
|
continue;
|
||||||
if (sscanf(argv[i], "fy=%lf", &g_y) == 1)
|
}
|
||||||
|
if (sscanf(argv[i], "fnewt=%lf,%lf", &fa, &fb) == 2) {
|
||||||
|
gravity_newton_field (fa,fb);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (sscanf(argv[i], "radius=%u-%u", &radius_min, &radius_max) == 2)
|
if (sscanf(argv[i], "radius=%u-%u", &radius_min, &radius_max) == 2)
|
||||||
continue;
|
continue;
|
||||||
if (sscanf(argv[i], "v=%u-%u", &v_min, &v_max) == 2)
|
if (sscanf(argv[i], "v=%u-%u", &v_min, &v_max) == 2)
|
||||||
|
Loading…
Reference in New Issue
Block a user