ChessBuilder/Systems/Game/Map/DotPatternGenerator.gd
2025-03-04 12:07:14 -06:00

108 lines
3.4 KiB
GDScript

extends Control
class_name DotPatternGenerator
# Dot pattern settings
const DOT_SPACING = 30
const DOT_SIZE = 2
const DOT_COLOR = Color(0.3, 0.3, 0.3, 0.5)
const PATH_DOT_COLOR = Color(0.4, 0.4, 0.6, 0.8)
const PATH_DOT_SIZE = 3
const HIGHLIGHT_RADIUS = 150
# For path highlights
var map_screen = null
var highlight_dots = false
func _init(highlight: bool = false):
highlight_dots = highlight
# Don't process input
mouse_filter = Control.MOUSE_FILTER_IGNORE
func _ready():
# Apply the pattern
generate_dots()
# Find map screen if we're highlighting paths
if highlight_dots:
map_screen = find_map_screen()
func find_map_screen():
var parent = get_parent()
while parent != null:
if parent is MapScreen:
return parent
parent = parent.get_parent()
return null
func generate_dots():
# Clear existing dots
for child in get_children():
child.queue_free()
# Get the size of this control
var control_size = size
# Calculate how many dots we need
var cols = int(control_size.x / DOT_SPACING) + 1
var rows = int(control_size.y / DOT_SPACING) + 1
# Create dots
for i in range(rows):
for j in range(cols):
var dot_position = Vector2(j * DOT_SPACING, i * DOT_SPACING)
var on_path = false
# If highlighting, check if dot is near a path
if highlight_dots and map_screen != null:
on_path = is_near_path(dot_position)
# Create the dot with appropriate style
var dot = ColorRect.new()
dot.size = Vector2(DOT_SIZE, DOT_SIZE) if not on_path else Vector2(PATH_DOT_SIZE, PATH_DOT_SIZE)
dot.color = DOT_COLOR if not on_path else PATH_DOT_COLOR
dot.position = dot_position - (dot.size / 2)
add_child(dot)
func is_near_path(position: Vector2) -> bool:
# If no map screen, can't check paths
if map_screen == null:
return false
# Get connections from map screen
for line in map_screen.connection_lines:
if line.get_point_count() < 2:
continue
# Check distance to line segment
var start = line.get_point_position(0)
var end = line.get_point_position(1)
# Adjust for potential offset in the map container
start += map_screen.map_container.position
end += map_screen.map_container.position
# Check if point is near the line
var distance = distance_to_line_segment(position, start, end)
if distance < HIGHLIGHT_RADIUS:
return true
return false
# Calculate distance from point to line segment
func distance_to_line_segment(point: Vector2, line_start: Vector2, line_end: Vector2) -> float:
var line_vec = line_end - line_start
var point_vec = point - line_start
var line_length_squared = line_vec.length_squared()
if line_length_squared == 0:
return point_vec.length() # Line segment is a point
# Calculate projection of point onto line
var t = max(0, min(1, point_vec.dot(line_vec) / line_length_squared))
var projection = line_start + t * line_vec
# Return distance from point to projection
return (point - projection).length()
func update_dots():
if highlight_dots and map_screen != null:
generate_dots()