|
5 | 5 | #include <unistd.h> |
6 | 6 | #include <termios.h> |
7 | 7 | #include <sys/ioctl.h> |
8 | | -int t() |
9 | | -{ |
10 | | - struct timespec now; |
11 | | - timespec_get(&now, TIME_UTC); |
12 | | - return now.tv_sec * 1000 + now.tv_nsec / 1000000; |
| 8 | +#define g(x, y, u, v, s) for (int j = 0, X = x, Y = y; j < v && Y + j < h - X / w && Y >= 0 && X >= 0; ++j) memcpy(&f[Y + j][X], &s[j * u], u) |
| 9 | +#define l(x, y, w, h, a, b, c, d) !((x - a > c && x >= a) || (a - x > w && a >= x) || (y - b > d && y >= b) || (b - y > h && b >= y)) |
| 10 | +#define f(x, y, z) y += z * d; strcpy(b, x); break |
| 11 | +int t() { |
| 12 | + struct timespec now; |
| 13 | + timespec_get(&now, TIME_UTC); |
| 14 | + return now.tv_sec * 1000 + now.tv_nsec / 1000000; |
13 | 15 | } |
14 | | - |
15 | | -#define g(x, y, u, v, s) \ |
16 | | - for (int j = 0, X = x, Y = y; j < v && Y + j < h - X / w && Y >= 0 && X >= 0; ++j) \ |
17 | | - memcpy(&f[Y + j][X], &s[j * u], u) |
18 | | -#define l(x, y, w, h, a, b, c, d) \ |
19 | | - !((x - a > c && x >= a) || (a - x > w && a >= x) || (y - b > d && y >= b) || (b - y > h && b >= y)) |
20 | | -#define f(x, y, z) \ |
21 | | - y += z * d; \ |
22 | | - strcpy(b, x); \ |
23 | | - break |
24 | | - |
25 | | -int main() |
26 | | -{ |
27 | | - struct termios z, o; |
28 | | - tcgetattr(0, &z); // get current terminal settings as a "backup" |
29 | | - o = z; // save a copy |
30 | | - z.c_lflag &= ~ICANON; // disable canonical mode |
31 | | - z.c_cc[VMIN] = 0; // minimum number of characters to read |
32 | | - tcsetattr(0, TCSANOW, &z); // set new terminal settings |
33 | | - struct winsize v; // terminal size |
34 | | - ioctl(1, TIOCGWINSZ, &v); // get terminal size |
35 | | - int h = v.ws_row, w = v.ws_col, A = w * h / 100, l = t(), g = 1; |
36 | | - struct V |
37 | | - { |
38 | | - float x, y; |
39 | | - } p = {w / 2, h / 2}, a[A], m[A]; |
40 | | - char u = 0, f[h + 1][w], b[13] = " /\\ / \\ vv "; |
41 | | - while (1) |
42 | | - { |
43 | | - float d = (t() - l) * .001; |
44 | | - read(0, &u, 1); // read the next move |
45 | | - l = t(); |
46 | | - memset(f, ' ', h * w); // clear the screen |
47 | | - switch (u) // could be minified... |
48 | | - { |
49 | | - case 65: // up |
50 | | - f(" /\\ / \\ vv ", p.y, -20); |
51 | | - case 66: // down |
52 | | - f(" ^^ \\ / \\/ ", p.y, 20); |
53 | | - case 67: // right |
54 | | - f("<\\ < ></ ", p.x, 40); |
55 | | - case 68: // left |
56 | | - f(" />< > \\>", p.x, -40); |
57 | | - } |
58 | | - p.x = p.x < 4 ? 4 : p.x >= w - 4 ? w - 4 |
59 | | - : p.x; // make sure the player is in the screen (horizontally) |
60 | | - p.y = p.y < 1 ? 1 : p.y >= h - 3 ? h - 3 |
61 | | - : p.y; // make sure the player is in the screen (vertically) |
62 | | - for (int i = 0; i < A; ++i) |
63 | | - { |
64 | | - *f[h] = 0; |
65 | | - struct V *e = &a[i], *z = &m[i]; |
66 | | - e->x += d * z->x; // move the asteroid in the x direction |
67 | | - e->y += d * z->y; // move the asteroid in the y direction |
68 | | - e->x < 0 - 3 || e->x >= w + 3 || e->y >= h + 2 || g ? e->y = -rand() % h * (1 + g), |
69 | | - e->x = rand() % w, |
70 | | - z->x = -8 + rand() % 15, |
71 | | - z->y = 10 + rand() % 5 : 0; |
72 | | - if (l(p.x, p.y, 4, 3, e->x, e->y, 3, 2)) // if player hit an asteroid |
73 | | - { |
74 | | - tcsetattr(0, TCSADRAIN, &o); // restore the terminal |
75 | | - exit(0); // exit the program |
76 | | - }; |
77 | | - g(e->x, e->y, 3, 2, "OOOOOO"); // draw the asteroid |
78 | | - } |
79 | | - g(p.x, p.y, 4, 3, b); // draw the player |
80 | | - printf("\33[0;4H%s", &f[0][4]); // print the screen |
81 | | - while (t() - l < 10) |
82 | | - ; // wait for a bit |
83 | | - g = 0; |
84 | | - } |
| 16 | +int main() { |
| 17 | + struct termios z, o; |
| 18 | + tcgetattr(0, &z); // get current terminal settings as a "backup" |
| 19 | + o = z; // save a copy |
| 20 | + z.c_lflag &= ~ICANON; // disable canonical mode |
| 21 | + z.c_cc[VMIN] = 0; // minimum number of characters to read |
| 22 | + tcsetattr(0, TCSANOW, &z); // set new terminal settings |
| 23 | + struct winsize v; // terminal size |
| 24 | + ioctl(1, TIOCGWINSZ, &v); // get terminal size |
| 25 | + int h = v.ws_row, w = v.ws_col, A = w * h / 100, l = t(), g = 1; |
| 26 | + struct V { |
| 27 | + float x, y; |
| 28 | + } p = {w / 2, h / 2}, a[A], m[A]; |
| 29 | + char u = 0, f[h + 1][w], b[13] = " /\\ / \\ vv "; |
| 30 | + while (1) { |
| 31 | + float d = (t() - l) * .001; |
| 32 | + read(0, &u, 1); // read the next move |
| 33 | + l = t(); |
| 34 | + memset(f, ' ', h * w); // clear the screen |
| 35 | + switch (u) { // could be minified... |
| 36 | + case 65: // up |
| 37 | + f(" /\\ / \\ vv ", p.y, -20); |
| 38 | + case 66: // down |
| 39 | + f(" ^^ \\ / \\/ ", p.y, 20); |
| 40 | + case 67: // right |
| 41 | + f("<\\ < ></ ", p.x, 40); |
| 42 | + case 68: // left |
| 43 | + f(" />< > \\>", p.x, -40); |
| 44 | + } |
| 45 | + p.x = p.x < 4 ? 4 : p.x >= w - 4 ? w - 4 : p.x; // make sure the player is in the screen (horizontally) |
| 46 | + p.y = p.y < 1 ? 1 : p.y >= h - 3 ? h - 3 : p.y; // make sure the player is in the screen (vertically) |
| 47 | + for (int i = 0; i < A; ++i) { |
| 48 | + *f[h] = 0; |
| 49 | + struct V *e = &a[i], *z = &m[i]; |
| 50 | + e->x += d * z->x; // move the asteroid in the x direction |
| 51 | + e->y += d * z->y; // move the asteroid in the y direction |
| 52 | + e->x < 0 - 3 || e->x >= w + 3 || e->y >= h + 2 || g ? e->y = -rand() % h * (1 + g), e->x = rand() % w, z->x = -8 + rand() % 15, z->y = 10 + rand() % 5 : 0; |
| 53 | + if (l(p.x, p.y, 4, 3, e->x, e->y, 3, 2)) { // if player hit an asteroid |
| 54 | + tcsetattr(0, TCSADRAIN, &o); // restore the terminal |
| 55 | + exit(0); // exit the program |
| 56 | + }; |
| 57 | + g(e->x, e->y, 3, 2, "OOOOOO"); // draw the asteroid |
| 58 | + } |
| 59 | + g(p.x, p.y, 4, 3, b); // draw the player |
| 60 | + printf("\33[0;4H%s", &f[0][4]); // print the screen |
| 61 | + while (t() - l < 10); // wait for a bit |
| 62 | + g = 0; |
| 63 | + } |
85 | 64 | } |
0 commit comments