190 lines
7.8 KiB
GDScript
190 lines
7.8 KiB
GDScript
extends Node
|
|
class_name IsometricMapRenderer
|
|
|
|
var map_data = null
|
|
var isometric_map_layers = []
|
|
var highlighted_tiles = {} # Dictionary to store all currently highlighted tiles
|
|
|
|
var TILE_SIZE_ISOMETRIC_X = 32 # in px
|
|
var TILE_SIZE_ISOMETRIC_Y = 16 # in px
|
|
|
|
# Initialize with reference to a map data object and a tilemap to use as template
|
|
func _init(map_data_ref, tilemap_template):
|
|
map_data = map_data_ref
|
|
initialize_map_layers(tilemap_template)
|
|
|
|
# Initialize all the map layers for different heights
|
|
func initialize_map_layers(tilemap_template):
|
|
# Clear any existing layers
|
|
for layer in isometric_map_layers:
|
|
if is_instance_valid(layer):
|
|
layer.queue_free()
|
|
|
|
isometric_map_layers.clear()
|
|
|
|
# Create new layers for each height level
|
|
for z in map_data.GRID_SIZE_HEIGHT:
|
|
var new_layer = TileMapLayer.new()
|
|
new_layer.set_name("IsometricMapLayer_" + str(z))
|
|
new_layer.tile_set = tilemap_template.tile_set
|
|
new_layer.z_index = z # Set the z-index to match the layer's height
|
|
|
|
tilemap_template.get_parent().add_child(new_layer)
|
|
isometric_map_layers.append(new_layer)
|
|
|
|
# Draw all visible tiles on the map
|
|
func draw_visible_tiles():
|
|
# Clear all previously drawn tiles on each layer
|
|
for layer in isometric_map_layers:
|
|
layer.clear()
|
|
|
|
# Draw the map
|
|
for z in map_data.GRID_SIZE_HEIGHT:
|
|
for y in map_data.GRID_SIZE_LENGTH:
|
|
for x in map_data.GRID_SIZE_WIDTH:
|
|
var tile = map_data.get_tile(x, y, z)
|
|
if tile != null and tile["visibility"] and tile["atlas_base_position"] != null:
|
|
# Use the layer that corresponds to the tile's z-value
|
|
if z < isometric_map_layers.size():
|
|
isometric_map_layers[z].set_cell(
|
|
Vector2i(tile["x"], tile["y"]),
|
|
IsometricMapSystem.MAIN_SOURCE_ID,
|
|
tile["atlas_base_position"]
|
|
)
|
|
|
|
# Handle hovering over tiles
|
|
func handle_hover(mouse_position):
|
|
var hover_tile_position = isometric_map_layers[0].local_to_map(mouse_position)
|
|
var new_highlighted_tiles = {} # Will store tiles to highlight this frame
|
|
|
|
# First find all tiles that should be highlighted
|
|
for z in map_data.GRID_SIZE_HEIGHT:
|
|
for x in map_data.GRID_SIZE_WIDTH:
|
|
for y in map_data.GRID_SIZE_LENGTH:
|
|
var tile = map_data.get_tile(x, y, z)
|
|
|
|
if tile != null and tile["visibility"] and not tile["unit"]:
|
|
if tile["x"] == hover_tile_position.x and tile["y"] == hover_tile_position.y:
|
|
# Store this tile for highlighting
|
|
var tile_key = str(x) + "_" + str(y) + "_" + str(z)
|
|
|
|
new_highlighted_tiles[tile_key] = {
|
|
"x": x,
|
|
"y": y,
|
|
"z": z
|
|
}
|
|
|
|
# Highlight new tiles
|
|
for tile_key in new_highlighted_tiles:
|
|
var tile_data = new_highlighted_tiles[tile_key]
|
|
var tile = map_data.get_tile(tile_data.x, tile_data.y, tile_data.z)
|
|
if tile == null:
|
|
continue
|
|
|
|
if not tile["selected"] and not tile["unit"]:
|
|
# Only set cell if we have a valid highlight position
|
|
if tile["atlas_highlight_position"] != null:
|
|
isometric_map_layers[tile_data.z].set_cell(
|
|
Vector2i(tile["x"], tile["y"]),
|
|
IsometricMapSystem.MAIN_SOURCE_ID,
|
|
tile["atlas_highlight_position"]
|
|
)
|
|
else:
|
|
isometric_map_layers[tile_data.z].set_cell(
|
|
Vector2i(tile["x"], tile["y"]),
|
|
1,
|
|
Vector2i(3,1) #
|
|
)
|
|
|
|
tile["highlighted"] = true
|
|
|
|
# De-highlight tiles that are no longer under the cursor
|
|
for tile_key in highlighted_tiles:
|
|
if not (tile_key in new_highlighted_tiles):
|
|
var tile_data = highlighted_tiles[tile_key]
|
|
var tile = map_data.get_tile(tile_data.x, tile_data.y, tile_data.z)
|
|
|
|
if tile != null and tile["visibility"] and not tile["unit"]:
|
|
|
|
if not tile["selected"]:
|
|
# Only set cell if we have a valid base position
|
|
if tile["atlas_base_position"] != null:
|
|
isometric_map_layers[tile_data.z].set_cell(
|
|
Vector2i(tile["x"], tile["y"]),
|
|
IsometricMapSystem.MAIN_SOURCE_ID,
|
|
tile["atlas_base_position"] # Original appearance
|
|
)
|
|
else:
|
|
isometric_map_layers[tile_data.z].set_cell(
|
|
Vector2i(tile["x"], tile["y"]),
|
|
1,
|
|
Vector2i(0,1) #
|
|
)
|
|
tile["highlighted"] = false
|
|
|
|
# Update the highlighted tiles list
|
|
highlighted_tiles = new_highlighted_tiles
|
|
|
|
# Handle tile selection logic
|
|
func handle_tile_selection():
|
|
for z in map_data.GRID_SIZE_HEIGHT:
|
|
for x in map_data.GRID_SIZE_WIDTH:
|
|
for y in map_data.GRID_SIZE_LENGTH:
|
|
var tile = map_data.get_tile(x, y, z)
|
|
if tile == null or not tile["visibility"]:
|
|
continue
|
|
|
|
# Get valid coordinates
|
|
var tile_x = tile["x"]
|
|
var tile_y = tile["y"]
|
|
|
|
if tile["selected"] and tile["highlighted"]:
|
|
print("direct de selected: ", Vector2i(tile_x, tile_y))
|
|
isometric_map_layers[z].set_cell(
|
|
Vector2i(tile_x, tile_y),
|
|
IsometricMapSystem.MAIN_SOURCE_ID,
|
|
IsometricMapSystem.SELECTED_BLUE_ISOMETRICTILE_ATLAS_POSITION
|
|
)
|
|
tile["selected"] = false
|
|
|
|
elif tile["selected"] and not tile["highlighted"]:
|
|
print("old de selected: ", Vector2i(tile_x, tile_y))
|
|
# If there's a base position, restore it, otherwise use a default
|
|
if tile["atlas_base_position"] != null:
|
|
isometric_map_layers[z].set_cell(
|
|
Vector2i(tile_x, tile_y),
|
|
IsometricMapSystem.MAIN_SOURCE_ID,
|
|
tile["atlas_base_position"]
|
|
)
|
|
else:
|
|
isometric_map_layers[z].set_cell(
|
|
Vector2i(tile_x, tile_y),
|
|
IsometricMapSystem.MAIN_SOURCE_ID,
|
|
IsometricMapSystem.BLUE_ISOMETRICTILE_ATLAS_POSITION
|
|
)
|
|
tile["selected"] = false
|
|
|
|
elif not tile["selected"] and tile["highlighted"]:
|
|
print("new selected: ", Vector2i(tile_x, tile_y))
|
|
isometric_map_layers[z].set_cell(
|
|
Vector2i(tile_x, tile_y),
|
|
IsometricMapSystem.MAIN_SOURCE_ID,
|
|
IsometricMapSystem.SELECTED_WHITE_ISOMETRICTILE_ATLAS_POSITION
|
|
)
|
|
tile["selected"] = true
|
|
|
|
# Position a unit on the map visually
|
|
func position_unit(unit, tile_x, tile_y, tile_z):
|
|
var world_pos = IsometricMapSystem.iso_to_world(
|
|
tile_x,
|
|
tile_y,
|
|
tile_z,
|
|
TILE_SIZE_ISOMETRIC_X,
|
|
TILE_SIZE_ISOMETRIC_Y
|
|
)
|
|
|
|
unit.z_index = tile_z
|
|
# Assuming unit has a set_unit_position method to handle actual positioning
|
|
if unit.has_method("set_unit_position"):
|
|
unit.set_unit_position(world_pos.x, world_pos.y, tile_z)
|