Advertisement
Redxone

[C] (WIP) CMDGame (Zelda Style Scrolling)

Jan 24th, 2018
173
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.84 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <windows.h>
  4. #include <math.h>
  5. #include <time.h>
  6.  
  7. // Types
  8. typedef struct _COORD vec2;
  9.  
  10. typedef enum {
  11.     BLACK, BLUE, GREEN, AQUA, RED, PURPLE,
  12.     YELLOW, LGRAY, GRAY, LBLUE, LGREEN, LAQUA,
  13.     LRED, LPURPLE, LYELLOW, WHITE
  14. } colors;
  15.  
  16. typedef enum {false, true} bool;
  17. typedef enum {DEAD, INGAME, INMENU, INTITLE} state;
  18.  
  19. typedef struct blk
  20. {
  21.     int fg, bg;
  22.     char ascii;
  23.     bool collide;
  24. } block;
  25.  
  26. typedef struct _player
  27. {
  28.    int x,y;
  29.    int fg;
  30.    bool canMove;
  31.    char ascii;
  32. } player;
  33.  
  34. typedef struct _camera
  35. {
  36.     int x,y;
  37.     int px, py;
  38.     int *buffer;
  39.     int width,height;
  40. } camera;
  41.  
  42. // Static variables.
  43. static camera *cam;
  44. static player *plr;
  45. static vec2 curpos;
  46. static int map[100][100];
  47. static block *blocks;
  48. static state gameState;
  49.  
  50. // Functions
  51. void initGame();
  52. void endGame();
  53. void spos(int,  int);
  54. void scol(int , int);
  55. void moveCam(int, int);
  56. void setRenderOffs(int, int);
  57. void strpos(char*, int, int);
  58. void drawMap();
  59. int rand_range(int, int);
  60. void redrawMap(int, int);
  61. void clearMap(int);
  62. void drawPlayer();
  63. void setCamBuffer(int, int, int);
  64. int checkCamBuffer(int, int);
  65. bool movePlayer(int, int, bool);
  66. void scrollMap(int, int, int);
  67. block newBlock(int, int, char, bool);
  68. void drawBuffer(int, int);
  69. void drawMapBlock(int, int);
  70. void drawBlock(block);
  71. void setBlock(int, int, int);
  72. block getBlock(int, int);
  73. void setPlayerGraphic(int, char);
  74.  
  75. // Game loops;
  76. void update();
  77. void draw();
  78.  
  79.  
  80. // Macros
  81. #define rcols() ( scol(LGRAY,BLACK) )
  82. #define min(x, y)   ( (x < y) ? x : y )
  83. #define max(x, y)   ( (x > y) ? x : y )
  84. #define randomize() (  srand(time(NULL))  )
  85.  
  86. int main()
  87. {
  88.     initGame();
  89.     randomize();
  90.     setRenderOffs(10,2);
  91.     clearMap(0);
  92.     int i;
  93.     for ( i = 0; i < 369; i++)
  94.     {
  95.         int x = rand_range(1,99);
  96.         int y = rand_range(1,99);
  97.         int b = rand_range(0,4);
  98.  
  99.         setBlock(x,y,b);
  100.     }
  101.     drawMap();
  102.     while(gameState != DEAD)
  103.     {
  104.         draw();
  105.         update();
  106.         drawBuffer(65,2);
  107.     }
  108.  
  109.     endGame();
  110.     return 0;
  111. }
  112.  
  113. block newBlock(int fg, int bg, char a, bool c)
  114. {
  115.     block nBlock;
  116.     nBlock.fg = fg;
  117.     nBlock.bg = bg;
  118.     nBlock.ascii = a;
  119.     nBlock.collide = c;
  120.     return nBlock;
  121. }
  122.  
  123. void setBlock(int x, int y, int id)
  124. {
  125.     map[y][x] = id;
  126. }
  127.  
  128. block getBlock(int x, int y)
  129. {
  130.     return blocks[map[y][x]];
  131. }
  132.  
  133. void drawMap()
  134. {
  135.    // Fill map based on block id.
  136.    int msize = (int) sqrt(sizeof(map)/sizeof(int));
  137.    int h;
  138.    int w;
  139.    int id = 0;
  140.    int draw_w = min(cam->x+cam->width,  msize);
  141.    int draw_h = min(cam->y+cam->height, msize);
  142.    //printf("At X: %d \n At Y: %d",cam->x, cam->y);
  143.  
  144.    for (h = cam->y; h < draw_h; h++)
  145.    {
  146.        for (w = cam->x; w < draw_w; w++)
  147.        {
  148.           if(h >= 90 || w >= 90 || h < 0 || w < 0)
  149.           {
  150.              id = 5;
  151.           }
  152.           else
  153.           {
  154.              id = map[h][w];
  155.           }
  156.           if( blocks+id != NULL )
  157.           {
  158.              if(plr->x == w && plr->y == h)
  159.              {
  160.                  drawPlayer();
  161.              }
  162.              else
  163.              {
  164.                  if( checkCamBuffer(w-(cam->x), h-(cam->y)) != id)
  165.                  {
  166.                     spos(cam->px+( w-cam->x ), cam->py+( h-cam->y ) );
  167.                     drawBlock( *(blocks+id) );
  168.                     setCamBuffer(w-(cam->x), h-(cam->y), id);
  169.                  }
  170.              }
  171.           }
  172.        }
  173.    }
  174. }
  175.  
  176. void drawBuffer(int rx, int ry)
  177. {
  178.    int h;
  179.    int w;
  180.  
  181.    for (h = 0; h < cam->height; h++)
  182.    {
  183.        for (w = 0; w < cam->width; w++)
  184.        {
  185.             block blk = blocks[checkCamBuffer(w,h)];
  186.             spos(w+rx,h+ry);
  187.             scol(WHITE, GRAY);
  188.             printf("%d",checkCamBuffer(w,h));
  189.             rcols();
  190.        }
  191.    }
  192. }
  193.  
  194. void drawPlayer()
  195. {
  196.     int bg = getBlock(plr->x, plr->y).bg;
  197.     scol(plr->fg,bg);
  198.     spos( (plr->x - cam->x) + cam->px , (plr->y - cam->y) + cam->py);
  199.     putchar(plr->ascii);
  200. }
  201.  
  202. bool movePlayer(int xo, int yo, bool checkCollide)
  203. {
  204.     int msize = (int) sqrt(sizeof(map)/sizeof(int));
  205.     if( (!checkCollide || !blocks[map[plr->y+yo][plr->x+xo]].collide) &&
  206.          plr->x+xo >= 0 && plr->y+yo >= 0 && plr->x+xo < msize-10 && plr->y+yo < msize-10)
  207.     {
  208.         drawMapBlock(plr->x,plr->y);
  209.         plr->x += xo;
  210.         plr->y += yo;
  211.         drawPlayer();
  212.     }
  213. }
  214.  
  215. void scrollMap(int xo, int yo, int speed)
  216. {
  217.     int dX = 0;
  218.     int dY = 0;
  219.     int mX, mY;
  220.     mX = (xo > 0) ? 1 : (xo == 0) ? 0 : -1;
  221.     mY = (yo > 0) ? 1 : (yo == 0) ? 0 : -1;
  222.     plr->canMove = false;
  223.     fflush(stdin); // We don't want to move oddly once we're done scrolling.
  224.     while(dX != xo || dY != yo)
  225.     {
  226.        moveCam(mX,mY);
  227.        drawMap();
  228.        dX+=mX;
  229.        dY+=mY;
  230.        Sleep(speed);
  231.     }
  232.     Sleep(speed*2);
  233.     plr->canMove = true;
  234. }
  235.  
  236. void drawMapBlock(int x, int y)
  237. {
  238.     spos( (x-cam->x) + cam->px, (y-cam->y) + cam->py);
  239.     drawBlock( *(blocks+map[y][x]) );
  240. }
  241.  
  242.  
  243. void clearMap(int block)
  244. {
  245.    // Fill map based on block id.
  246.    int msize = (int) sqrt(sizeof(map)/sizeof(int));
  247.    int h;
  248.    int w;
  249.    for (h = 0; h < msize; h++)
  250.    {
  251.        for (w = 0; w < msize; w++)
  252.        {
  253.            map[h][w] = block;
  254.        }
  255.    }
  256. }
  257. void spos(int x, int y)
  258. {
  259.     vec2 pos;
  260.     pos.X = x;
  261.     pos.Y = y;
  262.     curpos.X = x;
  263.     curpos.Y = y;
  264.     HANDLE chand = GetStdHandle(STD_OUTPUT_HANDLE);
  265.     SetConsoleCursorPosition(chand, pos);
  266. }
  267.  
  268. void scol(int fg, int bg)
  269. {
  270.     bg = bg << 4;
  271.     unsigned char col = fg+bg;
  272.  
  273.     HANDLE chand = GetStdHandle(STD_OUTPUT_HANDLE);
  274.     SetConsoleTextAttribute(chand, col);
  275. }
  276.  
  277. void strpos(char *t, int x, int y)
  278. {
  279.     spos(x,y);
  280.     puts(t);
  281. }
  282.  
  283. void drawBlock(block blk)
  284. {
  285.     scol(blk.fg, blk.bg);
  286.     putchar(blk.ascii);
  287.     rcols();
  288. }
  289.  
  290. void setPlayerGraphic(int fg, char a)
  291. {
  292.     plr->fg = fg;
  293.     plr->ascii = a;
  294. }
  295.  
  296. int rand_range(int rmin, int rmax)
  297. {
  298.     return rand() % ((rmax+1) - rmin) + rmin;
  299. }
  300.  
  301. void moveCam(int xo, int yo)
  302. {
  303.     cam->x += xo;
  304.     cam->y += yo;
  305. }
  306.  
  307. void setRenderOffs(int rx, int ry)
  308. {
  309.     cam->px = rx;
  310.     cam->py = ry;
  311. }
  312.  
  313. void update()
  314. {
  315.     // Character controller.
  316.     char key = getch();
  317.     switch(key)
  318.     {
  319.         case 'w':
  320.             movePlayer(0,-1,1);
  321.         break;
  322.         case 's':
  323.             movePlayer(0,1,1);
  324.         break;
  325.         case 'a':
  326.             movePlayer(-1,0,1);
  327.         break;
  328.         case 'd':
  329.             movePlayer(1,0,1);
  330.         break;
  331.     }
  332. }
  333.  
  334. void draw()
  335. {
  336.     // Positional information.
  337.     scol(WHITE,BLACK);
  338.     spos(2,0);
  339.     printf("Pos -> X: %d \n  Pos -> Y: %d \n",plr->x,plr->y);
  340.  
  341.     // Scroll when player is at the edge of the screen (zelda style)
  342.     int scrollX = (cam->width/2 );
  343.     int scrollY = (cam->height/2);
  344.     if( (plr->x - cam->x) >= cam->width-1 )
  345.     {
  346.         scrollMap(scrollX,0,2);
  347.     }
  348.     if( (plr->x - cam->x) <= 0 )
  349.     {
  350.         scrollMap(-scrollX,0,2);
  351.     }
  352.     if( (plr->y - cam->y) >= cam->height-1 )
  353.     {
  354.         scrollMap(0,scrollY,2);
  355.     }
  356.     if( (plr->y - cam->y) <= 0 )
  357.     {
  358.         scrollMap(0,-scrollY,2);
  359.     }
  360.  
  361. }
  362.  
  363. int checkCamBuffer(int x, int y)
  364. {
  365.     int result = *(cam->buffer + (y * cam->width) + x);
  366.     if(result == NULL) return -1;
  367.     return result;
  368. }
  369.  
  370. void setCamBuffer(int x, int y, int id)
  371. {
  372.    *(cam->buffer + (y * cam->width) + x) = id;
  373. }
  374.  
  375.  
  376. void initGame()
  377. {
  378.     gameState = INGAME;
  379.     // Init blocks.
  380.     blocks = calloc(6, sizeof(block));
  381.     blocks[0] = newBlock(LGREEN, GREEN, '*',0);       // GRASS
  382.     blocks[1] = newBlock(RED,    LGRAY, '=',1);       // BRICK
  383.     blocks[2] = newBlock(LGRAY,  LGRAY, ' ',1);       // CEMENT
  384.     blocks[3] = newBlock(LAQUA,  AQUA,  '~',0);       // WATER
  385.     blocks[4] = newBlock(YELLOW, GREEN, '&',0);       // FLOWER
  386.     blocks[5] = newBlock(BLUE,   BLUE,  ' ',1);       // VOID
  387.     // Init camera / player.
  388.     cam = malloc(sizeof(camera));
  389.     plr = malloc(sizeof(player));
  390.     cam->x = 0;
  391.     cam->y = 0;
  392.     cam->px = 0;
  393.     cam->py = 0;
  394.     cam->width = 52;
  395.     cam->height = 19;
  396.     cam->buffer = NULL;
  397.     cam->buffer = calloc(cam->width * cam->height, sizeof(int));
  398.     plr->x = (cam->width/2);
  399.     plr->y = (cam->height/2);
  400.     plr->fg = LBLUE;
  401.     plr->canMove = true;
  402.     plr->ascii = '@';
  403.     // Setup cursor visibility
  404.     HANDLE chand = GetStdHandle(STD_OUTPUT_HANDLE);
  405.     CONSOLE_CURSOR_INFO cinfo;
  406.     cinfo.dwSize = 100;
  407.     cinfo.bVisible = false;
  408.     SetConsoleCursorInfo(chand, &cinfo);
  409. }
  410.  
  411. void endGame()
  412. {
  413.     HANDLE chand = GetStdHandle(STD_OUTPUT_HANDLE);
  414.     CONSOLE_CURSOR_INFO cinfo;
  415.     cinfo.dwSize = 100;
  416.     cinfo.bVisible = true;
  417.     SetConsoleCursorInfo(chand, &cinfo);
  418.     free(blocks);
  419.     free(cam);
  420.     free(plr);
  421.     free(cam->buffer);
  422. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement