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 <stdio.h> 38 #include <stdlib.h> 39 #include <X11/Xlib.h> 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 <time.h> 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>