GUI controls for restitution coefficient and gravity field
This commit is contained in:
parent
19125826bd
commit
c1dc49a9dc
11
balls.cc
11
balls.cc
@ -23,8 +23,6 @@ unsigned int n_balls = 50;
|
||||
// C_r == 0.0 ==> perfectly inelastic collisions
|
||||
//
|
||||
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) {
|
||||
C_r = c;
|
||||
@ -44,16 +42,10 @@ void restitution_coefficient_change (double d) {
|
||||
C_r = 1.0;
|
||||
else if (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) {
|
||||
static const double margin = 20;
|
||||
if (c_r_display_countdown != 0) {
|
||||
cairo_save(cr);
|
||||
cairo_new_path(cr);
|
||||
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_line_width(cr, margin/2);
|
||||
cairo_stroke(cr);
|
||||
if (c_r_display_countdown > 0)
|
||||
--c_r_display_countdown;
|
||||
cairo_restore(cr);
|
||||
}
|
||||
}
|
||||
|
||||
static vec2d random_velocity() {
|
||||
double r2;
|
||||
|
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 balls_draw (cairo_t * cr);
|
||||
|
||||
extern void restitution_coefficient_show ();
|
||||
extern void restitution_coefficient_draw (cairo_t * cr);
|
||||
extern void restitution_coefficient_set (double c);
|
||||
extern double restitution_coefficient_get ();
|
||||
|
46
gravity.cc
46
gravity.cc
@ -1,19 +1,20 @@
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <cmath>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "gravity.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_g = 10000000;
|
||||
|
||||
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) {
|
||||
constant_field = 1;
|
||||
g.x = x;
|
||||
@ -28,7 +29,6 @@ void gravity_newton_field (double r, double g) {
|
||||
|
||||
void gravity_draw (cairo_t * cr) {
|
||||
if (constant_field) {
|
||||
if (gravity_vector_countdown != 0) {
|
||||
cairo_save(cr);
|
||||
cairo_new_path(cr);
|
||||
cairo_move_to(cr, width/2, height/2);
|
||||
@ -38,13 +38,27 @@ void gravity_draw (cairo_t * cr) {
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
} 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_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
||||
cairo_new_path (cr);
|
||||
cairo_arc (cr, width/2, height/2, g_r, 0, 2*M_PI);
|
||||
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) {
|
||||
if (constant_field) {
|
||||
g.x += dx;
|
||||
g.y += dy;
|
||||
gravity_show ();
|
||||
g.x += dx*constant_field_increment;
|
||||
g.y += dy*constant_field_increment;
|
||||
} else {
|
||||
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 void gravity_draw_visible_field (cairo_t * cr);
|
||||
|
||||
extern void gravity_draw (cairo_t * cr);
|
||||
extern void gravity_change (double dx, double dy);
|
||||
extern void gravity_show ();
|
||||
|
||||
extern void gravity_collisions (ball * begin, ball * end);
|
||||
|
||||
|
122
main.cc
122
main.cc
@ -62,27 +62,101 @@ void game_destroy () {
|
||||
balls_destroy ();
|
||||
}
|
||||
|
||||
static guint timeout_source_id = 0;
|
||||
gboolean timeout (gpointer user_data);
|
||||
static guint animation_timeout_id = 0;
|
||||
gboolean animation_timeout (gpointer user_data);
|
||||
|
||||
static bool game_paused () {
|
||||
return timeout_source_id == 0;
|
||||
return animation_timeout_id == 0;
|
||||
}
|
||||
|
||||
void game_animation_on_off () {
|
||||
if (timeout_source_id == 0) {
|
||||
timeout_source_id = g_timeout_add (delta * 1000, timeout, canvas);
|
||||
if (animation_timeout_id == 0) {
|
||||
animation_timeout_id = g_timeout_add (delta * 1000, animation_timeout, canvas);
|
||||
} else {
|
||||
g_source_remove (timeout_source_id);
|
||||
timeout_source_id = 0;
|
||||
g_source_remove (animation_timeout_id);
|
||||
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) {
|
||||
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
|
||||
cairo_paint(cr);
|
||||
gravity_draw (cr);
|
||||
restitution_coefficient_draw (cr);
|
||||
if (param_control)
|
||||
param_control->draw (cr);
|
||||
gravity_draw_visible_field (cr);
|
||||
balls_draw (cr);
|
||||
spaceship_draw (cr);
|
||||
return FALSE;
|
||||
@ -104,33 +178,21 @@ gint configure_event (GtkWidget *widget, GdkEventConfigure * event) {
|
||||
gint keyboard_input (GtkWidget *widget, GdkEventKey *event) {
|
||||
if (event->type != GDK_KEY_PRESS)
|
||||
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) {
|
||||
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:
|
||||
restitution_coefficient_change (0.01);
|
||||
return TRUE;
|
||||
case GDK_KEY_r:
|
||||
restitution_coefficient_change (-0.01);
|
||||
param_control_activate (&restitution_coefficient_control);
|
||||
return TRUE;
|
||||
case GDK_KEY_G:
|
||||
case GDK_KEY_g:
|
||||
gravity_show ();
|
||||
param_control_activate (&gravity_control);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
switch(event->keyval) {
|
||||
case GDK_KEY_P:
|
||||
case GDK_KEY_p:
|
||||
game_animation_on_off ();
|
||||
@ -201,7 +263,7 @@ gboolean draw_event (GtkWidget *widget, cairo_t * cr, gpointer data) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean timeout (gpointer user_data) {
|
||||
gboolean animation_timeout (gpointer user_data) {
|
||||
if (stats_sampling > 0) {
|
||||
guint64 start = g_get_monotonic_time ();
|
||||
update_state();
|
||||
|
Loading…
Reference in New Issue
Block a user