stepstead-client/scripts/city_map.gd
jts 6a1706051d İlk commit: Stepstead Godot istemci (4.6 Mobile)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 11:31:35 +03:00

155 lines
5.2 KiB
GDScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

extends CanvasLayer
## Şehir haritası — bir şehir location'ının içi. Prosedürel placeholder zemin
## (bina blokları + yollar) üzerinde vendor NPC pinleri. Pine tıkla → dükkan (VendorShop).
## "🗺 Dünya Haritası" ile kapanır. world.gd oluşturur; açıkken world input'u durur.
## Node adı "CityMap".
var _root: Control
var _canvas: Control
var _pins_box: Control
var _title: Label
var _shop: PanelContainer
var _vendors: Array = [] # {npc_id,name,role}
var _pin_pos: Array = [] # Vector2 ekran koordinatları (canvas _draw kullanır)
var _location_name := ""
func _ready() -> void:
name = "CityMap"
layer = 4
visible = false
_build_ui()
func is_open() -> bool:
return visible
func _build_ui() -> void:
_root = Control.new()
_root.set_anchors_preset(Control.PRESET_FULL_RECT)
_root.mouse_filter = Control.MOUSE_FILTER_STOP
add_child(_root)
# Prosedürel zemin (buildings + yollar) — pin konumlarına göre çizilir
_canvas = CityCanvas.new()
_canvas.set_anchors_preset(Control.PRESET_FULL_RECT)
_canvas.mouse_filter = Control.MOUSE_FILTER_IGNORE
_root.add_child(_canvas)
# Pin container (butonlar mutlak konumlu)
_pins_box = Control.new()
_pins_box.set_anchors_preset(Control.PRESET_FULL_RECT)
_pins_box.mouse_filter = Control.MOUSE_FILTER_IGNORE
_root.add_child(_pins_box)
# Üst bar
var bar := PanelContainer.new()
bar.set_anchors_preset(Control.PRESET_TOP_WIDE)
bar.offset_bottom = 64
var sb := StyleBoxFlat.new()
sb.bg_color = Color(0.08, 0.09, 0.12, 0.95)
bar.add_theme_stylebox_override("panel", sb)
_root.add_child(bar)
var hb := HBoxContainer.new()
hb.add_theme_constant_override("separation", 10)
bar.add_child(hb)
var m := MarginContainer.new()
m.add_theme_constant_override("margin_left", 12)
m.add_theme_constant_override("margin_right", 12)
m.add_theme_constant_override("margin_top", 8)
m.add_theme_constant_override("margin_bottom", 8)
m.size_flags_horizontal = Control.SIZE_EXPAND_FILL
hb.add_child(m)
_title = Label.new()
_title.add_theme_font_size_override("font_size", 18)
m.add_child(_title)
var back := Button.new()
back.text = "🗺 Dünya Haritası"
back.pressed.connect(_close)
hb.add_child(back)
# Satıcı dükkanı (alt-sheet) — pinlerin üstünde
_shop = preload("res://scripts/vendor_shop.gd").new()
add_child(_shop)
func open() -> void:
visible = true
_title.text = "🏙 Yükleniyor…"
var res: Dictionary = await GameState.city_vendors()
if not res.ok or not (res.body is Dictionary):
_title.text = "🏙 Şehir yüklenemedi"
_vendors = []
else:
_location_name = str(res.body.get("location_name", "Şehir"))
_vendors = res.body.get("vendors", [])
_title.text = "🏙 %s" % _location_name
_layout_pins()
func _close() -> void:
_shop.visible = false
visible = false
func _layout_pins() -> void:
for c in _pins_box.get_children():
c.queue_free()
_pin_pos.clear()
var size := get_viewport().get_visible_rect().size
var n := _vendors.size()
if n == 0:
_canvas.queue_redraw()
return
# Zikzak yerleşim: üst bar altından alt nav üstüne kadar dağıt
var top := 110.0
var bottom := size.y - 140.0
for i in range(n):
var t := float(i) / float(maxi(1, n - 1)) if n > 1 else 0.5
var y := lerpf(top, bottom, t)
var x := size.x * (0.30 if i % 2 == 0 else 0.68)
var pos := Vector2(x, y)
_pin_pos.append(pos)
_add_pin(_vendors[i], pos)
_canvas.pins = _pin_pos
_canvas.queue_redraw()
func _add_pin(v: Dictionary, pos: Vector2) -> void:
var btn := Button.new()
var role := str(v.get("role", ""))
btn.text = "🏪\n%s" % str(v.get("name", ""))
btn.tooltip_text = role
btn.add_theme_font_size_override("font_size", 13)
btn.custom_minimum_size = Vector2(150, 64)
var sb := StyleBoxFlat.new()
sb.bg_color = Color(0.18, 0.15, 0.10, 0.96)
sb.border_color = Color(0.85, 0.7, 0.35)
sb.set_border_width_all(2)
sb.set_corner_radius_all(8)
btn.add_theme_stylebox_override("normal", sb)
_pins_box.add_child(btn)
btn.size = btn.custom_minimum_size
btn.position = pos - btn.custom_minimum_size / 2.0
var npc_id := int(v.get("npc_id", 0))
var vname := str(v.get("name", ""))
btn.pressed.connect(func() -> void: _shop.open(npc_id, vname))
## Prosedürel şehir zemini — zemin, yollar, pin altı bina blokları.
class CityCanvas extends Control:
var pins: Array = []
func _draw() -> void:
var s := size
# Zemin (toprak/çim degrade hissi)
draw_rect(Rect2(Vector2.ZERO, s), Color(0.16, 0.18, 0.13))
draw_rect(Rect2(Vector2(0, s.y * 0.5), Vector2(s.x, s.y * 0.5)), Color(0.14, 0.15, 0.11))
# Ana yol (dikey)
var road_col := Color(0.30, 0.27, 0.22)
draw_rect(Rect2(Vector2(s.x * 0.5 - 22, 90), Vector2(44, s.y - 220)), road_col)
# Pin altı bina blokları
for p in pins:
var bp: Vector2 = p
draw_line(Vector2(s.x * 0.5, bp.y), bp, road_col, 14.0)
var bsize := Vector2(120, 90)
var top_left := bp - Vector2(bsize.x / 2.0, bsize.y + 20)
draw_rect(Rect2(top_left, bsize), Color(0.28, 0.24, 0.20))
draw_rect(Rect2(top_left, bsize), Color(0.5, 0.42, 0.30), false, 2.0)
var roof := PackedVector2Array([
top_left + Vector2(-8, 0), top_left + Vector2(bsize.x + 8, 0),
top_left + Vector2(bsize.x / 2.0, -34)])
draw_colored_polygon(roof, Color(0.45, 0.22, 0.18))