From cd48894563052baeddff64f6bbc13ccc7fa6e081 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Thu, 19 Feb 2015 20:10:11 -0500 Subject: Added CRT mesh! Also a character sprite, changed up the map file format, fixed some shader bugs --- src/main.cpp | 21 ++++-- src/map.cpp | 10 ++- src/map.h | 4 +- src/mapview.cpp | 112 +++++++++++++++++++++++-------- src/mapview.h | 6 ++ src/mob.h | 2 + src/renderer.cpp | 197 +++++++++++++++++++++++++++++++++++++++++++++++-------- src/renderer.h | 1 + 8 files changed, 287 insertions(+), 66 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 2a1d9ea..ec485e7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,20 +30,31 @@ int main() glfwSwapInterval(1); glfwSetKeyCallback(window, key_callback); - Map* m = new Map("../maps/bigmap.txt"); - Map* m2 = new Map("../maps/cozy.txt"); + Map* m = new Map("../maps/embarass.txt"); + //Map* m2 = new Map("../maps/cozy.txt"); - m->setLeftMap(m2); - m2->setRightMap(m); + //m->setLeftMap(m2); + //m2->setRightMap(m); curGameState = new MapView(m, 100, 100); Texture* buffer = createTexture(GAME_WIDTH, GAME_HEIGHT); + double lastTime = glfwGetTime(); + double accum = 0.0; + while (!(quit || glfwWindowShouldClose(window))) { // Tick! - curGameState->tick(); + accum += (glfwGetTime() - lastTime); + if (accum < 0) accum = 0; + while (accum > SECONDS_PER_FRAME) + { + curGameState->tick(); + accum -= SECONDS_PER_FRAME; + } + + lastTime = glfwGetTime(); // Do rendering curGameState->render(buffer); diff --git a/src/map.cpp b/src/map.cpp index cb1ce72..5f9e7bd 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -4,11 +4,15 @@ Map::Map(char* filename) { FILE* f = fopen(filename, "r"); - m_mapdata = (char*) malloc(MAP_WIDTH*(MAP_HEIGHT-1)*sizeof(char)); + m_mapdata = (int*) malloc(MAP_WIDTH*(MAP_HEIGHT-1)*sizeof(int)); for (int i=0; ix_accel = 0; player->y_accel = jump_gravity; player->w = 10; - player->h = 14; + player->h = 12; + player->onGround = false; + player->animFrame = 0; + + bg = createTexture(GAME_WIDTH, GAME_HEIGHT); + chara = loadTextureFromBMP("../res/Starla.bmp"); + tiles = loadTextureFromBMP("../res/tiles2.bmp"); loadMap(first); } @@ -25,6 +31,8 @@ MapView::MapView(Map* first, int x, int y) MapView::~MapView() { destroyTexture(bg); + destroyTexture(chara); + destroyTexture(tiles); delete player; } @@ -41,55 +49,47 @@ void MapView::loadMap(Map* m) add_collision(-6, 0, GAME_WIDTH, left, (m->getLeftMap() == NULL) ? 1 : 2); add_collision(GAME_WIDTH+6, 0, GAME_WIDTH, right, (m->getRightMap() == NULL) ? 1 : 2); - if (bg == NULL) - { - bg = createTexture(GAME_WIDTH, GAME_HEIGHT); - } - fillTexture(bg, NULL, 0, 0, 0); - const char* mapbuf = m->mapdata(); + const int* mapbuf = m->mapdata(); for (int i=0; i 0) { - case ' ': break; - case 'X': fillTexture(bg, &dst, 255, 85, 85); break; - case 'P': fillTexture(bg, &dst, 85, 255, 255); break; - } - + blitTexture(tiles, bg, &src, &dst); + } //blitTexture(tiles, bg, &src, &dst); - if (mapbuf[i] == 'X') + if ((mapbuf[i] > 0) && (!((mapbuf[i] >= 5) && (mapbuf[i] <= 7)))) { - if ((x != 0) && (mapbuf[i-1] != 'X')) + //if ((x != 0) && (mapbuf[i-1] != 'X')) { add_collision(x*TILE_WIDTH, y*TILE_HEIGHT, (y+1)*TILE_HEIGHT, right, 0); } - if ((x != 39) && (mapbuf[i+1] != 'X')) + //if ((x != 39) && (mapbuf[i+1] != 'X')) { add_collision((x+1)*TILE_WIDTH, y*TILE_HEIGHT, (y+1)*TILE_HEIGHT, left, 0); } - if ((y != 0) && (mapbuf[i-MAP_WIDTH] != 'X')) + //if ((y != 0) && (mapbuf[i-MAP_WIDTH] != 'X')) { add_collision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, down, 0); } - if ((y != 23) && (mapbuf[i+MAP_WIDTH] != 'X')) + //if ((y != 23) && (mapbuf[i+MAP_WIDTH] != 'X')) { add_collision((y+1)*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, up, 0); } - } else if (mapbuf[i] == 'P') + } else if ((mapbuf[i] >= 5) && (mapbuf[i] <= 7)) { - add_collision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, down, 0); + add_collision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, down, 3); } } @@ -112,16 +112,38 @@ void MapView::input(int key, int action) { switch (key) { - case GLFW_KEY_LEFT: holding_left = true; break; - case GLFW_KEY_RIGHT: holding_right = true; break; - case GLFW_KEY_UP: player->y_vel = jump_velocity; break; + case GLFW_KEY_LEFT: + holding_left = true; + break; + case GLFW_KEY_RIGHT: + holding_right = true; + break; + case GLFW_KEY_UP: + if (player->onGround) + { + player->y_vel = jump_velocity; + player->onGround = false; + } + break; + case GLFW_KEY_DOWN: + holding_down = true; + break; } } else if (action == GLFW_RELEASE) { switch (key) { - case GLFW_KEY_LEFT: holding_left = false; break; - case GLFW_KEY_RIGHT: holding_right = false; break; + case GLFW_KEY_LEFT: + holding_left = false; + if (!holding_right) player->animFrame = 1; + break; + case GLFW_KEY_RIGHT: + holding_right = false; + if (!holding_left) player->animFrame = 0; + break; + case GLFW_KEY_DOWN: + holding_down = false; + break; } } } @@ -153,12 +175,37 @@ void MapView::tick() void MapView::render(Texture* tex) { + if (animFrame == 0) + { + if (holding_left) + { + if (player->animFrame == 3) + { + player->animFrame = 5; + } else { + player->animFrame = 3; + } + } else if (holding_right) + { + if (player->animFrame == 2) + { + player->animFrame = 4; + } else { + player->animFrame = 2; + } + } + } + + animFrame++; + animFrame %= 10; + // Draw the background blitTexture(bg, tex, NULL, NULL); // Draw the player + Rectangle src_rect(player->animFrame * 10, 0, 10, 12); Rectangle dst_rect(player->x, player->y, player->w, player->h); - fillTexture(tex, &dst_rect, 255, 255, 255); + blitTexture(chara, tex, &src_rect, &dst_rect); } void MapView::add_collision(int axis, int lower, int upper, direction_t dir, int type) @@ -305,9 +352,20 @@ void MapView::check_collisions(mob_t* mob, int x_next, int y_next) { y_next = it->axis - mob->h; mob->y_vel = 0; + mob->onGround = true; } else if (it->type == 1) { y_next = 1 - mob->h/2; + } else if (it->type == 3) + { + if (holding_down) + { + holding_down = false; + } else { + y_next = it->axis - mob->h; + mob->y_vel = 0; + mob->onGround = true; + } } break; diff --git a/src/mapview.h b/src/mapview.h index 70ffb3b..06309e3 100644 --- a/src/mapview.h +++ b/src/mapview.h @@ -16,6 +16,7 @@ const int MAP_WIDTH = GAME_WIDTH/TILE_WIDTH; const int MAP_HEIGHT = GAME_HEIGHT/TILE_HEIGHT; const int FRAMES_PER_SECOND = 60; +const double SECONDS_PER_FRAME = 1.0 / FRAMES_PER_SECOND; enum direction_t { up, left, down, right @@ -47,12 +48,17 @@ class MapView : public State { list down_collisions; Texture* bg = NULL; + Texture* chara; + Texture* tiles; bool holding_left = false; bool holding_right = false; + bool holding_down = false; mob_t* player; Map* curMap; + + int animFrame = 0; }; #endif diff --git a/src/mob.h b/src/mob.h index 7a4b707..213b062 100644 --- a/src/mob.h +++ b/src/mob.h @@ -7,4 +7,6 @@ typedef struct { double y_accel; int w; int h; + bool onGround; + int animFrame; } mob_t; diff --git a/src/renderer.cpp b/src/renderer.cpp index 2ee0642..00ae7ef 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "mapview.h" static bool rendererInitialized = false; @@ -10,6 +11,8 @@ static bool rendererInitialized = false; static GLFWwindow* window; static GLuint FramebufferName; // The framebuffer +static GLuint depthrenderbuffer; + static GLuint ntscShader; // The NTSC shader static GLuint finalShader; // The passthrough shader static GLuint blitShader; // The blitting shader @@ -33,6 +36,12 @@ static GLuint VertexArrayID; // A plane that fills the renderbuffer static GLuint quad_vertexbuffer; +// Buffers for the mesh +static GLuint mesh_vertexbuffer; +static GLuint mesh_uvbuffer; +static GLuint mesh_normalbuffer; +static int mesh_numvertices; + GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path) { // Create the shaders @@ -188,6 +197,58 @@ GLuint loadBMP_custom(const char * imagepath){ return textureID; } +void loadMesh(const char* filename, std::vector& out_vertices, std::vector& out_uvs, std::vector& out_normals) +{ + FILE* file = fopen(filename, "r"); + if (file == NULL) + { + fprintf(stderr, "Could not open mesh file %s\n", filename); + exit(1); + } + + std::vector temp_vertices; + std::vector temp_uvs; + std::vector temp_normals; + + for (;;) + { + char lineHeader[256]; + int res = fscanf(file, "%s", lineHeader); + if (res == EOF) + { + break; + } + + if (!strncmp(lineHeader, "v", 2)) + { + vec3 vertex; + fscanf(file, "%f %f %f\n", &vertex.x,&vertex.y,&vertex.z); + temp_vertices.push_back(vertex); + } else if (!strncmp(lineHeader, "vt", 3)) + { + vec2 uv; + fscanf(file, "%f %f\n", &uv.x, &uv.y); + temp_uvs.push_back(uv); + } else if (!strncmp(lineHeader, "vn", 3)) + { + vec3 normal; + fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z); + temp_normals.push_back(normal); + } else if (!strncmp(lineHeader, "f", 2)) + { + int vertexIDs[3], uvIDs[3], normalIDs[3]; + fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIDs[0], &uvIDs[0], &normalIDs[0], &vertexIDs[1], &uvIDs[1], &normalIDs[1], &vertexIDs[2], &uvIDs[2], &normalIDs[2]); + + for (int i=0; i<3; i++) + { + out_vertices.push_back(temp_vertices[vertexIDs[i] - 1]); + out_uvs.push_back(temp_uvs[uvIDs[i] - 1]); + out_normals.push_back(temp_normals[normalIDs[i] - 1]); + } + } + } +} + GLFWwindow* initRenderer() { if (rendererInitialized) @@ -230,12 +291,20 @@ GLFWwindow* initRenderer() glGenVertexArrays(1, &VertexArrayID); glBindVertexArray(VertexArrayID); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + // Set up the framebuffer glGenFramebuffers(1, &FramebufferName); glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName); GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0}; glDrawBuffers(1, DrawBuffers); + glGenRenderbuffers(1, &depthrenderbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, depthrenderbuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 1024, 768); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthrenderbuffer); + // Set up the NTSC rendering buffers glGenTextures(1, &renderedTex1); glBindTexture(GL_TEXTURE_2D, renderedTex1); @@ -274,6 +343,26 @@ GLFWwindow* initRenderer() curBuf = 0; + // Load the mesh! + std::vector mesh_vertices; + std::vector mesh_uvs; + std::vector mesh_normals; + loadMesh("../res/monitor-fef.obj", mesh_vertices, mesh_uvs, mesh_normals); + + mesh_numvertices = mesh_vertices.size(); + + glGenBuffers(1, &mesh_vertexbuffer); + glBindBuffer(GL_ARRAY_BUFFER, mesh_vertexbuffer); + glBufferData(GL_ARRAY_BUFFER, mesh_vertices.size() * sizeof(vec3), &mesh_vertices[0], GL_STATIC_DRAW); + + glGenBuffers(1, &mesh_uvbuffer); + glBindBuffer(GL_ARRAY_BUFFER, mesh_uvbuffer); + glBufferData(GL_ARRAY_BUFFER, mesh_uvs.size() * sizeof(vec3), &mesh_uvs[0], GL_STATIC_DRAW); + + glGenBuffers(1, &mesh_normalbuffer); + glBindBuffer(GL_ARRAY_BUFFER, mesh_normalbuffer); + glBufferData(GL_ARRAY_BUFFER, mesh_normals.size() * sizeof(vec3), &mesh_normals[0], GL_STATIC_DRAW); + // Load the vertices of a flat surface GLfloat g_quad_vertex_buffer_data[] = { -1.0f, -1.0f, 0.0f, @@ -314,6 +403,9 @@ void destroyRenderer() // Delete the plane buffer glDeleteBuffers(1, &quad_vertexbuffer); + glDeleteBuffers(1, &mesh_vertexbuffer); + glDeleteBuffers(1, &mesh_uvbuffer); + glDeleteBuffers(1, &mesh_normalbuffer); // Delete the shaders glDeleteProgram(ntscShader); @@ -332,6 +424,7 @@ void destroyRenderer() glDeleteTextures(1, &bloomPassTex); // Delete the framebuffer + glDeleteRenderbuffers(1, &depthrenderbuffer); glDeleteFramebuffers(1, &FramebufferName); // Delete the VAO @@ -466,6 +559,7 @@ void fillTexture(Texture* tex, Rectangle* dstrect, int r, int g, int b) glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); glViewport(0, 0, tex->width, tex->height); + glClear(GL_DEPTH_BUFFER_BIT); glUseProgram(fillShader); glUniform3f(glGetUniformLocation(fillShader, "vecColor"), r / 255.0, g / 255.0, b / 255.0); @@ -536,6 +630,7 @@ void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle // Set up the shader glUseProgram(blitShader); + glClear(GL_DEPTH_BUFFER_BIT); glViewport(0, 0, dsttex->width, dsttex->height); glActiveTexture(GL_TEXTURE0); @@ -552,6 +647,62 @@ void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle glDeleteBuffers(1, &vertexbuffer); } +void renderWithoutEffects(Texture* tex) +{ + if (!rendererInitialized) + { + fprintf(stderr, "Renderer not initialized\n"); + exit(-1); + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0, 0, 1024, 768); + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(blitShader); + + const GLfloat fullBlitVertices_data[] = { + -1.0, -1.0, + 1.0, -1.0, + -1.0, 1.0, + 1.0, 1.0 + }; + + GLuint fullBlitVertices; + glGenBuffers(1, &fullBlitVertices); + glBindBuffer(GL_ARRAY_BUFFER, fullBlitVertices); + glBufferData(GL_ARRAY_BUFFER, sizeof(fullBlitVertices_data), fullBlitVertices_data, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); + + const GLfloat fullBlitTex_data[] = { + 0.0, 0.0, + 1.0, 0.0, + 0.0, 1.0, + 1.0, 1.0 + }; + + GLuint fullBlitTex; + glGenBuffers(1, &fullBlitTex); + glBindBuffer(GL_ARRAY_BUFFER, fullBlitTex); + glBufferData(GL_ARRAY_BUFFER, sizeof(fullBlitTex_data), fullBlitTex_data, GL_STATIC_DRAW); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tex->texID); + glUniform1i(glGetUniformLocation(blitShader, "srctex"), 0); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + glDisableVertexAttribArray(1); + glDisableVertexAttribArray(0); + + glDeleteBuffers(1, &fullBlitTex); + glDeleteBuffers(1, &fullBlitVertices); + + glfwSwapBuffers(window); +} + void renderScreen(Texture* tex) { if (!rendererInitialized) @@ -565,9 +716,9 @@ void renderScreen(Texture* tex) glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName); glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexBufs[curBuf], 0); - // Set up the shaer + // Set up the shader glViewport(0,0,GAME_WIDTH,GAME_HEIGHT); - glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(ntscShader); // Use the current frame texture, nearest neighbor and clamped to edge @@ -601,26 +752,11 @@ void renderScreen(Texture* tex) glDrawArrays(GL_TRIANGLES, 0, 6); glDisableVertexAttribArray(0); - // Load the normal vertices of a flat surface - GLfloat g_norms_data[] = { - 0.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 1.0f - }; - - GLuint g_norms; - glGenBuffers(1, &g_norms); - glBindBuffer(GL_ARRAY_BUFFER, g_norms); - glBufferData(GL_ARRAY_BUFFER, sizeof(g_norms_data), g_norms_data, GL_STATIC_DRAW); - // We're going to render the screen now - //glBindFramebuffer(GL_FRAMEBUFFER, 0); glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, preBloomTex, 0); + //glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0,0,1024,768); - glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(finalShader); // Use the composited frame texture, linearly filtered and filling in black for the border @@ -641,9 +777,9 @@ void renderScreen(Texture* tex) glUniform1i(glGetUniformLocation(finalShader, "scanlinestex"), 1); // Initialize the MVP matrices - mat4 p_matrix = perspective(90.0f, 4.0f / 4.0f, 0.1f, 100.0f); - mat4 v_matrix = lookAt(vec3(0,0,1), vec3(0,0,0), vec3(0,1,0)); - mat4 m_matrix = mat4(1.0f); + mat4 p_matrix = perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f); + mat4 v_matrix = lookAt(vec3(2,0,0), vec3(0,0,0), vec3(0,1,0)); + mat4 m_matrix = mat4(1.0); mat4 mvp_matrix = p_matrix * v_matrix * m_matrix; //mat4 mv_matrix = v_matrix * m_matrix; @@ -651,21 +787,26 @@ void renderScreen(Texture* tex) glUniformMatrix4fv(glGetUniformLocation(finalShader, "worldMat"), 1, GL_FALSE, &m_matrix[0][0]); glEnableVertexAttribArray(0); - glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer); + glBindBuffer(GL_ARRAY_BUFFER, mesh_vertexbuffer); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); glEnableVertexAttribArray(1); - glBindBuffer(GL_ARRAY_BUFFER, g_norms); + glBindBuffer(GL_ARRAY_BUFFER, mesh_normalbuffer); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); - glDrawArrays(GL_TRIANGLES, 0, 6); + glEnableVertexAttribArray(2); + glBindBuffer(GL_ARRAY_BUFFER, mesh_uvbuffer); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); + + glDrawArrays(GL_TRIANGLES, 0, mesh_numvertices); + glDisableVertexAttribArray(2); glDisableVertexAttribArray(1); glDisableVertexAttribArray(0); // Do the first pass of bloom (downsampling and tapping) glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, bloomPassTex, 0); glViewport(0, 0, 64, 48); - glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(bloom1Shader); glActiveTexture(GL_TEXTURE0); @@ -683,7 +824,7 @@ void renderScreen(Texture* tex) // Do the second pass of bloom and render to screen glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0, 0, 1024, 768); - glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(bloom2Shader); glActiveTexture(GL_TEXTURE0); @@ -704,7 +845,5 @@ void renderScreen(Texture* tex) glfwSwapBuffers(window); - glDeleteBuffers(1, &g_norms); - curBuf = (curBuf + 1) % 2; } diff --git a/src/renderer.h b/src/renderer.h index 057337c..144956a 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -39,6 +39,7 @@ Texture* loadTextureFromBMP(char* filename); void saveTextureToBMP(Texture* tex, char* filename); void fillTexture(Texture* tex, Rectangle* loc, int r, int g, int b); void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle* dstrect); +void renderWithoutEffects(Texture* tex); void renderScreen(Texture* tex); #endif -- cgit 1.4.1