mvaganov

GSP420 block puzzle primer

Sep 11th, 2013
191
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <iostream>
  2. #include <fstream>
  3. #include <conio.h>
  4. #include <time.h>
  5. #include <windows.h>
  6. void setCursorXY(int x, int y) {
  7.     COORD point = {x, y};
  8.     SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), point);
  9. }
  10.  
  11. class Map {
  12.     char ** data;
  13.     int width, height;
  14.     static char ** createMap(int w, int h) {
  15.         char ** m = new char *[h];
  16.         for(int y = 0; y < h; ++y)
  17.             m[y] = new char [w];
  18.         return m;
  19.     }
  20.     static void releaseMap(char ** m, const int width, const int height) {
  21.         for(int y = 0; y < height; ++y)
  22.             delete [] m[y];
  23.         delete [] m;
  24.     }
  25. public:
  26.     const bool loadFile(const char * const filename) {
  27.         std::ifstream file;
  28.         file.open(filename);
  29.         if(!file.is_open())
  30.             return false;
  31.         file >> width >> height;
  32.         data = createMap(width, height);
  33.         int c, row = 0, col = 0;
  34.         do {
  35.             c = file.get();
  36.             if(c != EOF && c != '\n' && c != '\r') {
  37.                 data[row][col] = c;
  38.                 col++;
  39.                 if(col >= width) {
  40.                     col = 0;
  41.                     row++;
  42.                     if(row >= height)
  43.                         break;
  44.                 }
  45.             }
  46.         }while(c != EOF);
  47.         file.close();
  48.         return true;
  49.     }
  50.     void print() const {
  51.         for(int y = 0; y < height; ++y) {
  52.             for(int x = 0; x < width; ++x) {
  53.                 std::cout << data[y][x];
  54.             }
  55.             std::cout << std::endl;
  56.         }
  57.     }
  58.     /**
  59.      * @param x, y the coordinate of the upper left character
  60.      * @param transparent a character that will not be printed
  61.      */
  62.     void draw(int x, int y, char transparent) const {
  63.         for(int row = 0; row < height; ++row)
  64.         {
  65.             for(int col = 0; col < width; ++col)
  66.             {
  67.                 setCursorXY(x+col, y+row);
  68.                 if(data[row][col] != transparent)
  69.                     std::cout << data[row][col];
  70.             }
  71.         }
  72.     }
  73.     /** @param x, y the coordinate of the upper left character */
  74.     void draw(int x, int y) const {
  75.         draw(x,y,' ');  // borders on the edge of YAGNI
  76.     }
  77.     Map():data(0),height(-1),width(-1){}
  78.     ~Map() {
  79.         for(int y = 0; y < height; ++y)
  80.             delete [] data[y];
  81.         delete [] data;
  82.     }
  83.     char get(int x, int y) const { return data[y][x]; }
  84.     char & getRef(int x, int y) { return data[y][x]; }
  85.     void set(int x, int y, char c) { data[y][x] = c; }
  86.     void drawFlippedH(int x, int y) const {
  87.         for(int row = 0; row < height; ++row) {
  88.             for(int col = 0; col < width; ++col) {
  89.                 setCursorXY(x+col, y+row);
  90.                 std::cout << data[row][width-1-col];
  91.             }
  92.         }
  93.     }
  94.     void drawFlippedV(int x, int y) const {
  95.         for(int row = 0; row < height; ++row) {
  96.             for(int col = 0; col < width; ++col) {
  97.                 setCursorXY(x+col, y+row);
  98.                 std::cout << data[height-1-row][col];
  99.             }
  100.         }
  101.     }
  102.     void drawFlippedXY(int x, int y) const {
  103.         for(int row = 0; row < width; ++row) {
  104.             for(int col = 0; col < height; ++col) {
  105.                 setCursorXY(x+col, y+row);
  106.                 std::cout << data[col][row];
  107.             }
  108.         }
  109.     }
  110.     void drawRotatedCW(int x, int y) const {
  111.         for(int row = 0; row < width; ++row) {
  112.             for(int col = 0; col < height; ++col) {
  113.                 setCursorXY(x+col, y+row);
  114.                 std::cout << data[height-1-col][row];
  115.             }
  116.         }
  117.     }
  118.     void drawRotatedCCW(int x, int y) const {
  119.         for(int row = 0; row < width; ++row) {
  120.             for(int col = 0; col < height; ++col) {
  121.                 setCursorXY(x+col, y+row);
  122.                 std::cout << data[col][width-1-row];
  123.             }
  124.         }
  125.     }
  126.     void flipH(){
  127.         char ** m = createMap(width, height);
  128.         for(int row = 0; row < height; ++row) {
  129.             for(int col = 0; col < width; ++col) {
  130.                 m[row][col] = data[row][width-1-col];
  131.             }
  132.         }
  133.         releaseMap(data, width, height);
  134.         data = m;
  135.     }
  136.     void flipV(){
  137.         char ** m = createMap(width, height);
  138.         for(int row = 0; row < height; ++row) {
  139.             for(int col = 0; col < width; ++col) {
  140.                 m[row][col] = data[height-1-row][col];
  141.             }
  142.         }
  143.         releaseMap(data, width, height);
  144.         data = m;
  145.     }
  146.     void flipXY(){
  147.         char ** m = createMap(height, width);
  148.         for(int row = 0; row < width; ++row) {
  149.             for(int col = 0; col < height; ++col) {
  150.                 m[row][col] = data[col][row];
  151.             }
  152.         }
  153.         releaseMap(data, width, height);
  154.         int temp = width;   width = height; height = temp;
  155.         data = m;
  156.     }
  157.     void rotateCW(){    flipXY();   flipH();    }
  158.     void rotateCCW(){   flipXY();   flipV();    }
  159.     int getWidth() const {return width;}
  160.     int getHeight() const {return height;}
  161. };
  162. class Vector2D {
  163. public:
  164.     int x, y;
  165.     Vector2D():x(0),y(0){}
  166.     Vector2D(int x, int y):x(x),y(y){}
  167. };
  168. class Rect {
  169. public:
  170.     Vector2D pmin, pmax;
  171.     Rect(Vector2D a_min, Vector2D a_max):pmin(a_min),pmax(a_max){}
  172.     bool isWithin(Rect const & larger) const {
  173.         return pmin.x >= larger.pmin.x
  174.             && pmin.y >= larger.pmin.y
  175.             && pmax.x <= larger.pmax.x
  176.             && pmax.y <= larger.pmax.y;
  177.     }
  178. };
  179. struct Piece
  180. {
  181. public:
  182.     Map m;
  183.     Vector2D loc;
  184.     Piece(char * filename) {
  185.         m.loadFile(filename);
  186.     }
  187.     /** calls the Map draw using the loc argument for it's location */
  188.     void draw() {m.draw(loc.x,loc.y);}
  189.     int getWidth(){return m.getWidth();}
  190.     int getHeight(){return m.getHeight();}
  191.     /**
  192.      * does not take into account:
  193.      * - p might be bigger than this
  194.      * - this might be in a non-(0,0) location.
  195.      * @param p which piece is colliding with this (must be smaller)
  196.      * @param myCollidingChar, hisCollidingChar what counts as a collision?
  197.      * example: board.isCollidingWith(p, 'a', '*');
  198.      */
  199.     bool isCollidingWith(Piece & p, char myCollidingChar, char hisCollidingChar)
  200.     {
  201.         for(int row = 0; row < p.m.getHeight(); ++row)
  202.         {
  203.             for(int col = 0; col < p.m.getWidth(); ++col)
  204.             {
  205.                 if(m.get(col+p.loc.x, row+p.loc.y) == myCollidingChar
  206.                 && p.m.get(col, row) == hisCollidingChar)
  207.                 {
  208.                     return true;
  209.                 }
  210.             }
  211.         }
  212.         return false;
  213.     }
  214. };
  215. struct Game
  216. {
  217.     Piece a, b;
  218.     bool running;
  219.     int input;
  220.     char transparent;
  221.     Game():a("a.txt"),b("b.txt"),running(true)
  222.     {
  223. //      a.Piece::Piece("a.txt");
  224. //      b.Piece::Piece("b.txt");
  225. //      running = true;
  226.         transparent = ' ';
  227.     }
  228.     void drawingCode() {
  229.         a.draw();   b.draw();
  230.     }
  231.     void imprint()
  232.     {
  233.         for(int row = 0; row < b.getHeight(); ++row)
  234.         {
  235.             for(int col = 0; col < b.getWidth(); ++col)
  236.             {
  237.                 if(b.m.get(col,row) != transparent)
  238.                 {
  239.                     a.m.set(b.loc.x+col, b.loc.y+row, b.m.get(col, row));
  240.                 }
  241.             }
  242.         }
  243.     }
  244.     void update() {
  245.         Vector2D old = b.loc;
  246.         const int NONE = 0, MOVE = 1, ROT_CW = 2, ROT_CCW = 3;
  247.         int moveType = NONE;
  248.         switch(input) {
  249.         case 'w':   b.loc.y--;          moveType = MOVE;    break;
  250.         case 'a':   b.loc.x--;          moveType = MOVE;    break;
  251.         case 's':   b.loc.y++;          moveType = MOVE;    break;
  252.         case 'd':   b.loc.x++;          moveType = MOVE;    break;
  253.         case 'q':   b.m.rotateCCW();    moveType = ROT_CCW; break;
  254.         case 'e':   b.m.rotateCW();     moveType = ROT_CW;  break;
  255.         case 27:    running = false;    break;
  256.         case ' ':  
  257.             if(!a.isCollidingWith(b, '*', '*'))
  258.                 imprint();
  259.             break;
  260.         }
  261.         Rect board(a.loc, Vector2D(a.loc.x+a.getWidth(), a.loc.y+a.getHeight()));
  262.         Rect movingPiece(b.loc, Vector2D(b.loc.x+b.getWidth(), b.loc.y+b.getHeight()));
  263.         setCursorXY(0, 20);
  264.         if(!movingPiece.isWithin(board)
  265.         || a.isCollidingWith(b, 'a', '*')) {
  266.             std::cout << "OUTSIDE" << std::endl;
  267.             switch(moveType){
  268.             case MOVE:      b.loc = old;        break;
  269.             case ROT_CW:    b.m.rotateCCW();    break;
  270.             case ROT_CCW:   b.m.rotateCW();     break;
  271.             }
  272.         } else
  273.             std::cout << "       " << std::endl;
  274.     }
  275.     void getInput()
  276.     {
  277.         // throttle code, stalls the program to a
  278.         // 1/10th second frame rate, or till a key is pressed
  279.         long now = clock(), soon = now + 100;
  280.         while(clock() < soon && !_kbhit())
  281.         {
  282.             Sleep(1);
  283.         }
  284.         // only gets input if there is keyboard input to get
  285.         if(_kbhit())
  286.             input = _getch();
  287.         else
  288.             input = 0;
  289.     }
  290. };
  291.  
  292. int main(int argc, char * argv[]) {
  293.     Game g;
  294.     while(g.running) {
  295.         g.drawingCode();    // render
  296.         g.getInput();       // input
  297.         g.update();         // update
  298.     }
  299.     return 0;
  300. }
RAW Paste Data