123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- package me.hammerle.snuviengine.api;
- import org.lwjgl.glfw.*;
- import org.lwjgl.opengl.*;
- import static org.lwjgl.glfw.Callbacks.*;
- import static org.lwjgl.glfw.GLFW.*;
- import static org.lwjgl.opengl.GL11.*;
- import static org.lwjgl.system.MemoryUtil.*;
- public class Engine
- {
- private static long window;
-
- private static long nanosPerTick = 10_000_000;
- private static final int MAX_TICKS_PER_FRAME = 20;
-
- private static Timer fpsTimer;
- private static Timer tpsTimer;
-
- private static Renderer renderer;
-
- private Engine()
- {
- }
- public static void start(IGame game)
- {
- loop(game);
- glfwFreeCallbacks(window);
- glfwDestroyWindow(window);
- glfwTerminate();
- GLFWErrorCallback error = glfwSetErrorCallback(null);
- if(error != null)
- {
- error.free();
- }
- }
-
- public static void stop()
- {
- glfwSetWindowShouldClose(window, true);
- }
- public static void init(String name, int width, int height)
- {
- GLFWErrorCallback.createPrint(System.err).set();
-
- if(!glfwInit())
- {
- throw new IllegalStateException("Unable to initialize GLFW");
- }
- glfwDefaultWindowHints();
- glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
- glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
-
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
- window = glfwCreateWindow(width, height, name, NULL, NULL);
- if(window == NULL)
- {
- throw new IllegalStateException("Failed to create the GLFW window");
- }
- glfwSetKeyCallback(window, (w, key, scancode, action, mods) ->
- {
- if(action == GLFW_RELEASE)
- {
- KeyHandler.onKeyUpEvent(key);
- }
- else if(action == GLFW_PRESS)
- {
- KeyHandler.onKeyDownEvent(key);
- }
- });
-
- glfwMakeContextCurrent(window);
- glfwSwapInterval(2);
-
- GL.createCapabilities();
-
- renderer = new Renderer(width, height);
- fpsTimer = new Timer(60, 0.0f);
- tpsTimer = new Timer(1_000_000_000l / nanosPerTick, height * 0.25f);
-
- glfwSetFramebufferSizeCallback(window, (w, fwidth, fheight) ->
- {
- glViewport(0, 0, fwidth, fheight);
- renderer.setViewPort(fwidth, fheight);
- });
-
- glfwShowWindow(window);
- }
-
- private static void loop(IGame game)
- {
- long oldTime = System.nanoTime();
- long lag = 0;
- while(!glfwWindowShouldClose(window))
- {
- long newTime = System.nanoTime();
- lag += newTime - oldTime;
- oldTime = newTime;
- int ticksPerFrame = 0;
- while(lag >= nanosPerTick)
- {
- lag -= nanosPerTick;
- tpsTimer.update();
- GamepadHandler.tick();
- KeyHandler.tick();
- game.tick();
- ticksPerFrame++;
- if(ticksPerFrame >= MAX_TICKS_PER_FRAME)
- {
- long skip = lag / nanosPerTick;
- lag -= skip * nanosPerTick;
- if(skip > 0)
- {
- System.out.println(String.format("skipped %d game ticks %d", skip, lag));
- }
- break;
- }
- }
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- game.renderTick(renderer, (float) lag / nanosPerTick);
- tpsTimer.draw(renderer);
- fpsTimer.draw(renderer);
- fpsTimer.update();
- glfwSwapBuffers(window);
- glfwPollEvents();
- }
- game.onStop();
- }
-
- public static void setNanosPerTick(long nanos)
- {
- nanosPerTick = nanos;
- tpsTimer.setExpectedValue(1_000_000_000l / nanos);
- }
-
- public static long getNanosPerTick()
- {
- return nanosPerTick;
- }
-
- public static double getTicksPerSecond()
- {
- return tpsTimer.getCallsPerSecond();
- }
-
- public static void setRenderTicksPerSecond(boolean active)
- {
- tpsTimer.setActive(active);
- }
-
- public static double getFramesPerSecond()
- {
- return fpsTimer.getCallsPerSecond();
- }
- public static void setRenderFramesPerSecond(boolean active)
- {
- fpsTimer.setActive(active);
- }
- }
|