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.
Omy ! number 5 is just like a real glass ball. Superb graphics ! Star for you.
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]




