www.mtkn.jp

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

xlib_playground3.html (3972B)


      1 <h1>Xlibで遊んでみる3</h1>
      2 <time>2023-01-02</time>
      3 
      4 <p>
      5 前回: <a href="xlib_playground2.html">Xlibで遊んでみる2</a>
      6 </p>
      7 <p>
      8 言語: C言語<br />
      9 ソースコード: \
     10 <a href="https://git.mtkn.jp/xlib_playground">git</a>
     11 </p>
     12 
     13 <h2>画面サイズの変更</h2>
     14 <p>
     15 画面サイズが変更された時に表示している四角形が画面の外側に\
     16 出ないようにした。<code>XGetWindowAttributes()</code>で\
     17 画面の情報を取得し、グローバル変数の<code>win_width</code>\
     18 と<code>win_height</code>に幅と高さをそれぞれ代入して\
     19 <code>next_tick()</code>で四角形の位置を画面に収まるよう\
     20 にしている:
     21 </p>
     22 <pre><code>\
     23 int win_width, win_height;
     24 
     25 void
     26 receive_events(int key_state[])
     27 {
     28 	XEvent event;
     29 	XWindowAttributes wattr;
     30 
     31 	while (XPending(display) &gt; 0) {
     32 		XNextEvent(display, &event);
     33 		switch (event.type) {
     34 		case Expose: {
     35 			XGetWindowAttributes(display, window, &wattr);
     36 			win_width = wattr.width;
     37 			win_height = wattr.height;
     38 		} break;
     39 		/* ... */
     40 		}
     41 	}
     42 }
     43 
     44 void
     45 next_tick(long ndt) // nano second
     46 {
     47 	px = px + vx * ndt / 1000 / 1000 / 1000;
     48 	py = py + vy * ndt / 1000 / 1000 / 1000;
     49 	// bind within the window
     50 	if (px &lt; 0)
     51 		px = 0;
     52 	if (win_width &lt; px + width)
     53 		px = win_width - width;
     54 	if (py &lt; 0)
     55 		py = 0;
     56 	if (win_height &lt; py + height)
     57 		py = win_height - height;
     58 }
     59 </code></pre>
     60 
     61 <h2>メニュー画面の実装</h2>
     62 <p>
     63 ゲームのようなものを作るうえでメニュー画面とその推移が必要である。\
     64 ここではグローバル変数<code>next_menu</code>に現在のメニューを保存\
     65 することにした。それぞれのメニューはそれぞれ関数として記述し、\
     66 他のメニューに推移する必要が生じたときに<code>next_menu</code>\
     67 を変更するようにした:
     68 </p>
     69 <pre><code>\
     70 enum next_menu {
     71 	START_MENU,
     72 	GAME_PLAY,
     73 	GAME_OVER,
     74 	QUIT,
     75 };
     76 
     77 int next_menu = START_MENU;
     78 
     79 void
     80 start_menu(void)
     81 {
     82 	XEvent event;
     83 	char *menu_char_q = "press q to quit.";
     84 	char *menu_char_s = "press &lt;space&gt; to start.";
     85 
     86 	XClearArea(display, window,
     87 			   0, 0,                  // position
     88 			   win_width, win_height, // width and height
     89 			   False);
     90 	XDrawString(display, window, gc,
     91 				win_width/2 - strlen(menu_char_q)/2, win_height/2,
     92 				menu_char_q, strlen(menu_char_q));
     93 	XDrawString(display, window, gc,
     94 				win_width/2 - strlen(menu_char_s)/2, win_height/2 + 20,
     95 				menu_char_s, strlen(menu_char_s));
     96 
     97 	while (next_menu == START_MENU) {
     98 		XNextEvent(display, &event);
     99 		switch (event.type) {
    100 		case Expose: {
    101 			XDrawString(display, window, gc,
    102 						win_width/2 - strlen(menu_char_q)/2,
    103 						win_height/2,
    104 						menu_char_q, strlen(menu_char_q));
    105 			XDrawString(display, window, gc,
    106 						win_width/2 - strlen(menu_char_s)/2,
    107 						win_height/2 + 20,
    108 						menu_char_s, strlen(menu_char_s));
    109 
    110 		} break;
    111 		case KeyPress: {
    112 			switch (XLookupKeysym(&event.xkey, 0)) {
    113 			case 'q':
    114 				next_menu = QUIT;
    115 				break;
    116 			case ' ':
    117 				next_menu = GAME_PLAY;
    118 				break;
    119 			default:
    120 				break;
    121 			}
    122 		} break;
    123 		case ClientMessage: {
    124 			if ((Atom) event.xclient.data.l[0] == wm_delete_window) {
    125 				next_menu = QUIT;
    126 			}
    127 		} break;
    128 		default:
    129 			break;
    130 		}
    131 	}
    132 }
    133 
    134 int
    135 main(void)
    136 {
    137 	setup();
    138 	while (next_menu != QUIT){
    139 		switch (next_menu){
    140 		case START_MENU:
    141 			start_menu();
    142 			break;
    143 		case GAME_PLAY:
    144 			game_play();
    145 			break;
    146 		case GAME_OVER:
    147 			game_over();
    148 			break;
    149 		default:
    150 			break;
    151 		}
    152 	}
    153 
    154 	cleanup();
    155 	return 0;
    156 }
    157 </code></pre>
    158 <p><code>main()</code>関数がめっちゃすっきりした。</p>
    159 
    160 <h2>完成品</h2>
    161 <p>
    162 <a href="https://git.mtkn.jp/xlib_playground/file/ex3/ex3.c.html">git</a>
    163 </p>
    164 <p>
    165 <video controls>
    166 <source src="videos/ex3.webm" type="video/webm">
    167 </video>
    168 </p>
    169 
    170 <h2>参考</h2>
    171 <ul>
    172 <li><a href="https://tronche.com/gui/x/xlib/">The Xlib Manual(html conversion)</a></li>
    173 </ul>
    174 <p>
    175 次の記事: \
    176 <a href="xlib_playground4.html">Xlibで遊んでみる4</a>
    177 </p>