private void add_all_natural_features(List<NaturalFeature.Feature_Type> features) { for (int i = 0; i < features.Count; i++) { if (features[i] == NaturalFeature.Feature_Type.River || features[i] == NaturalFeature.Feature_Type.Chasm) { int feature_length_side1 = randGen.Next(15, 26); int feature_length_side2 = randGen.Next(15, 26); gridCoordinate feature_center = random_valid_position(current_floorsize); gridCoordinate feature_start = new gridCoordinate(-1, -1); gridCoordinate feature_end = new gridCoordinate(-1, -1); bool valid_feature = false; while (!valid_feature) { //Start with a random valid position feature_center = random_valid_position(current_floorsize); //Generate direction vectors for each side of the feature. float side_xVector = (float)Math.Cos(randGen.NextDouble() * Math.PI * 2); float side_yVector = (float)Math.Sin(randGen.NextDouble() * Math.PI * 2); Vector2 side_directionVector = new Vector2(side_xVector, side_yVector); //Adjust the endpoints. feature_start = new gridCoordinate(feature_center); feature_end = new gridCoordinate(feature_center); feature_start.add_vector2(side_directionVector * feature_length_side1); feature_end.add_vector2(side_directionVector * feature_length_side2 * -1); //Force the values to be safe. feature_start.force_safe_value(current_floorsize); feature_end.force_safe_value(current_floorsize); //Check to see whether the values are okay. All river values are accepted //Chasm values are rerolled if they're too close to the edge. if (features[i] == NaturalFeature.Feature_Type.River) valid_feature = true; else if (features[i] == NaturalFeature.Feature_Type.Chasm) { if (feature_start.x > 4 && feature_start.x < 47 && feature_start.y > 4 && feature_start.y < 47 && feature_end.x > 4 && feature_end.x < 47 && feature_end.y > 4 && feature_end.y < 47) valid_feature = true; } } if (features[i] == NaturalFeature.Feature_Type.River) { //Add the new river int deepwater_thickness = randGen.Next(2); int shallows_thickness = 1 + randGen.Next(3); int banks_thickness = 1 + randGen.Next(2); featurelayout.Add(new NaturalFeature(feature_start, feature_end, NaturalFeature.River_Type.Normal, deepwater_thickness, shallows_thickness, banks_thickness)); } else if (features[i] == NaturalFeature.Feature_Type.Chasm) { //Add the new chasm int max_thickness = randGen.Next(6, 13); featurelayout.Add(new NaturalFeature(feature_start, feature_end, max_thickness)); } } else if (features[i] == NaturalFeature.Feature_Type.Lake) { gridCoordinate feature_center = random_valid_position(current_floorsize); int xSize = randGen.Next(11, 18); int ySize = randGen.Next(11, 18); int room_thickness = 1 + randGen.Next(2); int shore_thickness = 1 + randGen.Next(2); int shallows_thickness = 1 + randGen.Next(2); gridCoordinate feature_start = new gridCoordinate(feature_center.x - xSize / 2, feature_center.y - ySize / 2); gridCoordinate feature_end = new gridCoordinate(feature_center.x + xSize / 2, feature_center.y + ySize / 2); feature_start.force_safe_value(current_floorsize); feature_end.force_safe_value(current_floorsize); featurelayout.Add(new NaturalFeature(feature_start, feature_end, room_thickness, shore_thickness, shallows_thickness)); } } }
public void draw_linear_feature(ref List<List<Tile>> grid, ref List<Fl_Special_Event> event_list, Random rGen, Tile.Tile_Type[] feature_tiletypes, Texture2D general_sheet, Texture2D dungeon_sheet, List<KeyValuePair<Tile.Tile_Type, gridCoordinate>> texture_map) { //First determine whether it's a mostly horizontal or vertical river. //Get differences. int abs_xDif = Math.Abs(feature_startCoord.x - feature_endCoord.x); int abs_yDif = Math.Abs(feature_startCoord.y - feature_endCoord.y); int xDif = feature_startCoord.x - feature_endCoord.x; int yDif = feature_startCoord.y - feature_endCoord.y; //Get Vector points. Vector2 end_position = new Vector2(feature_endCoord.x * 32, feature_endCoord.y * 32); //Get pixel differences double xPixels = xDif * 32; double yPixels = yDif * 32; gridCoordinate[,] dirs = {{new gridCoordinate(1, 0), new gridCoordinate(-1, 0)}, {new gridCoordinate(0, 1), new gridCoordinate(0, -1)}}; //Vertical int direct = 0; gridCoordinate.coord xy = gridCoordinate.coord.xCoord; //If x difference > y difference, it's a horizontally drawn feature if (abs_xDif > abs_yDif) { direct = 1; xy = gridCoordinate.coord.yCoord; } Vector2 c_position = new Vector2(feature_startCoord.x * 32, feature_startCoord.y * 32); double c_xvalue = c_position.X; double c_yvalue = c_position.Y; bool done = false; gridCoordinate current_position = new gridCoordinate(-1, -1); gridCoordinate previous_position = new gridCoordinate(-1, -1); int length_completed = 0; while (!done) { done = is_river_finished(c_xvalue, c_yvalue); current_position = new gridCoordinate((int)(c_xvalue / 32), (int)(c_yvalue / 32)); bool good_to_draw = false; if (xy == gridCoordinate.coord.yCoord && current_position.x != previous_position.x) good_to_draw = true; if (xy == gridCoordinate.coord.xCoord && current_position.y != previous_position.y) good_to_draw = true; if (good_to_draw) { //Determine whether or not the upcoming section of the river is a crossing point. length_completed += 1; bool crossing_point = false; if (my_fType == Feature_Type.River) { for (int i = 0; i < crossing_points.Count; i++) if (length_completed == crossing_points[i]) crossing_point = true; } //Get the sizes of the right edge int[] rr = { }; if (my_fType == Feature_Type.River) { rr = new int[] {rGen.Next(deepwater_thickness+1) + 1, rGen.Next(1, shallow_thickness+1), rGen.Next(1, banks_thickness+1)}; } else if (my_fType == Feature_Type.Chasm) { double v = (double)length_completed / (double)chasm_length; int width = (int)((1.0 - Math.Abs(Math.Sin(v * Math.PI - (Math.PI / 2)))) * maximum_thickness); width /= 2; rr = new int[] { width + 1, 2 + rGen.Next(2) }; } //Translate to actual coordinates. int[] rEdge = new int[1]; if (my_fType == Feature_Type.River) { rEdge = new int[3]; rEdge[0] = current_position.get_a_coord(xy) + 1 + rr[0]; rEdge[1] = rEdge[0] + rr[1]; rEdge[2] = rEdge[1] + rr[2]; } else if (my_fType == Feature_Type.Chasm) { rEdge = new int[2]; rEdge[0] = current_position.get_a_coord(xy) + 1 + rr[0]; rEdge[1] = rEdge[0] + rr[1]; } //Use deep water unless it's a crossing point. Tile.Tile_Type first_tiletype = feature_tiletypes[0]; if (my_fType == Feature_Type.River && crossing_point) first_tiletype = feature_tiletypes[1]; //Fill in the center coordinate. grid[current_position.x][current_position.y].set_tile_type(first_tiletype, general_sheet, dungeon_sheet, texture_map); int redge_max = rEdge[rEdge.Count() - 1]; //Fill in the right edge. for (gridCoordinate i = new gridCoordinate(current_position); i.get_a_coord(xy) < redge_max; i.combineCoords(dirs[direct, 0])) { if (i.get_a_coord(xy) >= grid.Count) break; if (i.get_a_coord(xy) < rEdge[0]) grid[i.x][i.y].set_tile_type(first_tiletype, general_sheet, dungeon_sheet, texture_map); else if (i.get_a_coord(xy) < rEdge[1]) grid[i.x][i.y].set_tile_type(feature_tiletypes[1], general_sheet, dungeon_sheet, texture_map); else grid[i.x][i.y].set_tile_type(feature_tiletypes[2], general_sheet, dungeon_sheet, texture_map); } //Get the sizes of the left edge int[] lr = { }; if (my_fType == Feature_Type.River) { lr = new int[] {rGen.Next(deepwater_thickness+1) + 1, rGen.Next(1, shallow_thickness+1), rGen.Next(1, banks_thickness+1)}; } else if (my_fType == Feature_Type.Chasm) { double v = (double)length_completed / (double)chasm_length; int width = (int)((1.0 - Math.Abs(Math.Sin(v * Math.PI - (Math.PI / 2)))) * maximum_thickness); width /= 2; lr = new int[] { width + 1, 2 + rGen.Next(2) }; } //Translate to actual coodinates int[] lEdge = new int[1]; if (my_fType == Feature_Type.River) { lEdge = new int[3]; lEdge[0] = current_position.get_a_coord(xy) - 1 - lr[0]; lEdge[1] = lEdge[0] - lr[1]; lEdge[2] = lEdge[1] - lr[2]; } else if (my_fType == Feature_Type.Chasm) { lEdge = new int[2]; lEdge[0] = current_position.get_a_coord(xy) - 1 - lr[0]; lEdge[1] = lEdge[0] - lr[1]; } //Fill in the left edge. int ledge_max = lEdge[lEdge.Count() - 1]; for (gridCoordinate i = new gridCoordinate(current_position); i.get_a_coord(xy) > ledge_max; i.combineCoords(dirs[direct, 1])) { if (i.get_a_coord(xy) < 0) break; if (i.get_a_coord(xy) > lEdge[0]) grid[i.x][i.y].set_tile_type(first_tiletype, general_sheet, dungeon_sheet, texture_map); else if (i.get_a_coord(xy) > lEdge[1]) grid[i.x][i.y].set_tile_type(feature_tiletypes[1], general_sheet, dungeon_sheet, texture_map); else grid[i.x][i.y].set_tile_type(feature_tiletypes[2], general_sheet, dungeon_sheet, texture_map); } if (my_fType == Feature_Type.Chasm && length_completed == cavern_point) { int x_position = 0; int y_position = 0; //Horizontal if (direct == 1) { x_position = current_position.x; if (cavern_right) y_position = redge_max; else y_position = ledge_max; } //Vertical else { y_position = current_position.y; if (cavern_right) x_position = redge_max; else x_position = ledge_max; } gridCoordinate cavern_entrance_coord = new gridCoordinate(x_position, y_position); cavern_entrance_coord.force_safe_value(grid.Count); grid[cavern_entrance_coord.x][cavern_entrance_coord.y].set_tile_type(Tile.Tile_Type.Cavern_Exit, general_sheet, dungeon_sheet, texture_map); event_list.Add(new Fl_Special_Event(Fl_Special_Event.event_triggers.player_in_area, Fl_Special_Event.event_type.spawn_weak_monster, 6, 3, true, cavern_entrance_coord)); } } Vector2 direction = end_position - c_position; direction.Normalize(); c_xvalue += direction.X; c_yvalue += direction.Y; previous_position = current_position; } }