主頁 | 自己紹介 | 日記 | 農業 | 台所 | 電算機 | | 本棚 | | Git

Xlibで遊んでみる3

前回: Xlibで遊んでみる2

言語: C言語
ソースコード: git

画面サイズの変更

画面サイズが変更された時に表示している四角形が画面の外側に出ないようにした。XGetWindowAttributes()で画面の情報を取得し、グローバル変数のwin_widthwin_heightに幅と高さをそれぞれ代入してnext_tick()で四角形の位置を画面に収まるようにしている:

int win_width, win_height;

void
receive_events(int key_state[])
{
	XEvent event;
	XWindowAttributes wattr;

	while (XPending(display) > 0) {
		XNextEvent(display, &event);
		switch (event.type) {
		case Expose: {
			XGetWindowAttributes(display, window, &wattr);
			win_width = wattr.width;
			win_height = wattr.height;
		} break;
		/* ... */
		}
	}
}

void
next_tick(long ndt) // nano second
{
	px = px + vx * ndt / 1000 / 1000 / 1000;
	py = py + vy * ndt / 1000 / 1000 / 1000;
	// bind within the window
	if (px < 0)
		px = 0;
	if (win_width < px + width)
		px = win_width - width;
	if (py < 0)
		py = 0;
	if (win_height < py + height)
		py = win_height - height;
}

メニュー画面の実装

ゲームのようなものを作るうえでメニュー画面とその推移が必要である。ここではグローバル変数next_menuに現在のメニューを保存することにした。それぞれのメニューはそれぞれ関数として記述し、他のメニューに推移する必要が生じたときにnext_menuを変更するようにした:

enum next_menu {
	START_MENU,
	GAME_PLAY,
	GAME_OVER,
	QUIT,
};

int next_menu = START_MENU;

void
start_menu(void)
{
	XEvent event;
	char *menu_char_q = "press q to quit.";
	char *menu_char_s = "press <space> to start.";

	XClearArea(display, window,
			   0, 0,                  // position
			   win_width, win_height, // width and height
			   False);
	XDrawString(display, window, gc,
				win_width/2 - strlen(menu_char_q)/2, win_height/2,
				menu_char_q, strlen(menu_char_q));
	XDrawString(display, window, gc,
				win_width/2 - strlen(menu_char_s)/2, win_height/2 + 20,
				menu_char_s, strlen(menu_char_s));

	while (next_menu == START_MENU) {
		XNextEvent(display, &event);
		switch (event.type) {
		case Expose: {
			XDrawString(display, window, gc,
						win_width/2 - strlen(menu_char_q)/2,
						win_height/2,
						menu_char_q, strlen(menu_char_q));
			XDrawString(display, window, gc,
						win_width/2 - strlen(menu_char_s)/2,
						win_height/2 + 20,
						menu_char_s, strlen(menu_char_s));

		} break;
		case KeyPress: {
			switch (XLookupKeysym(&event.xkey, 0)) {
			case 'q':
				next_menu = QUIT;
				break;
			case ' ':
				next_menu = GAME_PLAY;
				break;
			default:
				break;
			}
		} break;
		case ClientMessage: {
			if ((Atom) event.xclient.data.l[0] == wm_delete_window) {
				next_menu = QUIT;
			}
		} break;
		default:
			break;
		}
	}
}

int
main(void)
{
	setup();
	while (next_menu != QUIT){
		switch (next_menu){
		case START_MENU:
			start_menu();
			break;
		case GAME_PLAY:
			game_play();
			break;
		case GAME_OVER:
			game_over();
			break;
		default:
			break;
		}
	}

	cleanup();
	return 0;
}

main()関数がめっちゃすっきりした。

完成品

git

参考

次の記事: Xlibで遊んでみる4