]> git.armaanb.net Git - pong.git/blob - pong.c
Add keybindings to manpage
[pong.git] / pong.c
1 #include <ncurses.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <sys/time.h>
6 #include <time.h>
7 #include <math.h>
8
9 int
10 die(int code)
11 {
12         endwin();
13         exit(code);
14 }
15
16 int
17 randslope(void)
18 {
19         const int low = 2;
20         const int high = 10;
21         return (rand() % (high - low + 1)) + low;
22 }
23
24 double
25 randspeed(void)
26 {
27         const int low = 1;
28         const int high = 2;
29         return ((rand() % (high - low + 1)) + low) / 100.0;
30 }
31
32 int
33 randsign(void)
34 {
35         return pow(-1, rand());
36 }
37
38 int
39 main(void) {
40         srand((unsigned int)time(NULL));
41         int aoff = 0, boff = 0;
42         int max_y, max_x;
43         int max_y_new = 0, max_x_new = 0;
44         int pad_h = 5;
45         int a_score = 0, b_score = 0;
46         int slope_x = randslope();
47         int index_dir = randsign();
48         int direction = randsign();
49         double speed = randspeed();
50         struct timeval start, stop;
51
52         // Initialize curses
53         initscr();
54         noecho();
55         curs_set(0);
56         nodelay(stdscr, 1); // Don't wait for getch input
57         getmaxyx(stdscr, max_y, max_x);
58         --max_x;
59         --max_y;
60         int y = max_y/2;
61         int x = max_x/2;
62
63         gettimeofday(&start, NULL);
64         while(1) {
65                 // Handle resizes
66                 getmaxyx(stdscr, max_y_new, max_x_new);
67                 --max_x_new;
68                 --max_y_new;
69                 pad_h = 0.2 * max_y;
70                 if (max_y_new != max_y || max_x_new != max_x) {
71                         clear();
72                         max_x = max_x_new;
73                         max_y = max_y_new;
74                 }
75
76                 // Parse keypresses
77                 int key = getch();
78                 if (key == 'q') {
79                         die(0);
80                 } else if (key == 'k') {
81                         if (boff < max_y - pad_h) boff += 1;
82                 } else if (key == 'i') {
83                         if (boff > 0) boff -= 1;
84                 } else if (key == 's') {
85                         if (aoff < max_y - pad_h) aoff += 1;
86                 } else if (key == 'w') {
87                         if (aoff > 0) aoff -= 1;
88                 } else if (key == 27) {
89                         while(1) {
90                                 key = getch();
91                                 mvprintw(0, 0, "PAUSED");
92                                 if (key == 27) {
93                                         clear();
94                                         break;
95                                 } else if (key == 'q') {
96                                         die(0);
97                                 }
98                         }
99                 }
100
101                 // Clear screen
102                 for (int i = 0; i < max_y + 1; i++) {
103                         mvprintw(i, 0, " ");
104                         mvprintw(i, 1, " ");
105                         mvprintw(i, max_x, " ");
106                         mvprintw(i, max_x - 1, " ");
107                 }
108
109                 // Draw paddles
110                 for (int i = aoff; i < aoff + pad_h; i++) {
111                         mvprintw(i, 0, "|");
112                 }
113
114                 for (int i = boff; i < boff + pad_h; i++) {
115                         mvprintw(i, max_x, "|");
116                 }
117
118                 // Draw net
119                 for (int i = 0; i < max_y; i++) {
120                         mvprintw(i, max_x/2, ":");
121                 }
122
123                 // Draw scrores
124                 mvprintw(0, max_x/2 - 2, "%d", a_score);
125                 mvprintw(0, max_x/2 + 2, "%d", b_score);
126
127                 // Move ball if enough time has elapsed
128                 gettimeofday(&stop, NULL);
129                 if ((double)(stop.tv_usec - start.tv_usec) / 1000000 +
130                                 (double)(stop.tv_sec - start.tv_sec) > speed) {
131                         gettimeofday(&start, NULL);
132                         mvprintw(y, x, " ");
133                         x += direction;
134                         if (x % slope_x == 0) y += index_dir;
135                         mvprintw(y, x, "o");
136                 }
137
138                 if ((x >= max_x - 1 && y >= boff && y <= boff + pad_h) ||
139                                 (x <= 1 && y >= aoff && y <= aoff + pad_h)) {
140                         // Ball hits paddle
141
142                         /* Find the distance that the ball hits from the center of the padel and
143                                  accordingly adjust ball path */
144                         int poff = (x <= 1) ? aoff : boff;
145                         double fromc = fabs(0.5 * (poff + 0.5 * pad_h - y));
146                         slope_x *= (slope_x < 20) ? 1 : (int) ((double) slope_x / fromc);
147                         slope_x += 1;
148
149                         direction *= -1;
150                         x += direction;
151                         speed *= 0.9;
152                 } else if (x >= max_x - 1 || x <= 1) {
153                         // Ball goes out of bounds
154                         if (x <=1) {
155                                 b_score += 1;
156                         } else {
157                                 a_score += 1;
158                         }
159                         x = max_x/2;
160                         slope_x = randslope();
161                         index_dir = randsign();
162                         speed = randspeed();
163                         sleep(1);
164                 } else if (y == 0 || y == max_y) {
165                         // Ball hits top or bottom wall
166                         index_dir *= -1;
167                         mvprintw(y, x, " ");
168                         y = (y == max_y) ? max_y - 1 : 1;
169                 }
170         }
171 }