www.mtkn.jp

Manuscripts for my personal webpage.
git clone https://git.mtkn.jp/www.mtkn.jp
Log | Files | Refs | LICENSE

xlib2.html (6692B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4 	<meta charset="utf-8">
      5 	<meta name="viewport" content="width=device-width,initial-scale=1">
      6 	<link rel="stylesheet" type="text/css" href="/style.css">
      7 	<link rel="icon" type="image/x-icon" href="/pics/favicon.ico">
      8 	<title>Xlibで遊んでみる</title>
      9 </head>
     10 <body>
     11 	<header>
     12 		<a href="/">主頁</a> |
     13 		<a href="/about.html">自己紹介</a> |
     14 		<a href="/journal">日記</a> |
     15 		<a href="/farm">農業</a> |
     16 		<a href="/kitchen">台所</a> |
     17 		<a href="/computer">電算機</a> |
     18 		<a href="/poetry">詩</a> |
     19 		<a href="/books">本棚</a> |
     20 		<a href="/gallery">絵</a> |
     21 		<a href="/plant">植物</a> |
     22 		<a href="https://git.mtkn.jp">Git</a>
     23 	</header>
     24 	<main>
     25 		<article>
     26 <h1>Xlibで遊んでみる</h1>
     27 <time>2022-12-16</time>
     28 
     29 <h2>はじめに</h2>
     30 <p>X11でGUIのプログラミングをしてみようと思い、してみた。X11用の低レベルのライブラリはXlibとxcbの二つがあるようだ。x.orgのウェブページを見てみると、Xlibは古く、xcbに置きかわりつつあるという。そのため、新しくなにかを作る場合はxcbを使うようにとのことである。ところがこのxcbはドキュメンテーションに乏しく、X11を触るのが初めての人間にはなにをどうすればいいのかほとんど分からなかった。知らない関数や構造体やらがでてきても(殆ど全部知らないものだが)、その関数なり構造体なりの説明がどこにも見当たらない。manページもない。あるのはdoxygenなるものでソースコードのコメントから自動生成したいい加減なものだけで、使いものにならない。</p>
     31 <p>とりあえずX11のことを少しは理解してからでないと初められそうもないと思い、もう少しましな情報があるXlibから始めることにした。</p>
     32 <p>言語はC言語である。ソースコードは<a href="https://git.mtkn.jp/xlib_playground">ここ</a>にある。
     33 
     34 <h2>初期設定</h2>
     35 <p>ディスプレイを開き、ウィンドウを作成する。変数はとりあえずグローバルに宣言することにした。<code>main</code>関数はできるだけ小さくして実際の処理はそれぞれの関数にさせてみる:</p>
     36 <pre><code>
     37 #include &lt;stdio.h&gt;
     38 #include &lt;stdlib.h&gt;
     39 #include &lt;X11/Xlib.h&gt;
     40 
     41 /* macros */
     42 #define INIT_WIDTH 800
     43 #define INIT_HEIGHT 600
     44 
     45 /* variables */
     46 Display     *display;
     47 Window       window;
     48 unsigned int win_width = INIT_WIDTH, win_height = INIT_HEIGHT;
     49 GC           gc;
     50 Atom         wm_delete_window;
     51 
     52 void
     53 setup(void)
     54 {
     55 	// Open a display.
     56 	if ((display = XOpenDisplay(NULL)) == NULL){
     57 	    fprintf(stderr, "ERROR: could not open display\n");
     58 	    exit(1);
     59 	}
     60 	// Create a window.
     61 	window = XCreateSimpleWindow(
     62 	                    display,
     63 	                    XDefaultRootWindow(display),
     64 	                    0, 0,
     65 	                    win_width, win_height,
     66 	                    0, 0,
     67 	                    0);
     68 	XStoreName(display, window, "UNKO");
     69 
     70 	// Setup a graphical context.
     71 	gc = XCreateGC(display, window, 0, NULL);
     72 	XSetForeground(display, gc, 0xFFFFFF);
     73 
     74 	// Kill the application when the window is destroyed.	
     75 	wm_delete_window = XInternAtom(display,
     76 	                               "WM_DELETE_WINDOW", False);
     77 	XSetWMProtocols(display, window, &wm_delete_window, 1);
     78 
     79 	// Setup which input to process.
     80 	XSelectInput(display, window,
     81 	             ExposureMask|KeyPressMask|KeyReleaseMask);
     82 
     83 	// Actually draw the window.
     84 	XMapWindow(display, window);
     85 }
     86 
     87 void
     88 clean_up(void)
     89 {
     90 	XCloseDisplay(display);
     91 }
     92 </code></pre>
     93 
     94 <p>適当な四角形のものを表示し、その位置を時間の関数として動かしてみる。</p>
     95 <pre><code>#include &lt;time.h&gt;
     96 
     97 int
     98 main(void)
     99 {
    100     int px, py;
    101     int quit;
    102     struct timespec ts;
    103     XEvent event;
    104 
    105     setup();
    106     quit = 0;
    107 
    108     while (!quit){
    109         while(XPending(display) > 0){
    110             XNextEvent(display, &event);
    111             switch (event.type){
    112             case KeyPress: {
    113                 switch (XLookupKeysym(&event.xkey, 0)){
    114                 case 'q':
    115                     quit = 1;
    116                     break;
    117                 default:
    118                     break;
    119                 }
    120             } break;
    121             case ClientMessage: {
    122                 if ((Atom) event.xclient.data.l[0] == wm_delete_window) {
    123                     quit = 1;
    124                 }
    125             } break;
    126             default:
    127                 break;
    128             }
    129         }
    130         clock_gettime(CLOCK_MONOTONIC, &ts);
    131         px = 200 + (int) (100 * sinf(ts.tv_sec + ts.tv_nsec / 1000.0 / 1000 / 1000));
    132         py = 200 + (int) (100 * cosf(ts.tv_sec + ts.tv_nsec / 1000.0 / 1000 / 1000));
    133         XClearArea(display, window,
    134                    0, 0,                  // position
    135                    win_width, win_height, // width and height
    136                    False);
    137         XFillRectangle(display, window, gc,
    138                        px, py,    // position
    139                        100, 100);   // width and height
    140 
    141         ts.tv_sec = 0;
    142         ts.tv_nsec = 10 * 1000 * 1000;
    143         nanosleep(&ts, NULL);
    144 	}
    145 
    146 	cleanup();
    147 	return 0;
    148 }
    149 </code></pre>
    150 
    151 <p>文字を表示。<code>XDrawString</code></p>
    152 
    153 <h2>キーボード入力</h2>
    154 <p>キーボードの入力を受け付けるようにする。入力によって四角形の位置や速度を変化させる。</p>
    155 <p>ここまでできればかなりなんでもできるようになる。</p>
    156 
    157 <h2>FPSの固定</h2>
    158 <p>前のフレームからの経過時間を計測して1/FPSを越えるまで待機させる。このときに<code>nanosleep</code>を使うとなぜか上手くいかなかった。OSに処理をブロックされる為か?とりあえず<code>while</code>ループの中でひたすら時刻を読んでいるのだが、これでいいんかな。リソースの無駄遣いではないんかな。</p>
    159 
    160 <h2>メニューの実装</h2>
    161 <p>メニューとゲームの推移を実装した。</p>
    162 
    163 <h2>当たり判定</h2>
    164 <p>とりあえず適当に実装した。2体間の衝突のみ判定しているので近くに別の物体がいるとめりこむ場合がある。</p>
    165 </p>
    166 
    167 
    168 <h2>参考</h2>
    169 <ul>
    170 <li><a href="https://tronche.com/gui/x/xlib/">The Xlib Manual(html conversion)</a></li>
    171 <li><a href="https://www.youtube.com/watch?v=764fnfEb1_c">X11 App in C with Xlib(youtube video by tsoding)</a></li>
    172 </ul>
    173 		</article>
    174 
    175 	</main>
    176 	<footer>
    177 		<address>info(at)mtkn(dot)jp</address>
    178 		<a href="http://creativecommons.org/publicdomain/zero/1.0?ref=chooser-v1" rel="license noopener noreferrer">CC0 1.0</a>
    179 	</footer>
    180 </body>
    181 </html>