From 37f6177a175f9de4a6831a51fb1eb8ce8c3785f2 Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Mon, 12 Jul 2021 21:20:45 -0700 Subject: [PATCH] Zoom In/Out Feature: WorldIndexAt Fixed WorldIndexAt() translates the pixel below the mouse cursor in screen space (0,0 at top-left corner of the application window) into a world coordinate in the level shown inside the canvas, taking into account the canvas's position on the window and the scroll position. It now translates correctly when zoom In or Out, so the "Abs:" mouse position level in the status bar shows correctly. Zoom features that are still jank: - Scrolling while zoomed in, the chunks to the top/left start unloading too rapidly and outpacing the scroll, eventually level is invisible - Drawing and committing pixels to the image while zoomed in/out is unpredictable where the pixels actually land. - Actors in the level don't move or zoom at all. --- pkg/branding/branding.go | 2 +- pkg/uix/canvas.go | 14 ++++++++++++-- pkg/uix/canvas_present.go | 12 ++++++++---- pkg/uix/canvas_zoom.go | 24 ++++++++++++++++++++---- 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/pkg/branding/branding.go b/pkg/branding/branding.go index 62d8495..dae318e 100644 --- a/pkg/branding/branding.go +++ b/pkg/branding/branding.go @@ -4,7 +4,7 @@ package branding const ( AppName = "Sketchy Maze" Summary = "A drawing-based maze game" - Version = "0.7.1" + Version = "0.7.2" Website = "https://www.sketchymaze.com" Copyright = "2021 Noah Petherbridge" Byline = "a game by Noah Petherbridge." diff --git a/pkg/uix/canvas.go b/pkg/uix/canvas.go index f71cb52..ec47ebf 100644 --- a/pkg/uix/canvas.go +++ b/pkg/uix/canvas.go @@ -299,9 +299,19 @@ func (w *Canvas) WorldIndexAt(screenPixel render.Point) render.Point { // Handle Zoomies if w.Zoom != 0 { - world.X = w.ZoomMultiply(world.X) - world.Y = w.ZoomMultiply(world.Y) + // Zoom Out - logic is 100% correct, do not touch. + // ZoomDivide's logic at time of writing is to: + // return int(float64(v) * divider) + // Where divider is a map of w.Zoom to: + // -2=4 -1=2 0=1 1=0.5 2=0.25 3=0.125 + // The -2 and -1 do the right things (zoom out), zoom + // in was jank. NOW FIXED with the following maps: + // -2=4 -1=2 0=1 1=0.675 2=0.5 3=0.404 + // Values for zoom levels 1 and 3 are jank but works? + world.X = w.ZoomDivide(world.X) + world.Y = w.ZoomDivide(world.Y) } + return world } diff --git a/pkg/uix/canvas_present.go b/pkg/uix/canvas_present.go index fb120b1..699e283 100644 --- a/pkg/uix/canvas_present.go +++ b/pkg/uix/canvas_present.go @@ -38,6 +38,14 @@ func (w *Canvas) Present(e render.Engine, p render.Point) { } } + // Scale the viewport to account for zoom level. + if w.Zoom < 0 { + // Zoomed out (level go tiny) + // TODO: seems unstable as shit on Zoom In. + Viewport.W = w.ZoomDivide(Viewport.W) + Viewport.H = w.ZoomDivide(Viewport.W) + } + // Get the chunks in the viewport and cache their textures. for coord := range w.chunks.IterViewportChunks(Viewport) { if chunk, ok := w.chunks.GetChunk(coord); ok { @@ -143,10 +151,6 @@ func (w *Canvas) Present(e render.Engine, p render.Point) { dst.W = S.W - w.BoxThickness(1) } - if w.Zoom < 0 { - log.Warn("dst: %+v", dst) - } - // When zooming OUT, make sure the source rect is at least the // full size of the chunk texture; otherwise the ZoomMultiplies // above do correctly scale e.g. 128x128 to 64x64, but it only diff --git a/pkg/uix/canvas_zoom.go b/pkg/uix/canvas_zoom.go index 574057b..4768fd6 100644 --- a/pkg/uix/canvas_zoom.go +++ b/pkg/uix/canvas_zoom.go @@ -62,22 +62,38 @@ func (w *Canvas) ZoomMultiply(value int) int { /* ZoomDivide divides an integer by the zoom inversely. + +The algo is: int(float64(value) * divider) + +Where the divider is a map of: + + w.Zoom => divider + -2 => 4 + -1 => 2 + 0 => 1 + 1 => 0.675* + 2 => 0.5 + 3 => 0.404* + +The 0.675 and 0.404 numbers I don't understand but were +discovered the hard way when the 1.5x and 2.5x zoom levels +were coming out jank. Expected to be 0.25 and 0.75. */ func (w *Canvas) ZoomDivide(value int) int { var divider float64 switch w.Zoom { case -2: - divider = 2 + divider = 4 case -1: divider = 2 case 0: divider = 1 case 1: - divider = 0.5 + divider = 0.675 // JANK case 2: - divider = 0.25 + divider = 0.5 // GOOD, 2x (200%) zoom in case 3: - divider = 0.125 + divider = 0.404 // JANK default: divider = 1 }