#include #include #include #include #include void tc_move_viewer_to(float x, float y, float z) { if(tc_game_state_g.viewer == NULL) return; tc_set_float_for_entity(tc_game_state_g.viewer, "pos_x", x); tc_set_float_for_entity(tc_game_state_g.viewer, "pos_y", y); tc_set_float_for_entity(tc_game_state_g.viewer, "pos_z", z); } void tc_rotate_viewer_to(float x, float y, float z) { if(tc_game_state_g.viewer == NULL) return; tc_set_float_for_entity(tc_game_state_g.viewer, "rot_x", x); tc_set_float_for_entity(tc_game_state_g.viewer, "rot_y", y); tc_set_float_for_entity(tc_game_state_g.viewer, "rot_z", z); } void tc_get_viewer_position(float *x, float *y, float *z) { if(tc_game_state_g.viewer == NULL) return; if(x != NULL) (*x) = tc_get_float_from_entity(tc_game_state_g.viewer, "pos_x"); if(y != NULL) (*y) = tc_get_float_from_entity(tc_game_state_g.viewer, "pos_y"); if(z != NULL) (*z) = tc_get_float_from_entity(tc_game_state_g.viewer, "pos_z"); } void tc_get_viewer_rotation(float *x, float *y, float *z) { if(tc_game_state_g.viewer == NULL) return; if(x != NULL) (*x) = tc_get_float_from_entity(tc_game_state_g.viewer, "rot_x"); if(y != NULL) (*y) = tc_get_float_from_entity(tc_game_state_g.viewer, "rot_y"); if(z != NULL) (*z) = tc_get_float_from_entity(tc_game_state_g.viewer, "rot_z"); } void render() { float color[4] = { 0.12f, 0.5f, 0.8f, 1.0f }; glClearBufferfv(GL_COLOR, 0, color); float depth = 1000.0f; glClearBufferfv(GL_DEPTH, 0, &depth); int fb_width = 0; int fb_height = 0; SDL_GetWindowSize(tc_game_state_g.renderer.window, &fb_width, &fb_height); glViewport(0, 0, fb_width, fb_height); tc_vec3f_s camera_rotation; tc_vec3f_s camera_position; tc_get_viewer_rotation(&camera_rotation.x, &camera_rotation.y, &camera_rotation.z); tc_get_viewer_position(&camera_position.x, &camera_position.y, &camera_position.z); tc_vec3f_s camera_offset; camera_offset.z = camera_position.z; camera_offset.y = -camera_position.y; camera_offset.x = -camera_position.x; tc_mat4f_s view_matrix = tc_mat4f_identity(); tc_mat4f_s projection_matrix = tc_mat4f_perspective(120, ((float) fb_width) / ((float) fb_height), 0.0001f, 1000.0f ); view_matrix = tc_mat4f_translate(view_matrix, camera_offset); view_matrix = tc_mat4_rotate_z(view_matrix, tc_deg_to_rad(camera_rotation.z)); view_matrix = tc_mat4_rotate_y(view_matrix, tc_deg_to_rad(camera_rotation.y)); view_matrix = tc_mat4_rotate_x(view_matrix, tc_deg_to_rad(camera_rotation.x)); glUseProgram(tc_game_state_g.renderer.draw_shader.program_id); tc_shader_uniform_mat4f(&tc_game_state_g.renderer.draw_shader, "projection_matrix", projection_matrix); tc_shader_uniform_mat4f(&tc_game_state_g.renderer.draw_shader, "view_matrix", view_matrix); tc_draw_world(tc_game_state_g.main_world); SDL_GL_SwapWindow(tc_game_state_g.renderer.window); } bool shift_pressed = false; bool go_up = false; bool go_left = false; bool go_right = false; bool go_forward = false; bool go_backwards = false; bool rotate_left = false; bool rotate_right = false; uint64_t tc_last_update = 0; bool update() { tc_vec3f_s camera_rotation; tc_get_viewer_rotation(&camera_rotation.x, &camera_rotation.y, &camera_rotation.z); SDL_Event event; while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_QUIT: SDL_HideWindow(tc_game_state_g.renderer.window); return false; break; case SDL_WINDOWEVENT: { if(event.window.event == SDL_WINDOWEVENT_RESIZED) { } } break; case SDL_KEYDOWN: if(event.key.keysym.scancode == SDL_SCANCODE_Q) { rotate_left = true; } if(event.key.keysym.scancode == SDL_SCANCODE_E) { rotate_right = true; } if(event.key.keysym.scancode == SDL_SCANCODE_W) { go_forward = true; } if(event.key.keysym.scancode == SDL_SCANCODE_S) { go_backwards = true; } if(event.key.keysym.scancode == SDL_SCANCODE_A) { go_left = true; } if(event.key.keysym.scancode == SDL_SCANCODE_D) { go_right = true;; } if(event.key.keysym.scancode == SDL_SCANCODE_SPACE) { go_up = true; } if(event.key.keysym.scancode == SDL_SCANCODE_LSHIFT) { shift_pressed = true; } break; case SDL_KEYUP: if(event.key.keysym.scancode == SDL_SCANCODE_Q) { rotate_left = false; } if(event.key.keysym.scancode == SDL_SCANCODE_E) { rotate_right = false; } if(event.key.keysym.scancode == SDL_SCANCODE_W) { go_forward = false; } if(event.key.keysym.scancode == SDL_SCANCODE_S) { go_backwards = false; } if(event.key.keysym.scancode == SDL_SCANCODE_A) { go_left = false; } if(event.key.keysym.scancode == SDL_SCANCODE_D) { go_right = false;; } if(event.key.keysym.scancode == SDL_SCANCODE_SPACE) { go_up = false; } if(event.key.keysym.scancode == SDL_SCANCODE_LSHIFT) { shift_pressed = false; } break; case SDL_MOUSEMOTION: { if(!(event.motion.state & SDL_BUTTON_LMASK)) break; camera_rotation.y += event.motion.xrel / 10.0f; camera_rotation.x += event.motion.yrel / 10.0f; if(camera_rotation.x > 90) camera_rotation.x = 90; if(camera_rotation.x < -90) camera_rotation.x = -90; } break; } } tc_vec3f_s camera_position; tc_get_viewer_position(&camera_position.x, &camera_position.y, &camera_position.z); if(shift_pressed) { camera_position.y -= 0.75; } if(go_up) { camera_position.y += 0.75; } tc_vec3f_s difference_in_perspective; difference_in_perspective.x = 0.0f; difference_in_perspective.y = 0.0f; difference_in_perspective.z = 0.0f; if(go_left) { difference_in_perspective.x -= 0.45f; } if(go_right) { difference_in_perspective.x += 0.45f; } if(go_forward) { difference_in_perspective.z += 0.4f; } if(go_backwards) { difference_in_perspective.z -= 0.4f; } mat4x4 position_matrix; mat4x4_identity(position_matrix); mat4x4_translate(position_matrix, difference_in_perspective.x, 0.0f, difference_in_perspective.z); mat4x4_rotate_Z(position_matrix, position_matrix, tc_deg_to_rad(camera_rotation.z)); mat4x4_rotate_Y(position_matrix, position_matrix, tc_deg_to_rad(camera_rotation.y)); mat4x4_rotate_X(position_matrix, position_matrix, tc_deg_to_rad(camera_rotation.x)); vec4 viewed_difference = { difference_in_perspective.x, 0.0f, difference_in_perspective.z }; vec4 raw_difference = { 0.0f, 0.0f, 0.0f }; mat4x4_mul_vec4(raw_difference, position_matrix, viewed_difference); camera_position.x += raw_difference[0]; camera_position.z += raw_difference[2]; tc_move_viewer_to(camera_position.x, camera_position.y, camera_position.z); tc_rotate_viewer_to(camera_rotation.x, camera_rotation.y, camera_rotation.z); tc_game_state_g.main_world->spawn_loader->center.x = ((int32_t) camera_position.x) / 32 - UPDATE_DISTANCE; tc_game_state_g.main_world->spawn_loader->center.y = ((int32_t) camera_position.y) / 32 - UPDATE_DISTANCE; tc_game_state_g.main_world->spawn_loader->center.z = - ((int32_t) camera_position.z) / 32 - UPDATE_DISTANCE; tc_update_world(tc_game_state_g.main_world); return true; } int main(int argc, char **argv) { tc_init(); int64_t frame_index = 1; while(frame_index > 0) { if(!update()) { frame_index = -1; } tc_tick_intervals(); render(); if(frame_index == 1) { SDL_ShowWindow(tc_game_state_g.renderer.window); } ++frame_index; SDL_Delay(2); } tc_cleanup(); SDL_Quit(); return 0; }