#include #include #include #include "glad/glad.h" #include #include "cglm/cglm.h" #include "lib.h" #include "stb_image.h" #define PI 3.14159f int SCREEN_WIDTH = 1024; int SCREEN_HEIGHT = 768; typedef struct State { float camX; float camY; float px; float py; } State; void framebuffer_size_callback(GLFWwindow* window, int width, int height) { (void)window; glViewport(0, 0, width, height); SCREEN_WIDTH = width; SCREEN_HEIGHT = height; } void processInput(GLFWwindow *window, State* state) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { glfwSetWindowShouldClose(window, true); } float amount = 1.0f; if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) { state->camY -= amount; } if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) { state->camY += amount; } if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) { state->camX -= amount; } if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS) { state->camX += amount; } amount = 1.1f; if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { state->py -= amount; } if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { state->py += amount; } if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { state->px -= amount; } if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { state->px += amount; } } int main(void) { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); GLFWwindow* window = checkPtr(glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "2D Engine", NULL, NULL), "Error creating GLFW window"); if (window == NULL) glfwTerminate(); glfwMakeContextCurrent(window); checkCode(gladLoadGLLoader((GLADloadproc)glfwGetProcAddress), "Error initializing GLAD"); glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); unsigned int shaderProgram = compileShaderProgram("shaders/main.vert", "shaders/main.frag", NULL); glEnable(GL_FRAMEBUFFER_SRGB); glDisable(0x809D); glEnable(GL_BLEND); // CHECK: Do we need this? // glEnable(GL_DEPTH_TEST); // glDepthFunc(GL_GREATER); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); float vertices[] = { // pos // tex 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f }; unsigned int VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindVertexArray(VAO); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); mat4 camOrtho; glm_ortho(0.0f, SCREEN_WIDTH, SCREEN_HEIGHT, 0.0f, -1.0f, 1.0f, camOrtho); unsigned int textureID; int width, height, channels; char* data = (char*)stbi_load("assets/idle.png", &width, &height, &channels, 4); if (data == NULL) { fprintf(stderr, "Could not load texture"); return -1; } glGenTextures(1, &textureID); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textureID); // // set Texture wrap and filter modes glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); stbi_image_free(data); // glBindTexture(GL_TEXTURE_2D, 0); // float deltaTime = 0.0f; // float lastFrame = 0.0f; State state = {0}; int frameCount = 0; float elapsed = 0.0f; float lastFrame; while (!glfwWindowShouldClose(window)) { float currentFrame = glfwGetTime(); float deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; processInput(window, &state); glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(shaderProgram); // vec4 vec = {1.0f, 0.0f, 0.0f, 1.0f}; mat4 model; mat4 projection; glm_mat4_identity(model); glm_mat4_identity(projection); float pivotx = 0.5f; float pivoty = 0.5f; glm_translate(model, (vec3){state.px, state.py, 0.0f}); glm_translate(model, (vec3){0.f, 0.f, 0.0f}); glm_translate(model, (vec3){pivotx, pivoty, 0.0f}); // glm_rotate(model, currentFrame, (vec3){0.0f, 0.0f, 1.0f}); glm_scale(model, (vec3){100.0f, 100.0f, 0.0f}); glm_translate(model, (vec3){-pivotx, -pivoty, 0.0f}); // printf("X:%f Y:%f Z:%f\n", projection[3][0], projection[3][1], projection[3][2]); float worldUnitSizeInPixels = 2; // Desired size of a 1x1 area on the screen float hw = (SCREEN_WIDTH / 2.f) / worldUnitSizeInPixels; float hh = (SCREEN_HEIGHT / 2.f) / worldUnitSizeInPixels; glm_ortho(-hw, hw, hh, -hh, -1.0f, 1.0f, projection); glm_translate(projection, (vec3){0.0f + state.camX, 0.0f + state.camY, 0.0f}); GLint location = glGetUniformLocation(shaderProgram, "model"); glUniformMatrix4fv(location, 1, GL_FALSE, model[0]); location = glGetUniformLocation(shaderProgram, "projection"); glUniformMatrix4fv(location, 1, GL_FALSE, projection[0]); location = glGetUniformLocation(shaderProgram, "spriteColor"); glUniform3f(location, 1.0f, 1.0f, 1.0f); elapsed += deltaTime; if (elapsed > 0.1f) { frameCount += 1; if (frameCount > 9) { frameCount = 0; } elapsed = 0.0f; } location = glGetUniformLocation(shaderProgram, "spriteX"); float spriteX = (float)frameCount / 10; glUniform1f(location, spriteX); location = glGetUniformLocation(shaderProgram, "spriteY"); glUniform1f(location, state.py); glUniform1i(glGetUniformLocation(shaderProgram, "image"), 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textureID); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); glfwSwapBuffers(window); glfwPollEvents(); } glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteProgram(shaderProgram); glfwTerminate(); return 0; }