ridgekuhn [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=44175 Beautiful Runaway 💃 <p> <table><tr><td> <a href="/bbs/?pid=121486#p"> <img src="/bbs/thumbs/pico8_beautifulrunaway-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=121486#p"> Beautiful Runaway</a><br><br> by <a href="/bbs/?uid=44175"> ridgekuhn</a> <br><br><br> <a href="/bbs/?pid=121486#p"> [Click to Play]</a> </td></tr></table> </p> <p>This one is short but sweet. I hope you enjoy it! 😊</p> https://www.lexaloffle.com/bbs/?tid=50393 https://www.lexaloffle.com/bbs/?tid=50393 Sun, 27 Nov 2022 18:17:21 UTC Dragon Deity <p> <table><tr><td> <a href="/bbs/?pid=121318#p"> <img src="/bbs/thumbs/pico8_dragondeity-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=121318#p"> Dragon Deity</a><br><br> by <a href="/bbs/?uid=44175"> ridgekuhn</a> <br><br><br> <a href="/bbs/?pid=121318#p"> [Click to Play]</a> </td></tr></table> </p> <p>One last chiptune. I hope you like it! 😀</p> https://www.lexaloffle.com/bbs/?tid=50348 https://www.lexaloffle.com/bbs/?tid=50348 Thu, 24 Nov 2022 14:19:25 UTC The GodHand (is Real!) 👊 <p> <table><tr><td> <a href="/bbs/?pid=121148#p"> <img src="/bbs/thumbs/pico8_thegodhandisreal-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=121148#p"> The GodHand (is Real!)</a><br><br> by <a href="/bbs/?uid=44175"> ridgekuhn</a> <br><br><br> <a href="/bbs/?pid=121148#p"> [Click to Play]</a> </td></tr></table> </p> <p>One more! 😅</p> https://www.lexaloffle.com/bbs/?tid=50307 https://www.lexaloffle.com/bbs/?tid=50307 Tue, 22 Nov 2022 03:20:35 UTC Aura Power! <p> <table><tr><td> <a href="/bbs/?pid=121087#p"> <img src="/bbs/thumbs/pico8_aurapower-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=121087#p"> Aura Power!</a><br><br> by <a href="/bbs/?uid=44175"> ridgekuhn</a> <br><br><br> <a href="/bbs/?pid=121087#p"> [Click to Play]</a> </td></tr></table> </p> <p>Hi everyone, I wrote this song over the weekend, I hope you like it! 😀</p> https://www.lexaloffle.com/bbs/?tid=50291 https://www.lexaloffle.com/bbs/?tid=50291 Mon, 21 Nov 2022 00:44:25 UTC Downstream Dream <p> <table><tr><td> <a href="/bbs/?pid=112916#p"> <img src="/bbs/thumbs/pico8_downstreamdream-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=112916#p"> Downstream Dream</a><br><br> by <a href="/bbs/?uid=44175"> ridgekuhn</a> <br><br><br> <a href="/bbs/?pid=112916#p"> [Click to Play]</a> </td></tr></table> </p> <p>(UPDATE: I've added a special OST cart for the itch.io download, where you can select music from the soundtrack and watch the game play itself while you listen. I hope you enjoy it!)</p> <p>Hi everyone,</p> <p>Here's my new game. It's called Downstream Dream, it's a side-scroller that I guess is somewhere between kart racers and shoot-em-ups. I hope you like it!</p> <p>It's also <a href="https://ridgek.itch.io/downstream-dream">published on itch.io</a> if you'd like to support it. Most of the content from that page is duplicated below, but first, a few thanks to BBS members:</p> <ul> <li> <p>To <a href="https://www.lexaloffle.com/bbs/?uid=1"> <a href="https://www.lexaloffle.com/bbs/?uid=1"> @zep</a></a>, <a href="https://www.lexaloffle.com/bbs/?uid=10932"> <a href="https://www.lexaloffle.com/bbs/?uid=10932"> @Makke</a></a>, <a href="https://www.lexaloffle.com/bbs/?uid=12874"> <a href="https://www.lexaloffle.com/bbs/?uid=12874"> @Felice</a></a>, <a href="https://www.lexaloffle.com/bbs/?uid=11025"> <a href="https://www.lexaloffle.com/bbs/?uid=11025"> @Nodepond</a></a>, and <a href="https://www.lexaloffle.com/bbs/?uid=33292"> <a href="https://www.lexaloffle.com/bbs/?uid=33292"> @pahammond</a></a> for their code contributions to the community, some of which I wouldn't have been able to release this cart anytime soon without! (listed below)</p> </li> <li> <p>To <a href="https://www.lexaloffle.com/bbs/?uid=25532"> <a href="https://www.lexaloffle.com/bbs/?uid=25532"> @freds72</a></a> and <a href="https://www.lexaloffle.com/bbs/?uid=15227"> <a href="https://www.lexaloffle.com/bbs/?uid=15227"> @johanp</a></a> for their advice. This game would have been a lot worse if not for their kindness and willingness to help a stranger.</p> </li> <li> <p>To <a href="https://www.lexaloffle.com/bbs/?uid=13822"> <a href="https://www.lexaloffle.com/bbs/?uid=13822"> @Liquidream</a></a> for playtesting, and for lots of encouragement when I felt like giving up.</p> </li> <li>To everyone in the Pico-8 community. I'm very grateful that so many are willing to share your creativity and kindness with others. Trading knowledge and games with you all has brought me a lot of joy.</li> </ul> <p>Thank you all!</p> <h1>Game Controls</h1> <hr /> <h2>Legend:</h2> <p>⬅️➡️⬆️⬇️ = D-Pad or Keyboard Arrow Keys</p> <p>🅾️ = Button 1 or Keyboard Z</p> <p>❎ = Button 2 or Keyboard X</p> <img style="margin-bottom:16px" border=0 src="/media/44175/imVCF4.png" alt="" /> <h2>Movement:</h2> <p>⬅️ + 🅾️ - Paddle counter-clockwise</p> <p>➡️ + 🅾️ - Paddle clockwise</p> <p>⬆️ + 🅾️ - Steady ahead</p> <p>⬇️ - Move backwards (with motor)</p> <img style="margin-bottom:16px" border=0 src="/media/44175/controls 5.46.55 PM.gif" alt="" /> <img style="margin-bottom:16px" border=0 src="/media/44175/boils.gif" alt="" /> <h2>Offense/Defense:</h2> <p>❎ - Throw</p> <img style="margin-bottom:16px" border=0 src="/media/44175/throwcans.gif" alt="" /> <img style="margin-bottom:16px" border=0 src="/media/44175/dropturtles.gif" alt="" /> <img style="margin-bottom:16px" border=0 src="/media/44175/throwcans2.gif" alt="" /> <h1>How to Play</h1> <hr /> <img style="margin-bottom:16px" border=0 src="/media/44175/95oeqV.png" alt="" /> <img style="margin-bottom:16px" border=0 src="/media/44175/avoidrocks.gif" alt="" /> <img style="margin-bottom:16px" border=0 src="/media/44175/overboard.gif" alt="" /> <img style="margin-bottom:16px" border=0 src="/media/44175/spin.gif" alt="" /> <h1>From the Developer</h1> <hr /> <img style="margin-bottom:16px" border=0 src="/media/44175/34_17098483_10100149421192734_1797622040660512772_n.jpg" alt="" /> <p>My mom loved both adventure and the American southwest; she traveled there many times over her life, and her home was filled with art and souvenirs she'd collected from her visits to the region.</p> <p>When I was about seven years old, my parents rented a minivan and took me on a long roadtrip across the United States. I don&rsquo;t remember a lot from that trip other than staring out the window while the landscape slowly changed from cities and farmland, to mountains, to desert, but one memory stands out from the endless monotony of the road; a stop at the Grand Canyon where my mom went white water rafting.</p> <p>My dad never learned how to swim, and someone needed to watch me anyway, so the two of us waited downstream in the hot afternoon sun, looking for mom's boat to come in. I don&rsquo;t think the water was particularly rough at that time of year; but like my dad, I&rsquo;ve never been good at swimming either, and I spent most of the time thinking about how scary the water looked to me. I imagined how if I was on the boat with mom, I would probably fall out and be carried away by the river. She seemed very bold and brave that day!</p> <p>A couple years before she left this world, mom offered to take me on a trip out west; possibly to Las Vegas, or maybe the Grand Canyon. I politely turned her down for some made-up reason, while the real one probably had something to do with still being in my 20s and wrongly believing that I was too cool to go on vacation with my mother. As a young adult, I assumed that there would always be more time with the people in my life. Now that I'm a little older, I'm learning that there is rarely ever enough. I don&rsquo;t know where we might have gone or what we might have done on that trip, if I hadn't foolishly said no; but sometimes, it&rsquo;s nice to dream about it.</p> <p>Anyway, I hope you enjoy the game. It contains a lot of love, a little regret, and the best game I could make with Pico-8.</p> <p>-ridgek</p> <h1>Credits and Thanks</h1> <hr /> <p>External Libraries:</p> <ul> <li><a href="https://www.lexaloffle.com/bbs/?tid=34058">PX9</a> by <a href="https://www.lexaloffle.com/bbs/?uid=1"> <a href="https://www.lexaloffle.com/bbs/?uid=1"> @zep</a></a></li> <li><a href="https://www.lexaloffle.com/bbs/?tid=30518">Local fillp()</a> by <a href="https://www.lexaloffle.com/bbs/?uid=10932"> <a href="https://www.lexaloffle.com/bbs/?uid=10932"> @Makke</a></a> &amp; <a href="https://www.lexaloffle.com/bbs/?uid=12874"> <a href="https://www.lexaloffle.com/bbs/?uid=12874"> @Felice</a></a></li> <li><a href="https://www.lexaloffle.com/bbs/?tid=3718">pic2pico</a> by <a href="https://www.lexaloffle.com/bbs/?uid=11025"> <a href="https://www.lexaloffle.com/bbs/?uid=11025"> @Nodepond</a></a></li> <li><a href="https://pahammond.itch.io/gem-minify">GEM</a> by Paul Hammond (<a href="https://www.lexaloffle.com/bbs/?uid=33292"> <a href="https://www.lexaloffle.com/bbs/?uid=33292"> @pahammond</a></a>)</li> </ul> <p>Playtesters:</p> <ul> <li>Paul Nicholas (<a href="https://www.lexaloffle.com/bbs/?uid=13822"> <a href="https://www.lexaloffle.com/bbs/?uid=13822"> @Liquidream</a></a>)</li> <li>John Loiterman​ (<a href="http://sbigames.com">http://sbigames.com</a>​)</li> <li>Lex Rendon</li> </ul> <p>Special Thanks To:</p> <ul> <li>Fred Souchu​ (<a href="https://www.lexaloffle.com/bbs/?uid=25532"> <a href="https://www.lexaloffle.com/bbs/?uid=25532"> @freds72</a></a>)</li> <li>Johan Pietz​ (<a href="https://www.lexaloffle.com/bbs/?uid=15227"> <a href="https://www.lexaloffle.com/bbs/?uid=15227"> @johanp</a></a>)</li> </ul> https://www.lexaloffle.com/bbs/?tid=48081 https://www.lexaloffle.com/bbs/?tid=48081 Thu, 09 Jun 2022 01:13:58 UTC Yet Another Table String Serializer <p>Hi everyone,</p> <p>My new project uses massive tables of graphics metadata, so I've written a new table serializer inspired by <a href="https://github.com/benwiley4000/pico8-table-string/pull/1">this pull request</a> on <a href="https://www.lexaloffle.com/bbs/?uid=6654"> @BenWiley4000</a>'s <a href="https://www.lexaloffle.com/bbs/?tid=34342">pico8-table-string</a> to get the job done. Hopefully someone else finds this useful, too!</p> <p>It uses less characters to store your table as a string than pico8-table-string does (to take up less character / compressed space), but at the cost of 14 more tokens to deserialize, and possibly with less reliability. (It will break if the table contains a string a certain character sequence, see below.) You should also run the output through something like Zep's <a href="https://www.lexaloffle.com/bbs/?tid=38692">escape_binary_string</a> before saving to code.</p> <p>Supported:</p> <ul> <li>string/number/boolean values</li> <li>key/value pairs</li> <li>consecutive indexed values starting from 1</li> </ul> <p>Not supported:</p> <ul> <li>0-indexed values</li> <li>non-consecutive indexed values</li> <li>strings containing the ascii sequence <code>\3\120\23</code></li> </ul> <p>Writing parsers is not one of my strengths, so pull requests on the <a href="https://github.com/ridgekuhn/pico8-table-serialize">GitHub repo</a> are open and appreciated!</p> <h3>serialize</h3> <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> <div> <div class=scrollable_with_touch style="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>---serialize lua table to string --@param {table} tbl -- input table -- --@returns {string} -- serialized table function tbl_serialize(tbl) local function encode_value(value) --ascii unit separator --delimits number local value_token = &quot;\31&quot; --ascii acknowledge --delimits true boolean local bool_true = &quot;\6&quot; --ascii negative acknowledge --delimits false boolean local bool_false = &quot;\21&quot; --ascii start of text --delimits start of string local str_token = &quot;\2&quot; --end of string sequence --ascii end of text + x --ascii end of transmission block local str_end_token = &quot;\3x\23&quot; --asci group separator --delimits start of table local tbl_token = &quot;\29&quot; if type(value) == &quot;boolean&quot; then return value and bool_true or bool_false elseif type(value) == &quot;string&quot; then --check for --ascii control chars for i = 1, #value do if ord(sub(value, i, i)) &lt; 32 then --delimit binary string return str_token .. value .. str_end_token end end --encode regular string return value_token .. value elseif type(value) == &quot;table&quot; then return tbl_token .. tbl_serialize(value) end return value_token .. value end local str = &quot;&quot; --ascii record separator --delimits table key local key_token = &quot;\30&quot; --ascii end of medium --delimits end of table local tbl_end_token = &quot;\25&quot; --get indexed values for _, v in ipairs(tbl) do str = str .. encode_value(v) end --get keyed values for k, v in pairs(tbl) do if type(k) ~= &quot;number&quot; then str = str .. key_token .. k .. encode_value(v) end end str = str .. tbl_end_token return str end ---validate output --@usage -- output = tbl_serialize(my_table) -- -- tbl_serialize_validate( -- my_table, -- tbl_deserialize(output) -- ) -- --@param {table} tbl1 -- input table -- --@param {table} tbl2 -- output table function tbl_serialize_validate(tbl1, tbl2) for k, v in pairs(tbl1) do if type(v) == &quot;table&quot; then tbl_serialize_validate(tbl2[k], v) else assert( tbl2[k] == v, tostr(k) .. &quot;: &quot; .. tostr(v) .. &quot;: &quot; .. tostr(tbl2[k]) ) end end end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p></div></div></div></p> <h3>deserialize</h3> <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> <div> <div class=scrollable_with_touch style="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>---deserialize table --@param {string} str -- serialized table string -- --@returns {table} -- deserialized table function tbl_deserialize(str) ---get encoded value --@param {string} str -- serialized table string -- --@param {integer} i -- position of -- current delimiter -- in serialized table string local function get_value(str, i) local char, i_plus1 = sub(str, i, i), i + 1 --table if char == &quot;\29&quot; then local tbl, j = tbl_deserialize( sub(str, i_plus1) ) return tbl, i + j --binary string elseif char == &quot;\2&quot; then for j = i_plus1, #str do if sub(str, j, j + 2) == &quot;\3x\23&quot; then return sub(str, i_plus1, j - 1), j + 2 end end --bool true elseif char == &quot;\6&quot; then return true, i --bool false elseif char == &quot;\21&quot; then return false, i end --number, string, --or table key --(&quot;\30&quot; or &quot;\31&quot;) for j = i_plus1, #str do if ord(sub(str, j, j)) &lt; 32 then local value = sub(str, i_plus1, j - 1) return tonum(value) or value, j - 1 end end end local tbl, i = {}, 1 --loop start ::parse:: local char = sub(str, i, i) --end of table if char == &quot;\25&quot; then return tbl, i --table key elseif char == &quot;\30&quot; then local key, j = get_value(str, i) local value, k = get_value(str, j + 1) tbl[key] = value i = k + 1 --value elseif ord(char) &lt; 32 then local value, j = get_value(str, i) add(tbl, value) i = j + 1 end --loop end goto parse return tbl 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></div></div></div></p> <h3>usage</h3> <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> <div> <div class=scrollable_with_touch style="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>--example table tbl1 = { true, false, 3, &quot;four&quot;, &quot;binarystring\31\30\6\21\\2\3\23\4\0&quot;, foo = &quot;bar&quot;, { true, false, 3, &quot;four&quot;, &quot;binarystring\31\30\6\21\\2\3\23\4\0&quot;, foo = &quot;bar&quot;, { true, false, 3, &quot;four&quot;, &quot;binarystring\31\30\6\21\\2\3\23\4\0&quot;, foo = &quot;bar&quot; } } } --serialize str = tbl_serialize(tbl1) --deserialize tbl2 = tbl_deserialize(str) --validate tbl_serialize_validate(tbl1, tbl2) --output printh(escape_binary_str(str), &quot;@clip&quot;)</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p></div></div></div></p> https://www.lexaloffle.com/bbs/?tid=48023 https://www.lexaloffle.com/bbs/?tid=48023 Sat, 04 Jun 2022 00:46:17 UTC Unexpected .__index behavior with all() and foreach() vs ipairs() <p>I don't feel like I have the greatest grasp on Lua metatables/metamethods, but I came across some unexpected behavior this week and was wondering if this is a bug. Example cart attached.</p> <p>I'm setting up a &quot;class&quot; like so:</p> <div> <div class=scrollable_with_touch style="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>class = {} class.__index = class function class:new(instance) local instance = instance or {} setmetatable(instance, self) instance.__index = instance add(self, instance) return instance 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>To save tokens, and since I never expect to have numeric indexes in <code>class</code> or any subclasses I instantiate from it, I simply add the instance to whatever object is <code>self</code> when <code>:new()</code> is called. ie, <code>class[1]</code> is a subclass, and <code>subclass[1] == class[1][1]</code>.</p> <p>This works great if I use vanilla Lua <code>ipairs()</code> to iterate over <code>subclass</code>, but if I use Pico-8's <code>all()</code> or <code>foreach()</code> built-ins, things start breaking. Unlike with <code>ipairs()</code>, if <code>#subclass &lt; #class</code>, the loop continues and retrieves any remaining values from <code>class</code>! So, in the example below, the <code>all()</code> loop will correctly access <code>class[1][1].foo</code> on the first iteration, but instead of stopping, it will then try to access <code>class[2].foo</code>.</p> <p>EDIT: Forgot to mention, <code>#class[1][1]</code> / <code>#subclass1</code> and/or <code>count(class[1][1])</code> / <code>count(subclass1)</code> report the expected counts, so a C-style for loop would also work.</p> <div> <div class=scrollable_with_touch style="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>subclass1 = class:new() subclass2 = class:new() subclass1:new({ foo = &quot;bar&quot; }) -- assertion passes for _, instance in ipairs(subclass1) do assert(instance.foo) end -- assertion fails for instance in all(subclass1) do assert(instance.foo) 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 don't mind using <code>ipairs()</code>, but since it does cost an extra token, I'm hoping this is a bug!</p> <p> <table><tr><td> <a href="/bbs/?pid=108418#p"> <img src="/bbs/thumbs/pico8_yujisogeba-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=108418#p"> yujisogeba</a><br><br> by <a href="/bbs/?uid=44175"> ridgekuhn</a> <br><br><br> <a href="/bbs/?pid=108418#p"> [Click to Play]</a> </td></tr></table> </p> https://www.lexaloffle.com/bbs/?tid=46929 https://www.lexaloffle.com/bbs/?tid=46929 Fri, 11 Mar 2022 03:55:38 UTC Collision detection and rotated sprites? <p>Hi friends,</p> <p>My next project is likely going to need to rotate sprites, so I've been looking at the various methods posted on the bbs. Something I'm wondering about while I've been looking at everyone's examples is, how does one approach collision detection for when a sprite is rotated? </p> <p>I'm currently capable of AABB and bitmasking per row of pixels, but it seems I'm going to have to write some new methods to integrate either of these into a rotation algorithm, and I'm not sure where to start. I'd appreciate any links to any carts or non-p8 articles or anything, really!</p> <p>CPU is also a concern for me, as I think I'm going to need a lot of it dedicated to drawing the backgrounds I need which would be rendered via something like <a href="https://www.lexaloffle.com/bbs/?tid=38887">spellcaster's rle library</a>. </p> <p>Thanks in advance! :)</p> https://www.lexaloffle.com/bbs/?tid=39110 https://www.lexaloffle.com/bbs/?tid=39110 Tue, 04 Aug 2020 21:56:26 UTC How to get USB gamepads working on Raspberry Pi <p>EDIT: See the first reply below if you'd rather compile and use the native tool, which does seem more streamlined!</p> <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;">Hi, friends!</p> <p>I just put Pico-8 on my Raspberry Pi for the first time and ran into problems getting my USB gamepads to work. Unfortunately, there's no ARM build for the <a href="https://generalarcade.com/gamepadtool/">General Arcade SDL2 Gamepad Tool</a>, and I didn't want to bother with compiling the native helper, so I had to take this manual route. This will only take you a couple minutes.</p> <p>The final SDL string will look something like this:</p> <img style="margin-bottom:16px" border=0 src="/media/44175/Screen Shot 2020-07-15 at 11.02.40 PM.png" alt="" /> <hr /> <p>First, let's get the GUID.</p> <p><a href="https://github.com/gabomdq/SDL_GameControllerDB/issues/110">This issue</a> in the <a href="https://github.com/gabomdq/SDL_GameControllerDB">GameControllerDB repo</a> tells us a little bit about the GUID structure in SDL 2.0.5+. It varies between operating systems, and so if you copied it from a different OS to Raspbian, this might be the cause of your woes (as it was mine)!</p> <p>Open a terminal and run:</p> <div> <div class=scrollable_with_touch style="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>$ cat /proc/bus/input/devices</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>You should see your device listed in the output. We'll be concerned with the three circled values in the sysfs path, and also the version number above it. We'll come back to this output later for the name and input device path:</p> <img style="margin-bottom:16px" border=0 src="/media/44175/5_Screen Shot 2020-07-15 at 10.48.29 PM.png" alt="" /> <p>Convert the endianness of the three syspath IDs, and append the version. (Swap the first two characters with the last two and add four 0s). So for my gamepad:</p> <ul> <li>0003 = 03000000</li> <li>081f = 1f080000</li> <li>e401 = 01e40000</li> <li>0110 = 10010000</li> </ul> <p>and the end result: 030000001f08000001e4000010010000</p> <p>I'm not sure if case matters here, but I went with all lowercase since I know it works.</p> <hr /> <p>I tried different names and SDL doesn't seem to care what you call the gamepad, but I went with the weirdo name I was provided, extra spaces and all:</p> <img style="margin-bottom:16px" border=0 src="/media/44175/7_Screen Shot 2020-07-15 at 10.48.29 PM.png" alt="" /> <hr /> <p>Finally, let's get our mappings. Install jstest if you don't have it:</p> <div> <div class=scrollable_with_touch style="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>$ sudo apt update $ sudo apt install jstest</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>And also refer to the Handler section in our original output to know which input device to pass to jstest. </p> <img style="margin-bottom:16px" border=0 src="/media/44175/8_Screen Shot 2020-07-15 at 10.48.29 PM.png" alt="" /> <p>For me, it's js0, so I'll pass /dev/input/js0 to jstest:</p> <div> <div class=scrollable_with_touch style="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>$ jstest --normal /dev/input/js0</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 output looks like this, and is interactive. Each switch should flip when you push a button on the gamepad. Be sure to note the corresponding axis or button numbers. </p> <img style="margin-bottom:16px" border=0 src="/media/44175/Screen Shot 2020-07-16 at 12.28.12 AM.png" alt="" /> <p>Now that we know what button is what, we just need to add them to our config string. SDL assumes an Xbox-like gamepad layout. Together with the standard Pico-8 layout it will be mapped like this, but with the button numbers you collected from jstest:</p> <ul> <li>a: ❎</li> <li>b: 🅾️</li> <li>x: 🅾️</li> <li>y: ❎</li> <li>start: pause/options menu</li> <li>dpup: ⬆️</li> <li>dpdown: ⬇️</li> <li>dpleft: ⬅</li> <li>dpright: ➡</li> </ul> <hr /> <p>Finally, put it all together! Here's what mine looks like, with funky spaces in the name and all buttons mapped: (note how the axes are expressed as -a1, +a1, -a0, +a0)</p> <div> <div class=scrollable_with_touch style="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>030000001f08000001e4000010010000,USB gamepad ,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,lefttrigger:b6,righttrigger:b7,</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Drop that into your sdl_controllers.txt, and it should map successfully. Fire up Pico-8 in a separate terminal window, and then check the log. You should see something like this towards the end:</p> <img style="margin-bottom:16px" border=0 src="/media/44175/11_Screen Shot 2020-07-16 at 12.45.09 AM.png" alt="" /> <p>If it was unsuccessful, it will look like this:</p> <img style="margin-bottom:16px" border=0 src="/media/44175/Screen Shot 2020-07-16 at 12.46.41 AM.png" alt="" /> <p>Good luck! 😃</div></div></div></p> https://www.lexaloffle.com/bbs/?tid=38841 https://www.lexaloffle.com/bbs/?tid=38841 Thu, 16 Jul 2020 04:53:33 UTC Zipped MacOS binary won't launch if exported with a '.' in the name <p>Ran into this on MacOS Mojave. If you put a '.' in the filename when you export binaries, the unzipped app will launch just fine, but the zipped one won't.</p> <p>I made a quick video:<br /> <a href="https://youtu.be/NZHUZV4gLGU">https://youtu.be/NZHUZV4gLGU</a></p> https://www.lexaloffle.com/bbs/?tid=38830 https://www.lexaloffle.com/bbs/?tid=38830 Wed, 15 Jul 2020 14:40:26 UTC Star Trek: Killer Q'egh <p> <table><tr><td> <a href="/bbs/?pid=79308#p"> <img src="/bbs/thumbs/pico8_mozonogozi-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=79308#p"> Star Trek: Killer Q'egh</a><br><br> by <a href="/bbs/?uid=44175"> ridgekuhn</a> <br><br><br> <a href="/bbs/?pid=79308#p"> [Click to Play]</a> </td></tr></table> </p> <p>Hi, friends!</p> <p>I've just finished my first ever video game!</p> <p>I just want to thank this entire community for existing and being so helpful and friendly. I discovered Pico-8 in April; at the peak of COVID-19 hitting my hometown, and in the depths of a massive depression brought on by isolation/lack of work/personal losses from the pandemic. It's been a lifelong dream to make a game, but I never thought I'd ever actually accomplish it, and making a little progress on this project each day feels like one of the few things that has really kept me going. So, thank you all!!!</p> <p>Special thanks to <a href="https://www.lexaloffle.com/bbs/?uid=13822"> @Liquidream</a> for leading me here in the first place, and being kind enough to do some playtesting and providing lots of helpful feedback along the way. Also thanks to <a href="https://www.lexaloffle.com/bbs/?uid=10198"> @MBoffin</a> for their zine, which got me started, and for feedback in the forums when I was trying to figure out managing game state.</p> <p>Also, I have a resprite with (better?) music up on itch.io:<br /> <a href="https://ridgek.itch.io/killer-kegs">https://ridgek.itch.io/killer-kegs</a></p> <p>I think I'm here to stay! On to the next one!</p> https://www.lexaloffle.com/bbs/?tid=38816 https://www.lexaloffle.com/bbs/?tid=38816 Tue, 14 Jul 2020 11:00:07 UTC itch.io and iOS pinch/zoom workarounds? <p>Hi friends, does anyone have a hacky JS workaround for preventing pinch/zoom on itch.io in iOS? I just uploaded my first Pico-8 game there and it's more or less unplayable. (I don't own an Android device, so I don't know if this is also a problem on there.) Looks like the exported JS from 0.2.1b already employs a few workarounds to prevent touch gestures, but this doesn't do much when it's in an iFrame because you can still pinch and zoom on the parent document. </p> https://www.lexaloffle.com/bbs/?tid=38801 https://www.lexaloffle.com/bbs/?tid=38801 Mon, 13 Jul 2020 02:42:10 UTC Is this a sensible way to manage game state? <p>Hello, new friends! I discovered Pico-8 a few weeks ago and this is my first post in here!</p> <p>I'm currently trying to create a framework to manage game state for some future creation, and am hoping to get some feedback on what I've put together so far. Any insight would be greatly appreciated; I'm a web developer and consider myself reasonably proficient in PHP/JS, but this is my first Pico-8 project/first video game/first time working with Lua/first time writing my own FSM ever, so I'm feeling very unsure of myself! I'm looking over it and asking myself questions like; have I over-complicated this? Does the game/level hierarchy make sense? Is it DRY enough? Is there a better way!? etc, etc!</p> <p>The state hierarchy of the cart looks like this:</p> <div> <div class=scrollable_with_touch style="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>App |_Title Menu State |_Config Menu State |_Game State |_Init |_Running | |_Level State | |_Start | |_Running | |_End |_Over</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>So, the first state the app is in is the Title Menu state, where you can either start the game or enter the Config Menu (for picking levels to start on or some other arbitrary config). From either of those, you can enter the Game State. Once we're in the Game State, it initializes, then begins running through the Level States (which just run 3s timers for demo purposes). Each level gets a Start state for saying 'ready, go' or whatever, a Running state for actually playing the game, and an End state for congratulating the player for completing the level or something. </p> <p>One thing I did which I noticed is different from some of the tutorials I've seen is that I'm calling _init() rather than game_init() or level_init() when I make any state change. I realize this isn't super efficient, but I think it makes sense because any time I make a state change at any level, the program has to flow through the entire FSM hierarchy, which might be easier to debug in the future maybe? Does that make sense, or am I just wasting CPU cycles?</p> <p>I'm looking forward to learning more from everyone, and hopefully making something actually enjoyable some day! Thanks!!! :)</p> <p>Cart is attached, and also <a href="https://github.com/ridgekuhn/p8gamestate">on GitHub</a></p> <p> <table><tr><td> <a href="/bbs/?pid=77097#p"> <img src="/bbs/thumbs/pico8_dojotizoko-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=77097#p"> dojotizoko</a><br><br> by <a href="/bbs/?uid=44175"> ridgekuhn</a> <br><br><br> <a href="/bbs/?pid=77097#p"> [Click to Play]</a> </td></tr></table> </p> https://www.lexaloffle.com/bbs/?tid=38107 https://www.lexaloffle.com/bbs/?tid=38107 Sun, 24 May 2020 03:12:04 UTC