Zoom to a certain area of screen

Excellent.   I added a modified example using Dave’s code here: 

https://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2018/08/zoomToUni.zip

Now the active part of the code is less than 50 lines.

Note: There are two copies of main.lua:

  • main.lua - Just the code, all commented out lines removed. (Also removed content group.)
  • main_commented.lua - Code as posted by Dave, showing deltas from my code.

One way to do this would be scaling the necessary display groups in a transition. Just use transition.to to move the group(s) x and y coordinates and increase the scale. Then, if you want to zoom back, you just use another transition to reverse the transition that you just did.

Apologies for the delay in replying.

So… using a transition I would need to set the X/Y anchor points of the display group to match that of the object I want to zoom in on.

The app is a desktop based game running at 1280x800 resolution.  I’ll be honest I haven’t the first clue on how to  calculate the anchor points from the objects position.  Any help would be gratefully appreciated.

To get this work as you want it, you’ll need to nest your content in at least one group which you scale (zoom group), and ensure the content is centered at <0,0> of that group.  Then, you’ll need to offset the ‘zoom group’ to the position on the screen you want the zoomed object to be at.

Question: Is your game a ‘single screen’ game or do you have a game camera that pans?

I ask this because it directly affects the difficulty of making this zooming feature.  Thus it is relevant to the discussion.

A single screen game would be something like asteroids, centipede, space-invaders, …

A camera based panning game would be, any verical- or side-scroller or runner (1942, geometry dash, jetpack joyride, …), any omni-scroller( mario, geometry wars retro evolved, …)

It’s a single screen game.

Which?  Single screen or panning camera?

Also, if you meant, “my game is a single screen game”, do any of the zoom objects/targets come in from off screen or are they always visible?

Haha, you’re fast!  I realised as soon as I posted that answer that I hadn’t actually answered so went back and edited it by which time you had replied again :slight_smile:

Depending on the game options set by the player.  There will sometimes be walls around the edge of the screen to stop anything (players or bullets) leaving the arena.  If the option is set for no walls then anything leaving the screen just wraps around to the opposite side.

I’ve read this page (group programming) a few times and I’m sorry but I just can’t get my head around it.

Hi again.  I’m not ignoring this thread, but I’m having trouble finding the free time to make a mini-demo showing how to do this.

As soon as I have time, I’ll post something.

Not a problem at all Ed.  I know all too well what it’s like.

Probably not exactly what you want, but it should get you started.

https://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2018/08/zoomTo.zip

https://www.youtube.com/watch?v=cyaFN_aPHrc&feature=youtu.be

I had completely forgotten about this thread. In either case, roaminggamer’s solution seems much further thought out than mine was. Nice job!

Oh man!  That’s perfect for what i need.

As soon as I get it implemented I’ll post a quick video of it in action :slight_smile:

@rg  am curious why you used two “camera” groups?  (granted one is called “content”, but it too functions as a camera group) was there a reason for separately panning one, zooming the other?  i thought maybe it was for the different timings, but that aspect “feels” a bit awkward/unintended - so i wasn’t convinced that was why, leaving me curious, cheers

Camera only for doing the scaling.

Content is to contain all objects and allow me to move them at the same time.   Otherwise you need to re-position every object during the ‘zoom too’.  This lets me simply move the content group temporarily so the ‘focus’ object is centered, then scaling works properly and moving the ‘world’ is simple.

Excluding interfaces elements which would be in another group over content, all game groups and objects should go into ‘content’ so that everything works right including physics.  (The bodies won’t scale, but relative positions won’t get goofed.)

i’d pan and zoom with “camera”, leaving “content” alone

How?  I don’t think that would work.  How will you move the objects?  How will you get centered scaling?

If you move a group containing objects so a child object is centered on the screen and try to scale the group, the object won’t seem to scale correctly.  

Please modify my example and share it.  That would be a nicer solution for folks if you can make it work with one group.

PS - Another issue is movement while scaling.  I think this will make the group positioning harder, but again, I’m not sure.  I may have over complicated the solution.

let me find some time, i’ll see if yours can be modified.  in the mean time, i can guarantee that only one camera group is needed to do pan+zoom (for example) or even pan+zoom+rotate (for example) and have no impact on physics (so long as individual content aren’t independently transformed)

with the caveat that if i had written this from scratch it’d look totally different… here’s the minimal changes (look for “DB-” and “DB+”) to the as-written to do single-group camera pan+zoom:

io.output():setvbuf("no") display.setStatusBar(display.HiddenStatusBar) -- ===================================================== --require "ssk2.loadSSK" --\_G.ssk.init( { measure = false } ) --ssk.meters.create\_fps(true) --ssk.meters.create\_mem(true) --ssk.misc.enableScreenshotHelper("s") -- ===================================================== local cx = display.contentCenterX local cy = display.contentCenterY local fullw = display.actualContentWidth local fullh = display.actualContentHeight local left = cx - fullw/2 local right = cx + fullw/2 local top = cy - fullh/2 local bottom = cy + fullh/2 -- == Uncomment following lines if you need physics --local physics = require "physics" --physics.start() --physics.setGravity(0,10) --physics.setDrawMode("hybrid") -- == Uncomment following line if you need widget library --local widget = require "widget" -- ===================================================== local back = display.newImageRect( "protoBackX.png", 720, 1386 ) back.x = display.contentCenterX back.y = display.contentCenterY if( display.contentWidth \> display.contentHeight ) then back.rotation = 90 end -- ===================================================== local camera = display.newGroup() local content = display.newGroup() camera:insert( content ) --DB- camera.x = cx --DB- camera.y = cy --DB- content.x = -cx --DB- content.y = -cy --DB- content.x0 = content.x --DB- content.y0 = content.y local canExplode = true local explodeObject local zoomTo local revertCamera zoomTo = function ( obj, time ) local zz = 3 --DB+ local zx, zy = cx-obj.x\*zz, cy-obj.y\*zz --DB+ transition.to( camera, { time=time, x=zx, y=zy, xScale=zz, yScale=zz }) --DB+ --DB- transition.to( content, { x = content.x0 + cx - obj.x, --DB- y = content.y0 + cy - obj.y, --DB- time = time / 4 } ) --DB- transition.to( camera, { xScale = 3,yScale = 3, time = time } ) end revertCamera = function( time ) local function onComplete() canExplode = true end transition.to( camera, { time=time, x=0, y=0, xScale=1, yScale=1, onComplete=onComplete }) --DB+ --DB- transition.to( content, { x = content.x0, y = content.y0, time = time } ) --DB- transition.to( camera, { xScale = 1, yScale = 1, --DB- delay = time, time = time/2, onComplete = onComplete } ) end explodeObject = function( obj ) if( not canExplode ) then return end canExplode = false zoomTo( obj, 1500 ) local function onComplete() display.remove(obj) revertCamera( 500 ) end transition.to( obj, { delay = 1500, rotation = 360 \* 4, alpha = 0, time = 2000, onComplete = onComplete } ) end local function onTouch( self, event ) if( event.phase == "ended") then self:removeEventListener('touch') explodeObject( self ) end return true end for i = 1, 10 do local tmp = display.newRect( content, left + math.random( 40, fullw - 40), top + math.random( 40, fullh - 40), 40, 40 ) tmp.touch = onTouch tmp:addEventListener("touch") end