I made this the other day when just playing around with making an ellipse function for PICO-8 https://twitter.com/eggboycolor/status/949173853045043200 -- but I've decided to post on the BBS.

The core of the effect is a scanline-based ellipse drawing function, based on an algorithm that uses Bresenham style error calculation. The code for the ellipse function is described in a paper called "A Fast Bresenham Algorithm for Drawing Ellipses" by John Kennedy, and I've ported the pseudo-code to work with pico8.

Here's the ellipse function code:

-- based on: -- "a fast bresenham type -- algorithm for drawing -- ellipses" by john kennedy function ellipse( cx,cy,xr,yr,c,hlinefunc ) xr=flr(xr) yr=flr(yr) hlinefunc=hlinefunc or rectfill local xrsq=shr(xr*xr,16) local yrsq=shr(yr*yr,16) local a=2*xrsq local b=2*yrsq local x=xr local y=0 local xc=yrsq*(1-2*xr) local yc=xrsq local err=0 local ex=b*xr local ey=0 while ex>=ey do local dy=cy-y hlinefunc(cx-x,cy-y,cx+x,dy,c) dy+=y*2 hlinefunc(cx-x,dy,cx+x,dy,c) y+=1 ey+=a err+=yc yc+=a if 2*err+xc>0 then x-=1 ex-=b err+=xc xc+=b end end x=0 y=yr xc=yrsq yc=xrsq*(1-2*yr) err=0 ex=0 ey=a*yr while ex<=ey do local dy=cy-y hlinefunc(cx-x,cy-y,cx+x,dy,c) dy+=y*2 hlinefunc(cx-x,dy,cx+x,dy,c) x+=1 ex+=b err+=xc xc+=b if 2*err+yc>0 then y-=1 ey-=a err+=yc yc+=a end end end |

Could probably be optimized further.

The main difference from the original pseudo-code is just that rather than a "plot four ellipse points" function, I made the program a callback for each horizontal line segment to be drawn, and call that function twice for the top and bottom halves of the ellipse. This function defaults to rectfill but could be any function that takes (x, y, x2, y2, color), which is what I do for the wavy effect pictured in my cart. And if you poke certain settings, as you can see, fill patterns can be passed along too -- I guess really, you could interpret color any way you want for your particular scanline fill function.

Oh, also, it shifts the x and y radius down a bunch before squaring to avoid signed 16.16 fixed-point overflow.

And if you're more curious about the wavy effect, feel free to hit the view source (Code) button. I bet there are much cooler effects possible with a scanline based fill algorithm, but I was just trying to throw something together really quick.

Hey, I've just noticed PICO-8 0.2.1 added oval() and ovalfill(). Did you test them and see how it compares to your algorithm?

[Please log in to post a comment]