]> git.armaanb.net Git - pong.git/blobdiff - pong.c
Sleep during loops
[pong.git] / pong.c
diff --git a/pong.c b/pong.c
index e6b8f38d25f872fd02da7106edc374b12e7352d7..c15860731b9cabf998e285cb39223741450781d2 100644 (file)
--- a/pong.c
+++ b/pong.c
@@ -2,6 +2,10 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <sys/time.h>
+#include <sys/select.h>
+#include <time.h>
+#include <math.h>
 
 int
 die(int code)
@@ -10,31 +14,67 @@ die(int code)
        exit(code);
 }
 
+int
+randslope(void)
+{
+       const int low = 2;
+       const int high = 10;
+       return (rand() % (high - low + 1)) + low;
+}
+
+double
+randspeed(void)
+{
+       const int low = 1;
+       const int high = 2;
+       return ((rand() % (high - low + 1)) + low) / 100.0;
+}
+
+int
+randsign(void)
+{
+       return pow(-1, rand());
+}
+
+void
+msleep(void)
+{
+       struct timeval timeout;
+       timeout.tv_usec = 10000;
+       select(NULL, NULL, NULL, NULL, &timeout); // Sleep 100 ms
+}
+
 int
 main(void) {
-       int x = 1, y = 0, aoff = 0, boff = 0;
-       int max_y = 0, max_x = 0;
-       int max_y_new = 0, max_x_new = 0;
-       int direction = 1;
-       int pad_h = 5;
+       srand((unsigned int)time(NULL));
+       int max_y, max_x, max_y_new, max_x_new;
        int a_score = 0, b_score = 0;
-       int slope_x = 5;
-       int slope_y = 1;
-       int index = 0;
-       int index_dir = 1;
+       int slope_x = randslope();
+       int index_dir = randsign();
+       int direction = randsign();
+       double speed = randspeed();
+       struct timeval start, stop;
 
        // Initialize curses
        initscr();
        noecho();
        curs_set(0);
        nodelay(stdscr, 1); // Don't wait for getch input
-       index = max_y/2;
-       x = max_x/2;
+       getmaxyx(stdscr, max_y, max_x);
+       --max_x;
+       --max_y;
+       int y = max_y/2;
+       int x = max_x/2;
+       int pad_h = 0.2 * max_y;
+       int aoff = max_y / 2 - pad_h;
+       int boff = max_y / 2 - pad_h;
 
+       gettimeofday(&start, NULL);
        while(1) {
+               // Handle resizes
                getmaxyx(stdscr, max_y_new, max_x_new);
                --max_x_new;
-               --max_y_new; 
+               --max_y_new;
                pad_h = 0.2 * max_y;
                if (max_y_new != max_y || max_x_new != max_x) {
                        clear();
@@ -42,27 +82,41 @@ main(void) {
                        max_y = max_y_new;
                }
 
-               index += index_dir;
-
                // Parse keypresses
                int key = getch();
                if (key == 'q') {
                        die(0);
                } else if (key == 'k') {
-                       boff += 2;
+                       if (boff < max_y - pad_h) boff += 2;
                } else if (key == 'i') {
-                       boff -= 2;
+                       if (boff > 0) boff -= 2;
                } else if (key == 's') {
-                       aoff += 2;
+                       if (aoff < max_y - pad_h) aoff += 2;
                } else if (key == 'w') {
-                       aoff -= 2;
+                       if (aoff > 0) aoff -= 2;
+               } else if (key == 27) {
+                       while(1) {
+                               key = getch();
+                               mvprintw(0, 0, "PAUSED");
+                               if (key == 27) {
+                                       clear();
+                                       break;
+                               } else if (key == 'q') {
+                                       die(0);
+                               }
+                               msleep();
+                       }
                }
 
-               // Draw paddles
-               for (int i = 0; i < max_y; i++) {
+               // Clear screen
+               for (int i = 0; i < max_y + 1; i++) {
                        mvprintw(i, 0, " ");
+                       mvprintw(i, 1, " ");
                        mvprintw(i, max_x, " ");
+                       mvprintw(i, max_x - 1, " ");
                }
+
+               // Draw paddles
                for (int i = aoff; i < aoff + pad_h; i++) {
                        mvprintw(i, 0, "|");
                }
@@ -71,42 +125,68 @@ main(void) {
                        mvprintw(i, max_x, "|");
                }
 
+               // Draw net
                for (int i = 0; i < max_y; i++) {
                        mvprintw(i, max_x/2, ":");
                }
 
-               mvprintw(0, 2, "%d", a_score);
-               mvprintw(0, max_x - 1, "%d", b_score);
+               // Draw scrores
+               mvprintw(0, max_x/2 - 2, "%d", a_score);
+               mvprintw(0, max_x/2 + 2, "%d", b_score);
+
+               // Move ball if enough time has elapsed
+               gettimeofday(&stop, NULL);
+               if ((double)(stop.tv_usec - start.tv_usec) / 1000000 +
+                               (double)(stop.tv_sec - start.tv_sec) > speed) {
+                       gettimeofday(&start, NULL);
+                       mvprintw(y, x, " ");
+                       x += direction;
+                       if (x % slope_x == 0) y += index_dir;
+                       mvprintw(y, x, "o");
+               }
 
-               // Move ball
-               mvprintw(y, x, " ");
+               if ((x >= max_x - 1 && y >= boff && y <= boff + pad_h) ||
+                               (x <= 1 && y >= aoff && y <= aoff + pad_h)) {
+                       // Ball hits paddle
 
-               x += direction;
-               y = index / slope_x * slope_y;
-               mvprintw(y, x, "o");
+                       /* Find the distance that the ball hits from the center of the padel and
+                                accordingly adjust ball path */
+                       int poff = (x <= 1) ? aoff : boff;
+                       double fromc = (fabs(poff + 0.5 * pad_h - y) / 2);
+                       slope_x /= (abs(slope_x) > 25) ? 2 : fromc;
+                       slope_x = (slope_x < 2) ? 2 : slope_x;
 
-               // Check if touching paddle
-               if (x == max_x) {
-                       if (y >= boff && y <= boff + pad_h) {
-                               direction *= -1;
+                       direction *= -1;
+                       x += direction;
+                       speed *= 0.9;
+               } else if (x >= max_x - 1 || x <= 1) {
+                       // Ball goes out of bounds
+                       if (x <= 1) {
+                               b_score += 1;
+                               mvprintw(0, 0, "PLAYER B SCORES");
                        } else {
                                a_score += 1;
-                               usleep(600000);
-                               x = max_x/2;
-                               index = max_y/2;
-                       }
-               } else if (x == 0) {
-                       if (y >= aoff && y <= aoff + pad_h) {
-                               direction *= -1;
-                       } else {
-                               b_score += 1;
-                               usleep(600000);
-                               x = max_x/2;
-                               index = max_y/2;
+                               mvprintw(0, 0, "PLAYER A SCORES");
                        }
-               } else if (y < 0 || y > max_y) {
+                       refresh();
+
+                       // Reset to default values
+                       x = max_x/2;
+                       y = max_y / 2;
+                       slope_x = randslope();
+                       index_dir = randsign();
+                       speed = randspeed();
+                       aoff = max_y / 2 - pad_h;
+                       boff = max_y / 2 - pad_h;
+
+                       sleep(1);
+                       clear();
+               } else if (y == 0 || y == max_y) {
+                       // Ball hits top or bottom wall
                        index_dir *= -1;
+                       mvprintw(y, x, " ");
+                       y = (y == max_y) ? max_y - 1 : 1;
                }
-               usleep(3000000 * (1.0/((double)max_x + (double)max_y)));
+               msleep();
        }
 }