Guest User

pong clone in c using opengl and glfw

a guest
Nov 17th, 2013
446
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.73 KB | None | 0 0
  1. #include <GLFW/glfw3.h>
  2. #include <stdbool.h>
  3. #include <stdlib.h>     // exit
  4. #include <string.h>     // strcpy, strcat: for window title
  5. #include <math.h>       // sin, cos, M_PI, round
  6. #include <stdio.h>      // printf, snprintf
  7. #define printf(...)     // comment to enable console log output
  8.  
  9.  
  10. typedef struct app_s {
  11.     int width;
  12.     int height;
  13.     bool windowed;
  14.     bool benchmark;
  15.     bool multiplayer;
  16. } app_s;
  17.  
  18. app_s app = {
  19.     .width = 800,
  20.     .height = 600,
  21.     .windowed = true,
  22.     .benchmark = true,
  23.     .multiplayer = false,
  24. };
  25.  
  26.  
  27. typedef struct player_s {
  28.     double x;
  29.     double y;
  30.     double width;
  31.     double height;
  32.     double speed;
  33.     double speed_movement;
  34.     int score;
  35. } player_s;
  36.  
  37. player_s player1 = {
  38.     .x = 0.095,
  39.     .y = 0.45,
  40.     .width = 0.01,
  41.     .height = 0.1,
  42.     .speed = 0,
  43.     .speed_movement = 0.015,
  44.     .score = 0,
  45. };
  46.  
  47. player_s player2 = {
  48.     .x = 0.905,
  49.     .y = 0.45,
  50.     .width = 0.01,
  51.     .height = 0.1,
  52.     .speed = 0,
  53.     .speed_movement = 0.015,
  54.     .score = 0,
  55. };
  56.  
  57.  
  58. typedef struct ball_s {
  59.     double x;
  60.     double y;
  61.     double width;
  62.     double height;
  63.     double rad;
  64.     double speed;
  65.     double speed_increase;
  66. } ball_s;
  67.  
  68. ball_s ball = {
  69.     .x = 0.4925,
  70.     .y = 0.4925,
  71.     .width = 0.015,
  72.     .height = 0.015,
  73.     .rad = 0.1,
  74.     .speed = 0.01,
  75.     .speed_increase = 0.00001,
  76. };
  77.  
  78.  
  79. void handleError(int code, const char *text)
  80. {
  81.     printf("GLFW error code <%d>: %s\n", code, text);
  82.     exit(EXIT_FAILURE);
  83. }
  84.  
  85. void handleWindowClose(GLFWwindow *wind)
  86. {
  87.     printf("Window close signal received\n");
  88.     exit(EXIT_SUCCESS);
  89. }
  90.  
  91. void handleKey(GLFWwindow *wind, int key, int scancode, int action, int mods)
  92. {
  93.     printf("Key <%d>, scancode <%d>, action <%d>, mods <%d>\n", key, scancode,
  94.                                                                 action, mods);
  95.     if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS){
  96.         printf("Esc pressed, exiting\n");
  97.         exit(EXIT_SUCCESS);
  98.     }
  99.  
  100.     if (app.multiplayer) {
  101.         if (key == GLFW_KEY_A) {
  102.             if (action == GLFW_PRESS) {
  103.                 player1.speed = -player1.speed_movement;
  104.             } else if (action == GLFW_RELEASE) {
  105.                 if (glfwGetKey(wind, GLFW_KEY_Z) == GLFW_PRESS) {
  106.                     player1.speed = player1.speed_movement;
  107.                 } else {
  108.                     player1.speed = 0;
  109.                 }
  110.             }
  111.         } else if (key == GLFW_KEY_Z) {
  112.             if (action == GLFW_PRESS) {
  113.                 player1.speed = player1.speed_movement;
  114.             } else if (action == GLFW_RELEASE) {
  115.                 if (glfwGetKey(wind, GLFW_KEY_A) == GLFW_PRESS) {
  116.                     player1.speed = -player1.speed_movement;
  117.                 } else {
  118.                     player1.speed = 0;
  119.                 }
  120.             }
  121.         }
  122.     }
  123.  
  124.     if (key == GLFW_KEY_APOSTROPHE) {
  125.         if (action == GLFW_PRESS) {
  126.             player2.speed = -player2.speed_movement;
  127.         } else if (action == GLFW_RELEASE) {
  128.             if (glfwGetKey(wind, GLFW_KEY_SLASH) == GLFW_PRESS) {
  129.                 player2.speed = player2.speed_movement;
  130.             } else {
  131.                 player2.speed = 0;
  132.             }
  133.         }
  134.     } else if (key == GLFW_KEY_SLASH) {
  135.         if (action == GLFW_PRESS) {
  136.             player2.speed = player2.speed_movement;
  137.         } else if (action == GLFW_RELEASE) {
  138.             if (glfwGetKey(wind, GLFW_KEY_APOSTROPHE) == GLFW_PRESS) {
  139.                 player2.speed = -player2.speed_movement;
  140.             } else {
  141.                 player2.speed = 0;
  142.             }
  143.         }
  144.     }
  145. }
  146.  
  147. void handleFramebufferSize(GLFWwindow *wind, int x, int y)
  148. {
  149.     printf("Framebuffer size changed: %d %d\n", x, y);
  150.     app.width = x;
  151.     app.height = y;
  152.     glViewport (0, 0, app.width, app.height);
  153.     glMatrixMode (GL_PROJECTION);
  154.     glLoadIdentity ();
  155.     glOrtho(0.0, 1.0, 1.0, 0.0, -1.0, 1.0);
  156. }
  157.  
  158.  
  159. double fps()
  160. {
  161.     static double time = 0;
  162.     static double time_old = 0;
  163.     static double ret_val = 0;
  164.  
  165.     time = glfwGetTime();
  166.     ret_val = 1 / (time - time_old);
  167.     time_old = time;
  168.  
  169.     return ret_val;
  170. }
  171.  
  172. void reset()
  173. {
  174.     ball.x = 0.4925,
  175.     ball.y = 0.4925,
  176.     ball.speed = 0.01;
  177.     ball.rad = 0.1;
  178.  
  179.  
  180.     player1.y = 0.45;
  181.  
  182.     player2.y = 0.45;
  183.  
  184.     glfwSetTime(0);
  185. }
  186.  
  187. void calcLineY(struct player_s * player)
  188. {
  189.     double new_y = player->y + player->speed;
  190.  
  191.     if (new_y < 0) {
  192.         new_y = 0;
  193.     } else if (new_y + player->height > 1) {
  194.         new_y = 1 - player->height;
  195.     }
  196.    
  197.     player->y = new_y;
  198. }
  199.  
  200. double flipY(double rad)
  201. {
  202.     return -rad;
  203. }
  204.  
  205. // unused
  206. double flipX(double rad)
  207. {
  208.     return M_PI - rad;
  209. }
  210.  
  211. void calcBall(struct ball_s * b)
  212. {
  213.     double new_x = b->x + (cos(b->rad) * b->speed);
  214.     double new_y = b->y + (sin(b->rad) * b->speed);
  215.  
  216.     // Check new X coord
  217.     if (new_x < 0) {
  218.         player1.score += 1;
  219.         printf("Score: %d %d\n", player1.score, player2.score);
  220.         reset();
  221.         return;
  222.     } else if (new_x > 1 - b->width) {
  223.         player2.score += 1;
  224.         printf("Score: %d %d\n", player1.score, player2.score);
  225.         reset();
  226.         return;
  227.     } else {
  228.         b->x = new_x;
  229.     }
  230.  
  231.     // Check new Y coord
  232.     if (new_y < 0) {
  233.         b->rad = flipY(b->rad);
  234.     } else if (new_y > 1 - b->height) {
  235.         b->rad = flipY(b->rad);
  236.     } else {
  237.         b->y = new_y;
  238.     }
  239.  
  240.     b->speed += b->speed_increase;
  241. }
  242.  
  243. bool intersects(struct player_s * l, struct ball_s * b)
  244. {
  245.     if (b->x < (l->x + l->width) && (b->x + b->width) > l->x &&
  246.         b->y < (l->y + l->height) && (b->y + b->height) > l->y) {
  247.         return true;
  248.     } else {
  249.         return false;
  250.     }
  251. }
  252.  
  253. double getRelDistFromCenter(struct player_s * l, struct ball_s * b)
  254. {
  255.     double dist_from_center;
  256.     dist_from_center = l->y + (l->height / 2) - (b->y + (b->height / 2));
  257.     return dist_from_center / l->height;
  258. }
  259.  
  260. void calc()
  261. {
  262.     if (!app.multiplayer) {
  263.         if (ball.y < player1.y) {
  264.             player1.speed = -player1.speed_movement / 1.1; // up
  265.         } else if (ball.y + ball.height > player1.y + player1.height) {
  266.             player1.speed = player1.speed_movement / 1.1; // down
  267.         } else {
  268.             player1.speed = 0;
  269.         }
  270.     }
  271.     calcLineY(&player1);
  272.     calcLineY(&player2);
  273.  
  274.     if (glfwGetTime() > 1) {
  275.         calcBall(&ball);
  276.     }
  277.  
  278.     if (intersects(&player1, &ball)) {
  279.         ball.rad = - 2 * getRelDistFromCenter(&player1, &ball);
  280.     }
  281.     if (intersects(&player2, &ball)) {
  282.         ball.rad = M_PI + 2 * getRelDistFromCenter(&player2, &ball);
  283.     }
  284.  
  285. }
  286.  
  287. void draw()
  288. {
  289.     glClear (GL_COLOR_BUFFER_BIT);
  290.  
  291.     glColor3d(0.2, 0.9, 0.2);
  292.     glBegin(GL_LINES);
  293.         glVertex2d(0.5, 0.0);
  294.         glVertex2d(0.5, 1.0);
  295.     glEnd();
  296.  
  297.     glColor3d(0.9, 0.9, 0.9);
  298.     glRectd(player1.x, player1.y,
  299.             player1.x + player1.width,
  300.             player1.y + player1.height);
  301.     glRectd(player2.x, player2.y,
  302.             player2.x + player2.width,
  303.             player2.y + player2.height);
  304.     glColor3d(0.0, 1.0, 0.0);
  305.     glRectd(ball.x, ball.y,
  306.             ball.x + ball.width,
  307.             ball.y + ball.height);
  308.  
  309.     glFlush();
  310.  
  311.     if (glGetError() != GL_NO_ERROR) {
  312.         printf("GL Error: %#x\n", glGetError());
  313.     }
  314. }
  315.  
  316. void setTitle(GLFWwindow *window)
  317. {
  318.     char title[100];
  319.     char fps_string[6];
  320.     char score_string[10];
  321.  
  322.     strcpy(title, "");
  323.     strcat(title, "Pong clone  ");
  324.     strcat(title, "FPS: ");
  325.     snprintf(fps_string, sizeof(fps_string), "%d  ", (int)round(fps()));
  326.     strcat(title, fps_string);
  327.     strcat(title, "Score: ");
  328.     snprintf(score_string, sizeof(score_string), "%d:%d  ", player1.score, player2.score);
  329.     strcat(title, score_string);
  330.  
  331.     glfwSetWindowTitle(window, title);
  332. }
  333.  
  334. int main(void)
  335. {
  336.     GLFWwindow *window;
  337.  
  338.     glfwSetErrorCallback(handleError);
  339.     if (glfwInit() == GL_FALSE) {
  340.         printf("Could not init GLFW\n");
  341.         exit(EXIT_FAILURE);
  342.     }
  343.  
  344.     if (app.windowed) {
  345.         window = glfwCreateWindow(app.width, app.height, "", NULL, NULL);
  346.     } else {
  347.         const GLFWvidmode *vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
  348.         app.width = vidmode->width;
  349.         app.height = vidmode->height;
  350.         window = glfwCreateWindow(app.width, app.height, "",
  351.                                   glfwGetPrimaryMonitor(), NULL);
  352.     }
  353.     glfwMakeContextCurrent(window);
  354.     handleFramebufferSize(window, app.width, app.height);
  355.  
  356.     glfwSetWindowCloseCallback(window, handleWindowClose);
  357.     glfwSetFramebufferSizeCallback(window, handleFramebufferSize);
  358.     glfwSetKeyCallback(window, handleKey);
  359.  
  360.  
  361.     glClearColor(0.1f, 0.1f, 0.1f, 0.0f);
  362.     glEnable(GL_LINE_STIPPLE);
  363.     glLineStipple(1, 0xFF00);
  364.    
  365.     reset();
  366.     while(true) {
  367.         setTitle(window);
  368.         glfwPollEvents();
  369.         calc();
  370.         draw();
  371.         glfwSwapBuffers(window);
  372.     }
  373. }
Advertisement
Add Comment
Please, Sign In to add comment