GUI controls for restitution coefficient and gravity field

This commit is contained in:
Antonio Carzaniga 2022-12-28 18:50:12 +01:00
parent 19125826bd
commit c1dc49a9dc
5 changed files with 144 additions and 85 deletions

View File

@ -23,8 +23,6 @@ unsigned int n_balls = 50;
// C_r == 0.0 ==> perfectly inelastic collisions // C_r == 0.0 ==> perfectly inelastic collisions
// //
static double C_r = 1.0; static double C_r = 1.0;
static int c_r_display_countdown = 0;
static int c_r_display_init = 300;
void restitution_coefficient_set (double c) { void restitution_coefficient_set (double c) {
C_r = c; C_r = c;
@ -44,16 +42,10 @@ void restitution_coefficient_change (double d) {
C_r = 1.0; C_r = 1.0;
else if (C_r < 0.0) else if (C_r < 0.0)
C_r = 0.0; C_r = 0.0;
restitution_coefficient_show ();
} }
void restitution_coefficient_show () {
c_r_display_countdown = c_r_display_init;
};
void restitution_coefficient_draw (cairo_t * cr) { void restitution_coefficient_draw (cairo_t * cr) {
static const double margin = 20; static const double margin = 20;
if (c_r_display_countdown != 0) {
cairo_save(cr); cairo_save(cr);
cairo_new_path(cr); cairo_new_path(cr);
cairo_move_to(cr, margin, margin); cairo_move_to(cr, margin, margin);
@ -61,11 +53,8 @@ void restitution_coefficient_draw (cairo_t * cr) {
cairo_set_source_rgb(cr, 1.0, 1.0, 0.0); cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
cairo_set_line_width(cr, margin/2); cairo_set_line_width(cr, margin/2);
cairo_stroke(cr); cairo_stroke(cr);
if (c_r_display_countdown > 0)
--c_r_display_countdown;
cairo_restore(cr); cairo_restore(cr);
} }
}
static vec2d random_velocity() { static vec2d random_velocity() {
double r2; double r2;

View File

@ -43,7 +43,6 @@ extern void ball_ball_collision (ball * p, ball * q);
extern void ball_reposition (ball * b); extern void ball_reposition (ball * b);
extern void balls_draw (cairo_t * cr); extern void balls_draw (cairo_t * cr);
extern void restitution_coefficient_show ();
extern void restitution_coefficient_draw (cairo_t * cr); extern void restitution_coefficient_draw (cairo_t * cr);
extern void restitution_coefficient_set (double c); extern void restitution_coefficient_set (double c);
extern double restitution_coefficient_get (); extern double restitution_coefficient_get ();

View File

@ -1,19 +1,20 @@
#include <math.h> #include <string>
#include <sstream>
#include <cmath>
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include "gravity.h" #include "gravity.h"
#include "game.h" #include "game.h"
static vec2d g{.x = 0, .y = 20}; static const double constant_field_increment = 1.0;
static const double newton_field_increment = 1000.0;
static vec2d g{.x = 0, .y = 20};
static double g_r = 50; static double g_r = 50;
static double g_g = 10000000; static double g_g = 10000000;
static int constant_field = 1; static int constant_field = 1;
static int gravity_vector_countdown = 0;
static int gravity_vector_init = 300;
void gravity_constant_field (double x, double y) { void gravity_constant_field (double x, double y) {
constant_field = 1; constant_field = 1;
g.x = x; g.x = x;
@ -28,7 +29,6 @@ void gravity_newton_field (double r, double g) {
void gravity_draw (cairo_t * cr) { void gravity_draw (cairo_t * cr) {
if (constant_field) { if (constant_field) {
if (gravity_vector_countdown != 0) {
cairo_save(cr); cairo_save(cr);
cairo_new_path(cr); cairo_new_path(cr);
cairo_move_to(cr, width/2, height/2); cairo_move_to(cr, width/2, height/2);
@ -38,13 +38,27 @@ void gravity_draw (cairo_t * cr) {
cairo_stroke(cr); cairo_stroke(cr);
cairo_arc(cr, width/2 + g.x, height/2 + g.y, 3, 0, 2*M_PI); cairo_arc(cr, width/2 + g.x, height/2 + g.y, 3, 0, 2*M_PI);
cairo_fill(cr); cairo_fill(cr);
if (gravity_vector_countdown > 0) cairo_restore(cr);
--gravity_vector_countdown; } else {
std::ostringstream output;
output << (g_g/1000) << "K";
cairo_save (cr);
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size (cr, 16);
std::string output_str = output.str();
cairo_text_extents_t extent;
cairo_text_extents (cr, output_str.c_str(), &extent);
cairo_move_to (cr, width/2 - extent.width/2, height/2 + extent.height/2);
cairo_show_text (cr, output_str.c_str());
cairo_restore (cr); cairo_restore (cr);
} }
} else { }
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
void gravity_draw_visible_field (cairo_t * cr) {
if (!constant_field) {
cairo_save (cr); cairo_save (cr);
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
cairo_new_path (cr); cairo_new_path (cr);
cairo_arc (cr, width/2, height/2, g_r, 0, 2*M_PI); cairo_arc (cr, width/2, height/2, g_r, 0, 2*M_PI);
cairo_set_line_width(cr, 3.0); cairo_set_line_width(cr, 3.0);
@ -53,19 +67,13 @@ void gravity_draw (cairo_t * cr) {
} }
} }
void gravity_show () {
if (constant_field)
gravity_vector_countdown = gravity_vector_init;
};
void gravity_change (double dx, double dy) { void gravity_change (double dx, double dy) {
if (constant_field) { if (constant_field) {
g.x += dx; g.x += dx*constant_field_increment;
g.y += dy; g.y += dy*constant_field_increment;
gravity_show ();
} else { } else {
g_r += dx; g_r += dx;
g_g += dy; g_g -= dy*newton_field_increment;
} }
} }

View File

@ -8,9 +8,10 @@ extern void gravity_newton_field (double r, double g);
extern vec2d gravity_vector (const ball * b); extern vec2d gravity_vector (const ball * b);
extern void gravity_draw_visible_field (cairo_t * cr);
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_collisions (ball * begin, ball * end); extern void gravity_collisions (ball * begin, ball * end);

122
main.cc
View File

@ -62,27 +62,101 @@ void game_destroy () {
balls_destroy (); balls_destroy ();
} }
static guint timeout_source_id = 0; static guint animation_timeout_id = 0;
gboolean timeout (gpointer user_data); gboolean animation_timeout (gpointer user_data);
static bool game_paused () { static bool game_paused () {
return timeout_source_id == 0; return animation_timeout_id == 0;
} }
void game_animation_on_off () { void game_animation_on_off () {
if (timeout_source_id == 0) { if (animation_timeout_id == 0) {
timeout_source_id = g_timeout_add (delta * 1000, timeout, canvas); animation_timeout_id = g_timeout_add (delta * 1000, animation_timeout, canvas);
} else { } else {
g_source_remove (timeout_source_id); g_source_remove (animation_timeout_id);
timeout_source_id = 0; animation_timeout_id = 0;
} }
} }
struct param_controls {
void (*draw) (cairo_t * cr);
gint (*keyboard_input) (GdkEventKey *event);
gboolean (*mouse_scroll) (GtkWidget *widget, GdkEvent *event, gpointer user_data);
};
gint gravity_controls_keyboard_input (GdkEventKey *event) {
switch(event->keyval) {
case GDK_KEY_Up:
gravity_change (0, -10);
return TRUE;
case GDK_KEY_Down:
gravity_change (0, 10);
return TRUE;
case GDK_KEY_Left:
gravity_change (-10, 0);
return TRUE;
case GDK_KEY_Right:
gravity_change (10, 0);
return TRUE;
}
return FALSE;
}
param_controls gravity_control = {
.draw = gravity_draw,
.keyboard_input = gravity_controls_keyboard_input,
};
gint restitution_coefficient_controls_keyboard_input (GdkEventKey *event) {
switch(event->keyval) {
case GDK_KEY_Up:
restitution_coefficient_change (0.01);
return TRUE;
case GDK_KEY_Down:
restitution_coefficient_change (-0.01);
return TRUE;
case GDK_KEY_Left:
restitution_coefficient_change (-0.01);
return TRUE;
case GDK_KEY_Right:
restitution_coefficient_change (0.01);
return TRUE;
}
return FALSE;
}
param_controls restitution_coefficient_control = {
.draw = restitution_coefficient_draw,
.keyboard_input = restitution_coefficient_controls_keyboard_input,
};
static param_controls * param_control = nullptr;
static guint param_control_timeout_id = 0;
static const guint param_control_active_ms = 3000;
gboolean param_control_timeout (gpointer user_data) {
param_control = nullptr;
param_control_timeout_id = 0;
gtk_widget_queue_draw(canvas);
return FALSE;
}
void param_control_activate (struct param_controls * ctrl) {
if (param_control)
g_source_remove (param_control_timeout_id);
param_control = ctrl;
param_control_timeout_id = g_timeout_add (param_control_active_ms, param_control_timeout, canvas);
gtk_widget_queue_draw(canvas);
}
gboolean draw_frame (GtkWidget * widget, cairo_t *cr, gpointer data) { gboolean draw_frame (GtkWidget * widget, cairo_t *cr, gpointer data) {
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
cairo_paint(cr); cairo_paint(cr);
gravity_draw (cr); if (param_control)
restitution_coefficient_draw (cr); param_control->draw (cr);
gravity_draw_visible_field (cr);
balls_draw (cr); balls_draw (cr);
spaceship_draw (cr); spaceship_draw (cr);
return FALSE; return FALSE;
@ -104,33 +178,21 @@ gint configure_event (GtkWidget *widget, GdkEventConfigure * event) {
gint keyboard_input (GtkWidget *widget, GdkEventKey *event) { gint keyboard_input (GtkWidget *widget, GdkEventKey *event) {
if (event->type != GDK_KEY_PRESS) if (event->type != GDK_KEY_PRESS)
return FALSE; return FALSE;
if (! game_paused ()) { if (param_control && param_control->keyboard_input (event)) {
gtk_widget_queue_draw(canvas);
g_source_remove (param_control_timeout_id);
param_control_timeout_id = g_timeout_add (param_control_active_ms, param_control_timeout, canvas);
return TRUE;
}
switch(event->keyval) { switch(event->keyval) {
case GDK_KEY_Up:
gravity_change (0, -10);
return TRUE;
case GDK_KEY_Down:
gravity_change (0, 10);
return TRUE;
case GDK_KEY_Left:
gravity_change (-10, 0);
return TRUE;
case GDK_KEY_Right:
gravity_change (10, 0);
return TRUE;
case GDK_KEY_R: case GDK_KEY_R:
restitution_coefficient_change (0.01);
return TRUE;
case GDK_KEY_r: case GDK_KEY_r:
restitution_coefficient_change (-0.01); param_control_activate (&restitution_coefficient_control);
return TRUE; return TRUE;
case GDK_KEY_G: case GDK_KEY_G:
case GDK_KEY_g: case GDK_KEY_g:
gravity_show (); param_control_activate (&gravity_control);
return TRUE; return TRUE;
}
}
switch(event->keyval) {
case GDK_KEY_P: case GDK_KEY_P:
case GDK_KEY_p: case GDK_KEY_p:
game_animation_on_off (); game_animation_on_off ();
@ -201,7 +263,7 @@ gboolean draw_event (GtkWidget *widget, cairo_t * cr, gpointer data) {
return FALSE; return FALSE;
} }
gboolean timeout (gpointer user_data) { gboolean animation_timeout (gpointer user_data) {
if (stats_sampling > 0) { if (stats_sampling > 0) {
guint64 start = g_get_monotonic_time (); guint64 start = g_get_monotonic_time ();
update_state(); update_state();