extends Node2D @onready var tile_layer: TileMapLayer = $main_game_background_tiles @onready var camera: Camera2D = $main_game_camera @export var RENDER_RADIUS: int = 20 @export_range(0.0, 1.0) var producer_spawn_chance: float = 0.015 # 1.5% chance per tile @export var producer_scene: PackedScene @export var consumer_scene: PackedScene var render_radius_x = RENDER_RADIUS var render_radius_y = RENDER_RADIUS # --- PHASE 1 DATA STRUCTURES --- # This dictionary tracks what physical entity occupies a grid coordinate. # Format: Vector2i(x, y) : { "type": "consumer" } or { "type": "producer", "value": 10 } var grid_data: Dictionary = {} # This dictionary keeps track of where the floor tiles have already been visually placed var rendered_tiles: Dictionary = {} func _ready() -> void: # Explicitly pre-seed the center of the world data structure initialize_world_center() func _process(_delta: float) -> void: if camera: render_radius_x = RENDER_RADIUS / camera.zoom[0] render_radius_y = RENDER_RADIUS / camera.zoom[1] generate_and_render_around_camera() # Define the absolute center data rule func initialize_world_center() -> void: # Loop from -1 to 1 on both X and Y to cover a 3x3 area for x in range(-1, 2): for y in range(-1, 2): var current_coord = Vector2i(x, y) grid_data[current_coord] = { "type": "consumer", "is_center": (x == 0 and y == 0) # Only (0,0) is marked as the visual center } print("World Core Initialized: 3x3 Consumer registered from (-1,-1) to (1,1)") if producer_scene: print("Placing consumer at (0, 0)") # 1. Create a live instance of the saved scene file var consumer = consumer_scene.instantiate() # 2. Add it as a child of the world so it exists in the active game tree add_child(consumer) # 3. Convert grid coordinates back to exact engine pixel coordinates # map_to_local gives us the exact center point of that grid tile var pixel_position = tile_layer.map_to_local(Vector2i(0, 0)) consumer.global_position = pixel_position # Combined loop to manage both world data rules and visual rendering func generate_and_render_around_camera() -> void: var camera_grid_pos = tile_layer.local_to_map(camera.global_position) for x in range(camera_grid_pos.x - render_radius_x, camera_grid_pos.x + render_radius_x): for y in range(camera_grid_pos.y - render_radius_y, camera_grid_pos.y + render_radius_y): var tile_coords = Vector2i(x, y) # 1. VISUAL RENDERING (Always draw the background floor) if not rendered_tiles.has(tile_coords): # Draw your background tile asset (Source ID: 0, Atlas Coords: 0,0) tile_layer.set_cell(tile_coords, 0, Vector2i(0, 0)) rendered_tiles[tile_coords] = true # 2. DATA PROCESSING PLACEHOLDER # This is where Phase 2 will plug in to evaluate if a producer should spawn process_grid_data_at(tile_coords) # PHASE 2: Distance Math & Random Generation func process_grid_data_at(coords: Vector2i) -> void: # If this coordinate is already occupied (like by our 3x3 Consumer), skip it! if grid_data.has(coords): return # Roll the dice to see if a Producer should spawn here if randf() < producer_spawn_chance: # Calculate Manhattan Distance from the absolute center (0,0) var distance = abs(coords.x) + abs(coords.y) # Formula: Start at 1, add 1 extra value for every 10 tiles away var producer_value = 1 + floor(distance / 10.0) # Register the producer in our global data registry grid_data[coords] = { "type": "producer", "value": producer_value } if producer_scene: print("Placing producer at " + str(coords.x) + ", " + str(coords.y)) # 1. Create a live instance of the saved scene file var new_producer = producer_scene.instantiate() new_producer.setup(int(producer_value)) # 2. Add it as a child of the world so it exists in the active game tree add_child(new_producer) # 3. Convert grid coordinates back to exact engine pixel coordinates # map_to_local gives us the exact center point of that grid tile var pixel_position = tile_layer.map_to_local(coords) new_producer.global_position = pixel_position # 4. Optional: If your Producer scene has a script on it, # you can pass its distance value directly to it right here! # new_producer.output_value = producer_value ## --- VISUAL PLACEMENT --- ## Tell your TileMapLayer to draw the Producer asset on top of the floor. ## Replace Vector2i(1, 0) with the actual atlas coordinates of your Producer image in your TileSet! #tile_layer.set_cell(coords, 0, Vector2i(1, 0)) # Helper function: Check if a coordinate is occupied by a building func get_object_at_coordinate(coords: Vector2i): if grid_data.has(coords): return grid_data[coords] return null # Returns null if it's just an empty background tile # Helper function: Force place an object into the grid data registry func register_object_at_coordinate(coords: Vector2i, object_data: Dictionary) -> void: grid_data[coords] = object_data