kallanreed [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=58907 Disco Mouse <h1>Disco Mouse</h1> <p> <table><tr><td> <a href="/bbs/?pid=103123#p"> <img src="/bbs/thumbs/pico8_disco_mouse-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=103123#p"> disco_mouse</a><br><br> by <a href="/bbs/?uid=58907"> kallanreed</a> <br><br><br> <a href="/bbs/?pid=103123#p"> [Click to Play]</a> </td></tr></table> </p> <p>I loved the Rodent's Revenge game from Windows 3.1 so I wanted a PICO-8 demake.<br /> I'm not really sure where the disco idea came from, but Moskau is a perfectly ridiculous song.</p> <img style="margin-bottom:16px" border=0 src="/media/58907/mouse_0.gif" alt="" /> <h2>Features</h2> <ul> <li>Disco Music (that you can turn off)</li> <li>Cheese</li> <li>12 Levels</li> <li>Beat-synchronized Cats</li> <li>Teeny Tiny Sprites</li> <li>Challenging Gameplay</li> </ul> <h2>How to Play</h2> <p>Push gray block. Red blocks don't move.<br /> Trap cats in blocks and they'll turn into cheese.<br /> Cats are sneaky and can move diagonally.<br /> Collect cheese before the level timer is up.<br /> If you fall in a hole, you're stuck for 10 seconds.<br /> If you touch a mouse trap, you'll lose a life.</p> <p>Beat the high score and post your screenshot.</p> <p> <table><tr><td width=32> <img src="https://www.lexaloffle.com/bbs/gfxc/58907_0.png" width=32 height=32> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_58907_0"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/58907_0.txt", function (retdata){ var el = document.getElementById("gfxcode_58907_0"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [8x8]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_58907_0" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> </p> https://www.lexaloffle.com/bbs/?tid=45757 https://www.lexaloffle.com/bbs/?tid=45757 Sun, 19 Dec 2021 18:29:57 UTC Disco Mouse WIP <p> <table><tr><td> <a href="/bbs/?pid=103123#p"> <img src="/bbs/thumbs/pico8_disco_mouse-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=103123#p"> disco_mouse</a><br><br> by <a href="/bbs/?uid=58907"> kallanreed</a> <br><br><br> <a href="/bbs/?pid=103123#p"> [Click to Play]</a> </td></tr></table> </p> <p>I've published the cart here: <a href="https://www.lexaloffle.com/bbs/?tid=45757">https://www.lexaloffle.com/bbs/?tid=45757</a></p> https://www.lexaloffle.com/bbs/?tid=45355 https://www.lexaloffle.com/bbs/?tid=45355 Mon, 15 Nov 2021 04:49:30 UTC tline sprite rotation demo/mini-tutorial <p>I was only able to find a few examples of rotating sprites using tlines on the forums. While the code worked, I couldn't really make sense of all the variables and magic numbers.</p> <p>After spending quite a lot of time reading, debugging, and sketching hundreds of triangle, I think I have a decent understanding of the math and how it works. <a href="https://en.wikipedia.org/wiki/Mnemonics_in_trigonometry">SOH-CAH-TOA</a> haunts my dreams.<br /> At some point, I'd like to make a more detailed post, but for now, I've written a tile rotating function with a <em>lot</em> of comments.</p> <p>Hopefully it explains the math and the concept well enough that you can modify the code to suit your projects.<br /> This code is intentionally not optimized or minified.</p> <p> <table><tr><td> <a href="/bbs/?pid=99703#p"> <img src="/bbs/thumbs/pico8_tline_rotation_tutorial-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=99703#p"> tline_rotation_tutorial</a><br><br> by <a href="/bbs/?uid=58907"> kallanreed</a> <br><br><br> <a href="/bbs/?pid=99703#p"> [Click to Play]</a> </td></tr></table> </p> <div> <div class=scrollable_with_touch style="width:100%; 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>-- rtile -- draw rotated map tile -- x,y: output will be centered here -- tx,ty: map coords to the -- top,left tile to draw -- ang: rotation angle -- scale: scale factor -- default:1 -- tw,th: tiles to read -- default:1 -- tcxo,tcyo: -- tile center offsets -- in tile units -- default:0 -- nb: leave space around the -- tiles to rotate on the map -- or adjacent tiles may end -- up in the rotated output. function rtile(x,y,tx,ty,ang, scale,tw,th,tcxo,tcyo) local scale,tw,th= scale or 1,tw or 1,th or 1 local tcxo,tcyo= tcxo or 0,tcyo or 0 -- 8 is base tile-&gt;pixel scale scale*=8 -- precalculate a few values -- we need. using -sin because -- pico-8's sin func is inverted. local ca,sa=cos(ang),-sin(ang) -- there are two coordinate -- domains here, the input -- domain is in tile units -- and each tile has a domain -- of [0..1). the output domain -- is in pixels. we'll use &quot;t&quot; -- and &quot;p&quot; prefixes. -- what we're doing here -- is reading the source tile -- as a bunch of slices that -- stack up to form a square. -- we rotate that &quot;reading&quot; -- square and it changes how -- the input is read. the -- way we do this is with a -- rotation matrix that we -- apply to each point along -- one side of the &quot;read&quot; -- square. -- we need to know the center -- of the square for computing -- rotations. apply the center -- offsets here. -- tile center coords local tcx,tcy= tx+tcxo+tw/2,ty+tcyo+th/2 -- we're going to read the tile -- in a rotating square. if we -- use radius=tw/2, the corners -- will be clipped. we need the -- length from center to corner -- to use as the radius. we -- need to find the larger -- of the two radii to ensure -- the output fits. -- todo: make more efficient. -- tile radius local trad=max( sqrt((tx-tcx)^2+(ty-tcy)^2), sqrt((tx+tw-tcx)^2+(ty+th-tcy)^2)) -- to output the texture we -- draw a bunch of horizontal -- tlines. think of it as -- drawing scan lines on a -- display. using the p -- prefix to indicate &quot;pixel&quot;. -- in order for the output to -- be the correct scale and -- not clip, we need to have -- a output space which can -- hold the rotated output. -- scale trad by 'scale' to -- get a pixel radius that -- will hold everything we -- need to draw. -- pixel radius local prad=scale*trad -- line scale is the ratio -- of read len/write len. -- this just makes a few -- calculations clearer. local lns=1/scale -- remember there are two domains. -- as we draw the output lines -- 0 to 2*prad, we increment -- from 0 to 2*trad proportionally. -- for every 1 pixel y in the -- output, we increment toffy -- by tstep. -- toffy range is -trad,trad local tstep,toffy=lns,-trad -- we also need to tell tline -- the step of the read lines. -- this controls how &quot;far&quot; -- each line reads in the tile -- domain. we want the length -- of the &quot;read&quot; line to be -- scaled to the length of an -- output line. local tdx,tdy=ca*lns,sa*lns -- now lets actually rotate the -- &quot;read&quot; lines. here's the formula. -- [cos, -sin][tx] -- [sin, cos][ty] -- because tx is not varied in -- the draw loop, we can pre- -- compute some values here. -- -trad is the &quot;left&quot; side -- of the read line. it's an -- x offset from the tile center. local costx=ca*-trad local sintx=sa*-trad -- visualize the output space. rect(x-prad,y-prad,x+prad,y+prad,5) -- we're going to draw a rect -- line by line, top down. -- because we're centering on -- x and y, add and subtract -- the pixel radius. for poffy=-prad,prad do -- now compute the ty values -- which is just the ty offset local costy=ca*(toffy) local sinty=sa*(toffy) tline( x-prad,y+poffy, x+prad,y+poffy, tcx+costx-sinty, tcy+sintx+costy, tdx,tdy) toffy+=tstep 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>Here's the same code without comments if you just want to copy/paste in your project.</p> <div> <div class=scrollable_with_touch style="width:100%; 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>-- draw rotated map tile -- x,y: output will be centered here -- tx,ty: map coords to the -- top,left tile to draw -- ang: rotation angle -- scale: scale factor -- default:1 -- tw,th: tiles to read -- default:1 -- tcxo,tcyo: -- tile center offsets -- in tile units -- default:0 function rtile(x,y,tx,ty,ang, scale,tw,th,tcxo,tcyo) local scale,tw,th= scale or 1,tw or 1,th or 1 local tcxo,tcyo= tcxo or 0,tcyo or 0 scale*=8 local ca,sa=cos(ang),-sin(ang) local tcx,tcy= tx+tcxo+tw/2,ty+tcyo+th/2 local trad=max( sqrt((tx-tcx)^2+(ty-tcy)^2), sqrt((tx+tw-tcx)^2+(ty+th-tcy)^2)) local prad=scale*trad local lns=1/scale local tstep,toffy=lns,-trad local tdx,tdy=ca*lns,sa*lns local costx=ca*-trad local sintx=sa*-trad for poffy=-prad,prad do local costy=ca*(toffy) local sinty=sa*(toffy) tline( x-prad,y+poffy, x+prad,y+poffy, tcx+costx-sinty, tcy+sintx+costy, tdx,tdy) toffy+=tstep 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=45269 https://www.lexaloffle.com/bbs/?tid=45269 Sat, 06 Nov 2021 20:47:00 UTC Bubble Trouble <p> <table><tr><td> <a href="/bbs/?pid=99324#p"> <img src="/bbs/thumbs/pico8_bubble_trouble-7.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=99324#p"> Bubble Trouble</a><br><br> by <a href="/bbs/?uid=58907"> kallanreed</a> <br><br><br> <a href="/bbs/?pid=99324#p"> [Click to Play]</a> </td></tr></table> </p> <p>Bubble Trouble is a homage to <a href="https://en.wikipedia.org/wiki/Frozen_Bubble">Frozen Bubble</a> and <a href="https://en.wikipedia.org/wiki/Puzzle_Bobble">Puzzle Bobble</a>.<br /> Frozen Bubble got me though some long lectures in college so I thought it would be a perfect game for PICO-8. Now it can get me though some long meetings instead.</p> <img style="margin-bottom:16px" border=0 src="/media/58907/bubbles_1.gif" alt="" /> <h2>Features</h2> <ul> <li>20 hand-crafted levels</li> <li>Randomly generated levels</li> <li>Precision aiming</li> <li>One-Handed mode (on the pause menu)</li> <li>Bubbles</li> <li>A penguin with a bubble cannon</li> <li>Epic sprite rotation</li> <li>Music that loops (but not every 6 seconds)</li> <li>Explosions</li> </ul> <p>I hope you enjoy!<br /> <table><tr><td width=0> <img src="https://www.lexaloffle.com/bbs/gfxc/58907_1.png" width=0 height=0> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_58907_1"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/58907_1.txt", function (retdata){ var el = document.getElementById("gfxcode_58907_1"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [0x0]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_58907_1" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> </p> https://www.lexaloffle.com/bbs/?tid=45177 https://www.lexaloffle.com/bbs/?tid=45177 Fri, 29 Oct 2021 17:50:22 UTC Grave Matters <p> <table><tr><td> <a href="/bbs/?pid=99144#p"> <img src="/bbs/thumbs/pico8_grave_matters-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=99144#p"> Grave Matters</a><br><br> by <a href="/bbs/?uid=58907"> kallanreed</a> <br><br><br> <a href="/bbs/?pid=99144#p"> [Click to Play]</a> </td></tr></table> </p> <h1>Grave Matters</h1> <p>I'm proud to release my first PICO-8 game just in time for Halloween.</p> <img style="margin-bottom:16px" border=0 src="/media/58907/grave_matters_0.gif" alt="" /> <img style="margin-bottom:16px" border=0 src="/media/58907/grave_0.gif" alt="" /> <p>It's a short adventure platformer with spooky music inspired by Beethoven and Andrew Gold.</p> <p>Enter into a graveyard full of spiders and bats.<br /> Help a ghost find its lost gem and witch brew her potions.</p> <p>If you're having trouble with the bats, select &quot;Easy Mode&quot; from the pause menu.</p> <p>Happy Halloween! <table><tr><td width=32> <img src="https://www.lexaloffle.com/bbs/gfxc/58907_0.png" width=32 height=32> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_58907_0"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/58907_0.txt", function (retdata){ var el = document.getElementById("gfxcode_58907_0"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [8x8]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_58907_0" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> </p> <p>Updates:</p> <ul> <li>Add menu option to show the game timer.</li> </ul> https://www.lexaloffle.com/bbs/?tid=45134 https://www.lexaloffle.com/bbs/?tid=45134 Tue, 26 Oct 2021 01:44:28 UTC Generic method dispatch <p>I wrote a blog post about making a generic method dispatch helper for 'foreach'.<br /> It's more of a novelty than something really worth adding to code. It's better to just use 'for x in all(XS)' instead.</p> <p>Here's the mini summary:</p> <div> <div class=scrollable_with_touch style="width:100%; 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>function callm(method, ...) local params={...} return function(o) if type(o)==&quot;table&quot; then local m=o[method] if type(m)==&quot;function&quot; then m(o,unpack(params)) end end end end function _draw() cls() foreach(drawable, callm(&quot;draw&quot;, 11)) 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>Check it out: <a href="https://kallanreed.com/2021/10/17/pico-8-generic-dispatch-with-parameters/">https://kallanreed.com/2021/10/17/pico-8-generic-dispatch-with-parameters/</a></p> https://www.lexaloffle.com/bbs/?tid=45019 https://www.lexaloffle.com/bbs/?tid=45019 Sun, 17 Oct 2021 17:56:06 UTC Conway's Life <p>I'm tying to build GOL on PICO-8, but the per-pixel manipulation is just too slow. Anything more than about 48x48 is unacceptably slow.<br /> Initially I was reading/writing into temporary tables but that was <em>really</em> slow. This approach keeps all the state on the screen and in a sprite so there's about a quarter of the work from the table approach, but it's still slow.</p> <p>I've started another experiment with peek4/poke4 but the coordinate wrapping is a total pain.</p> <p> <table><tr><td> <a href="/bbs/?pid=98583#p"> <img src="/bbs/thumbs/pico8_the_slow_life-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=98583#p"> the_slow_life</a><br><br> by <a href="/bbs/?uid=58907"> kallanreed</a> <br><br><br> <a href="/bbs/?pid=98583#p"> [Click to Play]</a> </td></tr></table> </p> https://www.lexaloffle.com/bbs/?tid=44971 https://www.lexaloffle.com/bbs/?tid=44971 Wed, 13 Oct 2021 15:48:48 UTC Working on my spooky game <p> <table><tr><td> <a href="/bbs/?pid=99144#p"> <img src="/bbs/thumbs/pico8_grave_matters-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=99144#p"> Grave Matters</a><br><br> by <a href="/bbs/?uid=58907"> kallanreed</a> <br><br><br> <a href="/bbs/?pid=99144#p"> [Click to Play]</a> </td></tr></table> </p> <p>My first attempt at a PICO-8 game.<br /> I've never tried anything like this before, so it's been a fun learning experience.</p> <p>This is my spooky side scroller hopefully wrapped up by Halloween.</p> <p>Update 4)</p> <ul> <li>Adding a fade on death as well as some basic palette twiddling to make it look a little nicer.</li> <li>More music because I'm kind of tired of hearing it at this point.</li> <li>Spikes and death! Although the collision detection is going to need some major overhaul.</li> </ul> <p>Update 5)</p> <ul> <li>More interactions</li> <li>Starting enemies</li> <li>More music</li> <li>More map</li> </ul> <p>Update 6)</p> <ul> <li>Bats! Spiders! Spikes!</li> <li>Death!</li> <li>Pixel collision!</li> <li>If you can get the &quot;potion&quot;, you've &quot;won&quot; for now!</li> </ul> <p>Update 7)</p> <ul> <li>Health!</li> <li>End-game and win condition</li> <li>Spooky Scary Music!</li> </ul> <p>Update 8)</p> <ul> <li>Add Easy Mode</li> <li>Calling this one ready for Halloween</li> </ul> <p>Here's the &quot;Release Post&quot; <a href="https://www.lexaloffle.com/bbs/?tid=45134">https://www.lexaloffle.com/bbs/?tid=45134</a></p> https://www.lexaloffle.com/bbs/?tid=44959 https://www.lexaloffle.com/bbs/?tid=44959 Tue, 12 Oct 2021 17:58:11 UTC