GameEngine.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. #include "GameEngine.h"
  2. #include "Control.h"
  3. static GLuint program;
  4. static GLuint vShader;
  5. static GLuint fShader;
  6. static WindowResize windowResize;
  7. static MouseMove mouseMove;
  8. static int activeFocus = 0;
  9. static double oldMouseX = 0;
  10. static double oldMouseY = 0;
  11. static void flushOutput()
  12. {
  13. fflush(stdout);
  14. }
  15. static void onKeyEvent(GLFWwindow* w, int key, int scancode, int action, int mods)
  16. {
  17. if(action == GLFW_RELEASE)
  18. {
  19. if(key == GLFW_KEY_ESCAPE)
  20. {
  21. activeFocus = 0;
  22. glfwSetInputMode(w, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
  23. }
  24. keyRelease(key);
  25. }
  26. if(action == GLFW_PRESS)
  27. {
  28. keyPress(key);
  29. }
  30. }
  31. static void onMouseClick(GLFWwindow* w, int button, int action, int mods)
  32. {
  33. if(action == GLFW_PRESS)
  34. {
  35. if(!activeFocus)
  36. {
  37. glfwSetInputMode(w, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
  38. oldMouseX = 0;
  39. oldMouseY = 0;
  40. activeFocus = 1;
  41. }
  42. else
  43. {
  44. mousePress(button);
  45. }
  46. }
  47. else if(action == GLFW_RELEASE)
  48. {
  49. mouseRelease(button);
  50. }
  51. }
  52. static void onMouseMove(GLFWwindow* w, double x, double y)
  53. {
  54. if(activeFocus)
  55. {
  56. if(oldMouseX == 0 && oldMouseY == 0)
  57. {
  58. oldMouseX = x;
  59. oldMouseY = y;
  60. }
  61. else
  62. {
  63. mouseMove(x - oldMouseX, y - oldMouseY);
  64. oldMouseX = x;
  65. oldMouseY = y;
  66. }
  67. }
  68. }
  69. static void onWindowResize(GLFWwindow* w, int width, int height)
  70. {
  71. glViewport(0, 0, width, height);
  72. windowResize(width, height);
  73. }
  74. static GLchar* readFile(char* name)
  75. {
  76. FILE* file = fopen(name, "r");
  77. if(file != NULL)
  78. {
  79. int size = 128;
  80. int index = 0;
  81. GLchar* content = malloc(sizeof(GLchar) * size);
  82. while(1)
  83. {
  84. int c = fgetc(file);
  85. if(c == EOF)
  86. {
  87. break;
  88. }
  89. if(index >= size)
  90. {
  91. size *= 2;
  92. content = realloc(content, size);
  93. }
  94. content[index] = c;
  95. index++;
  96. }
  97. if(index >= size)
  98. {
  99. size++;
  100. content = realloc(content, size);
  101. }
  102. content[index] = '\0';
  103. index++;
  104. fclose(file);
  105. return content;
  106. }
  107. return NULL;
  108. }
  109. int checkShaderErrors(char* name, GLuint shader)
  110. {
  111. int returnValue = 0;
  112. printf("compiling %s shader ...\n", name);
  113. GLenum error = glGetError();
  114. if(error)
  115. {
  116. fprintf(stderr, "error: %u\n", glGetError());
  117. returnValue = 1;
  118. }
  119. else
  120. {
  121. printf("no error occured ...\n");
  122. }
  123. GLint compiled[1];
  124. glGetShaderiv(shader, GL_COMPILE_STATUS, compiled);
  125. if(compiled[0])
  126. {
  127. printf("%s shader successfully compiled\n", name);
  128. }
  129. else
  130. {
  131. fprintf(stderr, "compiling of %s shader failed:\n", name);
  132. GLchar buffer[512];
  133. GLsizei bufferSize = 512;
  134. GLsizei charsUsed = 0;
  135. glGetShaderInfoLog(shader, bufferSize, &charsUsed, buffer);
  136. buffer[bufferSize - 1] = '\0';
  137. fprintf(stderr, "%s\n", buffer);
  138. returnValue = 1;
  139. }
  140. return returnValue;
  141. }
  142. static GLuint compileProgram(const GLchar* vertex, const GLchar* fragment)
  143. {
  144. vShader = glCreateShader(GL_VERTEX_SHADER);
  145. glShaderSource(vShader, 1, &vertex, NULL);
  146. glCompileShader(vShader);
  147. if(checkShaderErrors("vertex", vShader))
  148. {
  149. return 0;
  150. }
  151. fShader = glCreateShader(GL_FRAGMENT_SHADER);
  152. glShaderSource(fShader, 1, &fragment, NULL);
  153. glCompileShader(fShader);
  154. if(checkShaderErrors("fragment", fShader))
  155. {
  156. return 0;
  157. }
  158. GLuint program = glCreateProgram();
  159. glAttachShader(program, vShader);
  160. glAttachShader(program, fShader);
  161. glLinkProgram(program);
  162. printf("linking shaders to program ...\n");
  163. GLenum error = glGetError();
  164. if(error)
  165. {
  166. fprintf(stderr, "error: %u\n", glGetError());
  167. return 0;
  168. }
  169. else
  170. {
  171. printf("no error occured ...\n");
  172. }
  173. GLint compiled[1];
  174. glGetProgramiv(program, GL_LINK_STATUS, compiled);
  175. if(compiled[0])
  176. {
  177. printf("shaders successfully linked\n");
  178. }
  179. else
  180. {
  181. fprintf(stderr, "linking of shaders failed:\n");
  182. GLchar buffer[512];
  183. GLsizei bufferSize = 512;
  184. GLsizei charsUsed = 0;
  185. glGetProgramInfoLog(program, bufferSize, &charsUsed, buffer);
  186. buffer[bufferSize - 1] = '\0';
  187. fprintf(stderr, "%s\n", buffer);
  188. return 0;
  189. }
  190. glUseProgram(program);
  191. return program;
  192. }
  193. static GLuint createProgram()
  194. {
  195. GLchar* vertex = readFile("vertex.vs");
  196. if(vertex == NULL)
  197. {
  198. fprintf(stderr, "cannot read vertex.vs\n");
  199. return 0;
  200. }
  201. GLchar* fragment = readFile("fragment.fs");
  202. if(fragment == NULL)
  203. {
  204. fprintf(stderr, "cannot read fragment.fs\n");
  205. free(vertex);
  206. return 0;
  207. }
  208. GLuint program = compileProgram(vertex, fragment);
  209. flushOutput();
  210. free(vertex);
  211. free(fragment);
  212. return program;
  213. }
  214. static void onTerm(GLFWwindow* window)
  215. {
  216. glfwDestroyWindow(window);
  217. glfwTerminate();
  218. }
  219. int startGame(char* name, InitFunction init, TickFunction tick, RenderTickFunction renderTick, WindowResize inWindowResize, MouseMove move)
  220. {
  221. if(!glfwInit())
  222. {
  223. fprintf(stderr, "could not initialize GLFW");
  224. return 1;
  225. }
  226. windowResize = inWindowResize;
  227. mouseMove = move;
  228. glfwDefaultWindowHints();
  229. glfwWindowHint(GLFW_VISIBLE, 0);
  230. glfwWindowHint(GLFW_RESIZABLE, 1);
  231. GLFWwindow* window = glfwCreateWindow(640, 480, name, NULL, NULL);
  232. if(!window)
  233. {
  234. fprintf(stderr, "could not create window");
  235. glfwTerminate();
  236. return 1;
  237. }
  238. glfwSetKeyCallback(window, onKeyEvent);
  239. glfwSetFramebufferSizeCallback(window, onWindowResize);
  240. glfwSetMouseButtonCallback(window, onMouseClick);
  241. glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
  242. activeFocus = 1;
  243. glfwSetCursorPosCallback(window, onMouseMove);
  244. glfwMakeContextCurrent(window);
  245. glfwSwapInterval(1);
  246. glfwShowWindow(window);
  247. GLenum err = glewInit();
  248. if (GLEW_OK != err)
  249. {
  250. fprintf(stderr, "Could not initialize GLEW: %s\n", glewGetErrorString(err));
  251. return 1;
  252. }
  253. printf("Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
  254. program = createProgram();
  255. if(program == 0)
  256. {
  257. onTerm(window);
  258. return 1;
  259. }
  260. //glEnable(GL_CULL_FACE);
  261. glEnable(GL_DEPTH_TEST);
  262. glDepthFunc(GL_LEQUAL);
  263. init(program);
  264. //printf("%lu\n", glfwGetTimerFrequency());
  265. //printf("%lu\n", glfwGetTimerValue());
  266. //printf("%lu\n", glfwGetTimerValue());
  267. long newTime = glfwGetTimerValue();
  268. long oldTime = newTime;
  269. long lag = 0;
  270. while(!glfwWindowShouldClose(window))
  271. {
  272. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  273. oldTime = newTime;
  274. newTime = glfwGetTimerValue();
  275. lag += newTime - oldTime;
  276. int ticksPerFrame = 0;
  277. while(lag >= NANOS_PER_TICK)
  278. {
  279. lag -= NANOS_PER_TICK;
  280. controlTick();
  281. tick(program);
  282. ticksPerFrame++;
  283. if(ticksPerFrame >= MAX_TICKS_PER_FRAME)
  284. {
  285. long skip = lag / NANOS_PER_TICK;
  286. lag -= skip * NANOS_PER_TICK;
  287. if(skip > 0)
  288. {
  289. printf("skipped %ld game ticks %ld\n", skip, lag);
  290. }
  291. break;
  292. }
  293. }
  294. renderTick(program, (float) lag / NANOS_PER_TICK);
  295. glfwSwapBuffers(window);
  296. glfwPollEvents();
  297. }
  298. glDeleteShader(vShader);
  299. glDeleteShader(fShader);
  300. glDeleteProgram(program);
  301. onTerm(window);
  302. return 0;
  303. }
  304. GLuint getProgram()
  305. {
  306. return program;
  307. }