Made this cart to test some distortion effects for future projects.
A lot of people got interested in a tweet I made with it so I'm posting here in case anyone wants to see the code or use it on a project.
Move with the mouse;
Z/X (O/X) to change size;
Left mouse click to switch effect.
Great job ! I was curious to see if it could be accelerated with some tricks I discovered recently and I get a 14% bonus on first effect. I was happy with this and try to increase radius, but it actually allow +2 before going >100% :'( It costs more token, is difficult to read and allow 2 pixels more on radius :D
It could be accelerated a bit more, using poke2 or poke4 but I didn't try.
for science :
function ef_vac(r) local r=r local rr=r*r for j=-r,r do for i=-r,r,2 do local s=i*i+j*j if s<rr then --vacuum local ss=1+(s/r-2*sqrt(s))/r local px,py=i+x,j+y local sidx= bor(band(shr(i+r,1),0x3f), shl(band(j+r,0x3f),6)) -- sset(i+r,j+r, -- pget( -- flr(px+i*ss), -- flr(py+j*ss) -- ) -- ) -- local c1= -- pget(flr(px+i*ss),flr(py+j*ss)) local of7= bor(band(px+i*ss,0x7f), shl(band(py+j*ss,0x7f),7)) local c1=band(shr( peek(0x6000+of7/2) ,of7%2*4) ,0xf) i+=1 px=i+x s=i*i+j*j ss=1+(s/r-2*sqrt(s))/r -- local c2= -- pget(flr(px+i*ss),flr(py+j*ss)) of7= bor(band(px+i*ss,0x7f), shl(band(py+j*ss,0x7f),7)) local c2=band(shr( peek(0x6000+of7/2) ,of7%2*4),0xf) poke(sidx, bor(shl(c2,4),c1)) -- sset(i+r-1,j+r,c1) -- sset(i+r,j+r,c2) end end end circfill(x,y,r-2,0) sspr(0,0,r*2,r*2,x-r,y-r) end
I think a good approach to make it less cpu intensive would be to mirror the effect in 4 quadrants since most effects are mirrored vertically and horizontally.
Another way could be to make a offset mask and save it on the spr memory, though this one only works if you don't indend to change the effect size/time at runtime.
It really depends on what it will be used for in the game :)
Commentated version of one of the effects:
function ef_mirr(r) --r = radius local rr=r*r --i,j = iterates every pixel in a square that will contain the circle for i=-r,r do for j=-r,r do --s = hypotenuse - it will calculate the distance from the center (0=center; 1=border) --sometimes will use "s=(i*i+j*j)/rr" instead to change s from a linear to a parabolic funtion s=sqrt(i*i+j*j)/r --s<1 will ensure you only draw in the circle and note the entire rectangle if s<1 then --ss is where the magic happens, each effect will distort s into ss using a different function --you can try to experiment other effects by changing how s and ss are calculated --mirror ball ss=-1/s --px and py are the actual pixel coordinates on the screen local px,py=i+x,j+y --sset will draw the effect on the sprite sheet sset(i+r,j+r, --pget will copy a pixel elswhere on the screen draw it inside the circle --you can replace this with "s*16" or "ss*16" to get a rough idea of how the pixel offset affects the final result --in some cases the sine/cosine effect will be used here pget( flr(px+i*ss), flr(py+j*ss) ) ) end end end --draw a black circle to erase the background inside the circle circfill(x,y,r-1,0) --copy the circle from the background to the screen sspr(0,0,r*2,r*2,x-r,y-r) end
[Please log in to post a comment]