bool Obstacle_Detection::is_obstacle_path(Pose &global_pose, const Command &command, double interval_time) { static double distance_interval = 0.8; double distance, distance_time; int size; Pose p; p = Ackerman::predict_next_pose(global_pose, command, interval_time); //verify final pose if (is_obstacle(p)) { return true; } distance = global_pose.distance(p); distance_time = min((distance_interval * interval_time) / distance, interval_time); size = ceil(interval_time / distance_time) - 1; p = global_pose; for (int i = 1; i < size; i++) { p = Ackerman::predict_next_pose(p, command, distance_time); if (is_obstacle(p)) { return true; } } return false; }
// seg004:08C3 void __pascal far check_guard_bumped() { short var_2; if ( word_1F950 == 0 && Char.action == actions_1_run_jump && Char.alive < 0 && Char.sword >= sword_2_drawn ) { if ( get_tile_at_char() == tiles_20_wall || curr_tile2 == tiles_7_doortop_with_floor || (curr_tile2 == tiles_4_gate && can_bump_into_gate()) || (Char.direction >= dir_0_right && ( get_tile(curr_room, --tile_col, tile_row) == tiles_7_doortop_with_floor || (curr_tile2 == tiles_4_gate && can_bump_into_gate()) )) ) { load_frame_to_obj(); set_char_collision(); if (is_obstacle()) { var_2 = dist_from_wall_behind(curr_tile2); if (var_2 < 0 && var_2 > -13) { Char.x = char_dx_forward(-var_2); seqtbl_offset_char(65); // pushed to wall with sword (Guard) play_seq(); load_fram_det_col(); } } } } }
int Model::highestBlock(float x, float z) { int result = -1; int nx = roundf(x); int nz = roundf(z); int p = Chunk::chunked(x); int q = Chunk::chunked(z); Chunk *chunk = chunks->findChunk(p, q); if (chunk) { Map *map = &chunk->map; MAP_FOR_EACH(map, ex, ey, ez, ew) { int ex2 = Map::getX(i)+p*(CHUNK_SIZE+1)-1; int ey2 = Map::getY(i); int ez2 = Map::getZ(i)-q*(CHUNK_SIZE+1)-1; /*int ex2 = ex+p*(CHUNK_SIZE+1)-1; int ey2 = ey; int ez2 = ez-q*(CHUNK_SIZE+1)-1;*/ if (is_obstacle(ew) && ex2 == nx && ez2 == nz) { result = MAX(result, ey2); } /*if (is_obstacle(ew) && ex == nx && ez == nz) { result = MAX(result, ey); }*/ } END_MAP_FOR_EACH; }
static int move_car(struct lthread* self) { goto *lthread_resume(self, &&update); update: if (is_game_over) return 0; if (race_is_car_moved()) { road[car_line_nr*RACE_ROAD_LEN] = RACE_SPACE; car_line_nr = (car_line_nr + 1) % RACE_ROAD_WDT; road[car_line_nr*RACE_ROAD_LEN] = RACE_CAR; race_print_road(road); is_game_over |= is_obstacle(car_line_nr*RACE_ROAD_LEN); if (is_game_over) return 0; } wait: if (SCHED_WAIT_TIMEOUT_LTHREAD(self, 0, RACE_CAR_UPD_MS) == -EAGAIN) { return lthread_yield(&&update, &&wait); } goto update; }
static int move_road(struct lthread *self) { int to_wait; /* Multiple entry points are provided by lthread_resume() and * lthread_yield() functions. */ goto *lthread_resume(self, &&update); update: is_game_over |= is_obstacle(car_line_nr*RACE_ROAD_LEN + 1); if (is_game_over) return 0; race_update_road(); race_print_road(road); wait: to_wait = RACE_ROAD_UPD_MS - (step / RACE_LVL_STEP) * RACE_LVLUP_MS; if (SCHED_WAIT_TIMEOUT_LTHREAD(self, 0, to_wait) == -EAGAIN) { /* Next time the function will start from the 'wait' label. Return * in order to not to block other threads. */ return lthread_yield(&&update, &&wait); } goto update; }
/** compute a mix of ponderated classes * * w/ threshold on obstacle and unknown * @returns weight from probabilities ponderated by robot model * (in seconds per meter) */ void weight_map::_load() { assert(terrains.bands.size() > 1); map.copy_meta(terrains, 1); gdalwrap::raster& weights = map.bands[0]; width = map.get_width(); map.names[0] = "WEIGHT"; float weight = 1.0; std::map<std::string, float> costs = rmdl.get_costs(); size_t idx_no_3d_class = terrains.get_band_id("NO_3D_CLASS"); size_t idx_obstacle = terrains.get_band_id("OBSTACLE"); for (size_t pos = 0; pos < width * map.get_height(); pos++) { if (terrains.bands[idx_no_3d_class][pos] > 0.9) weights[pos] = W_UNKNOWN; // UNKNOWN else if (terrains.bands[idx_obstacle][pos] > 0.4) // TODO tune this threshold weights[pos] = std::numeric_limits<float>::infinity(); // OBSTACLE else { weight = 1.0; // compute a mix of ponderated classes TODO dynamicaly json conf for (const auto& kv : costs) weight += kv.second * terrains.get_band(kv.first)[pos]; weights[pos] = weight / rmdl.get_velocity(); } } #if 0 // inflate obstacle by robot radius relative to map scale {x,y} // averaged up raduis {x,y} size_t rx = std::floor( map.get_scale_x() * rmdl.get_radius() ); size_t ry = std::floor( map.get_scale_y() * rmdl.get_radius() ); for (size_t px_x = rx; px_x < width - rx; px_x++) for (size_t px_y = ry; px_y < map.get_height() - ry; px_y++) { if ( is_obstacle(weights[px_x + px_y * width]) ) { for (size_t irx = 1; irx <= rx; irx++) for (size_t iry = 1; iry <= ry; iry++) { flag_as_obstacle(weights[px_x + (px_y - iry) * width]); flag_as_obstacle(weights[px_x + (px_y + iry) * width]); flag_as_obstacle(weights[px_x - irx + (px_y ) * width]); flag_as_obstacle(weights[px_x - irx + (px_y - iry) * width]); flag_as_obstacle(weights[px_x - irx + (px_y + iry) * width]); flag_as_obstacle(weights[px_x + irx + (px_y ) * width]); flag_as_obstacle(weights[px_x + irx + (px_y - iry) * width]); flag_as_obstacle(weights[px_x + irx + (px_y + iry) * width]); } } } // see http://www.ros.org/wiki/costmap_2d#Inflation for (auto& weight : weights) if (is_flag_obstacle(weight)) weight = 99; #endif }
// seg004:0343 int __pascal far is_obstacle_at_col(int tile_col) { short tile_row; tile_row = Char.curr_row; if (tile_row < 0) { tile_row += 3; } if (tile_row >= 3) { tile_row -= 3; } get_tile(curr_row_coll_room[tile_col], tile_col, tile_row); return is_obstacle(); }
int highest_block(Chunk *chunks, int chunk_count, float x, float z) { int result = -1; int nx = roundf(x); int nz = roundf(z); int p = floorf(roundf(x) / CHUNK_SIZE); int q = floorf(roundf(z) / CHUNK_SIZE); Chunk *chunk = find_chunk(chunks, chunk_count, p, q); if (chunk) { Map *map = &chunk->map; MAP_FOR_EACH(map, e) { if (is_obstacle(e->w) && e->x == nx && e->z == nz) { result = MAX(result, e->y); } } END_MAP_FOR_EACH; } return result; }
// seg004:08C3 void __pascal far check_guard_bumped() { if ( Char.action == actions_1_run_jump && Char.alive < 0 && Char.sword >= sword_2_drawn ) { if ( #ifdef FIX_PUSH_GUARD_INTO_WALL // Should also check for a wall BEHIND the guard, instead of only the current tile (fixes->fix_push_guard_into_wall && get_tile_behind_char() == tiles_20_wall) || #endif get_tile_at_char() == tiles_20_wall || curr_tile2 == tiles_7_doortop_with_floor || (curr_tile2 == tiles_4_gate && can_bump_into_gate()) || (Char.direction >= dir_0_right && ( get_tile(curr_room, --tile_col, tile_row) == tiles_7_doortop_with_floor || (curr_tile2 == tiles_4_gate && can_bump_into_gate()) )) ) { load_frame_to_obj(); set_char_collision(); if (is_obstacle()) { short delta_x; delta_x = dist_from_wall_behind(curr_tile2); if (delta_x < 0 && delta_x > -13) { Char.x = char_dx_forward(-delta_x); seqtbl_offset_char(seq_65_bump_forward_with_sword); // pushed to wall with sword (Guard) play_seq(); load_fram_det_col(); } } } } }
int collide( Chunk *chunks, int chunk_count, int height, float *x, float *y, float *z) { int result = 0; int p = floorf(roundf(*x) / CHUNK_SIZE); int q = floorf(roundf(*z) / CHUNK_SIZE); Chunk *chunk = find_chunk(chunks, chunk_count, p, q); if (!chunk) { return result; } Map *map = &chunk->map; int nx = roundf(*x); int ny = roundf(*y); int nz = roundf(*z); float px = *x - nx; float py = *y - ny; float pz = *z - nz; float pad = 0.25; for (int dy = 0; dy < height; dy++) { if (px < -pad && is_obstacle(map_get(map, nx - 1, ny - dy, nz))) { *x = nx - pad; } if (px > pad && is_obstacle(map_get(map, nx + 1, ny - dy, nz))) { *x = nx + pad; } if (py < -pad && is_obstacle(map_get(map, nx, ny - dy - 1, nz))) { *y = ny - pad; result = 1; } if (py > pad && is_obstacle(map_get(map, nx, ny - dy + 1, nz))) { *y = ny + pad; result = 1; } if (pz < -pad && is_obstacle(map_get(map, nx, ny - dy, nz - 1))) { *z = nz - pad; } if (pz > pad && is_obstacle(map_get(map, nx, ny - dy, nz + 1))) { *z = nz + pad; } } return result; }
int main(int argc, char **argv) { srand(time(NULL)); rand(); if (argc == 2 || argc == 3) { char *hostname = argv[1]; int port = DEFAULT_PORT; if (argc == 3) { port = atoi(argv[2]); } db_disable(); client_enable(); client_connect(hostname, port); client_start(); } if (!glfwInit()) { return -1; } create_window(); if (!window) { glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSwapInterval(VSYNC); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetKeyCallback(window, on_key); glfwSetMouseButtonCallback(window, on_mouse_button); glfwSetScrollCallback(window, on_scroll); #ifndef __APPLE__ if (glewInit() != GLEW_OK) { return -1; } #endif if (db_init()) { return -1; } glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_LINE_SMOOTH); glLogicOp(GL_INVERT); glClearColor(0.53, 0.81, 0.92, 1.00); GLuint texture; glGenTextures(1, &texture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); load_png_texture("texture.png"); GLuint block_program = load_program( "shaders/block_vertex.glsl", "shaders/block_fragment.glsl"); GLuint matrix_loc = glGetUniformLocation(block_program, "matrix"); GLuint camera_loc = glGetUniformLocation(block_program, "camera"); GLuint sampler_loc = glGetUniformLocation(block_program, "sampler"); GLuint timer_loc = glGetUniformLocation(block_program, "timer"); GLuint position_loc = glGetAttribLocation(block_program, "position"); GLuint normal_loc = glGetAttribLocation(block_program, "normal"); GLuint uv_loc = glGetAttribLocation(block_program, "uv"); GLuint line_program = load_program( "shaders/line_vertex.glsl", "shaders/line_fragment.glsl"); GLuint line_matrix_loc = glGetUniformLocation(line_program, "matrix"); GLuint line_position_loc = glGetAttribLocation(line_program, "position"); GLuint item_position_buffer = 0; GLuint item_normal_buffer = 0; GLuint item_uv_buffer = 0; int previous_block_type = 0; Chunk chunks[MAX_CHUNKS]; int chunk_count = 0; Player players[MAX_PLAYERS]; int player_count = 0; FPS fps = {0, 0}; float matrix[16]; float x = (rand_double() - 0.5) * 10000; float z = (rand_double() - 0.5) * 10000; float y = 0; float dy = 0; float rx = 0; float ry = 0; double px = 0; double py = 0; int loaded = db_load_state(&x, &y, &z, &rx, &ry); ensure_chunks(chunks, &chunk_count, floorf(roundf(x) / CHUNK_SIZE), floorf(roundf(z) / CHUNK_SIZE), 1); if (!loaded) { y = highest_block(chunks, chunk_count, x, z) + 2; } glfwGetCursorPos(window, &px, &py); double previous = glfwGetTime(); while (!glfwWindowShouldClose(window)) { update_fps(&fps, SHOW_FPS); double now = glfwGetTime(); double dt = MIN(now - previous, 0.2); previous = now; if (exclusive && (px || py)) { double mx, my; glfwGetCursorPos(window, &mx, &my); float m = 0.0025; rx += (mx - px) * m; ry -= (my - py) * m; if (rx < 0) { rx += RADIANS(360); } if (rx >= RADIANS(360)){ rx -= RADIANS(360); } ry = MAX(ry, -RADIANS(90)); ry = MIN(ry, RADIANS(90)); px = mx; py = my; } else { glfwGetCursorPos(window, &px, &py); } int sz = 0; int sx = 0; ortho = glfwGetKey(window, 'F'); fov = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) ? 15.0 : 65.0; if (glfwGetKey(window, 'Q')) break; if (glfwGetKey(window, 'W')) sz--; if (glfwGetKey(window, 'S')) sz++; if (glfwGetKey(window, 'A')) sx--; if (glfwGetKey(window, 'D')) sx++; float m = dt * 1.0; if (glfwGetKey(window, GLFW_KEY_LEFT)) rx -= m; if (glfwGetKey(window, GLFW_KEY_RIGHT)) rx += m; if (glfwGetKey(window, GLFW_KEY_UP)) ry += m; if (glfwGetKey(window, GLFW_KEY_DOWN)) ry -= m; float vx, vy, vz; get_motion_vector(flying, sz, sx, rx, ry, &vx, &vy, &vz); if (glfwGetKey(window, GLFW_KEY_SPACE)) { if (flying) { vy = 1; } else if (dy == 0) { dy = 8; } } if (glfwGetKey(window, 'Z')) { vx = -1; vy = 0; vz = 0; } if (glfwGetKey(window, 'X')) { vx = 1; vy = 0; vz = 0; } if (glfwGetKey(window, 'C')) { vx = 0; vy = -1; vz = 0; } if (glfwGetKey(window, 'V')) { vx = 0; vy = 1; vz = 0; } if (glfwGetKey(window, 'B')) { vx = 0; vy = 0; vz = -1; } if (glfwGetKey(window, 'N')) { vx = 0; vy = 0; vz = 1; } float speed = flying ? 20 : 5; int step = 8; float ut = dt / step; vx = vx * ut * speed; vy = vy * ut * speed; vz = vz * ut * speed; for (int i = 0; i < step; i++) { if (flying) { dy = 0; } else { dy -= ut * 25; dy = MAX(dy, -250); } x += vx; y += vy + dy * ut; z += vz; if (collide(chunks, chunk_count, 2, &x, &y, &z)) { dy = 0; } } if (y < 0) { y = highest_block(chunks, chunk_count, x, z) + 2; } for (int i = 0; i < chunk_count; i++) { Chunk *chunk = chunks + i; chunk->dirty = 0; } if (left_click) { left_click = 0; int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz); if (hy > 0 && is_destructable(hw)) { set_block(chunks, chunk_count, hx, hy, hz, 0, 1); } } if (right_click) { right_click = 0; int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 1, x, y, z, rx, ry, &hx, &hy, &hz); if (is_obstacle(hw)) { if (!player_intersects_block(2, x, y, z, hx, hy, hz)) { set_block(chunks, chunk_count, hx, hy, hz, block_type, 1); } } } if (middle_click) { middle_click = 0; int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz); if (is_selectable(hw)) { block_type = hw; } } if (teleport) { teleport = 0; if (player_count) { int index = rand_int(player_count); Player *player = players + index; x = player->x; y = player->y; z = player->z; rx = player->rx; ry = player->ry; ensure_chunks(chunks, &chunk_count, floorf(roundf(x) / CHUNK_SIZE), floorf(roundf(z) / CHUNK_SIZE), 1); } } client_position(x, y, z, rx, ry); char buffer[RECV_BUFFER_SIZE]; while (client_recv(buffer, RECV_BUFFER_SIZE)) { float ux, uy, uz, urx, ury; if (sscanf(buffer, "U,%*d,%f,%f,%f,%f,%f", &ux, &uy, &uz, &urx, &ury) == 5) { x = ux; y = uy; z = uz; rx = urx; ry = ury; ensure_chunks(chunks, &chunk_count, floorf(roundf(x) / CHUNK_SIZE), floorf(roundf(z) / CHUNK_SIZE), 1); y = highest_block(chunks, chunk_count, x, z) + 2; } int bx, by, bz, bw; if (sscanf(buffer, "B,%*d,%*d,%d,%d,%d,%d", &bx, &by, &bz, &bw) == 4) { set_block(chunks, chunk_count, bx, by, bz, bw, 0); if ((int)roundf(x) == bx && (int)roundf(z) == bz) { y = highest_block(chunks, chunk_count, x, z) + 2; } } int pid; float px, py, pz, prx, pry; if (sscanf(buffer, "P,%d,%f,%f,%f,%f,%f", &pid, &px, &py, &pz, &prx, &pry) == 6) { Player *player = find_player(players, player_count, pid); if (!player && player_count < MAX_PLAYERS) { player = players + player_count; player_count++; player->id = pid; player->position_buffer = 0; player->normal_buffer = 0; player->uv_buffer = 0; printf("%d other players are online\n", player_count); } if (player) { update_player(player, px, py, pz, prx, pry); } } if (sscanf(buffer, "D,%d", &pid) == 1) { delete_player(players, &player_count, pid); printf("%d other players are online\n", player_count); } } for (int i = 0; i < chunk_count; i++) { Chunk *chunk = chunks + i; if (chunk->dirty) { update_chunk(chunk); } } int p = floorf(roundf(x) / CHUNK_SIZE); int q = floorf(roundf(z) / CHUNK_SIZE); ensure_chunks(chunks, &chunk_count, p, q, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); update_matrix_3d(matrix, x, y, z, rx, ry); // render chunks glUseProgram(block_program); glUniformMatrix4fv(matrix_loc, 1, GL_FALSE, matrix); glUniform3f(camera_loc, x, y, z); glUniform1i(sampler_loc, 0); glUniform1f(timer_loc, glfwGetTime()); for (int i = 0; i < chunk_count; i++) { Chunk *chunk = chunks + i; if (chunk_distance(chunk, p, q) > RENDER_CHUNK_RADIUS) { continue; } if (!chunk_visible(chunk, matrix)) { continue; } draw_chunk(chunk, position_loc, normal_loc, uv_loc); } // render players for (int i = 0; i < player_count; i++) { Player *player = players + i; draw_player(player, position_loc, normal_loc, uv_loc); } // render focused block wireframe int hx, hy, hz; int hw = hit_test( chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz); if (is_obstacle(hw)) { glUseProgram(line_program); glLineWidth(1); glEnable(GL_COLOR_LOGIC_OP); glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix); GLuint cube_buffer = make_cube_buffer(hx, hy, hz, 0.51); draw_lines(cube_buffer, line_position_loc, 3, 48); glDeleteBuffers(1, &cube_buffer); glDisable(GL_COLOR_LOGIC_OP); } update_matrix_2d(matrix); // render crosshairs glUseProgram(line_program); glLineWidth(4); glEnable(GL_COLOR_LOGIC_OP); glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix); GLuint line_buffer = make_line_buffer(); draw_lines(line_buffer, line_position_loc, 2, 4); glDeleteBuffers(1, &line_buffer); glDisable(GL_COLOR_LOGIC_OP); // render selected item update_matrix_item(matrix); if (block_type != previous_block_type) { previous_block_type = block_type; make_single_cube( &item_position_buffer, &item_normal_buffer, &item_uv_buffer, 0, 0, 0, 0.5, block_type); } glUseProgram(block_program); glUniformMatrix4fv(matrix_loc, 1, GL_FALSE, matrix); glUniform3f(camera_loc, 0, 0, 5); glUniform1i(sampler_loc, 0); glUniform1f(timer_loc, glfwGetTime()); glDisable(GL_DEPTH_TEST); draw_single_cube( item_position_buffer, item_normal_buffer, item_uv_buffer, position_loc, normal_loc, uv_loc); glEnable(GL_DEPTH_TEST); glfwSwapBuffers(window); glfwPollEvents(); } client_stop(); db_save_state(x, y, z, rx, ry); db_close(); glfwTerminate(); return 0; }
int main(int argc, char **argv) { srand(time(NULL)); rand(); if (!glfwInit()) { return -1; } create_window(); if (!window) { glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSwapInterval(VSYNC); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetKeyCallback(window, on_key); glfwSetMouseButtonCallback(window, on_mouse_button); #ifndef __APPLE__ if (glewInit() != GLEW_OK) { return -1; } #endif if (db_init()) { return -1; } glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_LINE_SMOOTH); glLogicOp(GL_INVERT); glClearColor(0.53, 0.81, 0.92, 1.00); GLuint vertex_array; glGenVertexArrays(1, &vertex_array); glBindVertexArray(vertex_array); GLuint texture; glGenTextures(1, &texture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); load_png_texture("texture.png"); GLuint block_program = load_program( "shaders/block_vertex.glsl", "shaders/block_fragment.glsl"); GLuint matrix_loc = glGetUniformLocation(block_program, "matrix"); GLuint camera_loc = glGetUniformLocation(block_program, "camera"); GLuint sampler_loc = glGetUniformLocation(block_program, "sampler"); GLuint timer_loc = glGetUniformLocation(block_program, "timer"); GLuint position_loc = glGetAttribLocation(block_program, "position"); GLuint normal_loc = glGetAttribLocation(block_program, "normal"); GLuint uv_loc = glGetAttribLocation(block_program, "uv"); GLuint line_program = load_program( "shaders/line_vertex.glsl", "shaders/line_fragment.glsl"); GLuint line_matrix_loc = glGetUniformLocation(line_program, "matrix"); GLuint line_position_loc = glGetAttribLocation(line_program, "position"); GLuint item_position_buffer = 0; GLuint item_normal_buffer = 0; GLuint item_uv_buffer = 0; int previous_block_type = 0; Chunk chunks[MAX_CHUNKS]; int chunk_count = 0; FPS fps = {0, 0}; float matrix[16]; float x = (rand_double() - 0.5) * 10000; float z = (rand_double() - 0.5) * 10000; float y = 0; float dy = 0; float rx = 0; float ry = 0; double px = 0; double py = 0; int loaded = db_load_state(&x, &y, &z, &rx, &ry); ensure_chunks(chunks, &chunk_count, floorf(roundf(x) / CHUNK_SIZE), floorf(roundf(z) / CHUNK_SIZE), 1); if (!loaded) { y = highest_block(chunks, chunk_count, x, z) + 2; } glfwGetCursorPos(window, &px, &py); double previous = glfwGetTime(); while (!glfwWindowShouldClose(window)) { update_fps(&fps, SHOW_FPS); double now = glfwGetTime(); double dt = MIN(now - previous, 0.2); previous = now; if (exclusive && (px || py)) { double mx, my; glfwGetCursorPos(window, &mx, &my); float m = 0.0025; rx += (mx - px) * m; ry -= (my - py) * m; if (rx < 0) { rx += RADIANS(360); } if (rx >= RADIANS(360)){ rx -= RADIANS(360); } ry = MAX(ry, -RADIANS(90)); ry = MIN(ry, RADIANS(90)); px = mx; py = my; } else { glfwGetCursorPos(window, &px, &py); } if (left_click) { left_click = 0; int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz); if (hy > 0 && is_destructable(hw)) { set_block(chunks, chunk_count, hx, hy, hz, 0); } } if (right_click) { right_click = 0; int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 1, x, y, z, rx, ry, &hx, &hy, &hz); if (is_obstacle(hw)) { if (!player_intersects_block(2, x, y, z, hx, hy, hz)) { set_block(chunks, chunk_count, hx, hy, hz, block_type); } } } int sz = 0; int sx = 0; ortho = glfwGetKey(window, 'F'); fov = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) ? 15.0 : 65.0; if (glfwGetKey(window, 'Q')) break; if (glfwGetKey(window, 'W')) sz--; if (glfwGetKey(window, 'S')) sz++; if (glfwGetKey(window, 'A')) sx--; if (glfwGetKey(window, 'D')) sx++; if (dy == 0 && glfwGetKey(window, GLFW_KEY_SPACE)) { dy = 8; } float vx, vy, vz; get_motion_vector(flying, sz, sx, rx, ry, &vx, &vy, &vz); if (glfwGetKey(window, 'Z')) { vx = -1; vy = 0; vz = 0; } if (glfwGetKey(window, 'X')) { vx = 1; vy = 0; vz = 0; } if (glfwGetKey(window, 'C')) { vx = 0; vy = -1; vz = 0; } if (glfwGetKey(window, 'V')) { vx = 0; vy = 1; vz = 0; } if (glfwGetKey(window, 'B')) { vx = 0; vy = 0; vz = -1; } if (glfwGetKey(window, 'N')) { vx = 0; vy = 0; vz = 1; } float speed = flying ? 20 : 5; int step = 8; float ut = dt / step; vx = vx * ut * speed; vy = vy * ut * speed; vz = vz * ut * speed; for (int i = 0; i < step; i++) { if (flying) { dy = 0; } else { dy -= ut * 25; dy = MAX(dy, -250); } x += vx; y += vy + dy * ut; z += vz; if (collide(chunks, chunk_count, 2, &x, &y, &z)) { dy = 0; } } int p = floorf(roundf(x) / CHUNK_SIZE); int q = floorf(roundf(z) / CHUNK_SIZE); ensure_chunks(chunks, &chunk_count, p, q, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); update_matrix_3d(matrix, x, y, z, rx, ry); // render chunks glUseProgram(block_program); glUniformMatrix4fv(matrix_loc, 1, GL_FALSE, matrix); glUniform3f(camera_loc, x, y, z); glUniform1i(sampler_loc, 0); glUniform1f(timer_loc, glfwGetTime()); for (int i = 0; i < chunk_count; i++) { Chunk *chunk = chunks + i; if (chunk_distance(chunk, p, q) > RENDER_CHUNK_RADIUS) { continue; } if (!chunk_visible(chunk, matrix)) { continue; } draw_chunk(chunk, position_loc, normal_loc, uv_loc); } // render focused block wireframe int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz); if (is_obstacle(hw)) { glUseProgram(line_program); glLineWidth(1); glEnable(GL_COLOR_LOGIC_OP); glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix); GLuint buffer = make_cube_buffer(hx, hy, hz, 0.51); draw_lines(buffer, line_position_loc, 3, 48); glDeleteBuffers(1, &buffer); glDisable(GL_COLOR_LOGIC_OP); } update_matrix_2d(matrix); // render crosshairs glUseProgram(line_program); glLineWidth(4); glEnable(GL_COLOR_LOGIC_OP); glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix); GLuint buffer = make_line_buffer(); draw_lines(buffer, line_position_loc, 2, 4); glDeleteBuffers(1, &buffer); glDisable(GL_COLOR_LOGIC_OP); // render selected item update_matrix_item(matrix); if (block_type != previous_block_type) { previous_block_type = block_type; make_single_cube( &item_position_buffer, &item_normal_buffer, &item_uv_buffer, block_type); } glUseProgram(block_program); glUniformMatrix4fv(matrix_loc, 1, GL_FALSE, matrix); glUniform3f(camera_loc, 0, 0, 5); glUniform1i(sampler_loc, 0); glUniform1f(timer_loc, glfwGetTime()); glDisable(GL_DEPTH_TEST); draw_single_cube( item_position_buffer, item_normal_buffer, item_uv_buffer, position_loc, normal_loc, uv_loc); glEnable(GL_DEPTH_TEST); glfwSwapBuffers(window); glfwPollEvents(); } db_save_state(x, y, z, rx, ry); db_close(); glfwTerminate(); return 0; }
int main(int argc, char **argv) { srand(time(NULL)); rand(); if (argc == 2 || argc == 3) { char *hostname = argv[1]; int port = DEFAULT_PORT; if (argc == 3) { port = atoi(argv[2]); } db_disable(); client_enable(); client_connect(hostname, port); client_start(); } if (!glfwInit()) { return -1; } create_window(); if (!window) { glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSwapInterval(VSYNC); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetKeyCallback(window, on_key); glfwSetCharCallback(window, on_char); glfwSetMouseButtonCallback(window, on_mouse_button); glfwSetScrollCallback(window, on_scroll); #ifndef __APPLE__ if (glewInit() != GLEW_OK) { return -1; } #endif if (db_init()) { return -1; } glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_LINE_SMOOTH); glLogicOp(GL_INVERT); glClearColor(0.53, 0.81, 0.92, 1.00); GLuint texture; glGenTextures(1, &texture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); load_png_texture("texture.png"); GLuint font; glGenTextures(1, &font); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, font); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); load_png_texture("font.png"); GLuint block_program = load_program( "shaders/block_vertex.glsl", "shaders/block_fragment.glsl"); GLuint matrix_loc = glGetUniformLocation(block_program, "matrix"); GLuint camera_loc = glGetUniformLocation(block_program, "camera"); GLuint sampler_loc = glGetUniformLocation(block_program, "sampler"); GLuint timer_loc = glGetUniformLocation(block_program, "timer"); GLuint position_loc = glGetAttribLocation(block_program, "position"); GLuint normal_loc = glGetAttribLocation(block_program, "normal"); GLuint uv_loc = glGetAttribLocation(block_program, "uv"); GLuint line_program = load_program( "shaders/line_vertex.glsl", "shaders/line_fragment.glsl"); GLuint line_matrix_loc = glGetUniformLocation(line_program, "matrix"); GLuint line_position_loc = glGetAttribLocation(line_program, "position"); GLuint text_program = load_program( "shaders/text_vertex.glsl", "shaders/text_fragment.glsl"); GLuint text_matrix_loc = glGetUniformLocation(text_program, "matrix"); GLuint text_sampler_loc = glGetUniformLocation(text_program, "sampler"); GLuint text_position_loc = glGetAttribLocation(text_program, "position"); GLuint text_uv_loc = glGetAttribLocation(text_program, "uv"); GLuint item_position_buffer = 0; GLuint item_normal_buffer = 0; GLuint item_uv_buffer = 0; int previous_block_type = 0; char messages[MAX_MESSAGES][TEXT_BUFFER_SIZE] = {0}; int message_index = 0; Chunk chunks[MAX_CHUNKS]; int chunk_count = 0; Player players[MAX_PLAYERS]; int player_count = 0; FPS fps = {0, 0}; float matrix[16]; float x = (rand_double() - 0.5) * 10000; float z = (rand_double() - 0.5) * 10000; float y = 0; float dy = 0; float rx = 0; float ry = 0; double px = 0; double py = 0; int loaded = db_load_state(&x, &y, &z, &rx, &ry); ensure_chunks(chunks, &chunk_count, x, y, z, 1); if (!loaded) { y = highest_block(chunks, chunk_count, x, z) + 2; } glfwGetCursorPos(window, &px, &py); double previous = glfwGetTime(); while (!glfwWindowShouldClose(window)) { int width, height; glfwGetFramebufferSize(window, &width, &height); glViewport(0, 0, width, height); update_fps(&fps, SHOW_FPS); double now = glfwGetTime(); double dt = MIN(now - previous, 0.2); previous = now; if (exclusive && (px || py)) { double mx, my; glfwGetCursorPos(window, &mx, &my); float m = 0.0025; rx += (mx - px) * m; ry -= (my - py) * m; if (rx < 0) { rx += RADIANS(360); } if (rx >= RADIANS(360)){ rx -= RADIANS(360); } ry = MAX(ry, -RADIANS(90)); ry = MIN(ry, RADIANS(90)); px = mx; py = my; } else { glfwGetCursorPos(window, &px, &py); } int sz = 0; int sx = 0; if (!typing) { float m = dt * 1.0; ortho = glfwGetKey(window, CRAFT_KEY_ORTHO); fov = glfwGetKey(window, CRAFT_KEY_ZOOM) ? 15.0 : 65.0; if (glfwGetKey(window, CRAFT_KEY_QUIT)) break; if (glfwGetKey(window, CRAFT_KEY_FORWARD)) sz--; if (glfwGetKey(window, CRAFT_KEY_BACKWARD)) sz++; if (glfwGetKey(window, CRAFT_KEY_LEFT)) sx--; if (glfwGetKey(window, CRAFT_KEY_RIGHT)) sx++; if (glfwGetKey(window, GLFW_KEY_LEFT)) rx -= m; if (glfwGetKey(window, GLFW_KEY_RIGHT)) rx += m; if (glfwGetKey(window, GLFW_KEY_UP)) ry += m; if (glfwGetKey(window, GLFW_KEY_DOWN)) ry -= m; } float vx, vy, vz; get_motion_vector(flying, sz, sx, rx, ry, &vx, &vy, &vz); if (!typing) { if (glfwGetKey(window, CRAFT_KEY_JUMP)) { if (flying) { vy = 1; } else if (dy == 0) { dy = 8; } } if (glfwGetKey(window, CRAFT_KEY_XM)) { vx = -1; vy = 0; vz = 0; } if (glfwGetKey(window, CRAFT_KEY_XP)) { vx = 1; vy = 0; vz = 0; } if (glfwGetKey(window, CRAFT_KEY_YM)) { vx = 0; vy = -1; vz = 0; } if (glfwGetKey(window, CRAFT_KEY_YP)) { vx = 0; vy = 1; vz = 0; } if (glfwGetKey(window, CRAFT_KEY_ZM)) { vx = 0; vy = 0; vz = -1; } if (glfwGetKey(window, CRAFT_KEY_ZP)) { vx = 0; vy = 0; vz = 1; } } float speed = flying ? 20 : 5; int step = 8; float ut = dt / step; vx = vx * ut * speed; vy = vy * ut * speed; vz = vz * ut * speed; for (int i = 0; i < step; i++) { if (flying) { dy = 0; } else { dy -= ut * 25; dy = MAX(dy, -250); } x += vx; y += vy + dy * ut; z += vz; if (collide(chunks, chunk_count, 2, &x, &y, &z)) { dy = 0; } } if (y < 0) { y = highest_block(chunks, chunk_count, x, z) + 2; } if (left_click) { left_click = 0; int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz); if (hy > 0 && is_destructable(hw)) { set_block(chunks, chunk_count, hx, hy, hz, 0); int above = get_block(chunks, chunk_count, hx, hy + 1, hz); if (is_plant(above)) { set_block(chunks, chunk_count, hx, hy + 1, hz, 0); } } } if (right_click) { right_click = 0; int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 1, x, y, z, rx, ry, &hx, &hy, &hz); if (is_obstacle(hw)) { if (!player_intersects_block(2, x, y, z, hx, hy, hz)) { set_block(chunks, chunk_count, hx, hy, hz, block_type); } } } if (middle_click) { middle_click = 0; int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz); if (is_selectable(hw)) { block_type = hw; } } if (teleport) { teleport = 0; if (player_count) { int index = rand_int(player_count); Player *player = players + index; x = player->x; y = player->y; z = player->z; rx = player->rx; ry = player->ry; ensure_chunks(chunks, &chunk_count, x, y, z, 1); } } client_position(x, y, z, rx, ry); char buffer[RECV_BUFFER_SIZE]; while (client_recv(buffer, RECV_BUFFER_SIZE)) { float ux, uy, uz, urx, ury; if (sscanf(buffer, "U,%*d,%f,%f,%f,%f,%f", &ux, &uy, &uz, &urx, &ury) == 5) { x = ux; y = uy; z = uz; rx = urx; ry = ury; ensure_chunks(chunks, &chunk_count, x, y, z, 1); y = highest_block(chunks, chunk_count, x, z) + 2; } int bp, bq, bx, by, bz, bw; if (sscanf(buffer, "B,%d,%d,%d,%d,%d,%d", &bp, &bq, &bx, &by, &bz, &bw) == 6) { _set_block(chunks, chunk_count, bp, bq, bx, by, bz, bw); if (player_intersects_block(2, x, y, z, bx, by, bz)) { y = highest_block(chunks, chunk_count, x, z) + 2; } } int pid; float px, py, pz, prx, pry; if (sscanf(buffer, "P,%d,%f,%f,%f,%f,%f", &pid, &px, &py, &pz, &prx, &pry) == 6) { Player *player = find_player(players, player_count, pid); if (!player && player_count < MAX_PLAYERS) { player = players + player_count; player_count++; player->id = pid; player->position_buffer = 0; player->normal_buffer = 0; player->uv_buffer = 0; } if (player) { update_player(player, px, py, pz, prx, pry); } } if (sscanf(buffer, "D,%d", &pid) == 1) { delete_player(players, &player_count, pid); } if (buffer[0] == 'T' && buffer[1] == ',') { char *text = buffer + 2; printf("%s\n", text); snprintf( messages[message_index], TEXT_BUFFER_SIZE, "%s", text); message_index = (message_index + 1) % MAX_MESSAGES; } } int p = chunked(x); int q = chunked(z); ensure_chunks(chunks, &chunk_count, x, y, z, 0); // RENDER 3-D SCENE // glClear(GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT); set_matrix_3d(matrix, width, height, x, y, z, rx, ry, fov, ortho); // render chunks glUseProgram(block_program); glUniformMatrix4fv(matrix_loc, 1, GL_FALSE, matrix); glUniform3f(camera_loc, x, y, z); glUniform1i(sampler_loc, 0); glUniform1f(timer_loc, glfwGetTime()); for (int i = 0; i < chunk_count; i++) { Chunk *chunk = chunks + i; if (chunk_distance(chunk, p, q) > RENDER_CHUNK_RADIUS) { continue; } if (y < 100 && !chunk_visible(chunk, matrix)) { continue; } draw_chunk(chunk, position_loc, normal_loc, uv_loc); } // render players for (int i = 0; i < player_count; i++) { Player *player = players + i; draw_player(player, position_loc, normal_loc, uv_loc); } // render focused block wireframe int hx, hy, hz; int hw = hit_test( chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz); if (is_obstacle(hw)) { glUseProgram(line_program); glLineWidth(1); glEnable(GL_COLOR_LOGIC_OP); glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix); GLuint wireframe_buffer = gen_wireframe_buffer(hx, hy, hz, 0.51); draw_lines(wireframe_buffer, line_position_loc, 3, 48); glDeleteBuffers(1, &wireframe_buffer); glDisable(GL_COLOR_LOGIC_OP); } // RENDER 2-D HUD PARTS // glClear(GL_DEPTH_BUFFER_BIT); set_matrix_2d(matrix, width, height); // render crosshairs glUseProgram(line_program); glLineWidth(4); glEnable(GL_COLOR_LOGIC_OP); glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix); GLuint crosshair_buffer = gen_crosshair_buffer(width, height); draw_lines(crosshair_buffer, line_position_loc, 2, 4); glDeleteBuffers(1, &crosshair_buffer); glDisable(GL_COLOR_LOGIC_OP); // render text glUseProgram(text_program); glUniformMatrix4fv(text_matrix_loc, 1, GL_FALSE, matrix); glUniform1i(text_sampler_loc, 1); char text_buffer[1024]; float ts = 12; float tx = ts / 2; float ty = height - ts; snprintf( text_buffer, 1024, "%d, %d, %.2f, %.2f, %.2f [%d, %d]", p, q, x, y, z, player_count, chunk_count); print( text_position_loc, text_uv_loc, tx, ty, ts, text_buffer); for (int i = 0; i < MAX_MESSAGES; i++) { int index = (message_index + i) % MAX_MESSAGES; if (strlen(messages[index])) { ty -= ts * 2; print( text_position_loc, text_uv_loc, tx, ty, ts, messages[index]); } } if (typing) { ty -= ts * 2; snprintf(text_buffer, 1024, "> %s", typing_buffer); print( text_position_loc, text_uv_loc, tx, ty, ts, text_buffer); } // RENDER 3-D HUD PARTS // set_matrix_item(matrix, width, height); // render selected item if (block_type != previous_block_type) { previous_block_type = block_type; if (is_plant(block_type)) { gen_plant_buffers( &item_position_buffer, &item_normal_buffer, &item_uv_buffer, 0, 0, 0, 0.5, block_type); } else { gen_cube_buffers( &item_position_buffer, &item_normal_buffer, &item_uv_buffer, 0, 0, 0, 0.5, block_type); } } glUseProgram(block_program); glUniformMatrix4fv(matrix_loc, 1, GL_FALSE, matrix); glUniform3f(camera_loc, 0, 0, 5); glUniform1i(sampler_loc, 0); glUniform1f(timer_loc, glfwGetTime()); if (is_plant(block_type)) { draw_plant( item_position_buffer, item_normal_buffer, item_uv_buffer, position_loc, normal_loc, uv_loc); } else { draw_cube( item_position_buffer, item_normal_buffer, item_uv_buffer, position_loc, normal_loc, uv_loc); } // swap buffers glfwSwapBuffers(window); glfwPollEvents(); } client_stop(); db_save_state(x, y, z, rx, ry); db_close(); glfwTerminate(); return 0; }