1// input_demo.c
2// λΉλκΈ° ν€λ³΄λ μ
λ ₯ μμ° νλ‘κ·Έλ¨
3// termiosλ₯Ό μ¬μ©νμ¬ non-blocking μ
λ ₯μ ꡬνν©λλ€.
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <termios.h>
8#include <unistd.h>
9#include <fcntl.h>
10
11// μλ ν°λ―Έλ μ€μ μ μ₯
12static struct termios original_termios;
13
14// ν°λ―Έλμ raw λͺ¨λλ‘ μ€μ
15void enable_raw_mode(void) {
16 // νμ¬ ν°λ―Έλ μ€μ μ μ₯
17 tcgetattr(STDIN_FILENO, &original_termios);
18
19 struct termios raw = original_termios;
20
21 // μ
λ ₯ νλκ·Έ μμ
22 // ECHO: μ
λ ₯ν λ¬Έμ νλ©΄μ νμ μν¨
23 // ICANON: λΌμΈ λ²νΌλ§ λκΈ° (μν° μμ΄ μ¦μ μ½κΈ°)
24 raw.c_lflag &= ~(ECHO | ICANON);
25
26 // μ΅μ μ
λ ₯ λ¬Έμ μ: 0 (non-blocking κ°λ₯)
27 raw.c_cc[VMIN] = 0;
28 // νμμμ: 0 (μ¦μ λ°ν)
29 raw.c_cc[VTIME] = 0;
30
31 // μμ λ μ€μ μ μ©
32 tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
33}
34
35// ν°λ―Έλ μ€μ 볡μ
36void disable_raw_mode(void) {
37 tcsetattr(STDIN_FILENO, TCSAFLUSH, &original_termios);
38}
39
40// ν€ μ
λ ₯ νμΈ (non-blocking)
41// λ°ν: 1 = μ
λ ₯ μμ, 0 = μ
λ ₯ μμ
42int kbhit(void) {
43 int ch = getchar();
44 if (ch != EOF) {
45 ungetc(ch, stdin); // μ½μ λ¬Έμλ₯Ό λ€μ λ²νΌμ λ£μ
46 return 1;
47 }
48 return 0;
49}
50
51// ν€ μ½κΈ° (non-blocking)
52int getch(void) {
53 return getchar();
54}
55
56// λ°©ν₯ν€ λ° νΉμν€ μ½λ
57typedef enum {
58 KEY_NONE = 0,
59 KEY_UP,
60 KEY_DOWN,
61 KEY_LEFT,
62 KEY_RIGHT,
63 KEY_QUIT,
64 KEY_SPACE,
65 KEY_ENTER,
66 KEY_OTHER
67} KeyCode;
68
69// ν€ μ½κΈ° λ° ν΄μ (escape sequence μ²λ¦¬)
70KeyCode read_key(void) {
71 int ch = getchar();
72
73 // μ
λ ₯ μμ
74 if (ch == EOF) return KEY_NONE;
75
76 // μ’
λ£ ν€
77 if (ch == 'q' || ch == 'Q') return KEY_QUIT;
78
79 // μ€νμ΄μ€λ°
80 if (ch == ' ') return KEY_SPACE;
81
82 // μν°
83 if (ch == '\n' || ch == '\r') return KEY_ENTER;
84
85 // Escape sequence (λ°©ν₯ν€ λ±)
86 // λ°©ν₯ν€λ 3λ°μ΄νΈ: ESC(27) + '[' + λ¬Έμ
87 if (ch == '\033') {
88 int ch2 = getchar();
89 if (ch2 == '[') {
90 int ch3 = getchar();
91 switch (ch3) {
92 case 'A': return KEY_UP;
93 case 'B': return KEY_DOWN;
94 case 'C': return KEY_RIGHT;
95 case 'D': return KEY_LEFT;
96 }
97 }
98 // ESCλ§ λλ μ λ
99 return KEY_QUIT;
100 }
101
102 // WASD ν€ μ§μ
103 switch (ch) {
104 case 'w': case 'W': return KEY_UP;
105 case 's': case 'S': return KEY_DOWN;
106 case 'a': case 'A': return KEY_LEFT;
107 case 'd': case 'D': return KEY_RIGHT;
108 }
109
110 return KEY_OTHER;
111}
112
113// ν€ μ½λλ₯Ό λ¬Έμμ΄λ‘ λ³ν
114const char* keycode_to_string(KeyCode key) {
115 switch (key) {
116 case KEY_UP: return "μμͺ½";
117 case KEY_DOWN: return "μλμͺ½";
118 case KEY_LEFT: return "μΌμͺ½";
119 case KEY_RIGHT: return "μ€λ₯Έμͺ½";
120 case KEY_SPACE: return "μ€νμ΄μ€";
121 case KEY_ENTER: return "μν°";
122 case KEY_QUIT: return "μ’
λ£";
123 default: return "κΈ°ν";
124 }
125}
126
127int main(void) {
128 // raw λͺ¨λ νμ±ν
129 enable_raw_mode();
130 // νλ‘κ·Έλ¨ μ’
λ£ μ μλμΌλ‘ ν°λ―Έλ μ€μ 볡μ
131 atexit(disable_raw_mode);
132
133 // νλ©΄ μ΄κΈ°ν
134 printf("\033[2J\033[H"); // νλ©΄ μ§μ°κΈ° + 컀μ ν
135 printf("\033[?25l"); // 컀μ μ¨κΈ°κΈ°
136
137 printf("=== λΉλκΈ° ν€λ³΄λ μ
λ ₯ μμ° ===\n\n");
138 printf("μ‘°μλ²:\n");
139 printf(" - λ°©ν₯ν€ λλ WASD: μ΄λ\n");
140 printf(" - μ€νμ΄μ€: μ ν\n");
141 printf(" - Q λλ ESC: μ’
λ£\n\n");
142 printf("κ²μ νλ©΄:\n");
143 printf("ββββββββββββββββββββββββββββββββββββββββββ\n");
144 for (int i = 0; i < 15; i++) {
145 printf("β β\n");
146 }
147 printf("ββββββββββββββββββββββββββββββββββββββββββ\n");
148
149 // νλ μ΄μ΄ μ΄κΈ° μμΉ
150 int x = 20, y = 12;
151 int jump_height = 0;
152 int key_count = 0;
153
154 // μν νμ μμΉ
155 int status_row = 23;
156
157 // λ©μΈ 루ν
158 while (1) {
159 // ν€ μ
λ ₯ μ½κΈ° (non-blocking)
160 KeyCode key = read_key();
161
162 if (key == KEY_QUIT) break;
163
164 // μ΄μ μμΉ μ§μ°κΈ°
165 printf("\033[%d;%dH ", y - jump_height, x);
166
167 // μ
λ ₯ μ²λ¦¬
168 switch (key) {
169 case KEY_UP:
170 if (y > 7) y--;
171 key_count++;
172 break;
173 case KEY_DOWN:
174 if (y < 20) y++;
175 key_count++;
176 break;
177 case KEY_LEFT:
178 if (x > 3) x--;
179 key_count++;
180 break;
181 case KEY_RIGHT:
182 if (x < 41) x--;
183 key_count++;
184 break;
185 case KEY_SPACE:
186 jump_height = (jump_height == 0) ? 2 : 0;
187 key_count++;
188 break;
189 default:
190 break;
191 }
192
193 // μ μμΉμ νλ μ΄μ΄ 그리기
194 printf("\033[%d;%dH\033[32m@\033[0m", y - jump_height, x);
195
196 // μν μ 보 μ
λ°μ΄νΈ
197 printf("\033[%d;1H", status_row);
198 printf("μμΉ: (%d, %d) ", x, y);
199 printf("μ ν: %s ", jump_height > 0 ? "ON " : "OFF");
200 printf("μ
λ ₯ νμ: %d ", key_count);
201 if (key != KEY_NONE) {
202 printf("λ§μ§λ§ μ
λ ₯: %s ", keycode_to_string(key));
203 }
204
205 // νλ©΄ κ°±μ
206 fflush(stdout);
207
208 // νλ μ λ μ΄νΈ μ μ΄ (50ms = 20 FPS)
209 usleep(50000);
210 }
211
212 // μ’
λ£ μ²λ¦¬
213 printf("\033[2J\033[H"); // νλ©΄ μ§μ°κΈ°
214 printf("\033[?25h"); // 컀μ 보μ΄κΈ°
215
216 printf("νλ‘κ·Έλ¨μ μ’
λ£ν©λλ€.\n");
217 printf("μ΄ μ
λ ₯ νμ: %d\n", key_count);
218
219 return 0;
220}