Advertisement
Guest User

flappy.cc

a guest
Apr 11th, 2014
886
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.45 KB | None | 0 0
  1. /* flappy.cc --- ncurses flappy bird clone
  2.  * This is free and unencumbered software released into the public domain.
  3.  * c++ -std=c++11 flappy.cc -lncurses -lm -o flappy
  4.  */
  5.  
  6. #include <algorithm>
  7. #include <thread>
  8. #include <deque>
  9. #include <ctime>
  10. #include <cmath>
  11. #include <ncurses.h>
  12.  
  13. struct Display {
  14.   Display(int width = 40, int height = 20) : height{height}, width{width} {
  15.     initscr();
  16.     raw();
  17.     timeout(0);
  18.     noecho();
  19.     curs_set(0);
  20.     keypad(stdscr, TRUE);
  21.     erase();
  22.   }
  23.  
  24.   ~Display() { endwin(); }
  25.  
  26.   void erase() {
  27.     ::erase();
  28.     for (int y = 0; y < height; y++) {
  29.       mvaddch(y, 0, '|');
  30.       mvaddch(y, width - 1, '|');
  31.     }
  32.     for (int x = 0; x < width; x++) {
  33.       mvaddch(0, x, '-');
  34.       mvaddch(height - 1, x, '-');
  35.     }
  36.     mvaddch(0, 0, '/');
  37.     mvaddch(height - 1, 0, '\\');
  38.     mvaddch(0, width - 1, '\\');
  39.     mvaddch(height - 1, width - 1, '/');
  40.   }
  41.  
  42.   void refresh() { ::refresh(); }
  43.  
  44.   const int height, width;
  45.  
  46.   void pause(int c) {
  47.     refresh();
  48.     timeout(-1);
  49.     while (getch() != c)
  50.       ;
  51.     timeout(0);
  52.   }
  53. };
  54.  
  55. struct World {
  56.   World(Display *display) : display{display} {
  57.     for (int x = 1; x < display->width - 1; x++) {
  58.       walls.push_back(0);
  59.     }
  60.   }
  61.  
  62.   std::deque<int> walls;
  63.   Display *display;
  64.   int steps = 0;
  65.  
  66.   constexpr static int kRate = 2, kVGap = 2, kHGap = 10;
  67.  
  68.   int rand_wall() {
  69.     int h = display->height;
  70.     return (rand() % h / 2) + h / 4;
  71.   }
  72.  
  73.   void step() {
  74.     steps++;
  75.     if (steps % kRate == 0) {
  76.       walls.pop_front();
  77.       if ((steps % (kRate * kHGap)) == 0) {
  78.         walls.push_back(rand_wall());
  79.       } else {
  80.         walls.push_back(0);
  81.       }
  82.     }
  83.   }
  84.  
  85.   void draw() {
  86.     for (int i = 0; i < walls.size(); i++) {
  87.       int wall = walls[i];
  88.       if (wall != 0) {
  89.         for (int y = 1; y < display->height - 1; y++) {
  90.           if (y < wall - kVGap || y > wall + kVGap) {
  91.             mvaddch(y, i + 1, '*');
  92.           }
  93.         }
  94.       }
  95.     }
  96.     mvprintw(display->height + 1, 0, "Score: %d", score());
  97.   }
  98.  
  99.   int score() { return std::max(0, steps / (kRate * kHGap) - 2); }
  100. };
  101.  
  102. struct Bird {
  103.   Bird(Display *display) : y{display->height / 2.0}, display{display} {}
  104.  
  105.   double y, dy = 0;
  106.   Display *display;
  107.  
  108.   void gravity() {
  109.     dy += 0.1;
  110.     y += dy;
  111.   }
  112.  
  113.   void poke() { dy = -0.8; }
  114.  
  115.   void draw() { draw('@'); }
  116.  
  117.   void draw(int c) {
  118.     int h = std::round(y);
  119.     h = std::max(1, std::min(h, display->height - 2));
  120.     mvaddch(h, display->width / 2, c);
  121.   }
  122.  
  123.   bool is_alive(World &world) {
  124.     if (y <= 0 || y >= display->height) {
  125.       return false;
  126.     }
  127.     int wall = world.walls[display->width / 2 - 1];
  128.     if (wall != 0) {
  129.       return y > wall - World::kVGap && y < wall + World::kVGap;
  130.     }
  131.     return true;
  132.   }
  133. };
  134.  
  135. int main() {
  136.   srand(std::time(NULL));
  137.   Display display;
  138.   Bird bird{&display};
  139.   World world{&display};
  140.   while (bird.is_alive(world)) {
  141.     int c = getch();
  142.     if (c == 'q') {
  143.       return 0;
  144.     } else if (c != ERR) {
  145.       while (getch() != ERR)
  146.         ;  // clear repeat buffer
  147.       bird.poke();
  148.     }
  149.     display.erase();
  150.     world.step();
  151.     world.draw();
  152.     bird.gravity();
  153.     bird.draw();
  154.     display.refresh();
  155.     std::this_thread::sleep_for(std::chrono::milliseconds{67});
  156.   }
  157.   bird.draw('X');
  158.   mvprintw(display.height + 2, 0, "Game over! Press 'q' to exit.");
  159.   display.pause('q');
  160.   return 0;
  161. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement