diff --git a/c/gtk3/gravity-control/gravitycontrol.c b/c/gtk3/gravity-control/gravitycontrol.c new file mode 100644 index 0000000..fd3e783 --- /dev/null +++ b/c/gtk3/gravity-control/gravitycontrol.c @@ -0,0 +1,99 @@ +#include +#include +#include +#include + + +const double pi = 3.141592653589793; + +const guint interval_ms = 5; +const guint interval2_ms = 50; +const double G = 1000000; +const double radius = 30; + +int width = 700; +int height = 500; + +double mx = 0; +double my = 0; +double x = 200; +double y = 200; +double vx = 0; +double vy = 0; + +GtkWidget *window; + + +gboolean motion(GtkWidget *widget, GdkEventMotion *event, gpointer data) { + mx = event->x; + my = event->y; + return TRUE; +} + +gboolean timeout(gpointer data) { + double t = interval_ms/1000.0; + + double dx = mx - x; + double dy = my - y; + double d = sqrt(dx*dx + dy*dy); + + double ax = G*dx/(d*d*d); + double ay = G*dy/(d*d*d); + if (d < 10.0) ax = ay = 0.0; + + vx += ax*t; + vy += ay*t; + + x += vx*t; + y += vy*t; + + if (x < radius) + { x = radius; vx = fabs(vx); } + if (x > width - radius) + { x = width - radius; vx = -fabs(vx); } + if (y < radius) + { y = radius; vy = fabs(vy); } + if (y > height - radius) + { y = height - radius; vy = -fabs(vy); } + + return TRUE; +} + +gboolean timeout2(gpointer data) { + gtk_widget_queue_draw(window); + return TRUE; +} + +gboolean draw(GtkWidget *widget, cairo_t *cr, gpointer data) { + cairo_set_source_rgba(cr, 0.9, 0.9, 0.9, 1); + cairo_paint(cr); + + cairo_set_source_rgba(cr, 0, 0, 0, 1); + cairo_set_line_width(cr, 1.0); + cairo_arc(cr, x, y, radius, 0, 2*pi); + cairo_stroke(cr); + + return TRUE; +} + +void activate(GtkApplication* app, gpointer data) { + window = gtk_application_window_new (app); + g_signal_connect(window, "draw", G_CALLBACK(draw), NULL); + g_signal_connect(window, "motion-notify-event", G_CALLBACK(motion), NULL); + gtk_widget_add_events(window, GDK_POINTER_MOTION_MASK); + gtk_window_set_default_size(GTK_WINDOW(window), width, height); + gtk_widget_show_all(window); + + g_timeout_add(interval_ms, timeout, NULL); + g_timeout_add(interval2_ms, timeout2, NULL); +} + +int main(int argc, char **argv) { + GtkApplication *application = gtk_application_new(NULL, 0); + g_signal_connect(application, "activate", G_CALLBACK(activate), NULL); + int status = g_application_run(G_APPLICATION(application), argc, argv); + g_object_unref(application); + return status; +} + +