![]() |
![]() |
![]() |
タイムカウント
1秒ごとに変化させるプログラムを書いてみる。 まずは端末の標準出力から、タイムカウントを表示させてみる。
|
#include <gtk/gtk.h> static gboolean ivent_loop(gpointer user_data) { static gint count = 0; //g_printはprintfのgtk+版
g_print("progress(sec.):%2d\n", count++);return (TRUE); } int main(int argc, char *argv[]) { gtk_init(&argc, &argv); //1000ミリ秒毎にivent_loop()関数を呼び出す。
g_timeout_add(1000, (GSourceFunc)ivent_loop, NULL);gtk_main(); return 0; } |
GDKとCairo
GTK+マニュアルdevhelpの中に、GDKのCairoの説明が有った。 ウィンドウの中に描画し、形、色、サイズ、位置を指定できるらしい。 これは使ってみたいと思い、チャレンジしてみた。 まず、図形を描いてみる。
|
#include <gtk/gtk.h> #include <gdk/gdk.h> GtkWidget *window; static gboolean cb_expose_event(GtkWidget *widget, cairo_t *cr, gpointer data) { cr = gdk_cairo_create(gtk_widget_get_window(widget)); //線の太さ
cairo_set_line_width(cr, 5.0); //角を丸くする
cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); //長方形の描画
{ //赤色の指定(外枠:Red,Green,Blue)
cairo_set_source_rgb(cr, 1.0, 0.0, 0.0); //長方形(x,y,width,height)を描画
cairo_rectangle(cr, 50.0, 50.0, 50.0, 50.0); //長方形の外枠を作る
cairo_stroke_preserve(cr); //桃色の指定(塗りつぶし:Red,Green,Blue)
cairo_set_source_rgb(cr, 1.0, 0.8, 0.8); //長方形を塗りつぶす
cairo_fill(cr);} //グラデーション付き長方形
{ //外枠(青)を作る
cairo_set_source_rgb(cr, 0.0, 0.0, 1.0);cairo_rectangle(cr, 150.0, 50.0, 50.0, 50.0); cairo_stroke_preserve(cr); //グラデーションを作る
//どのようなグラデーションにするかをpattern変数で指定する
cairo_pattern_t *pattern;pattern = cairo_pattern_create_linear(200.0, 60.0, 200.0, 100.0); //白(1.0, 1.0, 1.0)から青(0.0, 1.0, 0.0)にグラデーションする
cairo_pattern_add_color_stop_rgb(pattern, 0.0, 1.0, 1.0, 1.0);cairo_pattern_add_color_stop_rgb(pattern, 1.0, 0.0, 0.0, 1.0); //上記のグラデーションを設定する
cairo_set_source(cr, pattern); //上記のグラデーションで長方形を塗りつぶす
cairo_rectangle(cr, 150.0, 50.0, 50.0, 50.0);cairo_fill(cr); } //円形(長方形とほぼ同じ)
{ //枠は緑色
cairo_set_source_rgb(cr, 0.0, 1.0, 0.0); //円(x,y,半径,角度(start):0°,角度(end):360°)を描画
cairo_arc(cr, 270.0, 75.0, 20.0, 0.0, 2.0*3.14);cairo_stroke_preserve(cr); //塗りつぶしは黄色
cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);cairo_fill(cr); } cairo_destroy(cr); return FALSE; } int main(int argc, char *argv[]) { gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "draw"); gtk_widget_set_size_request(window, 400,200); //ウインドウに図形を描けるように設定
gtk_widget_set_app_paintable(window, TRUE);gtk_widget_add_events (window, GDK_BUTTON_PRESS_MASK); //ウインドウが表示されたときにcb_expose_event()を呼び出す
g_signal_connect(G_OBJECT(window), "draw", G_CALLBACK(cb_expose_event), NULL);g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show_all(window); gtk_main(); return 0; } |
図形の等速移動
いま作った黄色い円を、上下左右に等速運動させてみる。画面の端で、円を跳ね返す。
|
#include <gtk/gtk.h> #include <gdk/gdk.h> GtkWidget *window; //ウインドウの横幅
#define W_WIDTH 350//ウインドウの縦幅
#define W_HEIGHT 500static gboolean cb_expose_event(GtkWidget *widget, cairo_t *cr, gpointer data) { cr = gdk_cairo_create(gtk_widget_get_window(widget)); //ボールに関する変数
//ボールのx座標
static gint x = W_WIDTH/2; //ボールのy座標
static gint y = W_HEIGHT/2; //ボールの半径
static gdouble radius = 20.0; //ボールの進む向きのx方向
static gint vx = 1; //ボールの進む向きのy方向
static gint vy = 1; //ボールの進む速さ
static gint velocity = 5; //ウインドウの端でボールを跳ね返す
if( x + radius > W_WIDTH || x - radius < 0 ) vx *= -1;if( y + radius > W_HEIGHT || y - radius < 0 ) vy *= -1; x += vx * velocity; y += vy * velocity; //図形の位置を指定する
cairo_translate(cr, x, y); //ボールを描画する
cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);cairo_arc(cr, 0.0, 0.0, radius, 0.0, 2.0*3.14); cairo_stroke_preserve(cr); cairo_set_source_rgb(cr, 1.0, 1.0, 0.0); cairo_fill(cr); cairo_destroy(cr); return FALSE; } static gboolean ivent_loop(GtkWidget *widget) { if (gtk_widget_get_window(widget) == NULL) { return FALSE; } gtk_widget_queue_draw(widget); return (TRUE); } int main(int argc, char *argv[]) { GtkWidget *window; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "move"); gtk_widget_set_size_request(window, W_WIDTH, W_HEIGHT); gtk_widget_set_app_paintable(window, TRUE); gtk_widget_add_events (window, GDK_BUTTON_PRESS_MASK); g_signal_connect(G_OBJECT(window), "draw", G_CALLBACK(cb_expose_event), NULL); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); g_timeout_add(50, (GSourceFunc)ivent_loop, window); gtk_widget_show_all(window); gtk_main(); return 0; } |
赤い矢印の方向に、円が等速で移動する。
図形の加速移動
錆びついた物理知識を掘り起こし、空気抵抗無しのスーパーボールを作ってみる。 位置エネルギーと運動エネルギーのみを使い、自由落下から永久にバウンドさせ続ける。 バウンド時の跳ね返り係数は1とする。
|
#include <gtk/gtk.h> #include <gdk/gdk.h> #include <math.h> GtkWidget *window; //ウインドウの横幅
#define W_WIDTH 350//ウインドウの縦幅
#define W_HEIGHT 500.0static gboolean cb_expose_event(GtkWidget *widget, cairo_t *cr, gpointer data) { cr = gdk_cairo_create(gtk_widget_get_window(widget)); //ボールに関する変数
//ボールの半径
static gint radius = 20; //ボールのx座標
static gint x = W_WIDTH/2; //ボールのy座標
static gdouble y = 20;static gdouble g = 9.8; static gint t = 0; static gint h1; static gint h0; static gint h; static gdouble v; static gdouble v0; static gboolean f = TRUE; static gint y2; h1 = W_HEIGHT - radius; h0 = radius; h = h1 - h0; v0 = sqrt( 2 * g * h ); ++t; if( f == TRUE ){ y = g * pow( t, 2 ) / 2; v = g * t; if( y >= 480 || v >= v0 ){ t = 0; y = h1; f = FALSE; v = v0; } } else{ y = h1 - v0 * t + g * pow( t, 2 ) / 2; v = v0 - g * t; if( y <= 20 || v <= 0 ){ t = 1; y = h0; f = TRUE; v = 0; } } y2 = y / 1; g_printf( "t:%d y:%d\n", t, y2 ); //図形の位置を指定する
cairo_translate(cr, x, y2); //ボールを描画する
cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);cairo_arc(cr, 0.0, 0.0, radius, 0.0, 2.0*3.14); cairo_stroke_preserve(cr); cairo_set_source_rgb(cr, 1.0, 1.0, 0.0); cairo_fill(cr); cairo_destroy(cr); return FALSE; } static gboolean ivent_loop(GtkWidget *widget) { if (gtk_widget_get_window(widget) == NULL){ return FALSE; } gtk_widget_queue_draw(widget); return (TRUE); } int main(int argc, char *argv[]) { GtkWidget *window; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "super ball"); gtk_widget_set_size_request(window, W_WIDTH, W_HEIGHT); gtk_widget_set_app_paintable(window, TRUE); gtk_widget_add_events (window, GDK_BUTTON_PRESS_MASK); g_signal_connect(G_OBJECT(window), "draw", G_CALLBACK(cb_expose_event), NULL); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); g_timeout_add(50, (GSourceFunc)ivent_loop, window); gtk_widget_show_all(window); gtk_main(); return 0; } |