Window.java 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package me.hammerle.snuviengine.api;
  2. import org.lwjgl.glfw.*;
  3. import org.lwjgl.opengl.*;
  4. import static org.lwjgl.glfw.GLFW.*;
  5. import static org.lwjgl.opengl.GL11.*;
  6. import static org.lwjgl.system.MemoryUtil.*;
  7. public final class Window {
  8. private final double secondsPerTick;
  9. private long window = NULL;
  10. private Keys keys = null;
  11. private Gamepad gamepad = null;
  12. private Renderer renderer;
  13. private final Stats stats = new Stats();
  14. public Window(long nanosPerTick) {
  15. secondsPerTick = nanosPerTick / 1_000_000_000.0;
  16. }
  17. public boolean initialize(String name, int width, int height) {
  18. setErrorCallback();
  19. if(initializeGLFW()) {
  20. return false;
  21. }
  22. setWindowHints();
  23. if(createWindow(name, width, height)) {
  24. return false;
  25. }
  26. setKeyCallback();
  27. setGamepad();
  28. setResizeCallback();
  29. createAndSetContext();
  30. setBufferSwapInterval();
  31. return !initializeRenderer(width, height);
  32. }
  33. private void setErrorCallback() {
  34. GLFWErrorCallback.createPrint(System.out).set();
  35. }
  36. private boolean initializeGLFW() {
  37. return !glfwInit();
  38. }
  39. private void setWindowHints() {
  40. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
  41. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
  42. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  43. }
  44. private boolean createWindow(String name, int width, int height) {
  45. window = glfwCreateWindow(width, height, name, NULL, NULL);
  46. if(window == NULL) {
  47. terminateGLFW();
  48. return true;
  49. }
  50. return false;
  51. }
  52. private void terminateGLFW() {
  53. glfwTerminate();
  54. }
  55. private void setKeyCallback() {
  56. keys = new Keys();
  57. glfwSetKeyCallback(window, (eventWindow, key, scancode, action, mods) -> {
  58. if(action == GLFW_PRESS) {
  59. keys.press(key);
  60. } else if(action == GLFW_RELEASE) {
  61. keys.release(key);
  62. }
  63. });
  64. }
  65. private void setGamepad() {
  66. gamepad = new Gamepad(GLFW_JOYSTICK_1);
  67. }
  68. private void setResizeCallback() {
  69. glfwSetFramebufferSizeCallback(window, (eventWindow, width, height) -> {
  70. glViewport(0, 0, width, height);
  71. renderer.setSize(width, height);
  72. });
  73. }
  74. private void createAndSetContext() {
  75. glfwMakeContextCurrent(window);
  76. GL.createCapabilities();
  77. }
  78. private void setBufferSwapInterval() {
  79. glfwSwapInterval(1);
  80. }
  81. private boolean initializeRenderer(int width, int height) {
  82. int shaderProgram = Shader.createShaderProgram("vertex.vs", "fragment.fs");
  83. if(shaderProgram == -1) {
  84. return true;
  85. }
  86. renderer = new Renderer(shaderProgram, width, height);
  87. return false;
  88. }
  89. public void open(Game game) {
  90. game.onCompleteInitialization(stats, keys, gamepad);
  91. runGameLoop(game);
  92. game.onStop();
  93. destroyWindow();
  94. terminateGLFW();
  95. freeErrorCallback();
  96. }
  97. private void runGameLoop(Game game) {
  98. double lastSecondTime = glfwGetTime();
  99. double lag = 0;
  100. while(!glfwWindowShouldClose(window) && game.isRunning()) {
  101. double newSecondTime = glfwGetTime();
  102. lag += newSecondTime - lastSecondTime;
  103. lastSecondTime = newSecondTime;
  104. while(lag >= secondsPerTick) {
  105. lag -= secondsPerTick;
  106. tick(game);
  107. }
  108. renderTick(game, (float) (lag / secondsPerTick));
  109. }
  110. }
  111. private void tick(Game game) {
  112. stats.updateTicksPerSecond();
  113. gamepad.tick();
  114. keys.tick();
  115. game.tick();
  116. }
  117. private void renderTick(Game game, float lag) {
  118. stats.updateFramesPerSecond();
  119. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  120. game.renderTick(renderer, lag);
  121. glfwSwapBuffers(window);
  122. glfwPollEvents();
  123. }
  124. private void destroyWindow() {
  125. glfwDestroyWindow(window);
  126. }
  127. private void freeErrorCallback() {
  128. GLFWErrorCallback error = glfwSetErrorCallback(null);
  129. if(error != null) {
  130. error.free();
  131. }
  132. }
  133. }