![](/media/69738/PICO-8_4.gif)
i've tried to make a function that scales and offsets sprites to simulate a camera zoom. The way it works is by pressing z and x will increase or decrease the pixel size, each object has x and y values, and sx and sy which are scaled and offset based on the pixel size value.
in this demo the black cats are based on the x and y values, the blue cats are based on the sx and sy values. The scaled blue cats movement is very jittery, especially when accelerating and decelerating, the non scaled black cats are not jittery.
So I think the controls are changing the x and y values correctly, and there isn't a problem with the camera being out of sync, it must be a problem with getting the sx and sy values from my x and y ones. Looking at it, it is like they are not moving in unison, instead the movement is rippling through the objects one by one.
it is the scale_x and scale_y functions that create the sx and sy, and these functions are called in the 'move' function
Any idea what I am doing wrong?
thanks
![](/gfx/play80.png)
![](/bbs/thumbs/pico8_camerazoom-0.png)
--function to scale and offset --the x co-ordinate when pixel --size is changed function scale_x (x) local newx=x*pixels local offset=newx-x local x1=x+newx-pixels*28 local zero=camera_x+64-pixels*(camera_x+64) x=(zero+newx) return(x) end --function to scale and offset --the y co-ordinate when pixel --size is changed function scale_y (y) local newy=y*pixels local offset=newy-y local y1=y+newy-pixels*28 local zero=camera_y+64-pixels*(camera_y+64) y=(zero+newy) return(y) end --moves all objects --calls boxhit function that --checks colisions function move(obj) if obj==pl then if btn(0) then obj.dx-=obj.acc --move left amount obj.flp=true sound=true end if btn(1) then obj.dx+=obj.acc --move right amount obj.flp=false sound=true end if btn(2) then obj.dy-=obj.acc --move up amount when jump sound=true end if btn(3) then obj.dy+=obj.acc --move up amount when jump sound=true end end --reduce vertical movement by gravity each update --obj.dy+=obj.gravity --reduce horizontal movement by friction obj.dx*=obj.friction obj.dy*=obj.friction --limit max speed in all directions obj.dy=mid(-obj.max_dy,obj.dy,obj.max_dy) obj.dx=mid(-obj.max_dx,obj.dx,obj.max_dx) --new locations if movement applied obj.newx=obj.x+obj.dx obj.newy=obj.y+obj.dy --check whether new locations collide with other objects --will adjust newx/newy positions to not overlap collided object for v in all(things) do if obj!=v then --check collision of new vertical -- box_hit(obj,v,"y") obj.y=obj.newy obj.sy=(scale_y(obj.y-obj.h)) end end for v in all(things) do if v!=obj then --check collision of new horizontal -- box_hit(obj,v,"x") obj.x=obj.newx obj.sx=(scale_x(obj.x-obj.w)) end end end function animate(obj) obj.s+=(abs(obj.dx)/3) if obj.s>4 then obj.s=0 end if obj.dx>0 then obj.flp=false elseif obj.dx<0 then obj.flp=true end end function _init() camera_x=0 camera_y=0 --used as camera zoom pixels=1 --create table for objects things={} --make objects function make_thing(x,y ,w,h,clr,g,f,s) thing={ x = x,-- horizontal position y = y,-- vertical position w = w,-- width h = h,-- height dx = 0,-- horizontal movement dy = 0,-- vertical movement sx = x,--scaled/offset to draw sy = y,--scaled/offset to draw max_dx=2, -- max horizontal speed max_dy=2, -- max vertical speed acc=0.5, -- acceleration boost=6, -- boost when jump colour=clr, gravity=g, friction=f, s=s, flp=true } --add object to things table add(things,thing) return thing end --make player pl=make_thing(64,64,4,4,1,0.3, 0.95,64) --make some npcs for i=1,16 do make_thing(flr(64+cos(i/16)*25), 64+(sin(i/16)*25),4,4,i,0.3,1, 64) end end function _update() --move and animate for v in all(things) do move(v) animate(v) end --update camera camera_x=(pl.x-64) camera_y=(pl.y-64) --zoom in and out if btn(4) then pixels=pixels*1.1 end if btn(5) then pixels=pixels*0.9 end end function _draw() cls(7) camera(camera_x,camera_y) --draw sprites based on --sx and sy for v in all(things) do pal() sspr( flr(v.s)*8, 32, 8, 8, (v.x)-v.w, (v.y)-v.h, (v.w*2), (v.h*2), v.flp) pal(1,12) sspr( flr(v.s)*8, 32, 8, 8, (v.sx), (v.sy), ((v.w*2)*pixels), ((v.h*2)*pixels), v.flp) end --border rect(camera_x,camera_y,camera_x+127,camera_y+127,12) rect(camera_x+1,camera_y+1,camera_x+126,camera_y+126,13) end |
![](/gfx/set_like0.png)
![](/gfx/top_drop.png)
![](/media/82211/7_realshadowcaster.png)
Your jitter is due to rounding : when you move the black cats, their coordinates are changed from integers to other integers so no relative movements between the cats.
For the scaled cats, the scaled movement in not an integer, and scaled cats do not cross the integer boundaries at the same time, hence the jitter. It's OK to move all your cats at once by a vector with fractionnal values, but their starting positions at zoom time must all be rounded to the nearest integer (flr(x+0.5) and flr(y+0.5)) To keep the roundings in synch and the circle as round as possible.
EDIT :
another unrelated mistake : your zoom in consists of multiplying by 1.1 or +10%, and the zoom out by multiplying by 0.9 or -10%. Seems right ? It actually isn't, if you zoom in and out, you don't land where you came from :
x 1.1 0.9 = 0.99x
the correct zoom out is to divide by 1.1 (or multiply by 1/1.1)
![](/gfx/set_like0.png)
![](/gfx/top_drop.png)
![](/media/69738/4_Screenshot 2023-10-01 at 11.53.08.png)
thanks, that makes sense, haven't managed to get it to work yet but will keep trying
![](/gfx/set_like0.png)
![](/gfx/top_drop.png)
![](/media/69738/4_Screenshot 2023-10-01 at 11.53.08.png)
I couldn't get it to work by rounding, I think because it still has the problem of movement not being applied to all the cats at the same time, but rather indirectly working out the movement by scaling the black cat's positions.
except for the player, the cats aren't actually moving the camera is, so instead of having a function that scales the cats and then offsets their co-ordinates to match the new scale I moved the offsetting part to the camera function, so the original camera follows the player and moves things in the background accordingly, and the scaled camera moves the scaled cats offset by the scaled amounts.
it is an improvement, it is still jittery but at least they all move in unison, and I think the jitteriness might just be because on a bigger scale slow small movements are going to appear more disjointed. I have made it so that if the speed falls bellow a certain point it stops, and might try update60() so the movements can be smaller at twice the speed which might help.
have added by collide function back in and seems to handle the other cats moving as well.
edit: haven't quite got it right, the scaled down ones are moving too fast
![](/gfx/play80.png)
![](/bbs/thumbs/pico8_camerazoom-1.png)
![](/gfx/set_like0.png)
![](/gfx/top_drop.png)
![](/media/69738/4_Screenshot 2023-10-01 at 11.53.08.png)
didn't notice my last attempt the scaled down was going in wrong direction as well as too fast, getting there with this version
![](/gfx/play80.png)
![](/bbs/thumbs/pico8_camerazoom-2.png)
[Please log in to post a comment]