#define _USE_MATH_DEFINES #include #include #include #include #include #include #include #include #include #include #include using namespace glm; using namespace std; #define MOVING_CONST 0.5f #define ROTATION_CONST 5.f * 3.14f / 180.f #define LOOK_MOVEMENT_CONST 0.2f void PrintVector(glm::vec3); /*--------------------------------------------------*/ char title[] = "Prozor"; int FPS = 60; vec3 CameraPosition(0.0, 1.0, 0.0); vec3 LookAt_vector(1.0, 1.0, 0.0); vec3 LookUp_vector(0.0, 1.0, 0.0); vector coordinateSystem; const int circle_dots = 50; const float height = 480; const float ratio = 16.f / 9.f; double upDownAngle = 0; int currentSpeed = 1; float arrowRotate = 0.f; /*--------------------------------------------------*/ // game state const int max_number_of_enemies = 6; int number_of_enemies_alive; int number_of_enemies_killed; vec3 enemy_positions[max_number_of_enemies]; vec3 enemy_directions[max_number_of_enemies]; vec3 enemy_color[max_number_of_enemies]; bool in_zoom = false; /*--------------------------------------------------*/ vec3 operator* (mat4x4 mat, vec3 vec) { vec4 v(vec.x, vec.y, vec.z, 1.f); v = mat * v; return vec3(v.x, v.y, v.z); } vector operator* (mat4x4 mat, vector vectors) { for (int i = 0; i < vectors.size(); i++) vectors[i] = mat * vectors[i]; return vectors; } /*--------------------------------------------------*/ float vec_distance(vec3 v1, vec3 v2) { return glm::length(v2 - v1); } float vec_magnitude(vec3 v) { return glm::length(v); } /*--------------------------------------------------*/ vector enemy; vector plane; vector construct_plane(float a, int s) { vector vertices = {}; float y = -a / 2.f; float dy = a / (float)s; for (int i = 0; i < 2 * s; i++) { vertices.push_back(vec3(-a / 2.f, 0.f, y)); vertices.push_back(vec3(a / 2.f, 0.f, y)); vertices.push_back(vec3(y, 0.f, -a / 2.f)); vertices.push_back(vec3(y, 0.f, a / 2.f)); y += dy; } return vertices; } vector construct_sphere(float r) { vector vertices = {}; float resolution_1 = 20; float resolution_2 = 50; float a1 = -M_PI / 2.f; float a1_d = M_PI / resolution_1; float a2 = 0.f; float a2_d = 2.f * M_PI / resolution_2; for (int i = 0; i < resolution_1; i++) { float a1l = a1 + a1_d; a2 = 0.f; for (int j = 0; j < resolution_2; j++) { float a2l = a2 + a2_d; vertices.push_back(vec3(r * cos(a1) * cos(a2), r * cos(a1) * sin(a2), r * sin(a1))); vertices.push_back(vec3(r * cos(a1l) * cos(a2), r * cos(a1l) * sin(a2), r * sin(a1l))); vertices.push_back(vec3(r * cos(a1) * cos(a2l), r * cos(a1) * sin(a2l), r * sin(a1))); vertices.push_back(vec3(r * cos(a1) * cos(a2l), r * cos(a1) * sin(a2l), r * sin(a1))); vertices.push_back(vec3(r * cos(a1l) * cos(a2), r * cos(a1l) * sin(a2), r * sin(a1l))); vertices.push_back(vec3(r * cos(a1l) * cos(a2l), r * cos(a1l) * sin(a2l), r * sin(a1l))); a2 = a2l; } a1 = a1l; } return vertices; } vector minimap; vector minimap_point; vector construct_circle(float r) { vector vertices = {}; int resolution = 50; // povecao sam rezoluciju da bi izgledalo malo bolje float a = 0.f; float da = 2.f * M_PI / resolution; for (int i = 0; i < resolution; i++) { float al = a + da; vertices.push_back(vec3(r * cos(a), r * sin(a), 0.f)); vertices.push_back(vec3(0.f, 0.f, 0.f)); vertices.push_back(vec3(r * cos(al), r * sin(al), 0.f)); a = al; } return vertices; } /*--------------------------------------------------*/ //o GLUT_BITMAP_TIMES_ROMAN_24 //o GLUT_BITMAP_TIMES_ROMAN_10 //o GLUT_BITMAP_HELVETICA_18 void RenderString(float x, float y, const unsigned char* s, vec3 color) { glColor3f(color.r, color.g, color.b); glRasterPos2f(x, y); glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, (const unsigned char*)s); } /*--------------------------------------------------*/ void createCoordinates() { coordinateSystem.resize(4); coordinateSystem[0] = vec3(0.0, 0.0, 0.0); coordinateSystem[1] = vec3(1.0, 0.0, 0.0); coordinateSystem[2] = vec3(0.0, 1.0, 0.0); coordinateSystem[3] = vec3(0.0, 0.0, 1.0); mat4 MT; MT = translate(vec3(0.0, -0.75, 0.0)); coordinateSystem = MT * coordinateSystem; } /*--------------------------------------------------*/ void drawLine(vec3 a, vec3 b, vec3 color) { glColor3f(color.x, color.y, color.z); glBegin(GL_LINE_LOOP); glVertex3f(a.x, a.y, a.z); glVertex3f(b.x, b.y, b.z); glEnd(); } void drawPlane(vector vertices, vec3 color) { for (int i = 0; i < vertices.size() / 2; i += 2) drawLine(vertices[i], vertices[i + 1], color); } void drawVertices(vector vertices, vec3 color) { glColor3f(color.x, color.y, color.z); glBegin(GL_TRIANGLES); for (auto v : vertices) glVertex3f(v.x, v.y, v.z); glEnd(); } void drawCoordinates() { glLineWidth(2.0); glBegin(GL_LINES); // X axis glColor3f(1.0f, 0.0f, 0.0f); // Red glVertex3d(coordinateSystem[0].x, coordinateSystem[0].y, coordinateSystem[0].z); glVertex3d(coordinateSystem[1].x, coordinateSystem[1].y, coordinateSystem[1].z); // Y axis glColor3f(0.0f, 1.0f, 0.0f); // Green glVertex3d(coordinateSystem[0].x, coordinateSystem[0].y, coordinateSystem[0].z); glVertex3d(coordinateSystem[2].x, coordinateSystem[2].y, coordinateSystem[2].z); // Z axis glColor3f(0.0f, 0.0f, 1.0f); // Blue glVertex3d(coordinateSystem[0].x, coordinateSystem[0].y, coordinateSystem[0].z); glVertex3d(coordinateSystem[3].x, coordinateSystem[3].y, coordinateSystem[3].z); glEnd(); } void draw_hud_background(float r, vec3 color) { float resolution = 100; float a = 0.f; float da = 2.f * M_PI / resolution; float h = height; float w = ratio * height; vec2 c = vec2(w / 2.f, h / 2.f); int i = 0; glColor3f(color.x, color.y, color.z); glBegin(GL_TRIANGLE_FAN); glVertex2f(w, h); for (; i < resolution / 4.f; i++) { glVertex2f(c.x + r * cos(a), c.y + r * sin(a)); a += da; } glVertex2f(0, h); glEnd(); i--; a -= da; glBegin(GL_TRIANGLE_FAN); glVertex2f(0, h); for (; i < resolution / 2.f; i++) { glVertex2f(c.x + r * cos(a), c.y + r * sin(a)); a += da; } glVertex2f(0, 0); glEnd(); i--; a -= da; glBegin(GL_TRIANGLE_FAN); glVertex2f(0, 0); for (; i < 3.f / 4.f * resolution; i++) { glVertex2f(c.x + r * cos(a), c.y + r * sin(a)); a += da; } glVertex2f(w, 0); glEnd(); i--; a -= da; glBegin(GL_TRIANGLE_FAN); glVertex2f(w, 0); for (; i <= resolution; i++) { glVertex2f(c.x + r * cos(a), c.y + r * sin(a)); a += da; } glVertex2f(w, h); glEnd(); } /*--------------------------------------------------*/ mat4x4 identity_mat = mat4x4(1.f); void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); float fov = 80.f; if (in_zoom) fov = 40.f; gluPerspective(fov, 16.f / 9.f, 0.1f, 50.f); gluLookAt( CameraPosition.x, CameraPosition.y, CameraPosition.z, LookAt_vector.x, LookAt_vector.y, LookAt_vector.z, LookUp_vector.x, LookUp_vector.y, LookUp_vector.z ); drawCoordinates(); mat4x4 tra; mat4x4 rot; mat4x4 sca; mat4x4 model; // plane drawPlane(plane, vec3(0, 1, 0)); // enemy // init for (int i = number_of_enemies_alive; i < max_number_of_enemies; i++) { enemy_positions[i] = vec3(rand() % 25, 1.f, rand() % 25); enemy_directions[i] = CameraPosition - enemy_positions[i]; enemy_color[i] = vec3(rand() % 256 / 255.f, rand() % 256 / 255.f, rand() % 256 / 255.f); number_of_enemies_alive = max_number_of_enemies; } // draw for (int i = 0; i < max_number_of_enemies; i++) { tra = translate(identity_mat, enemy_positions[i]); vector enemy_d = tra * enemy; drawVertices(enemy_d, enemy_color[i]); } glDisable(GL_DEPTH_TEST); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); float h = height; float w = ratio * height; gluOrtho2D(0.f, w, 0.f, h); // aim drawLine(vec3(w * 0.5f - h * 0.05f, h * 0.5f, 0.f), vec3(w * 0.5f + h * 0.05f, h * 0.5f, 0.f), vec3(1, 0, 0)); drawLine(vec3(w * 0.5f, h * 0.5f - h * 0.05f, 0.f), vec3(w * 0.5f, h * 0.5f + h * 0.05f, 0.f), vec3(1, 0, 0)); // zoom if (in_zoom) { // background draw_hud_background(200.f, vec3(0.8)); // number of enemies killed char s[20]; sprintf_s(s, "%d", number_of_enemies_killed); RenderString(h * 0.1f, h * 0.1f, (const unsigned char *)s, vec3(1, 0, 0)); // minimap vec3 minimap_position = vec3(w * 0.8f, h * 0.2f, 0.f); tra = translate(identity_mat, minimap_position); vector minimap_d = tra * minimap; vector minimap_point_d = tra * minimap_point; // minimap background drawVertices(minimap_d, vec3(0.f)); // minimap point for player drawVertices(minimap_point_d, vec3(0, 1, 0)); for (int i = 0; i < max_number_of_enemies; i++) { vec3 d = enemy_positions[i] - CameraPosition; d.y = d.x; d.x = d.z; // moramo okrenuti z i x d.z = 0; vec2 look_at = vec2(LookAt_vector.x - CameraPosition.x, LookAt_vector.z - CameraPosition.z); float a = atan2(look_at.y, look_at.x); rot = rotate(identity_mat, (float)(a), vec3(0, 0, 1)); d = rot * vec3(d); d *= 0.005f * h; tra = translate(identity_mat, d); // promenio scale if (vec_magnitude(d) < 0.14f * h) { // da ne bi crtao izvan kruga mini mape vector minimap_point_dd = tra * minimap_point_d; // treba point_d a ne point drawVertices(minimap_point_dd, vec3(1, 0, 0)); } } } glEnable(GL_DEPTH_TEST); glutSwapBuffers(); } void change_game_state() { for (int i = 0; i < max_number_of_enemies; i++) { enemy_positions[i] += 0.01f * enemy_directions[i]; if (vec_distance(CameraPosition, enemy_positions[i]) < 1.f) { exit(1); } } } void timer(int v) { change_game_state(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt( CameraPosition.x, CameraPosition.y, CameraPosition.z, LookAt_vector.x, LookAt_vector.y, LookAt_vector.z, LookUp_vector.x, LookUp_vector.y, LookUp_vector.z ); glutTimerFunc(1000 / FPS, timer, v); glutPostRedisplay(); } void construct_hud_objects(); void reshape(GLsizei width, GLsizei height) { if (height * ratio <= width) width = ratio * height; else height = width / ratio; glViewport(0, 0, width, height); construct_hud_objects(); } /*--------------------------------------------------*/ void PrintVector(vec3 vec) { printf("%.2f %.2f %.2f\n", vec.x, vec.y, vec.z); } /*--------------------------------------------------*/ void MoveForward() { mat4x4 mt; vec3 v = LookAt_vector - CameraPosition; v = normalize(v); v.y = 0.f; v = v * (currentSpeed * (float)MOVING_CONST); mt = translate(mat4x4(1.f), v); LookAt_vector = mt * LookAt_vector; CameraPosition = mt * CameraPosition; } void MoveBackward() { mat4x4 mt; vec3 v = LookAt_vector - CameraPosition; v.y = 0.f; v = normalize(v); v = -v * (currentSpeed * (float)MOVING_CONST); mt = translate(mat4x4(1.f), v); LookAt_vector = mt * LookAt_vector; CameraPosition = mt * CameraPosition; } void MoveLeft() { mat4x4 mt; vec3 f = LookAt_vector - CameraPosition; vec3 w = cross(LookUp_vector, f); w = normalize(w); w = w * (currentSpeed * (float)MOVING_CONST); mt = translate(mat4x4(1.f), w); CameraPosition = mt * CameraPosition; LookAt_vector = mt * LookAt_vector; } void MoveRight() { mat4x4 mt; vec3 f = LookAt_vector - CameraPosition; vec3 w = cross(LookUp_vector, f); w = normalize(w); w = -w * (currentSpeed * (float)MOVING_CONST); mt = translate(mat4x4(1.f), w); CameraPosition = mt * CameraPosition; LookAt_vector = mt * LookAt_vector; } void TurnLeft() { mat4x4 mt, identityMat, mt1, mt2, mtr; identityMat = mat4x4(1.f); mt1 = translate(identityMat, vec3(CameraPosition.x, CameraPosition.y, CameraPosition.z)); mtr = rotate(identityMat, ROTATION_CONST, vec3(0.f, 1.f, 0.f)); mt2 = translate(identityMat, vec3(-CameraPosition.x, -CameraPosition.y, -CameraPosition.z)); mt = mt1 * mtr * mt2; LookAt_vector = mt * LookAt_vector; arrowRotate += ROTATION_CONST; } void TurnRight() { mat4x4 mt, identityMat, mt1, mt2, mtr; identityMat = mat4x4(1.f); mt1 = translate(identityMat, vec3(CameraPosition.x, CameraPosition.y, CameraPosition.z)); mtr = rotate(identityMat, -ROTATION_CONST, vec3(0.f, 1.f, 0.f)); mt2 = translate(identityMat, vec3(-CameraPosition.x, -CameraPosition.y, -CameraPosition.z)); mt = mt1 * mtr * mt2; LookAt_vector = mt * LookAt_vector; arrowRotate -= ROTATION_CONST; } void TurnUp() { mat4x4 mt, mt1, mt2, mtr; vec3 f = LookAt_vector - CameraPosition; vec3 w = cross(f, LookUp_vector); w = normalize(w); if (upDownAngle + ROTATION_CONST < (float)M_PI_2) { mt1 = translate(mat4x4(1.f), vec3(-CameraPosition.x, -CameraPosition.y, -CameraPosition.z)); mtr = rotate(mat4x4(1.f), ROTATION_CONST, w); mt2 = translate(mat4x4(1.f), vec3(CameraPosition.x, CameraPosition.y, CameraPosition.z)); mt = mt2 * mtr * mt1; LookAt_vector = mt * LookAt_vector; //LookUp_vector = mt * LookUp_vector; sad sam primetio da ovde ima greska u onom nama datom kodu ker za ovim nema potrebe 6 upDownAngle += ROTATION_CONST; } } void TurnDown() { mat4x4 mt, mt1, mt2, mtr; vec3 f = LookAt_vector - CameraPosition; vec3 w = cross(f, LookUp_vector); w = normalize(w); if (upDownAngle - ROTATION_CONST > (float)-M_PI_2) { mt1 = translate(mat4x4(1.f), vec3(-CameraPosition.x, -CameraPosition.y, -CameraPosition.z)); mtr = rotate(mat4x4(1.f), -ROTATION_CONST, w); mt2 = translate(mat4x4(1.f), vec3(CameraPosition.x, CameraPosition.y, CameraPosition.z)); mt = mt2 * mtr * mt1; LookAt_vector = mt * LookAt_vector; //LookUp_vector = mt * LookUp_vector; upDownAngle -= ROTATION_CONST; } } void SpeedUp() { if (currentSpeed < 5) ++currentSpeed; } void SpeedDown() { if (currentSpeed > 0) --currentSpeed; } /*--------------------------------------------------*/ void initGL(void) { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); } void construct_objects() { plane = construct_plane(100, 100); enemy = construct_sphere(1); // hud construct_hud_objects(); } void construct_hud_objects() { minimap = construct_circle(height * 0.15f); minimap_point = construct_circle(height * 0.01f); } /*--------------------------------------------------*/ void mousePress(int button, int state, int x, int y) { switch (button) { case GLUT_LEFT_BUTTON: if (state == GLUT_DOWN) { } break; case GLUT_RIGHT_BUTTON: if (state == GLUT_DOWN) { in_zoom = !in_zoom; } break; default: break; } } void keyPress(unsigned char key, int x, int y) { switch (key) { case 27: //ESC key exit(0); break; case 'w': MoveForward(); break; case 's': MoveBackward(); break; case 'a': //FUNCTION MoveLeft(); break; case 'd': //FUNCTION MoveRight(); break; case 'u': SpeedUp(); break; case 'j': SpeedDown(); break; case 52: TurnLeft(); break; case 54: TurnRight(); break; case 50: TurnDown(); break; case 56: TurnUp(); break; case ' ': bool hit = false; for (int i = 0; i < max_number_of_enemies; i++) { if (hit) { enemy_positions[i - 1] = enemy_positions[i]; enemy_directions[i - 1] = enemy_directions[i]; enemy_color[i - 1] = enemy_color[i]; } else { // popravljena provera da li je lopta pogodjena mat4x4 tra1 = translate(identity_mat, -CameraPosition); mat4x4 sca = scale(identity_mat, vec3(vec_distance(enemy_positions[i], CameraPosition))); mat4x4 tra2 = translate(identity_mat, CameraPosition); mat4x4 model = tra2 * sca * tra1; if (vec_distance(model * LookAt_vector, enemy_positions[i]) < 1.f) { hit = true; number_of_enemies_alive--; number_of_enemies_killed++; } } } break; } } /*--------------------------------------------------*/ int main(int argc, char** argv) { srand(time(0)); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL); glutInitWindowSize(height * ratio, height); glutInitWindowPosition(150, 50); glutCreateWindow(title); createCoordinates(); glutDisplayFunc(display); glutTimerFunc(100, timer, 0); glutReshapeFunc(reshape); glutMouseFunc(mousePress); glutKeyboardFunc(keyPress); // construct construct_objects(); initGL(); glutMainLoop(); return 0; }