]> git.armaanb.net Git - pong.git/blob - pong.c
Don't allow paddles to go off of screen
[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                 }
89
90                 // Clear screen
91                 for (int i = 0; i < max_y + 1; i++) {
92                         mvprintw(i, 0, " ");
93                         mvprintw(i, 1, " ");
94                         mvprintw(i, max_x, " ");
95                         mvprintw(i, max_x - 1, " ");
96                 }
97
98                 // Draw paddles
99                 for (int i = aoff; i < aoff + pad_h; i++) {
100                         mvprintw(i, 0, "|");
101                 }
102
103                 for (int i = boff; i < boff + pad_h; i++) {
104                         mvprintw(i, max_x, "|");
105                 }
106
107                 // Draw net
108                 for (int i = 0; i < max_y; i++) {
109                         mvprintw(i, max_x/2, ":");
110                 }
111
112                 // Draw scrores
113                 mvprintw(0, max_x/2 - 2, "%d", a_score);
114                 mvprintw(0, max_x/2 + 2, "%d", b_score);
115
116                 // Move ball if enough time has elapsed
117                 gettimeofday(&stop, NULL);
118                 if ((double)(stop.tv_usec - start.tv_usec) / 1000000 +
119                                 (double)(stop.tv_sec - start.tv_sec) > speed) {
120                         gettimeofday(&start, NULL);
121                         mvprintw(y, x, " ");
122                         x += direction;
123                         if (x % slope_x == 0) y += index_dir;
124                         mvprintw(y, x, "o");
125                 }
126
127                 if ((x >= max_x - 1 && y >= boff && y <= boff + pad_h) ||
128                                 (x <= 1 && y >= aoff && y <= aoff + pad_h)) {
129                         // Ball hits paddle
130
131                         /* Find the distance that the ball hits from the center of the padel and
132                                  accordingly adjust ball path */
133                         int poff = (x <= 1) ? aoff : boff;
134                         double fromc = fabs(0.5 * (poff + 0.5 * pad_h - y));
135                         slope_x *= (slope_x < 20) ? 1 : (int) ((double) slope_x / fromc);
136                         slope_x += 1;
137
138                         direction *= -1;
139                         x += direction;
140                         speed *= 0.9;
141                 } else if (x >= max_x - 1 || x <= 1) {
142                         // Ball goes out of bounds
143                         if (x <=1) {
144                                 b_score += 1;
145                         } else {
146                                 a_score += 1;
147                         }
148                         x = max_x/2;
149                         slope_x = randslope();
150                         index_dir = randsign();
151                         speed = randspeed();
152                         sleep(1);
153                 } else if (y == 0 || y == max_y) {
154                         // Ball hits top or bottom wall
155                         index_dir *= -1;
156                         mvprintw(y, x, " ");
157                         y = (y == max_y) ? max_y - 1 : 1;
158                 }
159         }
160 }