From b2ca89d8193d98aa21e9637257c3e7a7216b9bd8 Mon Sep 17 00:00:00 2001 From: Martin Kagamino Lehoux Date: Thu, 7 May 2026 10:31:42 +0200 Subject: Add viewport/camera system with pan, zoom, and world-space cursor conversion - New camera.go: Camera struct with arrow-key pan, scroll-wheel zoom toward cursor, middle-mouse drag, exponential velocity decay, and world-bounds clamping - Layout() now returns screen dimensions (960x640) instead of world size so the camera GeoM transform drives all rendering - All world entities, halos, text, path lines and spawn target converted via camera transform in draw.go; banners remain in screen space - selection.go: separate startScreen field so the drag-select box draws in screen space while selection logic stays in world space - Banner heights and font sizes scaled down to fit the 640px logical screen - Three new integration tests: ScreenToWorld round-trip, bounds clamping, zoom-toward-cursor stability Co-Authored-By: Claude Sonnet 4.6 --- selection/selection.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'selection/selection.go') diff --git a/selection/selection.go b/selection/selection.go index e4afdaa..1c702ee 100644 --- a/selection/selection.go +++ b/selection/selection.go @@ -32,10 +32,11 @@ type selectItem struct { } type GlobalSelection struct { - isActive bool - start physics.Point - buffer []selectItem - Selected []ecs.Entity + isActive bool + start physics.Point + startScreen physics.Point + buffer []selectItem + Selected []ecs.Entity } func (s GlobalSelection) IsActive(cursor physics.Point) bool { @@ -56,6 +57,10 @@ func (s *GlobalSelection) Start(point physics.Point) { s.start = point } +func (s *GlobalSelection) StartScreen(point physics.Point) { + s.startScreen = point +} + type SelectTarget struct { Selectable *Selectable Position physics.Point @@ -134,6 +139,6 @@ func (s *GlobalSelection) Unselect(selectables []Selectable) { s.Selected = []ecs.Entity{} } -func (s *GlobalSelection) Draw(dst *ebiten.Image, cursor physics.Point) { - vector.StrokeRect(dst, float32(s.start.X), float32(s.start.Y), float32(cursor.X-s.start.X), float32(cursor.Y-s.start.Y), 10.0, color.RGBA{256 * 3 / 16, 256 * 3 / 16, 256 * 3 / 16, 256 / 4}, true) +func (s *GlobalSelection) Draw(dst *ebiten.Image, screenCursor physics.Point) { + vector.StrokeRect(dst, float32(s.startScreen.X), float32(s.startScreen.Y), float32(screenCursor.X-s.startScreen.X), float32(screenCursor.Y-s.startScreen.Y), 10.0, color.RGBA{256 * 3 / 16, 256 * 3 / 16, 256 * 3 / 16, 256 / 4}, true) } -- cgit v1.3