does anybody have a good rspr(n, x, y, w, h, r, ox, oy, flipx, flipy) function to draw rotated sprites?
I need this to make my 4 player spaceship battle game.
See these previous discussions:
https://www.lexaloffle.com/bbs/?tid=2189
https://www.lexaloffle.com/bbs/?tid=3936
And maybe useful:
https://www.lexaloffle.com/bbs/?tid=2592
https://www.lexaloffle.com/bbs/?tid=31106
See the ‘Gyrus’ demo cart in this thread:
https://www.lexaloffle.com/bbs/?tid=3593
You’ll find a rspr function that is fast and pixel perfect :)
@dddaaannn
the first one u linked doesn't seem to be in a function and I can't read it well enough to put it in one to try it out
the second one you linked doesn't fit what I need and when I tried to fix it it doesn't draw right
@freds72 u mean this one?
this uses weird arguments as it doesn't let me specify a height
function rspr(sx,sy,x,y,a,w) local ca,sa=cos(a),sin(a) local srcx,srcy,addr,pixel_pair local ddx0,ddy0=ca,sa local mask=shl(0xfff8,(w-1)) w*=4 ca*=w-0.5 sa*=w-0.5 local dx0,dy0=sa-ca+w,-ca-sa+w w=2*w-1 for ix=0,w do srcx,srcy=dx0,dy0 for iy=0,w do if band(bor(srcx,srcy),mask)==0 then local c=sget(sx+srcx,sy+srcy) sset(x+ix,y+iy,c) else sset(x+ix,y+iy,rspr_clear_col) end srcx-=ddy0 srcy+=ddx0 end dx0+=ddx0 dy0+=ddy0 end end |
also if you mean the first one then it doesn't work properly for example putting in 32 for argument s should be tile 0,2 but its not.
EDIT: something like sprr(s,x,y,w,h,r) should work
You can’t put height because I only ever needed to rotate square sprites!
Adding a height should be easy.
Note that this version actually writes to the sprite sheet, replace sset by pset to draw on screen.
As for:
«
EDIT: something like sprr(s,x,y,w,h,r) should work
«
Sorry, that’s Pico-8, either you roll put tour own sprr function or work with what other did.
Don’t expect someone else to do your own code!
ok sorry so I took a try at it from the top of my head and got this...
function sprr(s,x,y,w,h,r) local xr=sin(r/360) local yr=cos(r/360) local sx=flr(s%16) * 8 local sy=flr(s/16) * 8 for yy=sy,sy+h*8-1 do for xx=sx,sx+w*8-1 do local dc=sget(xx,yy) -- this should get the rotated loop position local dx=x+(xx-sx) * xr local dy=y+(yy-sy) * yr pset(x+xx,y+yy, dc) end end end |
however dx and dy is not correct do you know what could be wrong?
To have a clean rotated sprie with no holes, you must go through the target region (eg square ir rectangle) and get the rotated pixel that should be at position. Suggest to read the Dr Dobbs article I took the code from (linked in the post I mention)
I thought thats what I am doing.
I am offsetting the current pixel position by a angle and length.
I did take a look at that dr dobbs page you posted in the other topic though, I really didn't understand it.
@freds72 can you tell me what I am doing wrong with dx and dy?
so here is another attempt to create it..
function sprr(s,x,y,w,h,r) local rx=cos(r/360) local ry=sin(r/360) local sx=flr(s%16) * 8 local sy=flr(s/16) * 8 local ex=sy+h*8-1 local ey=sx+w*8-1 local rr=ry*ry+rx*rx for yy=sy,ey do for xx=sx,ex do local dx=( ry*yy+rx*xx)/rr+w local dy=(-ry*xx+rx*yy)/rr+h local dc=sget(dx,dy) pset(x+xx,y+yy, dc) end end end |
based it on this.. https://www.lexaloffle.com/bbs/?tid=2189
@freds72 so this time I tried my best to follow the dr dobbs tutorial and reference it to yours and I got this..
function sprr(s,x,y,w,h,r) local sx=flr(s % 16) * 8 local sy=flr(s / 16) * 8 local sw=w*8 local sh=h*8 local dx=x local dy=y local dw=w*8 local dh=h*8 local colx = sin(r/360) local coly = cos(r/360) local rowx = coly; local rowy =-colx; local srtu = sx - (dx * coly + dy * colx); local srtv = sy - (dx * rowy + dy * rowx); local rowu = srtu; local rowv = srtv; for y=0, dh do local u = rowu local v = rowv for x=0, dw do local su = ((u < 0.0 and -u or u) + sw) % sw local sv = ((v < 0.0 and -v or v) + sh) % sh pset(dx+x, dy+y, pget(su, sv)) u += rowx v += rowy end rowu += rowx rowv += rowy end end |
can you please take a look at it and tell me whats wrong?
Looks like a plain typo:
pset(..,..,pget(..))
should read:
pset(..,..,sget(..))
(that is read from spritesheet, write on screen)
edit: you are not iterating over the right direction:
u+=rowx
v+=rowy
must be:
u+=colx
v+=coly
Otherwise, looks ok (it’s fine to start with a very verbose version and optimize after)
@freds72 thankyou for the reply.
is there any optimizations I could make besides ingnoring color 0?
also I see your version has a mask so it doesn't draw outside of the source tiles, but I had a hard time understanding it can you explain how to do that in mine?
The fully optimized version is mine ;)
You’re version as a lot of useless variables and intermediate variables that you can rid of.
The mask indicates if the value is above the width/height of the sprite (expressed as a power of 2).
@freds72 I was messing around and I came up with a compact version.
the only problem is that it seems to rotate the src pixels and slows down at certain angles
function sprrt1(s,x,y,w,h,r) local spx=flr(s%16)*8 local spy=flr(s/16)*8 w*=8 h*=8 r=r/360 for iy=0,h do for ix=0,w do local sx=spx+ cos(-r)*ix+sin(-r)*iy local sy=spy+-sin(-r)*ix+cos(-r)*iy local sc=sget(sx,sy) //local bnd=sx<spx or sy<spy or sx>spx+w or sy>spy+h //if sc>0 and not bnd then pset(x+ix,y+iy,sc) end end end |
edit: i wanted it to rotate around center
Sorry @Shadowblitz but I gave the source code for a fast and correct sprite rotating function.
I am not going to redo the same work again for your version.
Hint: do not calculate 4 sin/cos for every single pixel...
can you at least fix your version then so it takes in a height parameter?
this is basically your code but with h implemented and mask taken out because I don't know how to do the mask with h included.
it also has a bug where it rotating the src rectangle.
function sprr(s,x,y,w,h,r) local rx=cos(r/360) local rx=cos(r/360) local ry=sin(r/360) local sx=flr(s % 16) * 8 local sy=flr(s / 16) * 8 local ddx0=rx local ddy0=ry w*=4 h*=4 rx*=w-0.5 ry*=h-0.5 local dx0= ry-rx+w local dy0=-rx-ry+h w=2*w-1 h=2*h-1 for iy=0,h do local srcx = dx0 local srcy = dy0 for ix=0,w do local c=sget(sx+srcx,sy+srcy) pset(x+ix,y+iy,c) srcx -= ddy0 srcy += ddx0 end dx0 += ddx0 dy0 += ddy0 end end |
if your not going to help people adapt your code for something that should have been implemented to begin with, then why did you even post a link to your code in the first place?
@freds72
so what do I do with this function to add a height paramater?
local mask=shl(0xfff8,(w-1)) |
you cannot unless you have 2 masks (which defeats the point).
So just check if source pixel is outside boundaries (0,0,w,h) and you should be good.
how would I add a rotation offset to the function?
function rspr(n,x,y,w,h,a,ax,ay) print(a,64,64,7) ax=ax or 0 ay=ay or 0 a = flr(a/22.5)*22.5 local sx,sy=flr(n%16)*8,flr(n/16)*8 local ca,sa=cos(a/360),sin(a/360) local srcx,srcy,addr,pixel_pair local ddx0,ddy0=ca,sa local mask=shl(0xfff8,(w-1)) w*=4 h*=4 ca*=w-0.5 sa*=h-0.5 local dx0,dy0=sa-ca+w,-ca-sa+h w=2*w-1 h=2*h-1 for ix=0,w do srcx,srcy=dx0,dy0 for iy=0,h do if contains(srcx,srcy,0,0,w,h) then local c=sget(sx+srcx,sy+srcy) pset(x+ix,y+iy,c) else pset(x+ix,y+iy,rspr_clear_col) end srcx-=ddy0 srcy+=ddx0 end dx0+=ddx0 dy0+=ddy0 end end |
This is done outside of the function - you need to decompose as:
- rotation around center
- translation to rotated position
[Please log in to post a comment]