#define MAIN #include "game.h" void GLAPIENTRY debug_callback(GLenum, GLenum type, GLuint, GLenum severity, GLsizei, const GLchar* message, const void*){ if(severity != GL_DEBUG_SEVERITY_HIGH && severity != GL_DEBUG_SEVERITY_MEDIUM ) return; fprintf( stderr, "GL ERROR MESSAGE: %s type = 0x%x, severity = 0x%x, message = %s\n", ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ), type, severity, message ); } bool clear_check(vec3 point, float margin){ for(auto &so : solid_objects){ if(so->is_inside(point, margin)){ return false; } } return true; } void general_management_function(){ float move_margin = 0.4; while(!g.shutdown) { vec3 step_to_point = vec3(1000000, 1000000, 1000000); if(g.forward) step_to_point = get_lookat_point(0, g.run? 0.8:0.2); if(g.right) step_to_point = get_lookat_point(1, g.run? 0.8:0.2); if(g.backward) step_to_point = get_lookat_point(2, g.run? 0.8:0.2); if(g.left) step_to_point = get_lookat_point(3, g.run? 0.8:0.2); if(step_to_point.y != 1000000){ /* Is anything in the way? If so, we shouldn't keep going! */ bool move_ok = true; if(!clear_check(step_to_point, move_margin)){ vec3 no_x = vec3(g.player_position.x, step_to_point.y, step_to_point.z); vec3 no_y = vec3(step_to_point.x, g.player_position.y, step_to_point.z); vec3 no_z = vec3(step_to_point.x, step_to_point.y, g.player_position.z); if(clear_check(no_x, move_margin)) step_to_point = no_x; else if(clear_check(no_y, move_margin)) step_to_point = no_y; else if(clear_check(no_z, move_margin)) step_to_point = no_z; else move_ok = false; } if(move_ok) g.player_position = step_to_point; } this_thread::sleep_for(chrono::milliseconds(10)); } } void movement_function() { /* We might need a shutdown procedure that ends this loop */ while(!g.shutdown) { for(auto o : game_objects) o->movement(10); /* TODO: Sleep for 10 ms - the time this iteration took */ this_thread::sleep_for(chrono::milliseconds(10)); } } /* direction: 0 - forward, 1 : right, 2 : backwards, 3 : left */ /* If r is set to 0, elevation is incorporated into the result. * Otherwise, it is ignored, and this function leaves y as 0 */ vec3 get_lookat_point(int direction, float r){ vec3 lap; if(r == 0.0f) { r = cos(g.elevation); lap.y = sin(g.elevation); } else { lap.y = 0; } if(direction == 0){ lap.x = g.player_position.x + r * cos(g.heading); lap.z = g.player_position.z + r * sin(g.heading); } else if (direction == 1){ lap.x = g.player_position.x + r * cos(g.heading + M_PI / 2); lap.z = g.player_position.z + r * sin(g.heading + M_PI / 2); } else if (direction == 2){ lap.x = g.player_position.x - r * cos(g.heading); lap.z = g.player_position.z - r * sin(g.heading); } else if (direction == 3){ lap.x = g.player_position.x + r * cos(g.heading - M_PI / 2); lap.z = g.player_position.z + r * sin(g.heading - M_PI / 2); } return lap; } void key_callback(GLFWwindow*, int key, int scancode, int action, int mods){ printf("key %d, mods = %d, is_ctrl = %d\n", key, mods, key == GLFW_KEY_LEFT_CONTROL); if(action == GLFW_PRESS) { // down if(key == GLFW_KEY_W) g.forward = true; if(key == GLFW_KEY_S) g.backward = true; if(key == GLFW_KEY_A) g.left = true; if(key == GLFW_KEY_D) g.right = true; if(key == GLFW_KEY_LEFT_CONTROL) g.run = true; } if(action == GLFW_RELEASE) { // UP if(key == GLFW_KEY_W) g.forward = false; if(key == GLFW_KEY_S) g.backward = false; if(key == GLFW_KEY_A) g.left = false; if(key == GLFW_KEY_D) g.right = false; if(key == GLFW_KEY_LEFT_CONTROL) g.run = false; } } void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos){ double dx = g.width/2 - xpos; double dy = g.height/2 - ypos; glfwSetCursorPos(window, g.width / 2, g.height / 2); g.heading -= (dx / 200.0); g.elevation += (dy / 200.0); if(g.elevation > 3.14f/2) g.elevation = 3.14f/2; if(g.elevation < -3.14f/2) g.elevation = -3.14f/2; } void window_size_callback(GLFWwindow* window, int width, int height){ g.width = width; g.height = height; glViewport(0, 0, width, height); } int main(int argc, char ** argv){ glfwInit(); GLFWwindow* window = glfwCreateWindow(g.width, g.height, "Simple OpenGL 4.0+ Demo", 0, 0); glfwMakeContextCurrent(window); // TODO: glad instead of glew #ifdef UNIX glewInit(); #else gladLoadGLLoader((GLADloadproc)glfwGetProcAddress); #endif // During init, enable debug output glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback(debug_callback, 0); // Set up callback functions for glfw glfwSetKeyCallback(window, key_callback); glfwSetCursorPosCallback(window, cursor_pos_callback); glfwSetFramebufferSizeCallback(window, window_size_callback); /* Level Loading Area */ g.player_position = vec3(0, 0, 10); /* EnlongatingCylinder *cylinder = new EnlongatingCylinder; if(!cylinder->init("objects/cylinder.obj", "textures/brick.jpg")){ printf("Object failed to load, giving up!\n"); return 1; } for(int i = -8; i < 8; i += 3) cylinder->add_location(vec3(i, 0, 0)); game_objects.push_back(cylinder); */ FloorPanel *floor = new FloorPanel; if(!floor->init("objects/cube.obj", "textures/brick.jpg")){ printf("Object failed to load, giving up!\n"); return 1; } for(int i = -30; i < 30; i+= 5) for(int j = -30; j < 30; j+= 5) floor->add_location_size(vec3(i, -2, j), vec3(5, 1, 5)); floor->add_location_size(vec3(0, 2, 0), vec3(10, 10, 10)); floor->add_location_size(vec3(10, 2, 0), vec3(10, 10, 10)); floor->add_location_size(vec3(10, 2, 10), vec3(10, 10, 10)); game_objects.push_back(floor); solid_objects.push_back(floor); /* GameObject *cube = new GameObject; cube->spin_rate = 0.05f; if(!cube->init("cube.obj", "brick.jpg")) return 1; for(int i = -8; i < 8; i += 3) cube->add_location(vec3(i, 3, 0)); game_objects.push_back(cube); */ /* Initialize all game objects now */ /* Done with level loading */ int count = 0; /* Ready to start! Time to start movement */ thread movement_thread(movement_function); thread general_management_thread(general_management_function); glEnable(GL_DEPTH_TEST); while(!glfwWindowShouldClose(window)){ /* Not for a particular object */ count++; glfwPollEvents(); glClearColor(1.0, 1.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT); /* This sets up the camera location, view angle, etc */ mat4 view = lookAt(g.player_position, get_lookat_point(), vec3(0, 1, 0)); mat4 projection = perspective(radians(45.0f), g.width/g.height, 0.1f, 1000.0f); mat4 vp = projection * view; /* Call draw and give it vp */ for(auto o : game_objects) o->draw(vp); /* Not for a particular object */ glfwSwapBuffers(window); // usleep(10000); } g.shutdown = true; movement_thread.join(); general_management_thread.join(); glfwDestroyWindow(window); glfwTerminate(); return 0; }