musurca [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=12772 Minsky Circle outperforms native circ() <p> <table><tr><td> <a href="/bbs/?pid=44528#p"> <img src="/bbs/thumbs/pico44632.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=44528#p"> Minsky Circle Demo</a><br><br> by <a href="/bbs/?uid=12772"> musurca</a> <br><br><br> <a href="/bbs/?pid=44528#p"> [Click to Play]</a> </td></tr></table> </p> <p><strong>EDIT:</strong> <em>updated demo to include huge optimizations contributed by Felice and ultrabrite in the thread below.</em></p> <p>After reading <a href="https://nbickford.wordpress.com/2011/04/03/the-minsky-circle-algorithm/">this fascinating article about the Minsky Circle</a>, I started experimenting with the algorithm in Pico-8. In the process, I stumbled upon a method for rasterizing circles that seems to be faster than the native circ() and circfill() functions at larger sizes, and also has a more pleasing look that minimizes low-resolution aliasing.</p> <p>Demo attached in case anyone finds this useful. Press Z (or whatever key you've bound to button 1) to toggle between the Minsky Circle-based methods and the native Pico-8 draw functions.</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre> --by <a href="https://www.lexaloffle.com/bbs/?uid=12772"> <a href="https://www.lexaloffle.com/bbs/?uid=12772"> @musurca</a></a> and <a href="https://www.lexaloffle.com/bbs/?uid=12874"> <a href="https://www.lexaloffle.com/bbs/?uid=12874"> @Felice</a></a> function minskycirc(x,y,r,c) x,y=x+0.5,y+0.5 local j,k,rat=r,0,1/r poke(0x5f25,c) --set color for i=1,0.785*r do k-=rat*j j+=rat*k pset(x+j,y+k) pset(x+j,y-k) pset(x-j,y+k) pset(x-j,y-k) pset(x+k,y+j) pset(x+k,y-j) pset(x-k,y+j) pset(x-k,y-j) end pset(x,y-r) pset(x,y+r) pset(x-r,y) pset(x+r,y) end --<a href="https://www.lexaloffle.com/bbs/?uid=12772"> <a href="https://www.lexaloffle.com/bbs/?uid=12772"> @musurca</a></a>, <a href="https://www.lexaloffle.com/bbs/?uid=12874"> <a href="https://www.lexaloffle.com/bbs/?uid=12874"> @Felice</a></a>, and <a href="https://www.lexaloffle.com/bbs/?uid=13845"> @ultrabrite</a> function minskycircfill(x,y,r,c) x,y=x+0.5,y+0.5 local j,k,rat=r,0,1/r poke(0x5f25,c) --set color for i=1,r*0.786 do k-=rat*j j+=rat*k rectfill(x+j,y+k,x+j,y-k) rectfill(x-j,y+k,x-j,y-k) rectfill(x-k,y-j,x-k,y+j) rectfill(x+k,y-j,x+k,y+j) end rectfill(x,y-r,x,y+r) end </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> https://www.lexaloffle.com/bbs/?tid=29976 https://www.lexaloffle.com/bbs/?tid=29976 Sun, 24 Sep 2017 07:53:13 UTC It Is What It Is <p> <table><tr><td> <a href="/bbs/?pid=34577#p"> <img src="/bbs/thumbs/pico34620.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=34577#p"> It Is What It Is</a><br><br> by <a href="/bbs/?uid=12772"> musurca</a> <br><br><br> <a href="/bbs/?pid=34577#p"> [Click to Play]</a> </td></tr></table> </p> <p><strong>EDIT: changed the rendering style and improved performance. Happy New Year from a surly talking head!</strong></p> <p>Spend a long night with an uncooperative subject.</p> <p>(Just a quick sketch�thanks to electricgryphon for the <a href="https://www.lexaloffle.com/bbs/?tid=28346">RGB dither-plotter</a>. Head by <a href="http://opengameart.org/users/videroboy">Videroboy</a>.)</p> <p>old version: <div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"><br /> <table><tr><td> <a href="/bbs/?pid=34577#p"> <img src="/bbs/thumbs/pico34576.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=34577#p"> It Is What It Is</a><br><br> by <a href="/bbs/?uid=12772"> musurca</a> <br><br><br> <a href="/bbs/?pid=34577#p"> [Click to Play]</a> </td></tr></table> <br /> </div></div></div></p> https://www.lexaloffle.com/bbs/?tid=28376 https://www.lexaloffle.com/bbs/?tid=28376 Sat, 31 Dec 2016 03:35:23 UTC Trifill Thunderdome <p> <table><tr><td> <a href="/bbs/?pid=34266#p"> <img src="/bbs/thumbs/pico34502.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=34266#p"> Triangle Fill Thunderdome Round 2</a><br><br> by <a href="/bbs/?uid=12772"> musurca</a> <br><br><br> <a href="/bbs/?pid=34266#p"> [Click to Play]</a> </td></tr></table> </p> <p><strong>EDIT3: round 2 -- with updated algorithms, methodology, and results</strong><br /> <strong>EDIT2: added Catatafish's method -- we have a new champion!!</strong><br /> <strong>EDIT: added solar's method.</strong></p> <p><a href="https://www.lexaloffle.com/bbs/?tid=28312">EatMoreCheese's thread</a> about triangle rasterizers got me thinking about the different &quot;trifill&quot; methods that have been posted to the BBS�and so, in the spirit of the holiday season, I wrote a small profiler to pit them against each other in a brutal, winner-takes-all competition.</p> <p>Methodology: I measure the time it takes for each routine to draw the same table of 300 randomly-generated triangles ten times over. Vertex extents are in the range [-50, 178].</p> <p>CAVEATS: This is not an &quot;apples-to-apples&quot; comparison, or even apples-to-genetically-modified-oranges. For example, scgrn's method draws n-gons (not just triangles) and creamdog's method draws particularly chunky triangles. For personal edification only�no code-shaming intended!</p> <p>Results:<div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"><br /> Round 2: electricgryphon retakes the crown with a blistering ~5600 tris/sec, followed by Catatafish in a close second, and leaving musurca and NuSan tied for third (on average).</p> <p>Round 1: Catatafish's method takes first place with an absolutely insane ~0.4 secs, followed by the method from the Gryphon 3D engine in second place at a very stable ~0.8 secs.</p> <p>A lot of interesting discoveries�among them that rectfill() beats rect(), line(), AND memset().<br /> </div></div></div></p> <p>Let me know if you'd like me to change your entry, or add others!</p> <p>See round 1 here:<div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"><br /> <table><tr><td> <a href="/bbs/?pid=34266#p"> <img src="/bbs/thumbs/pico34326.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=34266#p"> Triangle Fill Thunderdome</a><br><br> by <a href="/bbs/?uid=12772"> musurca</a> <br><br><br> <a href="/bbs/?pid=34266#p"> [Click to Play]</a> </td></tr></table> </div></div></div></p> https://www.lexaloffle.com/bbs/?tid=28317 https://www.lexaloffle.com/bbs/?tid=28317 Mon, 26 Dec 2016 21:36:34 UTC PiCAD (vector gfx authoring/display) <p> <table><tr><td> <a href="/bbs/?pid=33832#p"> <img src="/bbs/thumbs/pico34530.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=33832#p"> PiCAD 0.21</a><br><br> by <a href="/bbs/?uid=12772"> musurca</a> <br><br><br> <a href="/bbs/?pid=33832#p"> [Click to Play]</a> </td></tr></table> </p> <p><strong>**UPDATE v0.21: click n' drag support, analog keyboard control, smaller template, and LOTS of bugfixes</strong></p> <p>A vector graphics authoring tool for your Pico8 demos, fonts, adventure games, etc. Draw an image, then save it as a highly compressed string which can be shared with other PiCAD users, or else displayed in your own cartridges without using any space in the spritesheet by including the PiCAD API.</p> <img style="" border=0 src="https://www.lexaloffle.com/bbs/files/12772/PICO-8_0 2.gif" width=256 height=256 alt="" /> <p><strong><span style="text-decoration: underline;">To use your PiCAD images in your own cartridges, start with this template API</span></strong> (click Show to see): <div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"> <table><tr><td> <a href="/bbs/?pid=33832#p"> <img src="/bbs/thumbs/pico34531.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=33832#p"> PiCAD Template 0.21</a><br><br> by <a href="/bbs/?uid=12772"> musurca</a> <br><br><br> <a href="/bbs/?pid=33832#p"> [Click to Play]</a> </td></tr></table> <br /> </div></div></div></p> <p><strong>Features:</strong><br /> -save/load images as compressed strings (saved to picad_string.p8l)<br /> -save to a spritesheet (saved to picad_export.p8)<br /> -paint with a variety of brushes, including pattern/gradient fill, bezier curves, and copy/clone screen rectangles<br /> -unlimited undo<br /> -autosave<br /> -mouse &amp; keyboard support</p> <p><strong>Controls:</strong><br /> ENTER: open save/load menu<br /> x: show/hide UI<br /> tab: undo<br /> q: show/hide guides<br /> s/f: scroll color<br /> e/d: scroll brush</p> <p><strong><em>To load strings into PiCAD, hit ENTER, select &quot;Load...&quot; and paste (Ctrl-V/Apple-V) the string into the Pico8 window. <span style="text-decoration: underline;">This must be done in the actual Pico8 console</span> as the web player does not support reading from the clipboard.</em></strong></p> <p><strong><span style="text-decoration: underline;">Tech info:</span></strong> Rather than raw pixel data, PiCAD images are composed of a series of encoded draw operations�like an assembly language for images�which allows them to be stored as highly compressed strings. The format is inspired by the Sierra AGI &quot;PICTURE&quot; specification. Thanks to <a href="https://www.lexaloffle.com/bbs/?uid=15232"> @dw817</a> for fast floodfill code.</p> <p>(PiCAD is a lot more useful when used inside the actual Pico8 console rather than on the web player, which does not support save/load.)</p> <p><strong>GUIDE TO SETTINGS:</strong><br /> <span style="text-decoration: underline;">Export CLS Cmds</span>: PiCAD strings generally begin with a &quot;clear screen&quot; opcode. That opcode is omitted from string exports when this setting is OFF. ON by default.<br /> <span style="text-decoration: underline;">Continue Lines</span>: When ON, lines and bezier curves can be continued relative to the previous operation, which will produce more efficient strings. OFF by default.<br /> <span style="text-decoration: underline;">Autosave</span>: When ON, saves your work to a string in picad_autosave.p8l after every new brush. OFF by default.<br /> <span style="text-decoration: underline;">Click n' Drag</span>: Turn ON if you're more comfortable with clicking and dragging to place brushes (rather than clicking and releasing for each operation). OFF by default.<br /> <span style="text-decoration: underline;">Analog Keyboard</span>: Simulates an analog joypad when using the keyboard instead of the mouse, which should make using PiCAD more pleasant on the PocketCHIP. ON by default. </p> https://www.lexaloffle.com/bbs/?tid=28272 https://www.lexaloffle.com/bbs/?tid=28272 Wed, 21 Dec 2016 05:00:41 UTC Scale2x/3x implementation <p>Pico-8 implementation of Scale2x and Scale3x. Original algorithms by Andrea Mazzoleni</p> <p>Scale2x:</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre> --[[ sind : sprite index sz_x : x size sz_y : y size sx : screen pos x sy : screen pos y alpha: color to make transparent ]]-- function scale2x(sind,sz_x,sz_y,sx,sy,alpha) alpha=alpha or 0 local offx=sind%16 local offy=flr(sind/16) local soffx=offx*8 local soffy=offy*8 local sizex=sz_x-1 local sizey=sz_y-1 local a,b,c,d,e,f,g,h,i, e0,e1,e2,e3,x0,y0 for y=0,sizey do for x=0,sizex do e=sget(soffx+x,soffy+y) a=e b=e c=e d=e f=e g=e h=e i=e if y&gt;0 then b=sget(soffx+x,soffy+y-1) end if y&lt;sizey then h=sget(soffx+x,soffy+y+1) end if x&gt;0 then d=sget(soffx+x-1,soffy+y) if y&gt;0 then a=sget(soffx+x-1,soffy+y-1) end if y&lt;sizey then g=sget(soffx+x-1,soffy+y+1) end end if x&lt;sizex then f=sget(soffx+x+1,soffy+y) if y&gt;0 then c=sget(soffx+x+1,soffy+y-1) end if y&lt;sizey then i=sget(soffx+x+1,soffy+y+1) end end e0=e e1=e e2=e e3=e if b!=h and d!=f then if(d==b) e0=d if(b==f) e1=f if(d==h) e2=d if(h==f) e3=f end --draw x0=sx+x*2 y0=sy+y*2 if(e0!=alpha) pset(x0, y0, e0) if(e1!=alpha) pset(x0+1,y0, e1) if(e2!=alpha) pset(x0, y0+1,e2) if(e3!=alpha) pset(x0+1,y0+1,e3) end end end </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Scale3x:</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre> --[[ sind : sprite index sz_x : x size sz_y : y size sx : screen pos x sy : screen pos y alpha: color to make transparent ]]-- function scale3x(sind,sz_x,sz_y,sx,sy,alpha) alpha=alpha or 0 local offx=sind%16 local offy=flr(sind/16) local soffx=offx*8 local soffy=offy*8 local sizex=sz_x-1 local sizey=sz_y-1 local a,b,c,d,e,f,g,h,i, e0,e1,e2,e3,e4,e5,e6,e7,e8, x0,y0 for y=0,sizey do for x=0,sizex do e=sget(soffx+x,soffy+y) a=e b=e c=e d=e f=e h=e i=e g=e if y&gt;0 then b=sget(soffx+x,soffy+y-1) end if y&lt;sizey then h=sget(soffx+x,soffy+y+1) end if x&gt;0 then d=sget(soffx+x-1,soffy+y) if y&gt;0 then a=sget(soffx+x-1,soffy+y-1) end if y&lt;sizey then g=sget(soffx+x-1,soffy+y+1) end end if x&lt;sizex then f=sget(soffx+x+1,soffy+y) if y&gt;0 then c=sget(soffx+x+1,soffy+y-1) end if y&lt;sizey then i=sget(soffx+x+1,soffy+y+1) end end e0=e e1=e e2=e e3=e e4=e e5=e e6=e e7=e e8=e if b!=h and d!=f then if(d==b) e0=d if((d==b and e!=c) or (b==f and e!=a)) e1=b if(b==f) e2=f if((d==b and e!=g) or (d==h and e!=a)) e3=d if((b==f and e!=i) or (h==f and e!=c)) e5=f if(d==h) e6=d if((d==h and e!=i) or (h==f and e!=g)) e7=h if(h==f) e8=f end --draw x0=sx+x*3 y0=sy+y*3 if(e0!=alpha) pset(x0, y0, e0) if(e1!=alpha) pset(x0+1,y0, e1) if(e2!=alpha) pset(x0+2,y0, e2) if(e3!=alpha) pset(x0, y0+1,e3) if(e4!=alpha) pset(x0+1,y0+1,e4) if(e5!=alpha) pset(x0+2,y0+1,e5) if(e6!=alpha) pset(x0, y0+2,e6) if(e7!=alpha) pset(x0+1,y0+2,e7) if(e8!=alpha) pset(x0+2,y0+2,e8) end end end </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> https://www.lexaloffle.com/bbs/?tid=3645 https://www.lexaloffle.com/bbs/?tid=3645 Sun, 19 Jun 2016 13:56:46 UTC UI/Mouse Library <p> <table><tr><td> <a href="/bbs/?pid=22582#p"> <img src="/bbs/thumbs/pico22727.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=22582#p"> UI/Mouse Library 0.2</a><br><br> by <a href="/bbs/?uid=12772"> musurca</a> <br><br><br> <a href="/bbs/?pid=22582#p"> [Click to Play]</a> </td></tr></table> </p> <p><strong>UPDATE</strong>: (0.2) Updated the mouse library so that the cursor can be driven by the gamepad OR the mouse at any time, to make the cart compatible with all Pico-8 devices.</p> <p>I'm cobbling together a UI/mouse library for my own use, and thought it might be useful to others. For now the only widget is a button, but I wrote the API so that it's easy to modify and extend (in theory). Will provide more documentation if there's interest.</p> <p>This would be a quick &quot;hello world&quot; with the library, for instance:</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre> --button &quot;onclick&quot; callback function hideme(this) this.visible=false end function _init() --enable the mouse and --set the cursor to a 6x6 sprite --at index 0 mouse_init(0,6,6) --create a new parent UI and --make it the active one mainui = ui_make() ui_setactive(mainui) --make a button labeled &quot;hello, world!&quot; --which calls hideme() when clicked. --It will draw at screen position (30,30). --I could also optionally specify a width and height, --but if I leave it out the button will be sized automatically --based on the length of the label text. btn_make(mainui, &quot;hello, world!&quot;, hideme, 30, 30) end function _update() --update mouse position and do event callbacks --as needed mouse_update() end function _draw() cls() --print mouse position print(mouse.x..&quot; &quot;..mouse.y,0,0,7) -- draw mouse on top of UI ui_draw() mouse_draw() end </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>thanks to gamax92 for uncovering this nifty feature...</p> https://www.lexaloffle.com/bbs/?tid=3574 https://www.lexaloffle.com/bbs/?tid=3574 Fri, 10 Jun 2016 02:25:26 UTC Brush Fire <p> <table><tr><td> <a href="/bbs/?pid=21388#p"> <img src="/bbs/thumbs/pico22146.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=21388#p"> Brush Fire 1.02</a><br><br> by <a href="/bbs/?uid=12772"> musurca</a> <br><br><br> <a href="/bbs/?pid=21388#p"> [Click to Play]</a> </td></tr></table> </p> <p>Wanted to throw something together for p8jam2, so did a spin on the forest-fire cellular automata.</p> <p><strong>Controls</strong><br /> Up/down: adjust probability of new fires<br /> Left/right: adjust probability of tree growth<br /> Button 1: reset probabilities<br /> Button 1+2: reset map</p> <p>(Warning: you could probably give yourself a seizure by cranking up the probabilities to the max.)</p> <p>If you're not familiar with forest-fire, the rules are as follows:<br /> 1) A burning cell will become an empty cell<br /> 2) A tree will start to burn if at least one neighbor is burning<br /> 3) A tree ignites with probability <em>f</em> even if no neighbor is burning<br /> 4) An empty space fills with a tree with probability <em>p</em><br /> (from <a href="https://en.wikipedia.org/wiki/Forest-fire_model">Wikipedia</a>)</p> https://www.lexaloffle.com/bbs/?tid=3455 https://www.lexaloffle.com/bbs/?tid=3455 Thu, 26 May 2016 08:11:51 UTC