Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
zmx0142857
GitHub Repository: zmx0142857/mini-games
Path: blob/master/c/include/game.h
363 views
1
/* header file for c games played on terminal */
2
#ifndef GAME_H
3
#define GAME_H
4
5
#include <stdio.h>
6
#include <stdlib.h>
7
#include <unistd.h> // sleep()
8
#include <stdbool.h> // bool
9
#include <signal.h> // signal()
10
#include <fcntl.h> // fcntl()
11
12
/******** windows ********/
13
14
#ifdef __MINGW32__
15
16
#include <conio.h>
17
#include <windows.h>
18
19
HANDLE cmd;
20
#define toggle_flush()
21
22
#define screen_clear() system("cls")
23
24
#define set_color(fg) SetConsoleTextAttribute(cmd, fg)
25
#define set_colors(fg, bg) SetConsoleTextAttribute(cmd, (bg<<4)|fg)
26
27
#define BG_BLACK 0x0
28
#define BG_BLUE 0x1
29
#define BG_GREEN 0x2
30
#define BG_CYAN 0x3
31
#define BG_RED 0x4
32
#define BG_MAGENTA 0x5
33
#define BG_YELLOW 0x6
34
#define BG_WHITE 0x7
35
#define FG_BLACK 0x8
36
#define FG_BLUE 0x9
37
#define FG_GREEN 0xa
38
#define FG_CYAN 0xb
39
#define FG_RED 0xc
40
#define FG_MAGENTA 0xd
41
#define FG_YELLOW 0xe
42
#define FG_WHITE 0xf
43
44
/*
45
void screen_size(int y, int x)
46
{
47
COORD size = {x, y};
48
SetConsoleScreenBufferSize(cmd, size); // set buffer size
49
SMALL_RECT rect = {0,0, x-1, y-1};
50
SetConsoleWindowInfo(cmd, 1, &rect); // set window size
51
}
52
*/
53
54
#ifndef EXTERN_GAME_H
55
void screen_size(unsigned height, unsigned width)
56
{
57
char buf[100];
58
sprintf(buf, "mode con lines=%d cols=%d", height, width);
59
system(buf);
60
screen_clear();
61
}
62
#else
63
extern void screen_size(unsigned height, unsigned width);
64
#endif
65
66
#ifndef EXTERN_GAME_H
67
void cursor_hide()
68
{
69
CONSOLE_CURSOR_INFO info;
70
info.dwSize = 100;
71
info.bVisible = FALSE;
72
SetConsoleCursorInfo(cmd, &info);
73
}
74
#else
75
extern void cursor_hide();
76
#endif
77
78
// 返回 wsad 表示上下左右, 否则返回 key 自身
79
#ifndef EXTERN_GAME_H
80
int arrow_key(int key)
81
{
82
if (key == -32) {
83
key = getch();
84
// HPKM = 上下左右
85
switch (key) {
86
case 'H': return 'w';
87
case 'P': return 's';
88
case 'K': return 'a';
89
case 'M': return 'd';
90
}
91
}
92
return key;
93
}
94
#else
95
extern int arrow_key(int key);
96
#endif
97
98
#define cursor_show()
99
100
#define cursor_goto(y,x)\
101
do {\
102
COORD pos = {x, y};\
103
SetConsoleCursorPosition(cmd, pos);\
104
} while (0)
105
106
#define game_init()\
107
do {\
108
cmd = GetStdHandle(STD_OUTPUT_HANDLE);\
109
signal(SIGINT, SIG_IGN);\
110
system("chcp 65001");\
111
cursor_hide();\
112
} while (0)
113
114
#define game_over()\
115
do {\
116
system("chcp 936");\
117
cursor_show();\
118
} while (0)
119
120
#define time_ms GetTickCount
121
122
#endif // __MINGW32__
123
124
/******** linux ********/
125
126
#ifdef __linux__
127
128
#include <sys/ioctl.h> // winsize, ioctl()
129
#include <sys/time.h> // gettimeofday
130
#include <termios.h> // termios
131
132
#ifndef EXTERN_GAME_H
133
struct winsize tty;
134
#else
135
extern struct winsize tty;
136
#endif
137
138
#define get_ttysize() ioctl(0, TIOCGWINSZ, &tty)
139
140
// enable/disable buffered I/O
141
#ifndef EXTERN_GAME_H
142
void toggle_flush()
143
{
144
static struct termios on, off;
145
static int ready = 0;
146
if (!ready) {
147
tcgetattr(STDIN_FILENO, &on);
148
off = on;
149
off.c_lflag &= ~(ICANON | ECHO); // 禁用 I/O 缓冲, 无回显
150
ready = 1;
151
}
152
static int flush_on = 1;
153
if (flush_on) {
154
tcsetattr(STDIN_FILENO, TCSANOW, &off);
155
} else {
156
tcsetattr(STDIN_FILENO, TCSANOW, &on);
157
}
158
flush_on = !flush_on;
159
}
160
#else
161
extern void toggle_flush();
162
#endif
163
164
#ifndef EXTERN_GAME_H
165
int getch()
166
{
167
toggle_flush();
168
int ret = getchar();
169
toggle_flush();
170
return ret;
171
}
172
#else
173
extern int getch();
174
#endif
175
176
#ifndef EXTERN_GAME_H
177
int kbhit()
178
{
179
int oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
180
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
181
int ch = getch();
182
fcntl(STDIN_FILENO, F_SETFL, oldf);
183
if (ch == EOF)
184
return 0;
185
ungetc(ch, stdin);
186
return ch;
187
}
188
#else
189
extern int kbhit();
190
#endif
191
192
#define Sleep(ms)\
193
do {\
194
toggle_flush();\
195
usleep((ms)*1000);\
196
toggle_flush();\
197
} while (0)
198
199
#ifndef EXTERN_GAME_H
200
long time_ms()
201
{
202
struct timeval t;
203
gettimeofday(&t, NULL);
204
return t.tv_sec * 1000 + t.tv_usec / 1000;
205
}
206
#else
207
extern long time_ms();
208
#endif
209
210
// POSIX escape sequences
211
212
#define STYLE_RESET "\033[0m"
213
#define STYLE_BRIGHT "\033[1m"
214
#define STYLE_DIM "\033[2m"
215
#define STYLE_UNDERLINE "\033[4m"
216
#define STYLE_BLINK "\033[5m"
217
#define STYLE_REVERSE "\033[7m"
218
#define STYLE_HIDDEN "\033[8m"
219
220
#define FG_BLACK "30"
221
#define FG_RED "31"
222
#define FG_GREEN "32"
223
#define FG_YELLOW "33"
224
#define FG_BLUE "34"
225
#define FG_MAGENTA "35"
226
#define FG_CYAN "36"
227
#define FG_WHITE "37"
228
#define BG_BLACK "40"
229
#define BG_RED "41"
230
#define BG_GREEN "42"
231
#define BG_YELLOW "43"
232
#define BG_BLUE "44"
233
#define BG_MAGENTA "45"
234
#define BG_CYAN "46"
235
#define BG_WHITE "47"
236
237
#define COLOR(fg) "\033[" fg "m"
238
#define COLORS(fg, bg) "\033[" fg ";" bg "m"
239
#define set_color(fg) printf("\033[%sm", (fg))
240
#define set_colors(fg, bg) printf("\033[%s;%sm", (fg), (bg))
241
242
#define screen_clear() printf("\033[2J\033[1;1H")
243
#define line_clear() printf("\033[K")
244
245
#define cursor_goto(y,x) printf("\033[%d;%dH", (y)+1, (x)+1)
246
#define cursor_cr() pritnf("\r")
247
#define cursor_up(n) printf("\033[%dA", (n))
248
#define cursor_down(n) printf("\033[%dB", (n))
249
#define cursor_right(n) printf("\033[%dC", (n))
250
#define cursor_left(n) printf("\033[%dD", (n))
251
#define cursor_hide() printf("\033[?25l");
252
#define cursor_show() printf("\033[?25h");
253
254
// 返回 wsad 表示上下左右, 否则返回 key 自身
255
#ifndef EXTERN_GAME_H
256
int arrow_key(int key)
257
{
258
if (key == 27) {
259
key = getch();
260
if (key != '[')
261
return key;
262
key = getch();
263
// ABDC = 上下左右
264
switch (key) {
265
case 'A': return 'w';
266
case 'B': return 's';
267
case 'D': return 'a';
268
case 'C': return 'd';
269
}
270
}
271
return key;
272
}
273
#else
274
int arrow_key(int key);
275
#endif
276
277
#ifndef EXTERN_GAME_H
278
void screen_size(unsigned height, unsigned width)
279
{
280
char buf[100];
281
sprintf(buf, "resize -s %d %d", height, width);
282
system(buf);
283
screen_clear();
284
}
285
#else
286
void screen_size(unsigned height, unsigned width);
287
#endif
288
289
#define game_init()\
290
do {\
291
signal(SIGINT, SIG_IGN);\
292
cursor_hide();\
293
} while (0)
294
295
#define game_over() cursor_show()
296
297
#endif // __linux__
298
299
#define mvprint(y, x, args...)\
300
do {\
301
cursor_goto(y, x);\
302
printf(args);\
303
} while (0)
304
305
#define color_print(fg, args...)\
306
do {\
307
set_color(fg);\
308
printf(args);\
309
} while (0)
310
311
#define colors_print(fg, bg, args...)\
312
do {\
313
set_colors(fg, bg);\
314
printf(args);\
315
} while (0)
316
317
#define color_mvprint(fg, y, x, args...)\
318
do{\
319
set_color(fg);\
320
mvprint(y, x, args);\
321
} while (0)
322
323
#define colors_mvprint(fg, bg, y, x, args...)\
324
do{\
325
set_colors(fg, bg);\
326
mvprint(y, x, args);\
327
} while (0)
328
329
#define keep_between(value, inf, sup)\
330
(value < inf ? (value = inf)\
331
: (value > sup ? (value = sup)\
332
: value))
333
334
#ifndef EXTERN_GAME_H
335
void play_loading(unsigned loop)
336
{
337
unsigned i, j;
338
for (i = 0; i != loop; ++i) {
339
printf("LOADING");
340
Sleep(255);
341
for (j = 0; j != 3; ++j) {
342
printf(".");
343
Sleep(255);
344
}
345
printf("\r \r");
346
}
347
screen_clear();
348
}
349
#else
350
void play_loading(unsigned loop);
351
#endif
352
353
/******** symbols ********/
354
355
#define SYM_BLANK " "
356
#define SYM_BLOCK_BRACK "[]"
357
#define SYM_CIRCLE_PAREN "()"
358
359
#ifdef __linux__
360
#define SYM_FILL " "
361
#define SYM_BLOCK "██"
362
#else
363
#define SYM_FILL
364
#define SYM_BLOCK "█"
365
#endif
366
367
#define SYM_SQUARE "■" SYM_FILL
368
#define SYM_DIAMOND "◆" SYM_FILL
369
#define SYM_STAR "★" SYM_FILL
370
#define SYM_ARROW_UP "↑" SYM_FILL
371
#define SYM_ARROW_LEFT "←" SYM_FILL
372
#define SYM_ARROW_DOWN "↓" SYM_FILL
373
#define SYM_ARROW_RIGHT "→" SYM_FILL
374
#define SYM_ARROWS SYM_ARROW_LEFT SYM_ARROW_DOWN SYM_ARROW_UP SYM_ARROW_RIGHT
375
#define SYM_CIRCLE_WHITE "○"
376
#define SYM_CIRCLE_BLACK "●"
377
378
#define KEY_ESC 27
379
380
#endif // GAME_H
381
382