extends TileMap var base_positions: Array[Vector2i] = [] # Called when the node enters the scene tree for the first time. func _ready(): MapConfig.reset_to_defaults() func load_map(file_name: String): MapConfig.num_errors = 0 MapConfig.reset_to_defaults() parse_map_file(file_name) apply_options() prints("Loaded", MapConfig.mapname, "by", MapConfig.mapauthor) if MapConfig.num_errors > 0: push_error("Map contains ", MapConfig.num_errors, " errors") func parse_map_file(file_name): # Remove current map if any clear() # Build a dictionary that translates letter codes from # the map format to tiles var tile_dictionary = {} var atlas_source = tile_set.get_source(0) for i in range(atlas_source.get_tiles_count()): var tile_id = atlas_source.get_tile_id(i) var tile_data = atlas_source.get_tile_data(tile_id, 0) var letter_code = tile_data.get_custom_data("Letter code") for letter in letter_code: tile_dictionary[letter] = tile_id # Load the map from file var mapfile = FileAccess.open(file_name, FileAccess.READ) if not mapfile: print("Couldn't open map file") return var multi_line_mode_option = "" var multi_line_terminator = "" var multi_line_content = "" var line_number = 0 while not mapfile.eof_reached(): var line = mapfile.get_line() line_number += 1 if multi_line_mode_option: if line.contains(multi_line_terminator): MapConfig.set_option(multi_line_mode_option, multi_line_content) multi_line_mode_option = "" else: multi_line_content += line else: # Remove comments var comment_pos = line.find('#') if comment_pos >= 0: line = line.left(comment_pos) # Get rid of extra whitespace line = line.strip_edges() # If what is left over is an empty line, skip it if line.length() == 0: continue var option = line.split(':', true, 1) if option.size() != 2: print("Invalid data on line ", line_number) continue # Multiline values expand over many lindes until a specified keyword is reached if option[1].contains("\\multiline:"): multi_line_mode_option = option[0].strip_edges().to_lower() multi_line_terminator = option[1].split("\\multiline:")[1].strip_edges() continue MapConfig.set_option(option[0].strip_edges(), option[1].strip_edges()) if multi_line_mode_option != "": print("EOF reached before end of multiline") if MapConfig.mapdata.length() > 0 and MapConfig.mapwidth > 0 and MapConfig.mapheight > 0: for iy in range(MapConfig.mapheight): for ix in range(MapConfig.mapwidth): var letter_code = MapConfig.mapdata[iy * MapConfig.mapwidth + ix] if tile_dictionary.has(letter_code): match letter_code: # Cannon "c", "d", "r", "f": var cannon = preload("res://World/cannon.tscn").instantiate() cannon.position = 64*Vector2i(ix, iy) + Vector2i(32, 32) match letter_code: "c": cannon.rotation_degrees = 180 "d": cannon.rotation_degrees = 270 "r": cannon.rotation_degrees = 0 "f": cannon.rotation_degrees = 90 if MapConfig.edgewrap: if ix < MapConfig.mapwidth / 2: cannon.position.x += 64*MapConfig.mapwidth if iy < MapConfig.mapheight / 2: cannon.position.y += 64*MapConfig.mapheight $"../Cannons".add_child(cannon, true) _: set_cell(0, Vector2i(ix, iy), 0, tile_dictionary[letter_code]) if "_0123456789".contains(letter_code): base_positions.push_back(Vector2i(ix, iy)) if MapConfig.edgewrap: if ix < MapConfig.mapwidth / 2: base_positions[-1].x += MapConfig.mapwidth if iy < MapConfig.mapheight / 2: base_positions[-1].y += MapConfig.mapheight if MapConfig.edgewrap: set_cell(0, Vector2i(ix + MapConfig.mapwidth, iy), 0, tile_dictionary[letter_code]) set_cell(0, Vector2i(ix + MapConfig.mapwidth, iy + MapConfig.mapheight), 0, tile_dictionary[letter_code]) set_cell(0, Vector2i(ix, iy + MapConfig.mapheight), 0, tile_dictionary[letter_code]) else: print("Map data or dimensions missing") func apply_options(): if MapConfig.edgewrap: $"../Map boundaries/CollisionShape2D".shape.size = 64 * Vector2i(MapConfig.mapwidth, MapConfig.mapheight) $"../Map boundaries".position = 64 * Vector2i(MapConfig.mapwidth, MapConfig.mapheight) if not $"../Map boundaries".is_connected("body_exited", $".."._on_map_boundaries_body_exited): $"../Map boundaries".connect("body_exited", $".."._on_map_boundaries_body_exited) else: if $"../Map boundaries".is_connected("body_exited", $".."._on_map_boundaries_body_exited): $"../Map boundaries".disconnect("body_exited", $".."._on_map_boundaries_body_exited) # Engine.physics_ticks_per_second = MapConfig.framespersecond