GUI controls for restitution coefficient and gravity field
This commit is contained in:
parent
19125826bd
commit
c1dc49a9dc
27
balls.cc
27
balls.cc
@ -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,27 +42,18 @@ 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);
|
cairo_line_to(cr, margin + (width - 2*margin)*C_r, margin);
|
||||||
cairo_line_to(cr, margin + (width - 2*margin)*C_r, margin);
|
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);
|
cairo_restore(cr);
|
||||||
if (c_r_display_countdown > 0)
|
|
||||||
--c_r_display_countdown;
|
|
||||||
cairo_restore(cr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static vec2d random_velocity() {
|
static vec2d random_velocity() {
|
||||||
|
1
balls.h
1
balls.h
@ -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 ();
|
||||||
|
66
gravity.cc
66
gravity.cc
@ -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,23 +29,36 @@ 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);
|
cairo_line_to(cr, width/2 + g.x, height/2 + g.y);
|
||||||
cairo_line_to(cr, width/2 + g.x, height/2 + g.y);
|
|
||||||
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
|
||||||
cairo_set_line_width(cr, 1.0);
|
|
||||||
cairo_stroke(cr);
|
|
||||||
cairo_arc(cr, width/2 + g.x, height/2 + g.y, 3, 0, 2*M_PI);
|
|
||||||
cairo_fill(cr);
|
|
||||||
if (gravity_vector_countdown > 0)
|
|
||||||
--gravity_vector_countdown;
|
|
||||||
cairo_restore(cr);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
||||||
|
cairo_set_line_width(cr, 1.0);
|
||||||
|
cairo_stroke(cr);
|
||||||
|
cairo_arc(cr, width/2 + g.x, height/2 + g.y, 3, 0, 2*M_PI);
|
||||||
|
cairo_fill(cr);
|
||||||
|
cairo_restore(cr);
|
||||||
|
} else {
|
||||||
|
std::ostringstream output;
|
||||||
|
output << (g_g/1000) << "K";
|
||||||
cairo_save (cr);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gravity_draw_visible_field (cairo_t * cr) {
|
||||||
|
if (!constant_field) {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
132
main.cc
132
main.cc
@ -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)) {
|
||||||
switch(event->keyval) {
|
gtk_widget_queue_draw(canvas);
|
||||||
case GDK_KEY_Up:
|
g_source_remove (param_control_timeout_id);
|
||||||
gravity_change (0, -10);
|
param_control_timeout_id = g_timeout_add (param_control_active_ms, param_control_timeout, canvas);
|
||||||
return TRUE;
|
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:
|
|
||||||
restitution_coefficient_change (0.01);
|
|
||||||
return TRUE;
|
|
||||||
case GDK_KEY_r:
|
|
||||||
restitution_coefficient_change (-0.01);
|
|
||||||
return TRUE;
|
|
||||||
case GDK_KEY_G:
|
|
||||||
case GDK_KEY_g:
|
|
||||||
gravity_show ();
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
switch(event->keyval) {
|
switch(event->keyval) {
|
||||||
|
case GDK_KEY_R:
|
||||||
|
case GDK_KEY_r:
|
||||||
|
param_control_activate (&restitution_coefficient_control);
|
||||||
|
return TRUE;
|
||||||
|
case GDK_KEY_G:
|
||||||
|
case GDK_KEY_g:
|
||||||
|
param_control_activate (&gravity_control);
|
||||||
|
return TRUE;
|
||||||
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();
|
||||||
|
Loading…
Reference in New Issue
Block a user