pancelor [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=27691 feature request: export -e folders <p>When exporting a game to a binary format (.exe, etc), the <a href="https://www.lexaloffle.com/dl/docs/pico-8_manual.html#Binary_Applications_">manual</a> says:</p> <p>&gt; To include an extra file in the output folders and archives, use the -E switch:</p> <p>&gt; &gt; EXPORT -E README.TXT MYGAME.BIN</p> <p>I tried this (<code>pico8 game.p8 -export &quot;-f game.bin -e examples/ -e samples/&quot;</code>) but it doesn't include those subfolders. If I <code>-e examples/kick.pcm</code>, then that file is included, but it's included at the top level, and not in an &quot;examples&quot; subfolder</p> <p>Am I doing this wrong somehow? I assume this just isn't supported (yet? fingers crossed)</p> https://www.lexaloffle.com/bbs/?tid=47834 https://www.lexaloffle.com/bbs/?tid=47834 Mon, 16 May 2022 22:38:59 UTC im hungry <p> <table><tr><td> <a href="/bbs/?pid=110904#p"> <img src="/bbs/thumbs/pico8_imhungry-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=110904#p"> imhungry</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=110904#p"> [Click to Play]</a> </td></tr></table> </p> <p>&gt; Vous contr&ocirc;lez un petit rennes qui doit attraper le plus de nourriture possible, il s'agit de pain et de m&ucirc;res. Plus vous attrapez de, plus la nourriture va vite et plus il est compliqu&eacute; de l'attraper. En haut &agrave; droite, vous verrez qu'il y a votre tableau de bord, chaque aliment p&ecirc;ch&eacute; vaut un point. Et en haut &agrave; gauche, il y a un panneau qui vous montre combien d'aliments vous n'avez pas attrap&eacute;s. Attention ! au bout d'une dizaine d'aliments non attrap&eacute;s vous perdez et le jeu affiche alors &laquo; GAME OVER ! &raquo;, alors il faut appuyer sur enter pour recommencer.</p> <p>&gt; Les commandes sont : la fl&egrave;che droite pour se d&eacute;placer vers la droite, la fl&egrave;che gauche pour se d&eacute;placer vers la gauche et la fl&egrave;che vers le haut pour sauter. C'est si simple !</p> <p>(for more info, see <a href="https://itch.io/jam/im-hungry">https://itch.io/jam/im-hungry</a> / <a href="https://pancelor.itch.io/im-hungry">https://pancelor.itch.io/im-hungry</a>)</p> https://www.lexaloffle.com/bbs/?tid=47552 https://www.lexaloffle.com/bbs/?tid=47552 Tue, 26 Apr 2022 21:12:05 UTC P8SCII repeat (\*) doesn't work with newline <p>I hit this bug while working on a tweetcart:</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>?&quot;\*6a&quot; -- prints 6 'a's (expected) ?&quot;\*6\&quot;&quot; -- prints 6 quotes (expected) ?&quot;\*6\n&quot; -- prints 1 newline (unexpected!) ?&quot;\n&quot; -- prints 1 newline (expected)</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <img style="" border=0 src="/media/27691/untitled_1.png" alt="" /> https://www.lexaloffle.com/bbs/?tid=47223 https://www.lexaloffle.com/bbs/?tid=47223 Sun, 03 Apr 2022 02:06:44 UTC input buffering in grid-based games <p>here's a demo cart showing off some different ways to handle input in grid-based games:</p> <p> <table><tr><td> <a href="/bbs/?pid=107587#p"> <img src="/bbs/thumbs/pico8_hojohiyomu-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=107587#p"> hojohiyomu</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=107587#p"> [Click to Play]</a> </td></tr></table> </p> <p>controls:</p> <ul> <li>move around with the arrow keys</li> <li>change &quot;chapters&quot; in the pause menu (enter + arrow keys)</li> <li>slow down the game speed (in the later chapters) in the pause menu</li> </ul> <p>I made this cart as a companion to a <a href="https://pancelor.tumblr.com/post/677053912115707904/input-buffering-in-grid-based-games">blog post about input buffering</a></p> https://www.lexaloffle.com/bbs/?tid=46735 https://www.lexaloffle.com/bbs/?tid=46735 Thu, 24 Feb 2022 09:19:19 UTC &quot;unsaved changes&quot; when there are no changes <p><a href="https://www.lexaloffle.com/bbs/?uid=1"> @zep</a> o/</p> <p>A weird bug has been messing with me recently: pico-8 keeps telling me I have &quot;unsaved changes&quot; when I'm <em>pretty</em> sure I don't. I caught the bug on camera this time:</p> <p><object width="640" height="400"><param name="movie" value="https://www.youtube.com/v/AEf0MN_tCUU&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/AEf0MN_tCUU&hl=en&fs=1&rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="400"></embed></object></p> <p>I don't know how to reproduce it; I tried adding a new tab and messing with the text cursor position (since I wondered if this had something to do with the fix for <a href="https://www.lexaloffle.com/bbs/?tid=39379">https://www.lexaloffle.com/bbs/?tid=39379</a> ) and soon after I was able to trigger the bug. But I was able to trigger the bug without even opening up the code editor -- all I did was <code>load cart1</code> <code>load cart2</code> <code>load cart1</code> over and over again until it said &quot;unsaved changes&quot;. strange</p> <p>Jump to 1:12 and 1:24 in the video to see me trigger the bug two separate times. (the video description has a few other timestamps too)</p> <hr /> <p>I'm worried I'll stop trusting that message and accidentally lose real changes!</p> <p>I think this bug is new as of 0.2.4b; I don't remember it happening beforehand.</p> https://www.lexaloffle.com/bbs/?tid=46601 https://www.lexaloffle.com/bbs/?tid=46601 Wed, 16 Feb 2022 05:04:43 UTC La Sal (puzzle-y celeste map mod) <p> <table><tr><td> <a href="/bbs/?pid=105290#p"> <img src="/bbs/thumbs/pico8_lasal-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=105290#p"> lasal</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=105290#p"> [Click to Play]</a> </td></tr></table> </p> <p>A short celeste map mod. It's built as a bit of a puzzle, meant to teach you one specific thing about the game's mechanics.</p> <p>This doesn't require any advanced speedrunning tech (spike clips, corner jumps, etc) -- executing the intended solutions should be possible for anyone who's beaten <a href="https://www.lexaloffle.com/bbs/?tid=2145">celeste classic</a> once or twice.</p> <p>If you're trying something that seems too hard or only barely possible, try looking for alternatives!</p> <h2>controls</h2> <ul> <li>arrow keys / Z / X: move / jump / dash</li> <li>E: toggle screenshake</li> </ul> <h2>credits</h2> <p><a href="https://www.lexaloffle.com/bbs/?tid=2145">celeste classic</a>: maddy thorson + noel berry</p> <p><a href="https://github.com/CelesteClassic/smalleste">smalleste</a>: a token-optimized version of classic celeste that I used as a starting point</p> <p>playtesting: cryss, sharkwithlasers, James, meep</p> <p>berry follow code: meep's <a href="https://www.lexaloffle.com/bbs/?tid=37117">Terra Australis</a></p> <h2>map editor</h2> <p>I made this map to see how my <a href="https://www.lexaloffle.com/bbs/?tid=46225">custom map editor</a> felt to use. I think it's pretty neat -- check it out! It lets you build much larger maps than the built-in pico-8 map editor.</p> <img style="" border=0 src="/media/27691/resize.gif" alt="" /> https://www.lexaloffle.com/bbs/?tid=46224 https://www.lexaloffle.com/bbs/?tid=46224 Wed, 19 Jan 2022 00:23:33 UTC bigmap editor <h2>demo cart</h2> <p> <table><tr><td> <a href="/bbs/?pid=105301#p"> <img src="/bbs/thumbs/pico8_bigmap_demo-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=105301#p"> bigmap_demo</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=105301#p"> [Click to Play]</a> </td></tr></table> </p> <h2>motivation</h2> <p>The recent <a href="https://www.lexaloffle.com/bbs/?tid=45538">0.2.4 release</a> added support for larger maps:</p> <p>&gt; Similar to gfx memory mapping, the map can now be placed at address 0x8000 and above (in increments of 0x100). This gives 4 times as much runtime space as the default map, and an additional POKE is provided to allow customisable map sizes.</p> <p>Larger maps are now possible, but it's difficult to get them into memory -- the built-in map editor only works with vanilla-sized maps.</p> <p>This cart is a full map editor that makes it easy to make these larger maps! </p> <h2>features</h2> <ul> <li>tight iteration loop - play a level in your game, jump into the map editor to make a small tweak, and return to the game with minimal friction <ul> <li> <img style="" border=0 src="/media/27691/iterloop.gif" alt="" /> </li> </ul></li> <li>change map size at any time <ul> <li> <img style="" border=0 src="/media/27691/resize.gif" alt="" /> </li> <li>max width: 256 tiles</li> <li>max height: none</li> <li>max total size: 32K tiles (e.g. 128*256, or 32*1024)</li> </ul></li> <li>easy copy-paste (right mouse + drag to copy, left mouse to paste)</li> <li>zooming in/out</li> <li>large brushes - place multiple tiles at a time</li> <li>show 16x16 &quot;room&quot; outlines (useful for carts like celeste that are made of many 16x16 rooms) <ul> <li> <img style="" border=0 src="/media/27691/outlines.gif" alt="" /> </li> </ul></li> <li>&quot;transparency&quot; - optionally treat sprite 0 in large brushes as &quot;transparent&quot; <ul> <li> <img style="" border=0 src="/media/27691/transparent.gif" alt="" /> </li> </ul></li> <li>compressed maps using <a href="https://www.lexaloffle.com/bbs/?tid=34058">PX9</a></li> <li>autosaving</li> <li>the map editor uses 0 of your tokens -- it's a completely separate cart that you only use during development<br /> (well, it costs ~300 tokens to load the map string and run the decompressor)</li> <li>your game will still be splore-compatible</li> <li>your game can call <code>map()</code>, <code>mget()</code>, <code>tline()</code> etc without any extra work</li> </ul> <h2>undo/redo?</h2> <p>The editor currently has no undo/redo functionality. That's not ideal! I'm hoping to get it working soon.</p> <p>To undo all changes since your last save (probably the end of your last session using bigmap), use the &quot;discard changes&quot; button in the top-right.</p> <p>If you make a large mistake, replace map.p8l with your an autosaved version (inside <code>mygame/autosave/</code>) and reload bigmap.</p> <h2>setup</h2> <p><object width="640" height="400"><param name="movie" value="https://www.youtube.com/v/llBF08wDT_U&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/llBF08wDT_U&hl=en&fs=1&rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="400"></embed></object></p> <p>Setting the bigmap editor up takes a bit of work. This is mainly necessary to enable a tight map iteration loop, and also to work around the restrictions of pico-8 (for example, it's impossible to read a file from disk without user interaction, and asking the user to drag-and-drop their map file every time they wanted to edit is way too much friction for my tastes)</p> <p>To start, make sure you have a folder (e.g. <code>mygame/</code>) with your game cart inside (e.g. <code>mygame/mygame.p8</code>)</p> <ol> <li><code>cd mygame</code> (navigate into the folder containing your game)</li> <li><code>mkdir autosave</code> (create a folder to store backups/autosaves)</li> <li><code>printh(&quot;&quot;,&quot;map.p8l&quot;)</code> (this creates an empty map.p8l file)</li> <li>Save this file (<a href="https://gist.github.com/pancelor/f933286f244c6b85b7720dbe6f809143">https://gist.github.com/pancelor/f933286f244c6b85b7720dbe6f809143</a>) as <code>px9_decomp.lua</code> (inside the <code>mygame/</code> directory)</li> <li><code>load #bigmap</code> (note: this is different from the bigmap_demo cart)</li> <li>Uncomment the two <code>#include</code> lines in the second tab (tab 1)</li> <li><code>save bigmap.p8</code></li> <li> <p>Paste this snippet into <code>mygame.p8</code>: (inside <code>_init()</code>, or at top-level; either works)</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>menuitem(1,&quot;▒ edit map&quot;,function() -- pass spritesheet through upper memory, -- avoiding an extra second of load time local focusx,focusy=0,0 memcpy(0x8000,0x0000,0x2000) poke(0x5500,1,focusx,focusy) --signal load(&quot;bigmap.p8&quot;,&quot;discard changes&quot;,&quot;mygame.p8&quot;) 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>(make sure you change &quot;mygame.p8&quot; to the actual filename of your game)</p> <p>This snippet adds the menu option to enter bigmap while playing your game. If you set <code>focusx</code> and <code>focusy</code>, bigmap will start focused on that map coordinate.</p> </li> <li>Paste this snippet into <code>mygame.p8</code> at top-level: <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>#include map.p8l #include px9_decomp.lua if map_import then map_import() end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div></li> <li><strong>Save <code>mygame.p8</code></strong></li> </ol> <p>You should now be good to go!</p> <h2>test+edit iteration loop</h2> <ol> <li>Save <code>mygame.p8</code>. <strong>any unsaved changes will be lost</strong> every time you launch bigmap. (I wish this was avoidable but I couldn't find a way around it that preserved the quick test+edit loop I wanted)</li> <li>Run <code>mygame.p8</code></li> <li>Pause the game (with P or Enter)</li> <li>Choose &quot;edit map&quot;</li> <li>Edit your map!<br /> <strong>If you accidentally press escape and exit the map editor</strong>, type <code>r</code> or <code>resume</code> into the console to resume the map editor.</li> <li>Return to your game with P, Enter, or the clickable &quot;Play&quot; button in the top-right</li> </ol> <img style="" border=0 src="/media/27691/iterloop.gif" alt="" /> <p>I advise setting up <code>mygame.p8</code> to jump you to the room you were editing when it starts - this can be done by reading the <code>focusx</code> and <code>focusy</code> global variables that are set inside the <code>map_import()</code> function (inside <code>map.p8l</code>)</p> <p>See <a href="https://www.lexaloffle.com/bbs/?tid=46224">my celeste mod</a> or the getting started video for an example of how to do this.</p> <h2>technical details</h2> <p>When you press the save or play button, bigmap uses <code>printh</code> to write a text file called <code>map.p8l</code> into the current directory. This text file happens to be valid lua code that defines a function called <code>map_import()</code>, so when <code>mygame.p8</code> executes <code>#include map.p8l</code> and <code>map_import()</code>, it runs the code generated by bigmap.</p> <p>Here's an example of what map.p8l looks like:</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>-- this file was auto-generated by bigmap.p8 function map_import() focusx=11 focusy=12 mapw=128 maph=64 poke(0x5f56,0x80,mapw) local function vget(x,y) return @(0x8000+x+y*mapw) end local function vset(x,y,v) return poke(0x8000+x+y*mapw,v) end px9_sdecomp(0,0,vget,vset,&quot;◝◝◝ユ◝7な◝◝✽,ゃf\0★)&amp;るちP;](&hearts;KねF ... many many more chars here ... X▤ミヘラ⬇️⬇️Bれん&quot;) 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 has 3 main parts:</p> <ol> <li>Set up some helpful global vars - <code>mapw</code> and <code>maph</code> are the width and height of the map, in tiles. <code>focusx</code> and <code>focusy</code> are the tile coordinate of the tile that was in the center of the screen when <code>map.p8l</code> was saved -- you can use this info to jump directly to that room to let you make small tweaks and test them very quickly</li> <li><code>poke(0x5f56,0x80,mapw)</code> -- this tells pico-8 to use mapdata stored at 0x8000, with map width <code>mapw</code></li> <li>The rest of the function uses PX9 to decompress the binary data stored in that long string. The decompressed data gets stored starting at 0x8000 and takes up <code>mapw*maph</code> bytes.</li> </ol> <p>That compressed data string is created using <a href="https://www.lexaloffle.com/bbs/?tid=34058">PX9</a> and <a href="https://www.lexaloffle.com/bbs/?tid=38692">this snippet</a> for encoding binary data in strings.</p> <h2>links</h2> <p>stuff I used:</p> <ul> <li>PX9, used for compression: <a href="https://www.lexaloffle.com/bbs/?tid=34058">https://www.lexaloffle.com/bbs/?tid=34058</a></li> <li>zep's string-packing snippet: <a href="https://www.lexaloffle.com/bbs/?tid=38692">https://www.lexaloffle.com/bbs/?tid=38692</a></li> <li>sprites used in bigmap_example.p8 (shown in the setup video): FROGBLOCK by Polyducks: <a href="https://polyducks.itch.io/frogblock">https://polyducks.itch.io/frogblock</a></li> </ul> <p>alternative map editors you might consider using instead:</p> <ul> <li><a href="https://www.lexaloffle.com/bbs/?tid=42848">https://www.lexaloffle.com/bbs/?tid=42848</a> -- make larger worlds out of metatiles</li> <li><a href="https://github.com/ExOK/Celeste2/">https://github.com/ExOK/Celeste2/</a> -- you can see in their source code how they make maps in individual carts and then combine+compress them all together into a single cart before release</li> <li><a href="https://github.com/samhocevar/tiled-pico8">https://github.com/samhocevar/tiled-pico8</a> -- use <a href="https://www.mapeditor.org/">Tiled</a> (an external program) to edit vanilla pico-8 maps. consider combining this with the Celeste2 method</li> </ul> <p>other:</p> <ul> <li>a celeste mod I made to make sure that it felt good to use this editor: <a href="https://www.lexaloffle.com/bbs/?tid=46224">https://www.lexaloffle.com/bbs/?tid=46224</a></li> <li>;) my webpage: <a href="https://pancelor.com">https://pancelor.com</a></li> </ul> <h2>happy map editing!</h2> <p>I'd like to see what you make -- let me know if you use this in your projects! And if you want to credit me I'd appreciate it :)</p> <p>Is bigmap helpful? Is it too confusing to set up? Find any bugs? Let me know what you think!</p> https://www.lexaloffle.com/bbs/?tid=46225 https://www.lexaloffle.com/bbs/?tid=46225 Wed, 19 Jan 2022 00:12:53 UTC cpu profiler / cycle counter <h2>what is this?</h2> <p>The <a href="https://pico-8.fandom.com/wiki/CPU">wiki</a> is nice for checking exactly how time-expensive various operations are, but it's a bit out of date. Also, it'd be nice to just be able to directly test two implementations against each other, rather than adding up how long each individual operation takes.</p> <p>The wiki also has a code listing for a <a href="https://pico-8.fandom.com/wiki/CPU_Profiler">cpu profiler</a>, but it's a bit hard to find if you don't know it exists. Plus, it was fun for me to dive in and double-check the math myself.</p> <p>My profiler is pretty similar to the one on the wiki, although IMO mine has a nicer/simpler interface. Additionally, I've commented exactly how the cycle calculation works, which might be useful for other people to see:</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>-- slightly simplified from the version in the cart function profile_one(func) local n = 0x1000 -- n must be larger than 256, or m will overflow assert(n&gt;0x100) -- we want to type -- local m = 0x80_0000/n -- but 8𝘮𝘩z is too large a number to handle in pico-8, -- so we do (0x80_0000&gt;&gt;16)/(n&gt;&gt;16) instead -- (n is always an integer, so n&gt;&gt;16 won't lose any bits) local m = 0x80/(n&gt;&gt;16) local function cycles(t0,t1,t2) return (t0+t2-2*t1)*m/30 end -- given three timestamps (pre-calibration, middle, post-measurement), -- calculate how many more 𝘤𝘱𝘶 cycles func() took compared to nop() -- derivation: -- 𝘵 := ((t2-t1)-(t1-t0))/n (frames) -- this is the extra time for each func call, compared to nop -- this is measured in #-of-frames (at 30fps) -- it will be a small fraction for most ops -- 𝘧 := 1/30 (seconds/frame) -- this is just the framerate that the tests run at, not the framerate of your game -- can get this programmatically with stat(8) if you really wanted to -- 𝘮 := 256*256*128 = 8𝘮𝘩z (cycles/second) -- (𝘱𝘪𝘤𝘰-8 runs at 8𝘮𝘩z; source: https://www.lexaloffle.com/bbs/?tid=37695) -- cycles := 𝘵 frames * 𝘧 seconds/frame * 𝘮 cycles/second -- optimization / working around pico-8's fixed point numbers: -- 𝘵2 := 𝘵*n = (t2-t1)-(t1-t0) -- 𝘮2 := 𝘮/n := m (e.g. when n is 0x1000, m is 0x800) -- cycles := 𝘵2*𝘮2*𝘧 -- calibrate, then measure local nop=function() end -- this must be local, because func is local flip() local atot,asys=stat(1),stat(2) for i=1,n do nop() end local btot,bsys=stat(1),stat(2) for i=1,n do func() end local ctot,csys=stat(1),stat(2) -- report local lua=cycles(atot-asys,btot-bsys,ctot-csys) local sys=cycles(asys,bsys,csys) local tot=lua+sys return { lua=lua, sys=sys, tot=tot, } end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <h2>how do I use it?</h2> <p>You can try it here online, but to really use it you'll want to download it yourself and edit the body of the <code>analyze()</code> function. There are instructions embedded in the cart with more details:</p> <p> <table><tr><td> <a href="/bbs/?pid=104795#p"> <img src="/bbs/thumbs/pico8_cyclecounter-2.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=104795#p"> cyclecounter</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=104795#p"> [Click to Play]</a> </td></tr></table> </p> <h2>misc results</h2> <h3>poke4 v. memcopy</h3> <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> profile(&quot;memcpy &quot;, function() memcpy(0,0x200,64) end) profile(&quot;poke4/poke4&quot;, function() poke4(0,peek4(0x200,16)) 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>&gt; memcpy : 7 +64 = 71 (lua+sys)<br /> &gt; poke4/poke4 : 7 +60 = 67 (lua+sys)</p> <p>Copying 64 bytes of memory is very slightly faster if you use poke4 instead of memcpy -- interesting!<br /> (iirc this is true for other data sizes... find out for yourself for sure by downloading and running the cart!)</p> <p><em>edit: this has changed in <a href="https://www.lexaloffle.com/bbs/?pid=105760">0.2.4b</a>! the memcpy in this example now takes 7 +32 cycles</em></p> <h3>constant folding</h3> <p>I thought lua code was not optimized by the lua compiler/JIT at all, but it turns out there are some very specific optimizations it will do. </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> profile(&quot; +&quot;, function() return 2+2 end) profile(&quot; +++&quot;, function() return 2+2+2+2+2+2+2+2 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>These functions both take a single cycle! That long addition gets optimized by lua, apparently. <a href="https://www.lexaloffle.com/bbs/?uid=24137"> <a href="https://www.lexaloffle.com/bbs/?uid=24137"> @luchak</a></a> found these explanations:</p> <p><a href="https://stackoverflow.com/questions/33991369/does-the-lua-compiler-optimize-local-vars/33995520">https://stackoverflow.com/questions/33991369/does-the-lua-compiler-optimize-local-vars/33995520</a><br /> &gt; Since Lua often compiles source code into byte code on the fly, it is designed to be a fast single-pass compiler. It does do some constant folding</p> <p><strong>A No Frills Introduction to Lua 5.1 VM Instructions</strong> (book)<br /> &gt; As of Lua 5.1, the parser and code generator can perform limited constant expression folding or evaluation. Constant folding only works for binary arithmetic operators and the unary minus operator (UNM, which will be covered next.) There is no equivalent optimization for relational, boolean or string operators.</p> <h3>constant folding...?</h3> <p>One further test case:</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> profile(&quot;tail add x3&quot;, function() local a=2 return 2+2+2+2+2+2+2+a end) profile(&quot;head add x3&quot;, function() local a=2 return a+2+2+2+2+2+2+2 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>&gt; tail add x3 : 2 + 0 = 2 (lua+sys)<br /> &gt; head add x3 : 8 + 0 = 8 (lua+sys)</p> <p>These cost different amounts! Constant-folding only seems to work at the start of expressions. (This is all highly impractical code anyway, but it's fun to dig in and figure out this sort of thing)</p> <h2>update the wiki?</h2> <p>I have not updated the <a href="https://pico-8.fandom.com/wiki/CPU">CPU</a> page on the wiki; it's a bit hard to pin down exactly which operations take cycles, and I would personally rather use a tool like this to compare two potential implementations.</p> <p><del>But, just so you're aware, the wiki is definitely out of date; when I ran the wiki's <a href="https://pico-8.fandom.com/wiki/CPU_Profiler">cpu profiler</a> on pico-8 0.2.4, it produced different results. (I put a summary of the raw differences <a href="https://www.diffchecker.com/iUF3xfZU">here</a>)</del></p> <p>edit: thisismypassword updated the wiki -- thank you!</p> <h2>credits</h2> <p>Cart by <a href="https://pancelor.com">pancelor</a>.</p> <p>Thanks to <a href="https://www.lexaloffle.com/bbs/?uid=14958"> @samhocevar</a> for the <a href="https://www.lexaloffle.com/bbs/?pid=60198#p">initial snippet</a> that I used as a basis for this profiler!</p> <p>Thanks to <a href="https://www.lexaloffle.com/bbs/?uid=25532"> @freds72</a> and <a href="https://www.lexaloffle.com/bbs/?uid=24137"> <a href="https://www.lexaloffle.com/bbs/?uid=24137"> @luchak</a></a> for discussing an earlier version of this with me!</p> <h2>changelog</h2> <p><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;"></p> <h3>v1.1</h3> <ul> <li>added: press X to copy to clipboard</li> <li>added: can pass args; e.g. <code>profile(&quot;lerp&quot;, lerp, {args={1,4,0.3}})</code></li> </ul> <h3>v1.0</h3> <ul> <li>intial release<br /> </div></div></div></li> </ul> https://www.lexaloffle.com/bbs/?tid=46117 https://www.lexaloffle.com/bbs/?tid=46117 Tue, 11 Jan 2022 03:31:01 UTC linecook v2.1 - multiplayer update <p> <table><tr><td> <a href="/bbs/?pid=103294#p"> <img src="/bbs/thumbs/pico8_linecook-2.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=103294#p"> linecook</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=103294#p"> [Click to Play]</a> </td></tr></table> </p> <p>these busy birds will eat almost anything that falls into their gullet -- what will you feed them? they have their preferences, but people food beats bird food any day of the week!</p> <p>a difficult, chaotic arcade game. now with local multiplayer support! also available on <a href="https://pancelor.itch.io/linecook">itch</a>.</p> <h2>controls:</h2> <ul> <li>left / right: move</li> <li>x / up: grab</li> <li>ESDF: movement keys for player 2</li> </ul> <h2>features</h2> <ul> <li>4 difficulty modes: &quot;easy&quot;, medium, hard, and practice</li> <li>3 different control schemes: <ul> <li>solo</li> <li>local multiplayer</li> <li>two-handed singleplayer </li> </ul></li> <li>4 challenging maps for 4 different flavors of gameplay</li> </ul> <img style="" border=0 src="/media/27691/maps.png" alt="" /> <h2>#ChainLetterJam</h2> <p>this was made for the #ChainLetterJam! <a href="https://patricktraynor.itch.io/">Patrick</a> nominated me; I had fun playing <a href="https://patrickgh3.itch.io/arithmetic-bounce">Arithmetic Bounce</a> (my high score on hard mode is 24), so I decided to try making a game that would feel similarly chaotic.</p> <p>I took inspiration from the fact that none of the target numbers in Arithmetic Bounce were inherently good or bad; their value changed depending on the current goal. This became the ingredient/recipe idea in linecook: specific ingredients are sometimes good and sometimes bad, depending on the current recipe. I also liked the chaos and time pressure caused by gravity in Arithmetic Bounce; I've gone for a slightly different but still chaotic spin by giving the player two grabber-claws that are tricky to aim.</p> <p>the continuation of this chain is: <a href="https://tallywinkle.itch.io/the-witchs-almanac">https://tallywinkle.itch.io/the-witchs-almanac</a></p> <img style="" border=0 src="/media/27691/thesave.gif" alt="" /> <h2>blog</h2> <p>I wrote about this game's design <a href="https://pancelor.com/posts/linecook">here</a>. tl;dr: if you allow your game systems to play out as physical processes in the game world, there's a lot more opportunities for the player to interrupt and cause surprising interactions</p> <img style="" border=0 src="/media/27691/banner.png" alt="" /> <p>hope you enjoy it!</p> https://www.lexaloffle.com/bbs/?tid=45799 https://www.lexaloffle.com/bbs/?tid=45799 Wed, 22 Dec 2021 02:03:23 UTC Upper memory: 4 more spritesheets! <p><a href="https://www.lexaloffle.com/bbs/?tid=45538">0.2.4</a> has been released, and we now have an extra segment of memory to play with from 0x8000 to 0xffff. That's 32K, or 0x8000 bytes. A spritesheet takes up 0x2000 bytes... so we could stuff 4 extra spritesheets in there!</p> <p>I've created a system where you can call my custom function <code>cspr</code> the same way you would normally call <code>spr</code>, and everything &quot;just works&quot;. The difference is, cspr can handle up to 1024 sprites instead of the standard 256-sprite-limit of spr. (also, cspr is a bit slower (but not much!) than spr, because it has to manage a cache)</p> <p>Here's a demo that uses 4 full spritesheets; search the code for &quot;cspr&quot; to see how easy it is to use, once you've set it up!</p> <p> <table><tr><td> <a href="/bbs/?pid=103168#p"> <img src="/bbs/thumbs/pico8_hefafanino-4.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=103168#p"> hefafanino</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=103168#p"> [Click to Play]</a> </td></tr></table> </p> <p>(the games are all by me: <a href="https://www.lexaloffle.com/bbs/?tid=45799">#linecook</a>, <a href="https://www.lexaloffle.com/bbs/?tid=41647">#remains</a>, <a href="https://www.lexaloffle.com/bbs/?tid=42704">#ocelotsafari</a>, and <a href="https://www.lexaloffle.com/bbs/?tid=39443">#escalatorworld</a>)</p> <h2>technical details</h2> <p>The core ideas are the blit and cspr functions:</p> <ul> <li>blit: this is used to move sprites between the 4 upper spritesheets and the sprite cache (located at 0x0000, where the spritesheet normally is)</li> <li>cspr: <code>cspr_simple</code> gets the core idea of the sprite caching across; the full <code>cspr</code> in the cart can deal with any arguments you would normally pass to <code>spr</code> (like the width/height/flip parameters)</li> </ul> <p>These are the simple/readable versions; the versions in the cart have some optimizations such as replacing <code>y0*64</code> with <code>y0&lt;&lt;6</code> that may make it more difficult to follow:</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>-- copies a sprite from x0,y0 -- (from spritesheet based at -- memory address base0) -- into x1,y1 on the spritesheet -- based at address base1 -- set base1 to 0x6000 to use the -- screen as the destination -- all coordinates are measured -- in pixels -- note! odd x-coordinates will -- be rounded down -- by pancelor function blit(base1,x1,y1,base0,x0,y0, w,h) local a0=base0+y0*64+x0\2 --source local a1=base1+y1*64+x1\2 --destination local w2=w and w\2 or 4 --half-width for da=0,(h or 8)*64-1,64 do memcpy(a1+da,a0+da,w2) end end -- &quot;cached sprite&quot; by pancelor -- uses a direct-mapped cache -- up to 4 spritesheets are -- stored in 0x8000+ -- they are numbered 0-1023 -- using any sprite s will write -- it to spritesheet slot s%256 -- and then use it from there _cspr_bank={} -- maps slots (0-255) to which bank the sprite comes from (0-3) function cspr_simple(sbig,x,y) local bank,s=sbig&gt;&gt;8&amp;3,sbig&amp;0xff -- bank is 0-3, sbig is 0-255 (inclusive) if _cspr_bank[s]~=bank then -- cache miss! -- blit sprite s from its bank into the cache: local sx,sy=s%16*8,s\16*8 blit(0,sx,sy, 0x8000+bank*0x2000,sx,sy, 8,8) _cspr_bank[s]=bank end spr(s,x,y) end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <h2>drawbacks:</h2> <p><em>An earlier version of this demo used something called <code>upspr</code> instead of <code>cspr</code> and had many drawbacks (do <code>load #hefafanino-1</code> in your local pico-8 to see that old version). I've updated the demo cart to a way better version that &quot;just works&quot;, using <code>cspr</code>.</em></p> <ol> <li><del>sprites can only be blitted on even x-pixel values. e.g., <code>upspr(290,11,11)</code> will draw sprite 290 to 10,11 instead</del></li> <li>you can't store anything inside upper memory until runtime, so you'll probably want to use <a href="https://www.lexaloffle.com/bbs/?tid=34058">PX9</a> or something similar to store your extra spritesheets (as code strings? inside 0x0000-0x2000?) and then decompress them at startup</li> <li><del>flipping sprites takes extra work</del></li> <li><del>palette and transparency will not be respected</del></li> <li>sprite editing is more difficult (due to 2)</li> <li>the upper memory is being used by spritesheets, which may get in the way of other uses for the upper memory (such as larger maps). But you don't need to completely fill the upper memory with spritesheets; you <em>could</em> have, say, 512 sprites (2x normal) and still have 0x4000 bytes leftover for a 128x128 map. we've got more room for either, but we still have to make a tradeoff between the two!</li> <li><strong>map() no longer works</strong> -- you'll need to write your own version of map() that calls spr() repeatedly. luckily this is about as fast as calling map() directly. note that mget() and mset() will need to be rewritten too, because they only handle 1-byte entries.</li> </ol> <h2>extension ideas:</h2> <ol> <li><del>if you stored <em>all</em> of your sprites in upper memory and used the spritesheet at 0x0000 as a cache for the sprites you're actively using, you can fix drawbacks 1, 3, and 4 (above) &quot;for free&quot;. See &quot;Virtual Sprites&quot; in <a href="https://www.lexaloffle.com/bbs/?uid=25532"> @freds72</a>'s <a href="https://freds72.itch.io/poom/devlog/241700/journey-to-poom">POOM devlog</a> for an idea of how to do this</del> <ul> <li>Done! I used a direct-mapping cache instead of an LRU cache, which might cause performance problems if you repeatedly draw sprite x and then sprite x+256*n (because those sprites both map to the same slot, x). For example, sprites 17, 256+17,512+17, and 768+17 all get stored in slot 17 of my direct-mapped sprite cache.</li> <li>However, <code>cspr</code>/<code>blit</code> is quite fast, so you might not even see performance problems. (see my next post for performance details)</li> </ul></li> </ol> <h2>recommendations:</h2> <p>Someone on discord asked: &quot;should people draw all sprites from bank 1, then swap for bank 2, etc?&quot;</p> <p>My recommendation: That would help, but I don't recommend it -- there are more effective ways to improve the performance, I think:</p> <ul> <li>If you're okay with needing to manage which sprite banks are currently loaded, you could avoid all of the overhead of calling cspr() and just call spr() directly. This lets you use map(), too. You would of course need to manually memcpy the sprite banks into the 0x0000 region when appropriate.</li> <li>If you want better performance but want a low-maintenance cache that's easy to use, you should probably write an LRU cache instead of my simple direct-mapped cache. (I may do this myself soon)</li> </ul> <h3>is cspr good enough to just use?</h3> <p>I think so! it's fast enough; it uses up to 10~15% of a frame (in my limited testing) and you get 4x the sprite space, without needing to think about the cache at all. An LRU cache might make this number way better, but I haven't tried that yet.</p> <p>Keep in mind that map() does not work with cspr -- this may be a dealbreaker for some. (you'll need to roll your own implementation of map/mget/mset)</p> <p>If you are willing to give up the &quot;without needing to think about the cache at all&quot; requirement, you should maybe manually move pages of sprites (128x32? 128x64? 128x128?) around instead -- it'd be mostly pretty simple, and very token-efficient. (thanks to merwok for the suggestion!)</p> https://www.lexaloffle.com/bbs/?tid=45769 https://www.lexaloffle.com/bbs/?tid=45769 Mon, 20 Dec 2021 12:38:07 UTC help: &quot;attempt to yield from outside a coroutine&quot; <p>I've hit a really bizarre error; my code has no coroutines, but it fails with &quot;attempt to yield from outside a coroutine&quot;</p> <p>I've simplified it down as much as I could; while removing unrelated cruft (e.g. the <code>sort</code> function from my new project template that I wasn't actually using anywhere) the bug would arbitrarily appear or disappear.</p> <p>The bug will either get triggered 100% of the time or 0% of the time when you run the cart, but its presence or disappearance arbitrarily changes depending on what other unrelated code there is in the cart.</p> <p>For example, tab 0 is 15K of <code>function foo() end</code> repeated over and over again. They're commented out right now, and the bug is present. If you comment them back in, the bug disappears.</p> <p>Commenting out the body of <code>pqb</code> (which prints many many u64 objects) seems to remove the bug for good (no matter how many <code>foo</code>s I comment in or out). I'm not too experienced with metatables; I think I may be at fault for something I'm doing inside <code>u64.__tostring</code>? sometime variation of this code give a slightly differently-formatted error message that jumps me into the middle of my <code>__tostring</code> method. or maybe <code>printh</code> is having issues dumping so much text to the console? I dunno</p> <p>I'm using pico-8 0.2.4 for windows 7.</p> <p> <table><tr><td> <a href="/bbs/?pid=102444#p"> <img src="/bbs/thumbs/pico8_pbomdme-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=102444#p"> pbomdme</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=102444#p"> [Click to Play]</a> </td></tr></table> </p> <hr /> <p>the more common error screen:</p> <img style="" border=0 src="/media/27691/buggy_1.png" alt="" /> <hr /> <p>the more rare error screen (can be triggered if there are exactly 144 foos in tab 0)</p> <img style="" border=0 src="/media/27691/buggy_0.png" alt="" /> https://www.lexaloffle.com/bbs/?tid=45671 https://www.lexaloffle.com/bbs/?tid=45671 Sun, 12 Dec 2021 04:06:29 UTC no trailing newline in .p8 causes &quot;attempt to call a string value&quot; <p>This is #bubblecat-0</p> <ul> <li>It doesn't reload properly (launch it and then press ctrl-R; an &quot;attempt to call a string value&quot; error message appears, and is very different from the normal error messages. pico-8 is unresponsive after this)</li> <li>It <em>does</em> reload fine through the menu (press P; choose &quot;reset cart&quot;)</li> </ul> <p> <table><tr><td> <a href="/bbs/?pid=100464#p"> <img src="/bbs/thumbs/pico8_bubblecat-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=100464#p"> bubblecat</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=100464#p"> [Click to Play]</a> </td></tr></table> </p> <hr /> <p>This is #bubblecat-2</p> <ul> <li>It reloads just fine (using both methods)</li> <li>However, reloading with ctrl-R causes a strange &quot;loaded external changes&quot; message</li> </ul> <p> <table><tr><td> <a href="/bbs/?pid=100464#p"> <img src="/bbs/thumbs/pico8_bubblecat-2.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=100464#p"> bubblecat</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=100464#p"> [Click to Play]</a> </td></tr></table> </p> <hr /> <p>The difference between the two carts is a single newline between the end of the <code>__lua__</code> section and the <code>__gfx__</code> section:</p> <img style="" border=0 src="/media/27691/unknown.png" alt="" /> <p>These errors only happen in the web player or exported binaries; they do not happen inside pico8.exe.</p> <p>I'm 90% sure I created #bubblecat inside pico8 itself; I didn't edit bubblecat.p8 using my external text editor.</p> <hr /> <p>Expected behavior:</p> <ul> <li>a cart without a final newline in the last tab should work fine in the web player and in binary exports</li> <li>no &quot;loaded external changes&quot; message should be shown when reloading</li> </ul> <p>I'm running pico8 0.2.4; I noticed this issue on 0.2.3 but I believe the web player is running 0.2.4, and I confirmed the issue is present in binary exports for windows from 0.2.4</p> https://www.lexaloffle.com/bbs/?tid=45551 https://www.lexaloffle.com/bbs/?tid=45551 Sat, 04 Dec 2021 01:10:39 UTC bubble cat <p> <table><tr><td> <a href="/bbs/?pid=100464#p"> <img src="/bbs/thumbs/pico8_bubblecat-2.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=100464#p"> bubblecat</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=100464#p"> [Click to Play]</a> </td></tr></table> </p> <p>welcome back, bubble cat. we have another situation, and this time you've only got 60 seconds</p> <h2>how to play:</h2> <ul> <li>arrow keys: move</li> <li>ctrl-m: mute</li> <li>X/Z: continue to next level</li> </ul> <p>you don't have to full-clear every level! skipping a level without clearing it just gives you a points penalty (-5 per remaining bubble)</p> <h2>code:</h2> <p>this game was made to fit inside <a href="https://twitter.com/pancelor/status/1461887025540337664">two tweets</a>; i.e. &lt;560 characters of code and no sprites! here's the full code:</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>x=3y=3o={}m=0n=0p=circfill::_::z={}for j=1,13do z[j]=rnd(49)\1end?&quot;⁶!5f2cC&quot; while t()&lt;60do?&quot;⁶1⁶c&quot; b=btnp()q=b&gt;8and&quot;⁷fdc&quot;d=sgn(n-m)u=x if(n~=m)m+=d d+=6 p(32,32,60-t(),1)v=y?&quot;⁶w⁶t&quot;..m,24,27,4+d if(b%16&gt;0)s=b*.5938&amp;.75 if(not r)r,s=s if(r)x+=cos(r)y+=sin(r) w=x\7+y\7~=0 for j=#z,1,-1do i=z[j]d=q and&quot;-5&quot;b=i\7*9a=i%7*9p(a+4,b+4,3,j|8) if(y*7+x-x\7==i)w=del(z,i)d=&quot;+1&quot;?&quot;⁷d&quot; if(#z&lt;1)d=&quot;+10&quot;q=&quot;⁷egc4&quot; if(d)add(o,{d,a,b,d*11})n+=d end?&quot;★⁵8d🐱&quot;,x*9+1,y*9+3,7 if(w)x,y,r=u,v for a in all(o)do a[3]-=1?unpack(a) end?q or&quot;&quot; if(q)goto _ end?&quot;⁷dafa&quot; ::e::goto e</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 only 548 characters, but some of them (like the cat face) cost two characters on twitter. remember to ctrl-p to enter puny-text mode before pasting this into your local console!)</p> <h2>some code highlights:</h2> <ul> <li><a href="https://twitter.com/pancelor/status/1411553720051986433">convert</a> btnp() bitfield into movement: <code>b=btnp()if(b&gt;0)s=b*.5938&amp;.75if(r)x+=cos(r)y+=sin(r)</code></li> <li>buffered input: <code>if(not r)r,s=s</code></li> <li>out-of-bounds check: <code>w=x\7+y\7~=0</code></li> <li>animated score display: <code>d=sgn(n-m) if(n~=m)m+=d</code></li> <li>collision checking: <code>if(y*7+x-x\7==i)</code></li> <li>draw player: <code>?&quot;★⁵8d🐱&quot;,x*9+1,y*9+3,7</code></li> <li>animated score floaters: <code>for a in all(o)do a[3]-=1?unpack(a) end</code></li> </ul> <h2>full code history:</h2> <p><a href="https://github.com/pancelor/bubble-cat">https://github.com/pancelor/bubble-cat</a></p> <h2>high score:</h2> <p>my high score is <del>207!</del> 240! what's yours?</p> https://www.lexaloffle.com/bbs/?tid=45406 https://www.lexaloffle.com/bbs/?tid=45406 Sat, 20 Nov 2021 03:23:05 UTC crash when doing memset p8scii poke <p>I was messing around with the new p8scii memset command, and it sometimes crashes my console at weird times. once, it crashed when I did this:</p> <p><code>?&quot;\^!0000&quot;</code></p> <p>(i.e. using memset with an address but no actual arguments)</p> <img style="" border=0 src="/media/27691/2021_10_28_16_20_59_398_pico8.png" alt="" /> <p>Another time I did a similar command and then did &quot;reboot&quot;, and it crashed then</p> <hr /> <p>system info: pico-8 0.2.3 / windows 7</p> <p>the error message:<br /> &gt; Microsoft Visual C++ Runtime Library<br /> &gt;<br /> &gt; This application has requested the Runtime to terminate it in an unusual way.<br /> &gt; Please contact the application's support team for more information.</p> https://www.lexaloffle.com/bbs/?tid=45174 https://www.lexaloffle.com/bbs/?tid=45174 Thu, 28 Oct 2021 23:27:02 UTC feature request: bitplanes for sset() <p> <table><tr><td> <a href="/bbs/?pid=98668#p"> <img src="/bbs/thumbs/pico8_firroref-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=98668#p"> firroref</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=98668#p"> [Click to Play]</a> </td></tr></table> </p> <p>Here's some code:</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>poke(0x5f5e,0x11) --only enable bitplane 1 sset(0,0,15) --edit sprite 0</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 would expect the sset() call to set the spritesheet's corner to color 1 (dark blue) because of the bitplane setting. However, this instead sets the corner to 15 (tan).</p> <p>I can workaround this for now by using pset and then memcopying the screen to the spritesheet, but that means my decompression code (which wants to call sset with bitplanes active) will need to either take less than a frame to run, or show artifacts onscreen while it runs.</p> https://www.lexaloffle.com/bbs/?tid=44990 https://www.lexaloffle.com/bbs/?tid=44990 Fri, 15 Oct 2021 01:19:11 UTC Feature request: custom palette in exported binary icon <p>I just found out that you can turn a specific sprite into the icon for the binary export: <a href="https://www.lexaloffle.com/dl/docs/pico-8_manual.html#Binary_Applications_">https://www.lexaloffle.com/dl/docs/pico-8_manual.html#Binary_Applications_</a> and whoa, this is really great! But afaict it's restricted to the standard palette. Is there some way to set a custom palette for the icon in the export? If not, adding some sort of palette flag might be a nice feature:</p> <p><code>EXPORT -I 32 -C 12 -Z 0,132,4,140,134,6,135,7,8,137,139,11,138,130,13,131 MYGAME.BIN</code></p> <p>or maybe reuse the -C flag, and a -1 entry means transparent?</p> <p><code>EXPORT -I 32 -C 0,132,4,140,134,6,135,7,8,137,139,11,-1,130,13,131 MYGAME.BIN</code></p> <p>(although that might be a bit awkward because using pal(12,-1,1) ingame means to map 12-&gt;0x8F, not 12-&gt;transparent...)</p> https://www.lexaloffle.com/bbs/?tid=44918 https://www.lexaloffle.com/bbs/?tid=44918 Thu, 07 Oct 2021 20:06:39 UTC Free Cell 1K <p> <table><tr><td> <a href="/bbs/?pid=97939#p"> <img src="/bbs/thumbs/pico8_freecell1k-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=97939#p"> freecell1k</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=97939#p"> [Click to Play]</a> </td></tr></table> </p> <p>Free Cell, in 1022 characters of code, and no sprites! <a href="https://twitter.com/pancelor/status/1441510314193784832?s=20">twitter</a> | <a href="https://pancelor.itch.io/free-cell-1k">itch</a></p> <h2>CONTROLS:</h2> <ul> <li>click and drag cards around <ul> <li>you cannot move stacks of cards; one at a time only!</li> </ul></li> <li>stack descending cards of alternating colors in the main play area <ul> <li>any card may be placed in an empty column of the main area</li> </ul></li> <li>store any card in the four &quot;free cells&quot; at the top left</li> <li>make a stack of each suit A-&gt;K in the top right to win</li> <li>reset the cart to start a new game</li> </ul> <img style="" border=0 src="/media/27691/tutorial.gif" alt="" /> <h2>ONE AT A TIME?</h2> <p>You can only move one card at a time; if you want to move a stack of cards you have to take it apart and put it back together manually. This is different from &quot;standard&quot; solitaire, and it makes Free Cell particularly interesting! It also makes the implementation a bit easier to fit into the tiny code-size constraint ;)</p> <img style="" border=0 src="/media/27691/stacking.gif" alt="" /> <h2>I WON!</h2> <p>Congrats! Enjoy the win animation here: <a href="https://pancelor.itch.io/solitaire-win-animation">https://pancelor.itch.io/solitaire-win-animation</a> (I wanted to add a &quot;you win&quot; animation to this game, but I didn't have the room to fit it in... so I made it as a separate cartridge)</p> <img style="" border=0 src="/media/27691/cover.gif" alt="" /> <h2>SOURCE CODE</h2> <p>The source is in the cart, of course, but it's here too. Remember to enable puny text mode (cmd-p) before pasting this into your local PICO-8 console:</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>A=add W=12w=13Z=16s={}B={}Q=1T=0M=9q=poke2 function F(i)S=s[i]J=i\W I=i\8O=1-I U=I*(i-8+J)*14+O*i*Z+2V=O*max(#S*6+22,28)+5end for i=0,51do s[i]={m=i\W}A(B,{x=i,y=400,k=i+i\w*3},rnd(i+1)+1)end q(-15-😐,264,2043,4,3843)D=rectfill::_::L=T%8T+=1K=B[T]N=not btn(5)X=stat(32)-6Y=stat(33)-8C=fillp if(T&gt;52)q(14-😐,3)M=T%3 for i=15,0,-1do F(i)M|=S.m C(▒)a=5+O*28D(U,a,U+W,a+Z,2)C()for _ENV in all(S)do x=u+3*x+.5&gt;&gt;2y=v+3*y+.5&gt;&gt;2end G=abs(X-U)\8+abs(Y-V)\Z&lt;&lt;6v=S[#S]k=w if(v)k=v.k if(2&gt;&gt;k%Z&gt;M+J*2)K=A(B,del(B,v))L=W+k\Z if(H and N and(J+G+#S&lt;1or Z-I|k+G==Z|1+H.k^^32or H.k==J+k|G))K=H L=i if(btnp(5+J+G))H=A(B,del(B,v))end if(K)del(s[K.h],A(s[L],K))F(L)S.m/=2K.u,K.v,K.h=U,V,L?&quot;⁷i6v1d1&quot; if(H)H.x,H.y=X,Y if(N)H=nil for r in all(B)do x=r.x y=r.y q(63-😐,244)D(x-1,y-1,x+W,y+Z,4)q(61-😐,-1,-1)D(x,y,x+W,y+Z,3)a=r.k%Z+1?(a==10and&quot;&sup3;f|&sup3;f0 &sup3;b&quot;or sub(&quot;a23456789|jqk&quot;,a,a)..&quot; &sup3;d&quot;)..split(&quot;&hearts;,◆,◆⁵8f..&sup3;aᶜ3.,◆⁵8fニ&quot;)[r.k\Z+1],x+1,y+1,r.k\32 for i=0,77do pset(x+W-i%w,y+Z-i\w,pget(x+i%w,y+i\w))end end?&quot;●⁶1⁶c6&quot;,X+2,Y+7,5 if(M&lt; Q/⧗)Q=0?&quot;⁷ceg4&quot; goto _</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>(there's an extra space in there near the end because the BBS text editor seems to choke on the &lt; symbol)</p> <p>An earlier, more readable, and much longer version of this code can be found <a href="https://gist.github.com/pancelor/8da7b490b6605c330b8fa84762432a9b">here</a></p> <h2>SOME CODE HIGHLIGHTS</h2> <p>Some of the more bizarre tricks I used to squeeze every bit of functionality out of my 1024-character budget:</p> <ul> <li>set the palette with <code>poke2(-15-😐,264,2043,4,3843)</code></li> <li>update card positions with <code>for _ENV in all(S)do x=u+3*x+.5&gt;&gt;2y=v+3*y+.5&gt;&gt;2end</code></li> <li>dynamically cast shadows with a very particular palette and <code>poke2(63-😐,244)rectfill(x-1,y-1,x+W,y+Z,4)poke2(61-😐,-1,-1)</code></li> <li>draw the 4 suit icons with <code>split(&quot;&hearts;,◆,◆⁵8f..&sup3;aᶜ3.,◆⁵8fニ&quot;)[suit_id]</code></li> <li>check if you can drop your held card with <code>i\12+G+#S&lt;1or 16-i\8|k+G==16|1+H.k^^32or H.k==i\12+k|G</code></li> <li> <p>wait until the next frame and clear the screen with <code>?&quot;⁶1⁶c6&quot;</code></p> <ul> <li>(thanks to zep for pointing out that \^ can be written as ⁶!)</li> </ul> </li> <li>auto-move cards to the top right by tracking the minimum stack height with bitshifting (search for M (and m) to see the relevant code)</li> <li>check whether the game is won by taking advantage of the fact that <code>2^12&lt;⧗ and ⧗&lt;2^13</code></li> </ul> <h2>I'M SORRY, &quot;poke2(63-😐,244)&quot;???</h2> <p>Yeah! 63-😐 is 24414.5, which is the address I need to poke to get those slick shadows! Check out <a href="https://www.lexaloffle.com/bbs/?tid=44801">this post</a> for more info.</p> https://www.lexaloffle.com/bbs/?tid=44802 https://www.lexaloffle.com/bbs/?tid=44802 Tue, 28 Sep 2021 22:10:28 UTC constant companion: shorten your tweetcart constants! <p> <table><tr><td> <a href="/bbs/?pid=97937#p"> <img src="/bbs/thumbs/pico8_constantcompanion-8.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=97937#p"> constantcompanion</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=97937#p"> [Click to Play]</a> </td></tr></table> </p> <h2>controls:</h2> <p>This is a niche tool to help you save characters when writing carts that are codesize-constrained.</p> <ul> <li>type in a number; press enter</li> <li>then press up/down and ctrl-c/enter to copy a code</li> <li>navigate back up (or press backspace) to start typing a new number</li> </ul> <p>Example: 0x6000 can be written as 0x6000 (6 chars), 24576 (5 chars), 6^13 (4 chars) or ⌂-🐱 (3 chars!)</p> <p>The tool sorts the results by character count (on twitter), so the top results are your best bet.</p> <p><em>Update: The latest versions of pico8 have</em> <a href="https://www.lexaloffle.com/dl/docs/pico-8_manual.html#Raw_memory_writes">special P8SCII codes for poking</a> <em>which are often fewer characters than calling poke directly (even after using this tool). e.g. <code>?&quot;\^!5f10249?&quot;</code> instead of <code>poke(0x5f10,50,52,57,63)</code>. Consider using that instead! But this tool might still be useful sometimes, and at the very least, it's an interesting artifact.</em></p> <h2>motivation:</h2> <p>While I was making Free Cell 1K (<a href="https://pancelor.itch.io/free-cell-1k">itch</a> | <a href="https://twitter.com/pancelor/status/1441510314193784832?s=20">twitter</a> | <a href="https://www.lexaloffle.com/bbs/?tid=44802">bbs</a>) for the #Pico1K jam, I realized I could save characters by taking advantage of the built-in constants. I needed to poke a few things to various addresses (for setting the palette, drawing dynamic shadows with bitplanes, and enabling the mouse) so I had code that looked 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>-- 94 chars (not including comments or newlines) poke(0x5F10,8,1,251,7,4,0,3,15) --palette poke(0x5F2D,3) --mouse poke(0x5F5C,-1) --disable btnp repeat poke(0x5F5E,0xF4) --shadows on poke(0x5F5E,0xFF) --shadows off</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Each of those poke addresses uses 6 characters; we can do better! The first thing I did to save characters was 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>-- 84 chars (not including comments or newlines) A=24365 poke(A-78,8,1,251,7,4,0,3,15) poke(A-49,3) poke(A-2,-1) poke(A,0xF4) poke(A,0xFF)</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>But then I saw <a href="https://www.lexaloffle.com/bbs/?uid=1"> @zep</a> tweet a <a href="https://twitter.com/lexaloffle/status/1439263350475550729?s=20">trick</a> for writing sqrt(x) as x^█ instead (because █ (shift+A) is defined to have a value of 0.5), and I realized I could do even better: the 😐 (shift+M) character is defined to have a value of -24351.5, so I did 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>-- 95 chars (not including comments or newlines) poke(-15.5-😐,8,1,251,7,4,0,3,15) poke(13.5-😐,3) poke(60.5-😐,-1) poke(62.5-😐,0xF4) poke(62.5-😐,0xFF)</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>95 chars is not an improvement... yet! However, poke() ignores fractional addresses, so those .5s aren't necessary. Also, I was able to combine the 0x5F5C and 0x5F5E pokes into a single poke, which nullifies some of the relative advantage of the A=24365 technique. In the end, this was the shortest code I could find:</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>-- 64 chars (not including comments or newlines) q=poke2 q(-15-😐,264,2043,4,3843) q(14-😐,3) q(63-😐,244) q(61-😐,-1,-1)</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 saves 2 characters over the equivalent version that uses A=24365 instead of the moon face. (or maybe just 1 character, if the newline after q=poke2 can't be removed)</p> <h2>how did you know moon face was the one to use?!</h2> <p>I didn't! I wrote a program to brute-force try all the built-in symbols and see if any were useful for my needs. Check out tab 5 of the cart (&quot;analysis&quot;) to see the brute-force algorithm I used.</p> <p>I've cleaned that program up and posted it here for you. It might be less useful for tweetcarts (because stuff like 😐 takes up 2 characters on twitter) but it saved me 1~2 entire characters (genuinely very helpful!) during the Pico1K jam, and I hope it helps you too.</p> <p>Leave a message here or tag me on <a href="https://twitter.com/pancelor">twitter</a> if you found it useful; I'd like to see what you make!</p> <h2>how does it work?</h2> <ol> <li>build a list of all 150 &quot;symbols&quot; under consideration: <ul> <li><code>█▒🐱░✽●&hearts;☉웃⌂😐♪◆&hellip;★⧗ˇ&and;▤▥</code> (most symbols)</li> <li>the numbers 0-9</li> <li>and the negated version of everything above</li> <li>the numbers 10-99 (but not their negated versions)</li> </ul></li> <li>try combining every pair of symbols a,b with these operations: <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>a a*b a+b a&amp;b a|b a~b a-b a/b a^b</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div></li> <li>if any result is between <code>target</code> and <code>target+1</code>, display the result. this was chosen because poke/memset/etc round their inputs down to the nearest integer. custom checks are easy to hack in yourself; search for &quot;function near&quot; in the code</li> </ol> <h2>changelog</h2> <ul> <li>v8: <ul> <li>add support for new pico-8 syntax <code>a~b</code> for bitwise not (1 char shorter than the old <code>a^^b</code>)</li> <li>sort results by twitter character count instead of naive character count. thanks to jadelombax for the handy reference table here: <a href="https://www.lexaloffle.com/bbs/?tid=44375">https://www.lexaloffle.com/bbs/?tid=44375</a></li> </ul></li> <li>v7: fix typo in v6</li> <li>v6: <ul> <li>fix exponentiation parse order (<code>-a^b</code> gets parsed by pico8 as <code>-(a^b)</code>, unlike any other operation on the list)</li> <li>increase list scroll speed</li> <li>clean up output list results a bit (e.g. no more <code>-a+b</code>, since <code>b-a</code> is shorter)</li> <li>remove <code>~x</code> from consideration; it's very similar mathematically to <code>-x</code>, so calculating it was making all searches slower for hardly any benefit. (the code is commented out, so you can re-add it yourself pretty easily if you download the cart and search for <code>~</code>)</li> <li>make it easier to do custom &quot;is close enough&quot; checking; search for &quot;function near&quot; in the code</li> </ul></li> <li>v5: show options (and allow them to be copied) as soon as they're found. (no longer need to wait for the entire search to complete)</li> </ul> https://www.lexaloffle.com/bbs/?tid=44801 https://www.lexaloffle.com/bbs/?tid=44801 Tue, 28 Sep 2021 21:48:51 UTC Ocelot Safari <p> <table><tr><td> <a href="/bbs/?pid=91318#p"> <img src="/bbs/thumbs/pico8_ocelotsafari-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=91318#p"> ocelotsafari</a><br><br> by <a href="/bbs/?uid=27691"> pancelor</a> <br><br><br> <a href="/bbs/?pid=91318#p"> [Click to Play]</a> </td></tr></table> </p> <h2>welcome to the ocelot safari!</h2> <p>enjoy the ocelots, and do let us know if you find any long-lost relics deep in the jungle :)</p> <img style="" border=0 src="/media/27691/machete.gif" alt="" /> <h2>instructions</h2> <ul> <li>hold Z to drag things</li> <li>arrow keys to move</li> <li>retrieve the lost gemstone of Tezcatlipoca! some say it&rsquo;s as far as fvkgl-sbhe meters deep in the jungle!</li> </ul> <h3>tips</h3> <ul> <li>we'll leave you some new tools at the initial drop point, if the ocelots steal your gear</li> <li>ocelots can crawl through vines and trees -- they're tricksters!</li> <li>be sure to <strong>bring some matches</strong>; the nights are long and dark, and who knows what lurks in the jungle...</li> </ul> <img style="" border=0 src="/media/27691/cover2.png" alt="" /> <h2>tutorial</h2> <p>I didn't make the time to make an interactive tutorial, so here's a video instead:</p> <p><object width="640" height="400"><param name="movie" value="https://www.youtube.com/v/tYDLA6QXjM4&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/tYDLA6QXjM4&hl=en&fs=1&rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="400"></embed></object></p> <p>And here's a gif showing how to use each tool:</p> <img style="" border=0 src="/media/27691/tools.gif" alt="" /> <p>(light a fire by <strong>bumping matches into wood</strong>)</p> <h2>good luck in there!</h2> <img style="" border=0 src="/media/27691/icon.png" alt="" /> <hr /> <h3>postscript</h3> <ul> <li>This was made for the Ludum Dare 48 compo in 48 hours. (plus minor bugfixes; read changelog <a href="https://pancelor.itch.io/ocelot-safari/devlog/246780/v11-minimal-bugfixes">here</a> and <a href="https://pancelor.itch.io/ocelot-safari/devlog/247906/v12-more-minimal-bugfixes">here</a>). Rate my entry! <a href="https://ldjam.com/events/ludum-dare/48/ocelot-safari">https://ldjam.com/events/ludum-dare/48/ocelot-safari</a></li> <li>My initial goal was to make a game exploring how items feel if you have no inventory system or &quot;use item&quot; button, and I'm happy with the results. Sometimes movement can feel a bit awkward, especially at the start, but that's what the whole game is built around, so I think it's fine.</li> <li>I really like how the nighttime and the ocelots make it a visceral struggle to advance deeper and deeper into the jungle.</li> </ul> https://www.lexaloffle.com/bbs/?tid=42704 https://www.lexaloffle.com/bbs/?tid=42704 Thu, 29 Apr 2021 22:01:52 UTC fonter: 0.2.2 font importer+exporter <p>In the 0.2.2 release, zep made a small tool for creating custom fonts:<br /> <a href="https://www.lexaloffle.com/bbs/?tid=41544">https://www.lexaloffle.com/bbs/?tid=41544</a> (search for &quot;Custom Fonts&quot;)</p> <p>It's a great tool, but if you only have a font snippet (and no longer have the spritesheet), it's hard to edit that font again. So, I extended the tool to also support font importing!</p> <p>You can get my font tool from the pico-8 console:</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>LOAD #FONTER</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <img style="" border=0 src="/media/27691/fonter_0.gif" alt="" /> <p>Instructions on how to use the tool are in tab 0 of the cart. happy fonting!</p> https://www.lexaloffle.com/bbs/?tid=42560 https://www.lexaloffle.com/bbs/?tid=42560 Wed, 21 Apr 2021 09:29:18 UTC