ludic/packages/ludic.minimap/view.ludic
Orkuncakilkaya 19fcf60599 wip(0.S3): packages and examples migrated again from their pre-0.S sources in one run
ludic migrate state packages <every example program> packages/ludic.lab/example/plate.ludic
  1804 vars into 126 states, 64 into lets; 23498 edits in 460 files

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 15:31:34 +03:00

70 lines
4 KiB
Text

# view.ludic - the window onto the map: a square of `size` pixels at (x0, y0) showing `span` metres
# across at zoom 1, centred on a world point. World to window and back, and a scale bar's length.
# metres across the window at zoom 1, the zoom's range, and how close a focus goes at least
export function minimap_config_view(minimap_st: mut MinimapState, span: float, zoom_min: float, zoom_max: float, focus: float) -> void {
minimap_st.mm_span = Math.max(span, 1.0)
minimap_st.mm_zoom_min = zoom_min
minimap_st.mm_zoom_max = Math.max(zoom_max, zoom_min)
minimap_st.mm_zoom_focus = focus
minimap_st.mm_zoom = Math.clamp(1.0, minimap_st.mm_zoom_min, minimap_st.mm_zoom_max)
minimap_st.mm_have_view = false
}
# where the window is on the screen this frame
export function minimap_window(minimap_st: mut MinimapState, x0: float, y0: float, size: float) -> void {
minimap_st.mm_x0 = x0
minimap_st.mm_y0 = y0
minimap_st.mm_size = Math.max(size, 1.0)
}
export function minimap_size(minimap_st: MinimapState) -> float { return minimap_st.mm_size }
export function minimap_zoom(minimap_st: MinimapState) -> float { return minimap_st.mm_zoom }
export function minimap_view_x(minimap_st: MinimapState) -> float { return minimap_st.mm_vx }
export function minimap_view_z(minimap_st: MinimapState) -> float { return minimap_st.mm_vz }
export function minimap_have_view(minimap_st: MinimapState) -> bool { return minimap_st.mm_have_view }
# the metres the window shows across at the zoom
export function minimap_span(minimap_st: MinimapState) -> float { return minimap_st.mm_span / minimap_st.mm_zoom }
# pixels per metre
export function minimap_scale(minimap_st: MinimapState) -> float { return minimap_st.mm_size / minimap_span(minimap_st) }
# a world point on the screen
export function minimap_px(minimap_st: MinimapState, x: float) -> float { return minimap_st.mm_x0 + minimap_st.mm_size * 0.5 + (x - minimap_st.mm_vx) * minimap_scale(minimap_st) }
export function minimap_py(minimap_st: MinimapState, z: float) -> float { return minimap_st.mm_y0 + minimap_st.mm_size * 0.5 + (z - minimap_st.mm_vz) * minimap_scale(minimap_st) }
# the world under a point of the window (pixels from its corner)
export function minimap_wx(minimap_st: MinimapState, rx: float) -> float { return minimap_st.mm_vx + (rx - minimap_st.mm_size * 0.5) / minimap_scale(minimap_st) }
export function minimap_wz(minimap_st: MinimapState, ry: float) -> float { return minimap_st.mm_vz + (ry - minimap_st.mm_size * 0.5) / minimap_scale(minimap_st) }
# a round distance whose bar is no wider than a quarter of the window
export function minimap_scale_metres(minimap_st: MinimapState) -> int {
let steps = [2000, 1000, 500, 250, 100, 50, 25]
for k in 0 .. len(steps) { if float(steps[k]) * minimap_scale(minimap_st) <= minimap_st.mm_size / 4.0 { return steps[k] } }
return 25
}
# the view's centre is kept where MinimapWorld allows, so the land can reach the edge but not leave
export function minimap_clamp(minimap_st: mut MinimapState) -> void {
minimap_st.mm_vx = Math.clamp(minimap_st.mm_vx, MinimapWorld.lo_x(), MinimapWorld.hi_x())
minimap_st.mm_vz = Math.clamp(minimap_st.mm_vz, MinimapWorld.lo_z(), MinimapWorld.hi_z())
}
export function minimap_centre(minimap_st: mut MinimapState, x: float, z: float) -> void {
minimap_st.mm_vx = x
minimap_st.mm_vz = z
minimap_st.mm_have_view = true
minimap_clamp(minimap_st)
}
# the view on the camp, or on you
export function minimap_recentre(minimap_st: mut MinimapState, on_you: bool) -> void {
if on_you { minimap_centre(minimap_st, MinimapWorld.you_x(), MinimapWorld.you_z()) } else { minimap_centre(minimap_st, MinimapWorld.camp_x(), MinimapWorld.camp_z()) }
}
# go there AND close in; never out, since a player already closer asked for that
export function minimap_focus(minimap_st: mut MinimapState, on_you: bool) -> void {
minimap_recentre(minimap_st, on_you)
if minimap_st.mm_zoom < minimap_st.mm_zoom_focus { minimap_st.mm_zoom = Math.clamp(minimap_st.mm_zoom_focus, minimap_st.mm_zoom_min, minimap_st.mm_zoom_max) }
}