#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <gtk/gtk.h>
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;
}