www.mtkn.jp

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

commit 522775b9915efc5243b8b541b718e30c3d7f4908
parent 15f08b96089791b266023ad51b595d6d2380bef7
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Wed, 21 Dec 2022 15:56:24 +0900

split xlib playground

Diffstat:
Aman/draft/xlib2.html | 169+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apub/draft/xlib2.html | 178+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 347 insertions(+), 0 deletions(-)

diff --git a/man/draft/xlib2.html b/man/draft/xlib2.html @@ -0,0 +1,169 @@ +<h1>Xlibで遊んでみる</h1> +<time>2022-12-16</time> + +<h2>はじめに</h2> +<p>X11でGUIのプログラミングをしてみようと思い、してみた。\ +X11用の低レベルのライブラリはXlibとxcbの二つがあるようだ。\ +x.orgのウェブページを見てみると、Xlibは古く、xcbに置きかわりつつあるという。\ +そのため、新しくなにかを作る場合はxcbを使うようにとのことである。\ +ところがこのxcbはドキュメンテーションに乏しく、\ +X11を触るのが初めての人間にはなにをどうすればいいのかほとんど分からなかった。\ +知らない関数や構造体やらがでてきても(殆ど全部知らないものだが)、\ +その関数なり構造体なりの説明がどこにも見当たらない。\ +manページもない。あるのはdoxygenなるものでソースコードのコメントから\ +自動生成したいい加減なものだけで、使いものにならない。</p> +<p>とりあえずX11のことを少しは理解してからでないと初められそうもないと思い、\ +もう少しましな情報があるXlibから始めることにした。\ +</p> +<p>言語はC言語である。ソースコードは\ +<a href="https://git.mtkn.jp/xlib_playground/log.html">ここ</a>にある。 + +<h2>初期設定</h2> +<p>ディスプレイを開き、ウィンドウを作成する。\ +変数はとりあえずグローバルに宣言することにした。\ +<code>main</code>関数はできるだけ小さくして実際の処理は\ +それぞれの関数にさせてみる:</p> +<pre><code> +#include &lt;stdio.h&gt; +#include &lt;stdlib.h&gt; +#include &lt;X11/Xlib.h&gt; + +/* macros */ +#define INIT_WIDTH 800 +#define INIT_HEIGHT 600 + +/* variables */ +Display *display; +Window window; +unsigned int win_width = INIT_WIDTH, win_height = INIT_HEIGHT; +GC gc; +Atom wm_delete_window; + +void +setup(void) +{ + // Open a display. + if ((display = XOpenDisplay(NULL)) == NULL){ + fprintf(stderr, "ERROR: could not open display\n"); + exit(1); + } + // Create a window. + window = XCreateSimpleWindow( + display, + XDefaultRootWindow(display), + 0, 0, + win_width, win_height, + 0, 0, + 0); + XStoreName(display, window, "UNKO"); + + // Setup a graphical context. + gc = XCreateGC(display, window, 0, NULL); + XSetForeground(display, gc, 0xFFFFFF); + + // Kill the application when the window is destroyed. + wm_delete_window = XInternAtom(display, + "WM_DELETE_WINDOW", False); + XSetWMProtocols(display, window, &wm_delete_window, 1); + + // Setup which input to process. + XSelectInput(display, window, + ExposureMask|KeyPressMask|KeyReleaseMask); + + // Actually draw the window. + XMapWindow(display, window); +} + +void +clean_up(void) +{ + XCloseDisplay(display); +} +</code></pre> + +<p>適当な四角形のものを表示し、その位置を時間の関数として動かしてみる。\ +</p> +<pre><code>#include &lt;time.h&gt; + +int +main(void) +{ + int px, py; + int quit; + struct timespec ts; + XEvent event; + + setup(); + quit = 0; + + while (!quit){ + while(XPending(display) > 0){ + XNextEvent(display, &event); + switch (event.type){ + case KeyPress: { + switch (XLookupKeysym(&event.xkey, 0)){ + case 'q': + quit = 1; + break; + default: + break; + } + } break; + case ClientMessage: { + if ((Atom) event.xclient.data.l[0] == wm_delete_window) { + quit = 1; + } + } break; + default: + break; + } + } + clock_gettime(CLOCK_MONOTONIC, &ts); + px = 200 + (int) (100 * sinf(ts.tv_sec + ts.tv_nsec / 1000.0 / 1000 / 1000)); + py = 200 + (int) (100 * cosf(ts.tv_sec + ts.tv_nsec / 1000.0 / 1000 / 1000)); + XClearArea(display, window, + 0, 0, // position + win_width, win_height, // width and height + False); + XFillRectangle(display, window, gc, + px, py, // position + 100, 100); // width and height + + ts.tv_sec = 0; + ts.tv_nsec = 10 * 1000 * 1000; + nanosleep(&ts, NULL); + } + + cleanup(); + return 0; +} +</code></pre> + +<p>文字を表示。<code>XDrawString</code></p> + +<h2>キーボード入力</h2> +<p>キーボードの入力を受け付けるようにする。\ +入力によって四角形の位置や速度を変化させる。</p> +<p>ここまでできればかなりなんでもできるようになる。</p> + +<h2>FPSの固定</h2> +<p>前のフレームからの経過時間を計測して1/FPSを越えるまで待機させる。\ +このときに<code>nanosleep</code>を使うとなぜか上手くいかなかった。\ +OSに処理をブロックされる為か?とりあえず<code>while</code>ループの中で\ +ひたすら時刻を読んでいるのだが、これでいいんかな。\ +リソースの無駄遣いではないんかな。</p> + +<h2>メニューの実装</h2> +<p>メニューとゲームの推移を実装した。</p> + +<h2>当たり判定</h2> +<p>とりあえず適当に実装した。\ +2体間の衝突のみ判定しているので近くに別の物体がいるとめりこむ場合がある。</p> +</p> + + +<h2>参考</h2> +<ul> +<li><a href="https://tronche.com/gui/x/xlib/">The Xlib Manual(html conversion)</a></li> +<li><a href="https://www.youtube.com/watch?v=764fnfEb1_c">X11 App in C with Xlib(youtube video by tsoding)</a></li> +</ul> diff --git a/pub/draft/xlib2.html b/pub/draft/xlib2.html @@ -0,0 +1,178 @@ +<!DOCTYPE html> +<html lang="ja"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <link rel="stylesheet" type="text/css" href="/style.css" /> + <link rel="icon" type="image/x-icon" href="/pics/favicon.ico" /> + <title>Xlibで遊んでみる</title> +</head> +<body> + <header> + <a href="/">主頁</a> | + <a href="/about.html">自己紹介</a> | + <a href="/journal">日記</a> | + <a href="/farm">農業</a> | + <a href="/kitchen">台所</a> | + <a href="/computer">コンピュータ</a> | + <a href="/poetry">詩</a> | + <a href="/books">本棚</a> | + <a href="https://git.mtkn.jp">Git</a> + </header> + <main> + <article> +<h1>Xlibで遊んでみる</h1> +<time>2022-12-16</time> + +<h2>はじめに</h2> +<p>X11でGUIのプログラミングをしてみようと思い、してみた。X11用の低レベルのライブラリはXlibとxcbの二つがあるようだ。x.orgのウェブページを見てみると、Xlibは古く、xcbに置きかわりつつあるという。そのため、新しくなにかを作る場合はxcbを使うようにとのことである。ところがこのxcbはドキュメンテーションに乏しく、X11を触るのが初めての人間にはなにをどうすればいいのかほとんど分からなかった。知らない関数や構造体やらがでてきても(殆ど全部知らないものだが)、その関数なり構造体なりの説明がどこにも見当たらない。manページもない。あるのはdoxygenなるものでソースコードのコメントから自動生成したいい加減なものだけで、使いものにならない。</p> +<p>とりあえずX11のことを少しは理解してからでないと初められそうもないと思い、もう少しましな情報があるXlibから始めることにした。</p> +<p>言語はC言語である。ソースコードは<a href="https://git.mtkn.jp/xlib_playground/log.html">ここ</a>にある。 + +<h2>初期設定</h2> +<p>ディスプレイを開き、ウィンドウを作成する。変数はとりあえずグローバルに宣言することにした。<code>main</code>関数はできるだけ小さくして実際の処理はそれぞれの関数にさせてみる:</p> +<pre><code> +#include &lt;stdio.h&gt; +#include &lt;stdlib.h&gt; +#include &lt;X11/Xlib.h&gt; + +/* macros */ +#define INIT_WIDTH 800 +#define INIT_HEIGHT 600 + +/* variables */ +Display *display; +Window window; +unsigned int win_width = INIT_WIDTH, win_height = INIT_HEIGHT; +GC gc; +Atom wm_delete_window; + +void +setup(void) +{ + // Open a display. + if ((display = XOpenDisplay(NULL)) == NULL){ + fprintf(stderr, "ERROR: could not open display\n"); + exit(1); + } + // Create a window. + window = XCreateSimpleWindow( + display, + XDefaultRootWindow(display), + 0, 0, + win_width, win_height, + 0, 0, + 0); + XStoreName(display, window, "UNKO"); + + // Setup a graphical context. + gc = XCreateGC(display, window, 0, NULL); + XSetForeground(display, gc, 0xFFFFFF); + + // Kill the application when the window is destroyed. + wm_delete_window = XInternAtom(display, + "WM_DELETE_WINDOW", False); + XSetWMProtocols(display, window, &wm_delete_window, 1); + + // Setup which input to process. + XSelectInput(display, window, + ExposureMask|KeyPressMask|KeyReleaseMask); + + // Actually draw the window. + XMapWindow(display, window); +} + +void +clean_up(void) +{ + XCloseDisplay(display); +} +</code></pre> + +<p>適当な四角形のものを表示し、その位置を時間の関数として動かしてみる。</p> +<pre><code>#include &lt;time.h&gt; + +int +main(void) +{ + int px, py; + int quit; + struct timespec ts; + XEvent event; + + setup(); + quit = 0; + + while (!quit){ + while(XPending(display) > 0){ + XNextEvent(display, &event); + switch (event.type){ + case KeyPress: { + switch (XLookupKeysym(&event.xkey, 0)){ + case 'q': + quit = 1; + break; + default: + break; + } + } break; + case ClientMessage: { + if ((Atom) event.xclient.data.l[0] == wm_delete_window) { + quit = 1; + } + } break; + default: + break; + } + } + clock_gettime(CLOCK_MONOTONIC, &ts); + px = 200 + (int) (100 * sinf(ts.tv_sec + ts.tv_nsec / 1000.0 / 1000 / 1000)); + py = 200 + (int) (100 * cosf(ts.tv_sec + ts.tv_nsec / 1000.0 / 1000 / 1000)); + XClearArea(display, window, + 0, 0, // position + win_width, win_height, // width and height + False); + XFillRectangle(display, window, gc, + px, py, // position + 100, 100); // width and height + + ts.tv_sec = 0; + ts.tv_nsec = 10 * 1000 * 1000; + nanosleep(&ts, NULL); + } + + cleanup(); + return 0; +} +</code></pre> + +<p>文字を表示。<code>XDrawString</code></p> + +<h2>キーボード入力</h2> +<p>キーボードの入力を受け付けるようにする。入力によって四角形の位置や速度を変化させる。</p> +<p>ここまでできればかなりなんでもできるようになる。</p> + +<h2>FPSの固定</h2> +<p>前のフレームからの経過時間を計測して1/FPSを越えるまで待機させる。このときに<code>nanosleep</code>を使うとなぜか上手くいかなかった。OSに処理をブロックされる為か?とりあえず<code>while</code>ループの中でひたすら時刻を読んでいるのだが、これでいいんかな。リソースの無駄遣いではないんかな。</p> + +<h2>メニューの実装</h2> +<p>メニューとゲームの推移を実装した。</p> + +<h2>当たり判定</h2> +<p>とりあえず適当に実装した。2体間の衝突のみ判定しているので近くに別の物体がいるとめりこむ場合がある。</p> +</p> + + +<h2>参考</h2> +<ul> +<li><a href="https://tronche.com/gui/x/xlib/">The Xlib Manual(html conversion)</a></li> +<li><a href="https://www.youtube.com/watch?v=764fnfEb1_c">X11 App in C with Xlib(youtube video by tsoding)</a></li> +</ul> + </article> + + </main> + <footer> + <address>info(at)mtkn(dot)jp</address> + </footer> +</body> +</html>