////////////////////////////////////////////////////////////////////// bool fast_forward(Level level) { Level l = Instantiate(level); l.reset_board(); l.copy_blocks_from(level); int move = l.solution.Count - 1; while (move >= 0) { int2 v = l.solution[move] * -1; move -= 1; int distance; Level.move_result r = l.get_move_result(v, out distance); if (r == Level.move_result.hit_side) { return(false); } if (r == Level.move_result.hit_solution) { return(true); } l.update_block_positions(v * distance); l.update_hit_blocks(v); } return(l.is_solution_complete(int2.zero)); }
////////////////////////////////////////////////////////////////////// void Update() { switch (current_level.current_mode) { // drag mouse to set size of grid case Game.Mode.set_grid_size: Vector2 grid_pos = intersect_front_face_f(16, 16, Input.mousePosition); float w = Mathf.Min(8, Mathf.Max(1.5f, Mathf.Abs(grid_pos.x - 8))); float h = Mathf.Min(8, Mathf.Max(1.5f, Mathf.Abs(grid_pos.y - 8))); destroy_grid(); int bw = (int)Mathf.Round(w * 2); int bh = (int)Mathf.Round(h * 2); if (Input.GetMouseButtonDown(0)) { current_level = ScriptableObject.CreateInstance <Level>(); current_level.get_board_coordinate = editor_board_coordinate; current_level.create_block_object = create_block_object; current_level.reset(); reset_level(current_level); current_level.create_board(bw, bh); current_level.current_mode = Game.Mode.create_solution; Debug.Log($"Board is {bw}x{bh}"); } create_grid(bw, bh, square_size, grid_color, grid_line_width); break; // click some squares to create the solution blocks case Game.Mode.create_solution: int2 cp = intersect_front_face(current_level.width, current_level.height, Input.mousePosition); if (current_level.out_of_bounds(cp)) { cursor_quad.SetActive(false); } else { Color cursor_color = Color.magenta; cursor_quad.transform.position = board_coordinate_z(cp, cursor_depth); cursor_quad.SetActive(true); Block cb = current_level.block_at(cp); if (cb != null) { cursor_color = Color.Lerp(cursor_color, Color.black, 0.5f); } if (Input.GetMouseButtonDown(0)) { cursor_color = Color.white; // if cursor on top of a solution block, click removes it if (cb != null) { cursor_color = Color.black; solution_objects.Remove(cb.game_object); Destroy(cb.game_object); current_level.set_block_at(cp, null); current_level.active_win_blocks.Remove(cb.position); } // otherwise click adds one (TODO (chs): check it's a valid place to put a block else { Block b = new Block(); b.position = cp; b.game_object = create_block_object(solution_color); b.game_object.transform.position = board_coordinate_z(cp, solution_depth); current_level.set_block_at(cp, b); solution_objects.Add(b.game_object); current_level.active_win_blocks.Add(cp); } } set_color(cursor_quad, cursor_color); // right click moves to next phase (setting moves) if (Input.GetMouseButtonDown(1)) { current_level.solution.Clear(); move_direction = int2.zero; cursor_quad.SetActive(false); foreach (GameObject b in solution_objects) { b.transform.position = new Vector3(b.transform.position.x, b.transform.position.y, solution_depth); } current_level.blocks.Clear(); for (int y = 0; y < current_level.height; ++y) { for (int x = 0; x < current_level.width; ++x) { Block blk = current_level.block_at(x, y); if (blk != null) { current_level.active_win_blocks.Add(blk.position); blk.game_object = create_block_object(stuck_color); blk.game_object.transform.position = board_coordinate_z(blk.position, block_depth); blk.stuck = true; current_level.blocks.Add(blk); } } } current_level.current_mode = Game.Mode.edit_solution; } } break; // create the moves // TODO (chs): store solution direction thingy case Game.Mode.edit_solution: choose_unstuck_blocks(); int2 start_movement = KeyboardInput.get_key_movement(); // check if it's valid to move in this direction if (!start_movement.Equals(int2.zero)) { if (move_direction.Equals(int2.zero)) { Debug.Log("Movement!"); move_direction = start_movement; current_level.solution.Add(move_direction); } if (move_direction.Equals(start_movement)) { current_level.move_all_stuck_blocks(start_movement); } if (!fast_forward(current_level)) { current_level.move_all_stuck_blocks(start_movement * -1); current_level.solution.RemoveAt(current_level.solution.Count - 1); move_direction = int2.zero; } } if (Input.GetKeyDown(KeyCode.P)) { current_level.set_banner_text("Play!"); // create loaded_level from current_level foreach (Block b in current_level.blocks) { current_level.active_start_blocks.Add(create_block(b)); } cursor_quad.SetActive(false); start_level(current_level); current_level.current_mode = Game.Mode.make_move; } break; case Game.Mode.prepare_to_play: current_level.current_mode = Game.Mode.make_move; break; case Game.Mode.prepare_to_show_solution: if (current_level.mode_time_elapsed > 0.5f) { current_level.current_mode = Game.Mode.show_solution; } break; case Game.Mode.show_solution: if (solution_turn_enumerator < 0) { current_level.current_mode = Game.Mode.prepare_to_play; } else if (current_level.mode_time_elapsed > 0.333f) { current_move_vector = current_level.solution[solution_turn_enumerator] * -1; solution_turn_enumerator -= 1; current_move_result = current_level.get_move_result(current_move_vector, out move_distance); move_start_time = Time.realtimeSinceStartup; move_end_time = move_start_time + (move_distance * 0.04f); current_level.current_mode = Game.Mode.make_help_move; } break; case Game.Mode.make_help_move: do_game_move(Game.Mode.show_solution); break; case Game.Mode.maybe: do_game_move(Game.Mode.make_move); break; case Game.Mode.make_move: current_move_vector = KeyboardInput.get_key_movement(); if (!current_move_vector.Equals(int2.zero)) { current_move_result = current_level.get_move_result(current_move_vector, out move_distance); move_start_time = Time.realtimeSinceStartup; move_end_time = move_start_time + (move_distance * 0.05f); current_level.current_mode = Game.Mode.maybe; } break; case Game.Mode.failed: Color f = solution_color; win_flash_timer = (win_flash_timer + 1) % 10; if (win_flash_timer > 3) { f = solution_flash_color; } foreach (GameObject o in solution_objects) { set_color(o, f); } break; case Game.Mode.winner: Color c = win_color; win_flash_timer = (win_flash_timer + 1) % 10; if (win_flash_timer > 3) { c = stuck_color; } foreach (Block b in current_level.blocks) { set_color(b.game_object, c); } break; } debug($"MODE: {current_level.current_mode}"); // space to reset level if (Input.GetKeyDown(KeyCode.Space)) { start_level(current_level); current_level.current_mode = Game.Mode.make_move; } // Escape to quit if (Input.GetKeyDown(KeyCode.Escape)) { Statics.Quit(); } // cube animation cube_angle += cube_angle_velocity; main_cube.transform.rotation = Quaternion.Euler(cube_angle.x, cube_angle.y, cube_angle.z); cube_angle_velocity *= 0.95f; cube_angle *= 0.65f; current_level.update_banner_pos(); debug_end_scene(); }
// Update is called once per frame void Update() { current_level.update_banner_pos(); switch (current_level.current_mode) { case Mode.make_move: flash_solution(); current_move_vector = KeyboardInput.get_key_movement(); if (!current_move_vector.Equals(int2.zero)) { current_move_result = current_level.get_move_result(current_move_vector, out move_distance); Debug.Log($"MOVE: {current_move_result}"); move_start_time = Time.realtimeSinceStartup; move_end_time = move_start_time + (move_distance * 0.025f); current_level.current_mode = Mode.maybe; } break; case Mode.prepare_to_play: current_level.current_mode = Mode.make_move; break; case Mode.maybe: flash_solution(); do_game_move(Mode.make_move, Mode.winner); break; case Mode.failed: { float t = Mathf.Sin(current_level.mode_timer) * 0.35f + 0.5f; foreach (GameObject o in boundary_objects) { Main.set_color(o, Color.red); // new Color(t, t, t, t)); } if (current_level.mode_time_elapsed > 1) { SceneManager.LoadScene("GameScene", LoadSceneMode.Single); } } break; case Mode.solution_ended: animate_win(0); break; case Mode.winner: animate_win(1); break; case Mode.prepare_to_show_solution: if (current_level.mode_time_elapsed > 1) { current_level.current_mode = Mode.show_solution; } break; case Mode.show_solution: if (current_level.mode_time_elapsed > 0.333f) { current_move_vector = current_level.solution[solution_turn_enumerator] * -1; solution_turn_enumerator -= 1; current_move_result = current_level.get_move_result(current_move_vector, out move_distance); move_start_time = Time.realtimeSinceStartup; move_end_time = move_start_time + (move_distance * 0.04f); current_level.current_mode = Mode.make_help_move; } break; case Mode.make_help_move: do_game_move(Mode.show_solution, Mode.solution_ended); break; } // space to reset level if (Input.GetKeyDown(KeyCode.Space)) { restart(); } if (Input.GetKeyDown(KeyCode.Escape)) { quit(); } // cube animation cube_angle += cube_angle_velocity; main_cube.transform.rotation = Quaternion.Euler(cube_angle.x, cube_angle.y, cube_angle.z); cube_angle_velocity *= 0.95f; cube_angle *= 0.65f; }