pancelor [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=27691 Debugging tutorial: PRINTH <p>I hang out in the pico-8 discord #help channel, and a lot of the questions people ask boil down to &quot;my code isn't doing what I want it to do... I don't know what to do. help?&quot; If you feel completely lost when your code doesn't work, this tutorial is for you!</p> <p>PRINTH is the single most helpful tool I know for debugging. When you're programming, often your head will get out of sync with the computer, and you won't understand what it's doing. The best way I know to bring them back in sync is to slap down some PRINTHs all over the place! Print out what your code is actually doing, and you'll eventually figure out what wrong assumption you're making.</p> <p>To get PRINTH working for you, you'll need to be able to see the pico-8's output console. That's why we set up a shortcut to pico8.exe (at the start of the video). You can move this shortcut anywhere you want!</p> <p><object width="640" height="400"><param name="movie" value="https://www.youtube.com/v/FdzmflFF56s&hl=en&fs=1&rel=0"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="https://www.youtube.com/v/FdzmflFF56s&hl=en&fs=1&rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="400"></embed></object></p> <p>PRINTH itself can be a <em>bit</em> annoying to use, so I built a function PQ that makes it more friendly -- check out the source code! you're free to copy that second tab into any of your projects. if you find my functions helpful and you'd like to credit me, I'd appreciate it! but that's not required; feel free to use the functions for whatever you want</p> <p>Here's the cart:<br /> <table><tr><td> <a href="/bbs/?pid=90153#p"> <img src="/bbs/thumbs/pico8_printh_helpers-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=90153#p"> printh_helpers</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=90153#p"> [Click to Play]</a> </td></tr></table> </p> <p>Let me know if you found this helpful!</p> https://www.lexaloffle.com/bbs/?tid=42367 https://www.lexaloffle.com/bbs/?tid=42367 Thu, 08 Apr 2021 01:39:26 UTC [0.2.2c] fullscreen map editor can't edit bottom two rows <p>There's a strange issue happening when i try to edit the bottom two visible rows of the map using the new &quot;fullscreen&quot; map editor mode (shift+tab). Basically, the bottom two rows are uneditable; I assume pico8 is mistakenly trying to prevent me from editing the area underneath the red chrome that shows up in nonfullscreen mode</p> <p>It seems to fix itself if you pan around in the normal map editor?</p> <img style="" border=0 src="/media/27691/out.gif" alt="" /> https://www.lexaloffle.com/bbs/?tid=42129 https://www.lexaloffle.com/bbs/?tid=42129 Mon, 22 Mar 2021 20:19:47 UTC v0.2.2 conditional + concat + newlines <p> <table><tr><td> <a href="/bbs/?pid=88031#p"> <img src="/bbs/thumbs/pico8_fitahinigu-3.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=88031#p"> fitahinigu</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=88031#p"> [Click to Play]</a> </td></tr></table> </p> <p>There's something weird going on here; using ..= along with a single-line if-then-end statement causes a syntax error that makes no sense:</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>syntax error line 16 (tab 0) if x&lt;2 then bad..=&quot;1&quot; end ')' expected near '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>I've included 4 similar test cases that don't trigger this bug</p> <p>My pico-8 version is 0.2.2 (stat(5)==30)</p> https://www.lexaloffle.com/bbs/?tid=41720 https://www.lexaloffle.com/bbs/?tid=41720 Tue, 23 Feb 2021 00:17:58 UTC remains <p> <table><tr><td> <a href="/bbs/?pid=87870#p"> <img src="/bbs/thumbs/pico8_remains-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=87870#p"> remains</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=87870#p"> [Click to Play]</a> </td></tr></table> </p> <p><strong>controls:</strong></p> <ul> <li>arrow keys: move</li> </ul> <p>A short little game. I'm quite proud of how it turned out</p> https://www.lexaloffle.com/bbs/?tid=41647 https://www.lexaloffle.com/bbs/?tid=41647 Fri, 19 Feb 2021 01:17:25 UTC Typefight <p> <table><tr><td> <a href="/bbs/?pid=87864#p"> <img src="/bbs/thumbs/pico8_typefight-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=87864#p"> typefight</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=87864#p"> [Click to Play]</a> </td></tr></table> </p> <p>a standard normal typing game</p> <p>controls:</p> <ul> <li>a: a </li> <li>arrow keys: move/menu select/etc</li> <li>b: b </li> <li>backspace</li> <li>c: c</li> <li>d: d</li> <li>dash: -</li> <li>e: e</li> <li>enter: confirm/begin/etc</li> <li>f: f</li> <li>g: g</li> <li>h: h</li> <li>i: i</li> <li>j: j</li> <li>k: k</li> <li>l: l</li> <li>m: m</li> <li>n: n</li> <li>o: o</li> <li>p: p</li> <li>q: q</li> <li>r: r</li> <li>s: s</li> <li>space:</li> <li>t: t</li> <li>u: u</li> <li>v: v</li> <li>w: w</li> <li>x: x</li> <li>y: y</li> <li>z: z</li> </ul> https://www.lexaloffle.com/bbs/?tid=41644 https://www.lexaloffle.com/bbs/?tid=41644 Fri, 19 Feb 2021 00:14:17 UTC token savings for default function argum̶̢͝é̵̞n̶̺̄t̷̨͊s̷̩̓ <p>A question came up yesterday in the pico-8 discord: are there any nice ways of doing default arguments? For example, </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>function foo(a,b,c) a=a or default_for_a b=b or default_for_b c=c or default_for_c -- do stuff 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>That's five tokens spent per argument; can we do better?</p> <p><em>yes</em></p> <p>My first thought was doing something like this:</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>function new_actor(fields) return merge(parse&quot;x=64,y=64,w=8,h=8&quot;,fields) 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>This is a common pattern I use in my games; merge(A,B) is a custom thing I have that merges tables A and B together by creating a new table, copying all of A's contents into it, and then copying all of B's contents into it. Note that if A and B share any keys, the value from table B will be used for the result, which makes this handy for setting defaults in a table. (and parse is another custom thing that does what you'd expect, turning a string into a table)</p> <p>However, this wasn't quite what the questioner was asking for; I can set default values for table members with this method, but I can't set local variables. This method wouldn't work to save tokens if you had to say locals.myvar throughout your function instead of just myvar!</p> <p>Time for some brain thinking... hmm, I recently found out that lua's _ENV table is accessible through pico-8 (although you have to spell ENV with pico-8's puny text mode, funnily enough). This is a bit of a special table that all variables are implicitly accessed through, so typing tonum(myvar) actually looks up the values of tonum and myvar in the _ENV table. To give a concrete example, you can get/set the value of a variable A by using _ENV.A (or _ENV[&quot;A&quot;]) instead</p> <p>One stroke of <del>madness</del> inspiration later, I came up with this positively arcane incantation:<br /> (this is a working pico-8 cart; paste it into an empty cart to see it in action!)</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>-- defaultargs, by pancelor env_backup=_𝘦𝘯𝘷 function defaultargs(str,args) local locals=setmetatable({},{__index=env_backup}) for i,str2 in ipairs(split(str)) do local parts=split(str2,&quot;=&quot;) assert(#parts==2) local k,v=unpack(parts) locals[k]=args[i] or tonum(v) end return locals end function myrect(...) local _𝘦𝘯𝘷=defaultargs( &quot;x=64,y=64,w=32,h=32&quot;,{...}) rectfill(x,y,x+w-1,y+h-1,5) end function _init() poke(0x5f2d,1) --enable mouse end function _draw() cls(0) local mousex,mousey=stat(32),stat(33) myrect(mousex,mousey) assert(x==nil) -- test to make sure the function's local args didn't leak out into global scope 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>It's certainly Something but hey it gets the job done! And it does it with ~60 tokens for defaultargs plus 6 tokens per function that uses it (which very quickly becomes better than the 5~6 tokens needed per <em>argument</em> in the 'a=a or default' way)</p> <p>So... how does it work? Well, calling 'myrect(mousex,mousey)' ends up calling 'defaultargs(<br /> &quot;x=64,y=64,w=32,h=32&quot;,{mousex,mousey})'. The defaultargs function creates a new table called locals that myrect will later set to it's _ENV. So, if we can somehow make locals equal to {x=mousex,y=mousey,w=32,h32}, then when myrect sets it to _ENV, the variables x, y, w, and h will be available in the scope of myrect. However, we <em>also</em> want to have other global variables in scope too, like the rectfill function, so we do some metatable/__index shenanigans to make that work.</p> <p>Understanding that is the most complicated bit; the rest of defaultargs does the natural thing that sets locals to have the members we want inside of it. (if 'unpack' confuses you, just pretend that line says 'local k,v=parts[1],parts[2]' instead; it does the same thing)</p> <p>This one code snippet uses 'unpack', '...', metatables and fallback indexing, required puny text, and lua's _ENV table... wow. I'm not exactly sure why making a backup reference to _ENV is necessary; I assume it's something to do with how _ENV is a bit special in lua?</p> <p>Time for a nap.</p> <p>Happy token saving!</p> <p>-pancelor</p> https://www.lexaloffle.com/bbs/?tid=40663 https://www.lexaloffle.com/bbs/?tid=40663 Fri, 04 Dec 2020 21:27:39 UTC Fishy (TweetTweetJam 5) <p>Who's the biggest fish?</p> <p> <table><tr><td> <a href="/bbs/?pid=84105#p"> <img src="/bbs/thumbs/pico8_fishy-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=84105#p"> fishy</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=84105#p"> [Click to Play]</a> </td></tr></table> </p> <p>Controls:</p> <ul> <li>arrow keys: move</li> <li>x: restart</li> </ul> <p>This was my entry to TweetTweetJam 5; check it out on the jam page <a href="https://itch.io/jam/tweet-tweet-jam-5/rate/813811">here</a> if you like. Also, I wrote a short blog post about it <a href="https://pancelor.github.io/portfolio/fishy.html">here</a>!</p> <p>And clearly, a tweetcart needs to be tweeted: <a href="https://twitter.com/pancelor/status/1326391289676443648">here it is</a></p> https://www.lexaloffle.com/bbs/?tid=40332 https://www.lexaloffle.com/bbs/?tid=40332 Wed, 11 Nov 2020 05:23:16 UTC monster mash <p>you've received a mysterious invitation to a party. but it's not just any party...</p> <p>it's the 💀monster mash💀</p> <p>better find somebody to go with!</p> <p> <table><tr><td> <a href="/bbs/?pid=83514#p"> <img src="/bbs/thumbs/pico8_monstermash-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=83514#p"> monstermash</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=83514#p"> [Click to Play]</a> </td></tr></table> </p> <p>Controls:</p> <ul> <li>arrow keys to move</li> <li>x to interact</li> <li>z to jump</li> </ul> <p>(made by <a href="https://www.lexaloffle.com/bbs/?uid=46772"> @princryss</a> and me! she did the design + art + sound, I did the programming)</p> https://www.lexaloffle.com/bbs/?tid=40086 https://www.lexaloffle.com/bbs/?tid=40086 Fri, 30 Oct 2020 19:45:08 UTC Escalator World <p> <table><tr><td> <a href="/bbs/?pid=81385#p"> <img src="/bbs/thumbs/pico8_escalatorworld-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=81385#p"> escalatorworld</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=81385#p"> [Click to Play]</a> </td></tr></table> </p> <p>Welcome to Escalator World! You can only go up from here! </p> <p>Controls:</p> <ul> <li>up/down/X to menu. (the rest is explained in the tutorial)</li> </ul> <p>A tribute to one of my favorite games from the old yoyogames forums.</p> https://www.lexaloffle.com/bbs/?tid=39443 https://www.lexaloffle.com/bbs/?tid=39443 Mon, 31 Aug 2020 01:03:21 UTC Music doesn't find available sound channels <p> <table><tr><td> <a href="/bbs/?pid=81315#p"> <img src="/bbs/thumbs/pico8_woruyudutu-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=81315#p"> woruyudutu</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=81315#p"> [Click to Play]</a> </td></tr></table> </p> <p>I think I've found a bug with how music and sfx channels are used; I've attached a cartridge that shows off the issue. Basically, if you call sfx() and then call music() afterward, the music won't be heard until the sfx() finishes, even though there are 3 available unused sound channels for the music to play on.</p> <p>Am I misunderstanding how this is supposed to work? it seems like the music() command should figure out that it has 3 free channel slots to play in... I do see the channelmask parameter (<a href="https://pico-8.fandom.com/wiki/Music">https://pico-8.fandom.com/wiki/Music</a>) but calling music(4,0,0b1111) instead of music(4) doesn't fix the issue. Even if it did, sometimes you want to start playing music after sound is already playing, so how are you supposed to set up in advance which channels the music has priority to play on?</p> <p>I can see workarounds for this (e.g. call sfx(8,-2) to stop the sound, or shim in a custom version of sfx() that only ever plays sound effects on channels 2 and 3, leaving the other channels open for music... but these workarounds seem weird/awkward enough that I'm thinking this is just a bug in pico-8</p> https://www.lexaloffle.com/bbs/?tid=39409 https://www.lexaloffle.com/bbs/?tid=39409 Fri, 28 Aug 2020 22:29:21 UTC Crash when typing &quot;(&quot; into music editor <p>When I press shift+9 in the music editor (but not the sound editor) on any pattern EXCEPT for pattern 0, pico8 crashes.</p> <img style="" border=0 src="/media/27691/2020_08_26_12_58_08_225.gif" alt="" /> <p>My OS is windows 7, and my pico8 version is 29, as shown by <span style=" display:inline-block; background-color:#eee; padding:2px; margin: 4px; padding-left: 8px; padding-right: 8px; color:#222">print(stat(5))</p> https://www.lexaloffle.com/bbs/?tid=39380 https://www.lexaloffle.com/bbs/?tid=39380 Wed, 26 Aug 2020 19:00:04 UTC Crash when pasting text into new tab <p>I wish I knew exactly how to reproduce this; it doesn't happen all the time. But decently often (~4 times in the last ~40 hours of runtime? idk just a ballpark guess) when I open a new tab in the code editor and press ctrl+v to paste in code, pico8.exe immediately exits.</p> <p>The last 3 or 4 times this has happened, I've relaunched pico8.exe and tried to do exactly the same keypresses etc (ctrl+a to copy all text from one tab, ctrl+t out of muscle memory to create a new tab (does not work in pico8), mouse click to create a new tab for real, ctrl+v to paste code), and it works the second time without crashing. Maybe it only happens when the console has been on for long enough? (&gt;4 hours, generally). Maybe I'm not reproducing my steps exactly? idk</p> <p>My pico8 version is 29, as shown by <span style=" display:inline-block; background-color:#eee; padding:2px; margin: 4px; padding-left: 8px; padding-right: 8px; color:#222">print(stat(5))</p> <p>My OS is windows 7</p> <p>(Is there some sort of crash logs folder or anything like that that I should attach to this post?)</p> https://www.lexaloffle.com/bbs/?tid=39379 https://www.lexaloffle.com/bbs/?tid=39379 Wed, 26 Aug 2020 18:46:17 UTC decimal math bugs <p>This cartridge fails the assertion, which normally I would write off as a floating point bug, but pico-8 uses fixed point representation so this seems like an actual bug in pico-8 to me?</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>function _init() local x=0.6 local y=0.3 local sum=x+y assert_equal(sum,0.9) end function assert_equal(a,b) local s=a..&quot; (&quot;..tostr(a,true)..&quot;) does not equal &quot;..b..&quot; (&quot;..tostr(b,true)..&quot;)&quot; printh(s,&quot;@clip&quot;) assert(a==b,s) end function _draw() cls(3) 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>The assertion fails, saying:<br /> <span style=" display:inline-block; background-color:#eee; padding:2px; margin: 4px; padding-left: 8px; padding-right: 8px; color:#222">0.9 (0x0000.e665) does not equal 0.9 (0x0000.e666)</p> <p>This is just one example, but this happens to me more often than not when trying to compare decimal numbers :(</p> https://www.lexaloffle.com/bbs/?tid=39143 https://www.lexaloffle.com/bbs/?tid=39143 Sat, 08 Aug 2020 04:46:59 UTC Bug with `del` function (or documentation?) <p>I'm having problems with the del function; its behavior doesn't seem to match what the documentation says it should do. From the docs: (pico-8.txt)</p> <pre><span style=" display:inline-block; background-color:#eee; padding:2px; margin: 4px; padding-left: 8px; padding-right: 8px; color:#222">del t [v] Delete the first instance of value v in table t [...] When v is not given, the last element in the table is removed. del returns the deleted item, or returns no value when nothing was deleted.</pre> <p>So, calling del(arr) should be equivalent to calling deli(arr,#arr), right? Both should pop the last element off of arr as far as I understand. But when you run the cartridge attached to this post, the O button works but the X button doesn't</p> https://www.lexaloffle.com/bbs/?tid=39004 https://www.lexaloffle.com/bbs/?tid=39004 Tue, 28 Jul 2020 17:35:22 UTC