Xlibで遊んでみる3
前回: Xlibで遊んでみる2
言語: C言語
ソースコード: git
画面サイズの変更
画面サイズが変更された時に表示している四角形が画面の外側に出ないようにした。XGetWindowAttributes()
で画面の情報を取得し、グローバル変数のwin_width
とwin_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()
関数がめっちゃすっきりした。
完成品
参考
次の記事: Xlibで遊んでみる4