www.mtkn.jp

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

xlib_playground3.html (4005B)


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