JadeLombax [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=42638 Sector 498: A tiny space shmup <p> <table><tr><td> <a href="/bbs/?pid=167226#p"> <img src="/bbs/thumbs/pico8_sector498-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=167226#p"> sector498</a><br><br> by <a href="/bbs/?uid=42638"> JadeLombax</a> <br><br><br> <a href="/bbs/?pid=167226#p"> [Click to Play]</a> </td></tr></table> <br /> Galactic year 2387. Things have been rather dull on your first assignment for the Star Corps, patrolling a quiet trade route. Suddenly a massive, deadly Zorlon swarm appears, seemingly from nowhere, and you're the only thing standing between it and a nearby peaceful planet. You frantically punch out a distress call, but a sinking feeling in your gut tells you help might not come soon enough. Well, time to blast as many as you can...</p> <hr /> <p>Controls:<br /> Dpad - Move<br /> Z/X - Fire</p> <hr /> <p>This is my attempt at fitting a simple shmup into &lt;=500 characters for Tweet Tweet Jam 10. Shoutout to Krystman, whose Youtube shmup tutorials were a big inspiration.</p> https://www.lexaloffle.com/bbs/?tid=149073 https://www.lexaloffle.com/bbs/?tid=149073 Mon, 19 May 2025 03:44:21 UTC Super Mario Bros. <p> <table><tr><td> <a href="/bbs/?pid=156989#p"> <img src="/bbs/thumbs/pico8_smbp8-13.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=156989#p"> smbp8</a><br><br> by <a href="/bbs/?uid=42638"> JadeLombax</a> <br><br><br> <a href="/bbs/?pid=156989#p"> [Click to Play]</a> </td></tr></table> </p> <ul> <li>Version 1.04</li> </ul> <p>This is a recreation of the original Super Mario Bros, crammed into under 24KB of a Pico-8 cartridge (spritesheet memory is unused). The code is all new and not ported from the original game, so things work differently, but I tried to make it feel similar.</p> <p>It includes all original levels, the minus world, and the second quest. Due to the token limit and limited likelihood of use, the alternating 2-player mode has been replaced with just playing as Mario or Luigi. Hope you enjoy playing!</p> <hr /> <p>Controls:</p> <p>L/R--------------Move/Select world on title screen<br /> X/V--------------Run/Shoot Fireball<br /> Z/C--------------Jump/Start</p> <hr /> <p>Changelog:</p> <p>V1.01</p> <ul> <li>Added Attract Mode</li> <li>Narrow cloud platforms now draw correctly</li> <li>Pressing run button while on vine no longer causes error</li> </ul> <p>V1.02</p> <ul> <li>Fixed flagpole cutscene glitch</li> </ul> <p>V1.03</p> <ul> <li>Running momentum is now maintained while jumping and shooting fireballs</li> <li>Cart now fits within compressed code size limit</li> </ul> <p>V1.04</p> <ul> <li>Fixed errors caused by fragile lifts and shooting a fireball just before touching a flagpole</li> </ul> <hr /> <p>Special thanks to:</p> <ul> <li>Jwinslow23 for composing the music and many of the sound effects</li> <li>Zep for his PX9 compression system</li> <li>Thisismypassword for the Shrinko-8 minifier</li> <li>Nick N. Bruns of NESmaps.com for documenting level maps</li> </ul> https://www.lexaloffle.com/bbs/?tid=145191 https://www.lexaloffle.com/bbs/?tid=145191 Thu, 07 Nov 2024 04:16:26 UTC Celeste 1K <p> <table><tr><td> <a href="/bbs/?pid=155640#p"> <img src="/bbs/thumbs/pico8_celeste1k-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=155640#p"> celeste1k</a><br><br> by <a href="/bbs/?uid=42638"> JadeLombax</a> <br><br><br> <a href="/bbs/?pid=155640#p"> [Click to Play]</a> </td></tr></table> <br /> This is a scaled-back version of Celeste Classic in just 1KB of compressed code. Originally planned to submit it to Pico1K Jam 2024, but didn't make the deadline. It includes the first 3 levels of the original game, and runs at 60FPS. I tried to make it feel as much like the original as possible, hope you enjoy playing it.</p> https://www.lexaloffle.com/bbs/?tid=144717 https://www.lexaloffle.com/bbs/?tid=144717 Sat, 12 Oct 2024 16:56:23 UTC Resurface <p> <table><tr><td> <a href="/bbs/?pid=155121#p"> <img src="/bbs/thumbs/pico8_resurface-4.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=155121#p"> resurface</a><br><br> by <a href="/bbs/?uid=42638"> JadeLombax</a> <br><br><br> <a href="/bbs/?pid=155121#p"> [Click to Play]</a> </td></tr></table> </p> <p>System Rebooting...</p> <p>GZ-Series Autonomous Mapping Platform, Serial No. 82910-K5</p> <p>Multiple component errors detected due to EM Pulse and impacts sustained from fall</p> <p>Mission-critical systems damaged and/or missing</p> <p>Long-range radio inoperative</p> <p>Recalculating mission parameters...</p> <ul> <li>Explore newly-discovered subterranian biome of exoplanet and reacquire 4 missing mobility components and 8 power cells</li> <li>Attempt to resurface and rendezvous with mobile base to transmit stored data and receive necessary repairs</li> </ul> <p>Minimal power remaining...</p> <hr /> <p>This is my entry for Pico1K Jam 2024, and my first attempt at a Metroidvania game. Hope you enjoy playing it!</p> <hr /> <p>V1.01: Wall jump behavior is now more consistent, and destructible blocks now differ slightly in appearance<br /> V1.02: Fixed double jump glitch</p> https://www.lexaloffle.com/bbs/?tid=144517 https://www.lexaloffle.com/bbs/?tid=144517 Tue, 01 Oct 2024 03:05:08 UTC Snake 1999 (TweetTweet Jam 9) <p> <table><tr><td> <a href="/bbs/?pid=148603#p"> <img src="/bbs/thumbs/pico8_snake1999-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=148603#p"> snake1999</a><br><br> by <a href="/bbs/?uid=42638"> JadeLombax</a> <br><br><br> <a href="/bbs/?pid=148603#p"> [Click to Play]</a> </td></tr></table> </p> <p>This is a version of the Snake game that came on old Nokia phones, complete with simulated phone bezel and greenscale display. To fit within the 500 character jam limit, I had to change a couple mechanics to save space, which made it play a bit more like the later Snake II, so I guess you could think of this as a a late 90's missing link. The name's also a reference to an awesomely funky 70's sci-fi show. <a href="https://www.imdb.com/title/tt0072564/">https://www.imdb.com/title/tt0072564/</a> Hope you enjoy playing it!</p> <p>Controls</p> <p>Dpad----Move</p> <p>Menu----Restart</p> <p>Sourcecode:</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>c={}n=5k=20h=9p=85::_::o=ovalfill?&quot;⁶1⁶c6⁶!5f10+⬅️5✽●6⌂3&quot; for j=0,1do for i=1,#c do z=i%4if(btn(z))➡️=(z+(z+1)%3)/4 camera(j,j)?&quot;□⁶!5f34&sup2;&quot;,p%k*5+16,p\k*5+41,j*7 s=c[i]?'⁶x1█',s%k*5+15,s\k*5+41 rect(13,39,116,102)?n*5-25,16,32 if(█&gt;0and s==h)█=0?&quot;⁷e6&quot; if(s==p)p=rnd(240)\1n+=1?&quot;⁷e5&quot; end end if(⬅️%5&lt;█)add(c,h)ˇ=(➡️-ˇ)^2!=.25and ➡️ or ˇ h=(h+sin(ˇ))%k+(h\k+cos(ˇ))%12*k deli(c,#c\n)⬅️+=1for i=1,3do rectfill(14-i,32-i,118,105,6143+i)end for i=0,2do o(4-i,-94-i,125+i,186+i,6147+i)o(33,122+i,94,140)end goto _</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> https://www.lexaloffle.com/bbs/?tid=142334 https://www.lexaloffle.com/bbs/?tid=142334 Sat, 18 May 2024 23:33:15 UTC Super Mario Bros. Demo <p> <table><tr><td> <a href="/bbs/?pid=141381#p"> <img src="/bbs/thumbs/pico8_smbdemo-9.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=141381#p"> smbdemo</a><br><br> by <a href="/bbs/?uid=42638"> JadeLombax</a> <br><br><br> <a href="/bbs/?pid=141381#p"> [Click to Play]</a> </td></tr></table> </p> <p><strong>V1.02 --Added Minus World</strong><br /> <strong>V1.03 --Fixed minus world bugs, completed scoring system, tweaked jump physics</strong></p> <p>This is a demo for my Pico-8 port of Super Mario Bros., and it includes all of World 1, along with the secret 'minus world'. I plan to reskin the game before a full release to avoid potential Cease-and-Desist letters, but wanted to give people a taste of it in its original form. Also, not everything is quite finished, and I figured this would be a good way to get some playtesting and feedback, so please let me know if you encounter any bugs.</p> <p>Special thanks to:</p> <ul> <li>Jwinslow23 for composing the music and many of the sound effects</li> <li>Zep for his PX9 compression system</li> <li>Thisismypassword for the Shrinko-8 minifier</li> <li>Nick N. Bruns of NESmaps.com for documenting level maps</li> </ul> https://www.lexaloffle.com/bbs/?tid=140166 https://www.lexaloffle.com/bbs/?tid=140166 Sat, 10 Feb 2024 20:01:52 UTC Help recovering a corrupted .p8 file? <p>For the past several months I've been working on a full port of the original Super Mario Bros. for Pico-8. Just today, I was working on implementing level checkpoints, and a few hours after stopping work on the prototype and putting my laptop to sleep, I came back to it. As happens sometimes, Windows went through a lengthy update process, and after it ended I attempted to bring up the file, and this did not work. On investigation, I found that the file now took 102KB, and was unloadable. I then attempted to load it using Notepad++, but all I saw was a tremendously long single line of blank spaces that read &quot;nul&quot; when I highlighted them.</p> <p>If anyone knows of any methods for recovering .p8 files that have become corrupted, I would greatly appreciate any advice. I have been saving the prototype using the same file name for a long time, and the most recent alternate version I have is from 3 months ago, and it would require a great deal of time and work to rebuild.</p> https://www.lexaloffle.com/bbs/?tid=55096 https://www.lexaloffle.com/bbs/?tid=55096 Tue, 21 Nov 2023 02:22:56 UTC Any suggestions for saving video clips with audio? <p>I was wondering, what's a good straightforward way to directly record video of your Pico-8 project with audio? I've been working to implement music and sound effects in a game, and wanted to figure out how to share what it sounds like without requiring people to download the unfinished cart. I imagine I'm far from the first person to ask this, but a search didn't turn up any results. Thanks.</p> https://www.lexaloffle.com/bbs/?tid=54646 https://www.lexaloffle.com/bbs/?tid=54646 Wed, 18 Oct 2023 05:50:23 UTC Quest for the Master Sword <p> <table><tr><td> <a href="/bbs/?pid=135322#p"> <img src="/bbs/thumbs/pico8_qftms-2.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=135322#p"> qftms</a><br><br> by <a href="/bbs/?uid=42638"> JadeLombax</a> <br><br><br> <a href="/bbs/?pid=135322#p"> [Click to Play]</a> </td></tr></table> </p> <p>Legend says an ancient blade with the power to banish evil lies in this uninhabited land. Explore mountains, plains, lakes, and caverns in your search for the hidden Shrine of Illusion which guards the blade, and strengthen yourself by seeking out all seven heart containers scattered throughout the land. Godspeed, hero!</p> <hr /> <p><strong>Controls</strong></p> <p>Arrow keys - Move<br /> X button - Search solid tiles above you for secret passages</p> <hr /> <p>Entry for Pico1K jam 2023 using &lt;=1024 compressed bytes<br /> <a href="https://jadelombax.itch.io/quest-for-the-master-sword">https://jadelombax.itch.io/quest-for-the-master-sword</a></p> <p>Code:</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>s=&quot;も&sup3;ン▥ホ▥ン」ホ」ン。もᵉちちも&sup2;し」ˇ」ˇ」ˇ▥し▥&lt;ᵉちちむ⌂&gt;3シぬCひSほC3b⌂ちちむち&gt;はシ4C4S3Cはbちちちそむち🅾️◜に&sup3;てそッち█+マゆ?P&sup1;tんUコツレWョュエユれ\0@◝よつjつjつjつjつjつjVU◝よつjつjつjつjつjつjVUちち&sup2;ち&sup2;そ\nき&sup2;そ&sup2;ちちちちちちちちちちちちちちむUレ\0ユちむたちすちあちjちちたちすちあちjちjちあちすちたjちあちすちたちちちちちむちちちちちちなちちちち❎ち❎ち❎ち❎ちしちしなしちしち&quot;for i=0,895 do sset(i\8,i%8,ord(&quot;34903416701m1l6&quot;,i\128*2+ord(s,i\4+1)\4^(i%4)%4))end cls(☉)?&quot;⁶!5f56█&quot; s=&quot;\0フひᵉ⁴か\0コ/KすかCのo⁙[=&sup1;\\&lt;&gt;nュ cU、テo⁷しD(#dᶠぬD ᵇo@2oVのケ⁷Zよ゜○よ*ふて\0ひ\rPむふᵉ よ|Q⁵⁴#$(。ア\nみふ0*よ6{に&sup3;fm&sup1;g\\?rに。d4&gt;ゅO,&sup3;ᶠ⬇️はoRひ?Hひl&sup1;は\rZラノ⁴○に⁸□⁸⁘ぬオ⁴{g&sup3;fO ⁘;&sup1;⁵ 8ひア^の○&sup2;&sup3;⁸4\n\n゛⁸\nᶜ{g&sup3;q⁶&sup1;⁴6▶'ᶠ⁸{g⁙ ?Tひに&gt;⁵「&lt;{gᵇ⁘;ᵇ&sup3;V⁵&amp;ᵇ⁸{g.&hellip;█\0&sup1;\n\0 ᵇ&yen; \n\0&sup1;ᵇ,⁶\nl{g⁷;⁶⁵⁘\nヌひO⁴ \n&yen; \n ⁶⁸6z_⁶⁷\n⁶&sup3;⁸&quot;for i=1,#s,3 do a,b,c=ord(s,i,3)⬅️+=a\2({rectfill,ovalfill})[a%2+1](⬅️%128,⬅️\128*11+b%11,⬅️%128+max(b\11,b\11*16-223),⬅️\128*11+b%11+max(c\16,c\16*11-98),c%16)end for i=0,▥ do mset(i%128,i\128,pget(i%128,i\128))end a,b,c=128*4,88*4,&quot;⁶y3&yen;&yen;&yen;&quot;x=584y=400::s:: cls(☉)h=btn()%2-btn()\2%2v=btn()\4%2-btn()\8%2 if(h!=0)p=2+x\4%2웃=h if(v!=0)p=1+v/2웃=y\4%2 if(mget(x/8,y/8)==10)y+=v*560b+=v*528☉=v/2 if(mget(x/8,y/8)==7)☉=13 if(btn()\28*mget(x/8,y/8+71-.5)==10)mset(x/8,y/8-.5,10) if(mget(x/8,y/8)==8)mset(x/8,y/8,15)c..=&quot;&yen;&quot; if(mget(x/8-h/2,y/8-v/2)\7&gt;a%128+b%88)x-=h y-=v a=mid(a+4,x\128*128,a-4)b=mid(b+4,y\88*88,b-4)map(0,0,-a,32-b) spr(p,x-3-a,y+28-b,.9,1-mget(x/8,y/8)%14\12/2,웃&gt;0) ?&quot;⁶!5f0c⁶\r0000😐⬅️&quot; if(☉&gt;1)map(56,88,-a%128,32-b%88,16,11)map(56,88,-a%128-128,32-b%88,16,11)map(56,88,-a%128,120-b%88,16,11) rectfill(0,0,128,31,0) rectfill(0,120,128,128) ?c,88,16,8 ?&quot;⁶1⁶!5f0c&sup2;&sup1;&quot; goto s</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> https://www.lexaloffle.com/bbs/?tid=54435 https://www.lexaloffle.com/bbs/?tid=54435 Tue, 03 Oct 2023 03:57:10 UTC Run, Jelpi, Run! <p> <table><tr><td> <a href="/bbs/?pid=129760#p"> <img src="/bbs/thumbs/pico8_rjr-2.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=129760#p"> rjr</a><br><br> by <a href="/bbs/?uid=42638"> JadeLombax</a> <br><br><br> <a href="/bbs/?pid=129760#p"> [Click to Play]</a> </td></tr></table> </p> <p><em>v1.1: Fixed occasional impossible jumps</em></p> <p>This is a little endless runner game featuring Pico-8 mascot Jelpi in just 500 characters of code. I tried to cram in the best graphics and parallax scrolling that would fit. Hope you enjoy it.<br /> (Submission to TweetTweetJam 8)</p> <p>Controls:</p> <p>Jump----Any button<br /> Restart--reset</p> https://www.lexaloffle.com/bbs/?tid=52734 https://www.lexaloffle.com/bbs/?tid=52734 Mon, 15 May 2023 19:27:51 UTC Mega Man Demo (updated 6/5/25) <p> <table><tr><td> <a href="/bbs/?pid=123975#p"> <img src="/bbs/thumbs/pico8_mmdemo_1-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=123975#p"> mmdemo_1</a><br><br> by <a href="/bbs/?uid=42638"> JadeLombax</a> <br><br><br> <a href="/bbs/?pid=123975#p"> [Click to Play]</a> </td></tr></table> </p> <p> <table><tr><td> <a href="/bbs/?pid=123975#p"> <img src="/bbs/thumbs/pico8_mmdemo_0-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=123975#p"> mmdemo_0</a><br><br> by <a href="/bbs/?uid=42638"> JadeLombax</a> <br><br><br> <a href="/bbs/?pid=123975#p"> [Click to Play]</a> </td></tr></table> </p> <p>This is a work-in-progress demo of my Pico-8 port of the original NES Mega Man. It's a longer-term project, so I figured I'd put out some demos as I finish parts of it.</p> <p>V1.0:</p> <ul> <li>Cut Man's stage playable with enemies, objects, powerups, music, and sound effects<br /> (music and sound effects by <a href="https://www.lexaloffle.com/bbs/?uid=30036"> @ScrubSandwich</a>)</li> </ul> <p>V0.1:</p> <ul> <li>All 6 robot master stages available to explore, but no enemies or sound</li> </ul> <p>Controls:</p> <p>Dpad-----Move<br /> Z/C--------Shoot<br /> X/V--------Jump/Select stage<br /> Enter:<br /> Tap------Select weapon<br /> Hold-----Menu</p> https://www.lexaloffle.com/bbs/?tid=51064 https://www.lexaloffle.com/bbs/?tid=51064 Sun, 08 Jan 2023 22:22:34 UTC 0.2.5e breaks some tweetcarts <p>Just updated to v0.2.5e, and found that it breaks a number of my tweetcarts.<br /> The issue specifically seems to be that this shortcut is no longer supported:</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>if(...)do --thing1 --thing2 --etc. 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>Now to make things work, I have to replace the &quot;do&quot; with &quot;then&quot;. Not a huge change, but it does require a couple more characters, and every one counts when dealing with strict character limits.</p> https://www.lexaloffle.com/bbs/?tid=50785 https://www.lexaloffle.com/bbs/?tid=50785 Fri, 23 Dec 2022 21:33:05 UTC World 1-K (Pico 1k Jam 2022) <p> <table><tr><td> <a href="/bbs/?pid=118195#p"> <img src="/bbs/thumbs/pico8_world1k-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=118195#p"> world1k</a><br><br> by <a href="/bbs/?uid=42638"> JadeLombax</a> <br><br><br> <a href="/bbs/?pid=118195#p"> [Click to Play]</a> </td></tr></table> </p> <p>This is a playable version of World 1-1 from Super Mario Bros. in just 1KB of compressed code. It's basically a proof-of-concept for a number of super-condensed game systems that I've been working on, but hopefully it's fun to play around with, too.</p> <p>Controls:</p> <p>Arrow keys: Move<br /> X button: jump</p> https://www.lexaloffle.com/bbs/?tid=49543 https://www.lexaloffle.com/bbs/?tid=49543 Fri, 30 Sep 2022 07:53:38 UTC Mega Man Test <p> <table><tr><td> <a href="/bbs/?pid=114282#p"> <img src="/bbs/thumbs/pico8_mmdemo-4.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=114282#p"> mmdemo</a><br><br> by <a href="/bbs/?uid=42638"> JadeLombax</a> <br><br><br> <a href="/bbs/?pid=114282#p"> [Click to Play]</a> </td></tr></table> </p> <p>I've been working on a platformer game engine for a little while, but I'd only made a basic run-and-jump. This was an excuse to develop something more capable. While I'm not immediately planning to demake an entire Mega Man game, with PicoMap, my metatile-based map system, it seems possible. I've been working on pixel art and layouts for some levels, so I'll see where things go.</p> <p>Changelog:</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;"><br /> v1.02</p> <ul> <li>Added start menu with 8 selectable weapons</li> <li>Weapon type changes character colors</li> <li>Each weapon type has unique behavior</li> <li>Addded entity spawning system</li> <li>Added enemies that fire bullets at player and respawn</li> <li>Added simple explosions when enemies are destroyed</li> <li>Added a couple frames of coyote time for jumping off of platform edges</li> <li>Improved ladder collision</li> <li>Under 2000 tokens</li> </ul> <p>v1.01</p> <ul> <li>Added teleport intro and auto restart</li> <li>Added damage system and energy meter</li> <li>Tweaked run animation</li> </ul> <p>v1.0</p> <ul> <li>60 fps</li> <li>Variable jump height</li> <li>Scrolling threshold</li> <li>Full character animation</li> <li>Ladders</li> <li>Shooting while running, jumping, and climbing</li> <li>Insta-kill spikes</li> <li>Death explosions</li> <li>Conveyor belts</li> <li>Restart</li> <li>Under 1000 tokens<br /> </div></div></div></li> </ul> <p>Controls:</p> <p>Left/Right---Move<br /> Z------------Shoot<br /> X------------Jump<br /> Enter--------Weapon Select Menu</p> https://www.lexaloffle.com/bbs/?tid=48495 https://www.lexaloffle.com/bbs/?tid=48495 Thu, 14 Jul 2022 01:32:17 UTC Trying to fix jittery character movement <p>I've been working on building a simple and efficient platformer engine, and while it basically works, the character sprite can appear jittery depending on the character and camera movement, and I haven't figured out why. I've uploaded a prototype it you'd like to check it out. If anyone has some ideas or suggestions, I'd appreciate it, thanks.</p> <p>Controls:</p> <p>L\R-----------Move<br /> Z-------------Run<br /> X-------------Jump</p> <p> <table><tr><td> <a href="/bbs/?pid=113854#p"> <img src="/bbs/thumbs/pico8_munirumepe-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=113854#p"> munirumepe</a><br><br> by <a href="/bbs/?uid=42638"> JadeLombax</a> <br><br><br> <a href="/bbs/?pid=113854#p"> [Click to Play]</a> </td></tr></table> </p> https://www.lexaloffle.com/bbs/?tid=48377 https://www.lexaloffle.com/bbs/?tid=48377 Fri, 01 Jul 2022 05:19:22 UTC LCD Clock <p> <table><tr><td> <a href="/bbs/?pid=113342#p"> <img src="/bbs/thumbs/pico8_lcd_clock-2.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=113342#p"> lcd_clock</a><br><br> by <a href="/bbs/?uid=42638"> JadeLombax</a> <br><br><br> <a href="/bbs/?pid=113342#p"> [Click to Play]</a> </td></tr></table> </p> <p>A segmented LCD-style clock. It's pretty simple, but figuring out an efficient way of storing the graphics and not using any spritesheet space was interesting. Entry for the <a href="https://itch.io/jam/pico-8-512-char-jam">Pico-8 512-Char Jam</a>.</p> https://www.lexaloffle.com/bbs/?tid=48215 https://www.lexaloffle.com/bbs/?tid=48215 Sun, 19 Jun 2022 05:26:47 UTC Tetris 1K (Pico1k Jam) <p> <table><tr><td> <a href="/bbs/?pid=97486#p"> <img src="/bbs/thumbs/pico8_tetris_1k-7.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=97486#p"> tetris_1k</a><br><br> by <a href="/bbs/?uid=42638"> JadeLombax</a> <br><br><br> <a href="/bbs/?pid=97486#p"> [Click to Play]</a> </td></tr></table> </p> <p><strong>Version 1.01: Fixed glitch, improved game over screen, corrected next piece preview orientation</strong><br /> <strong>Version 1.02: Fixed game-ending glitch arising from Pico-8 0.2.5 update</strong></p> <p>This is basically a full game of Tetris in 1024 characters, featuring:</p> <ul> <li> <p>Sprite Graphics</p> </li> <li> <p>Next Piece Preview</p> </li> <li> <p>Score System</p> </li> <li> <p>Left/Right Piece Rotation</p> </li> <li> <p>Pieces can be slotted in under ledges</p> </li> <li> <p>Title Screen</p> </li> <li>Game Over State/Restart</li> </ul> <p>Controls:</p> <p>L/R-------Move Piece</p> <p>O---------Rotate Counterclockwise</p> <p>X---------Rotate Clockwise</p> <p>Down---Soft Drop</p> <p>This is an upgrade of my previous Tweettweetjam version of Tetris, and I was able to add a lot of things due to the extra space. A few things that I wanted to include wouldn't fit, like sound effects, level selection, and a fancier title screen, but this has graphics, solid mechanics, and a full game loop. Hope you enjoy playing it!</p> https://www.lexaloffle.com/bbs/?tid=44668 https://www.lexaloffle.com/bbs/?tid=44668 Sat, 18 Sep 2021 11:14:51 UTC BBS won't let me upload text for tutorial <p>I'm currently working on a tutorial for fitting sprite graphics into tweetcarts (<a href="https://www.lexaloffle.com/bbs/?tid=44375">https://www.lexaloffle.com/bbs/?tid=44375</a>), but I've run into a problem. I have a lot of text to upload, but the BBS seems to be putting arbitrary limits on how much I can fit into a post, and it's very frustrating.</p> <p>I'm already stretching the tutorial into multiple posts because for some reason it won't let me add any more text to the intial post, but now it won't even let me upload a reasonably-sized bit of code into a post by itself. I put a similarly-sized chunk of code into the previous post, but in the next one I can only post about 60% of that amount. Any more and the little loading animation just endlessly loops and nothing gets uploaded. If anyone can help me out with this, I'd really appreciate it.</p> https://www.lexaloffle.com/bbs/?tid=44390 https://www.lexaloffle.com/bbs/?tid=44390 Fri, 27 Aug 2021 07:15:10 UTC Tweetcart Sprite Graphics Tutorial <p><strong>updated 9/3/22: Improved encoders with automatic escape-sequence insertion and updated tutorial.</strong></p> <p>Since getting into Pico-8, I've enjoyed finding ways to optimize my code and fit a lot in a small space, and this has included making Tweetcarts. Recently, I've found ways to cram detailed sprite graphics into a tweet and have made various animated demos like these:</p> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/42638/jelpi_tweet_0.gif" alt="" /> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>::_::cls()k=ˇ\2%5memset(26624,204,5^5)n=0for i=1,86do v=ord(&quot;cS2C2Cr232$R$31b1CES2Kc32cKc2#2cK2S2c3K2C2c32KcC23nNfffff6%6565&amp;E&amp;%'575g'%ggggggggggg'&quot;,i)-35for j=0,v\16do sset(n%8,n\8,v)n+=1end z=i%2sspr(0,z*(k*2+6),8,6-z*4,60,65-k\3+z*6)spr(32,i*8-ˇ%8-8,73,1,2)end ˇ+=1flip()goto _</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/42638/39_lemmings_tweet_1.gif" alt="" /> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>pal({-4,-5,15},1)::_::cls()for n=1,380do sset(n%6,n\6,(ord(&quot;+%K%C&amp;S2_$?$7(2_C%K.[2S$S$?$:(&amp;2K-K&amp;S2S$3&amp;S$?$S&amp;C-K&amp;S2S$3&amp;3V7/_#+%K%C&amp;S23&amp;307(2_C%K.[2S$S$3&amp;:(&amp;2K-K&amp;S2S$S$3$?$S&amp;C-K&amp;S2S$?$?T7/_&quot;,n\3+1)-35)\4^(n%3)%4) if(n&lt;7)spr((ˇ+n)\1%8*16,(ˇ+n*32)%176-8,60)end ˇ+=.5flip()goto _</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/42638/pitfall_tweet_0.gif" alt="" /> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>k=139pal(5,k,1)o=ord::_::cls()for i=0,509do v=o(&quot;;C$);C$);C$);C#%+C#%;D$);C$2?D$)?L$2;C$2=S$1[S$A;C$);O(1;C&amp;A/^%//T'#ES&amp;,*&amp;#;737####/+&quot;,i\6+1)-35sset(i%40,i\40,o(&quot;4?;;333&quot;,v\2^(i%6)%2*(i+120)\80))rectfill(0,i*8,k,i*8+7,o('55555::9',i-3))end spr(ˇ\3%5,ˇ%k-8,64,1,2)ˇ+=1flip()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>People have shown interest in learning my techniques, so I decided to make this tutorial. The ideas here could come in handy for tweetcarts, entries for TweetTweetJam or Pico1K Jam, or just fitting more into a regular cart.</p> <h2>Fitting sprite data into strings</h2> <p>In order to fit as much information as we can into a few characters, we'll need to use data strings with the largest possible range of of values, and therefore the largest range of symbols from Pico-8's character set.</p> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/42638/chrprinter_tutorial_0.png" alt="" /> <p>Here's a picture from my CHR Printer tool to illustrate. Characters 0-15 aren't pictured, as P8SCII control codes make printing them problematic, but all of them except characters 1,2,3, and 9 will count as two chars on Twitter. Of the remaining characters, 34, and 92 (shown in red) require an extra backslash character placed in front of them in a string, those which count as two chars on Twitter are shown in blue, and those that count as one are in white. This means the optimum range is the span of 92 characters from 35 (#) to 126 (~).</p> <p>Alternately, if you're not going to post your code to Twitter, such as in the case of the Pico1K Jam, you can use characters 0-255, and you don't need to worry about any counting as 2 chars, though symbols 0,10,13,34, and 92 will still require an extra backslash character, which the encoders below will add automatically.</p> <h3>Important: Since the range of characters we'll be using includes those for Pico-8's Puny Font, Pico-8 must be put into &quot;puny font mode&quot; by pressing ctrl+p before pasting your data strings into it, and you must be in puny font mode when copying from Pico-8 to paste into a tweet. I've had errors pop up many times because I forgot to do this. o_O</h3> <p>Anyway, to turn our string into values, we'll use Pico-8's ord() function, and since the optimal range of characters we can use for tweets start at #35, we'll need to correct for this by adding 35 when encoding. When decoding, we'll subtract 35, like this: <em>value = ord(string,character)-35</em>. If you're not posting to Twitter, you can pick your minimum starting value, for example, setting it to 16 to avoid the escape sequence characters needed for symbols 0,10, and 13, or just setting it to 0 for the full range of characters.</p> <p>Now we can find the maximum number of pixels that each string character can hold. So far I've used two different methods for encoding pixels into characters: directly encoding values for a number of pixels, or a simple version of Run Length Encoding (RLE). RLE is more efficient for sprites with lots of single-color spans, while direct encoding is better for more detailed graphics. For both types, there's a tradeoff between range of possible colors and how many pixels can be encoded within our character range. Here are some examples of different combinations:</p> <h3>Direct pixel encoding (92 possible characters)</h3> <p>6 2-color pixels (2^6=64)<br /> 3 4-color pixels (4^3=64)<br /> 2 9-color pixels (9^2=81)<br /> 1 16-color pixel (16^1=16)</p> <h3>Run-Length Encoding (92 possible characters)</h3> <p>1-46 2-color pixels (2x46=92)<br /> 1-23 4-color pixels (4x23=92)<br /> 1-10 9-color pixels (9x10=90)<br /> 1-5 16-color pixels (16x5=80)</p> <h2>Decoding strings</h2> <p>Once we've encoded our strings, we need to decode them back into images. The most straightforward method would use a few nested loops-- two outer loops for horizontal and vertical position, and an inner loop to iterate through the pixel values described by each character. It would take up a large chunk of a tweet just for these loops, though, so we've got to condense things. Fortunately, we can do this using math, specifically the floor divide () and modulo (%) operators. The modulo operator lets us loop through a specific range of values, while floor divison lets us switch to a new value at a specific point. Used together, these can have all kinds of non-linear effects and replace various conditional logic. Here, index_variable%width gives horizontal position and index_variable\width gives vertical position, and the operators are also used along with ^ to iterate through the color values in a single character for per-pixel decoding, or without to separate the color and run length values for an RLE decoder. In both cases, v equals the value derived from each character of the data string (represented by empty double quotes).</p> <p>Here's the basic setup for a direct pixel decoder, where:</p> <p><em>w = image width in pixels<br /> h = image height in pixels<br /> p = pixels stored per character<br /> c = possible colors per pixel</em></p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>for i=0,(w*h-1)do v=ord(&quot;&quot;,i\p+1)-35sset(i%w,i\w,v\c^(i%p)%c)end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>The expression <strong>v\c^(i%p)%c</strong>, which I guess I'll call the <strong>pixel value</strong>, is where v, the value of each character, is separated out into its component values for each pixel. For instance, if there are 4 possible colors, the value for each pixel will be found by separating out the multiples of 4^0, 4^1, and 4^2,-- AKA 1,4, and 16.</p> <p>And here's the basic setup for an RLE decoder, where:</p> <p><em>t = total characters in string<br /> w = image width in pixels<br /> c = possible colors per pixel</em></p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>k=0for i=1,t do v=ord(&quot;&quot;,i)-35for j=0,v\c do sset(k%w,k\w,v%c)k+=1end end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Here, the run length is stored as a multiple of the total number of possible colors, and the desired color is added to that value. At decoding, we get the pixel value <strong>v%c</strong> by using modulo, and the run length by using floor division. An inner 'for' loop then sets the specified number of pixels to the correct color.</p> <h2>Encoding sprites</h2> <p>Now we need some encoders to build strings for our decoders. The following two encoders work by scanning the top left portion of the spritesheet left to right and top to bottom, and storing either direct pixel values or color and length values in each character. They also automatically determine the largest color value present, and use that to determine how many pixels can be contained in each character. Since color 0 (transparent) is used, the total number of colors will be 1 greater than the highest color value, so if color 9 is used, there are 10 potential colors. If you aren't posting to Twitter and want to use the most possible characters, you can set 'min_val' to 0 and 'max_val' to 255 to use all 256 of them.</p> <h3>Direct pixel encoder</h3> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>width=8 height=8 min_val=35 max_val=126 ----------- cls() top_color=0 for i=0,width*height-1 do col=sget(i%width,i\width) top_color=max(col,top_color) end colors=top_color+1 p=0 while colors^(p+1)&lt;=(min(256,max_val-min_val+1)) do p+=1 end pixels=p tbl={} i=0 while i&lt;width*height do val=0 for j=0,pixels-1 do val+=sget((i+j)%width,(i+j)\width)*colors^j end add(tbl,val+min_val) i+=pixels end str=&quot;&quot; ch=0 for i=1,#tbl do val=tbl[i] nxtval=tbl[i+1] if i&lt;#tbl and nxtval&gt;47 and nxtval&lt;58 and val==0 then str..=&quot;\\000&quot; elseif val==0 then str..=&quot;\\0&quot; elseif val==10 then str..=&quot;\\n&quot; elseif val==13 then str..=&quot;\\r&quot; elseif val==34 then str..=&quot;\\\&quot;&quot; elseif val==92 then str..=&quot;\\\\&quot; else str..=chr(val) end end function cprint(s,y,c) ?s,64-#s*2,y,c end printh(str,'@clip') cprint('string pasted to clipboard',52,11) cprint(1+max_val-min_val..' possible values',60,13) cprint(colors..' colors/pixel',68,13) cprint(pixels..' pixels/character',76,13) cprint(#str..' characters total',84,12) cprint(width*height..' values total',92,6)</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <h3>RLE encoder</h3> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>width=8 height=8 min_val=35 max_val=126 -------- cls() top_color=0 for i=0,width*height-1 do col=sget(i%width,i\width) top_color=max(col,top_color) end colors=top_color+1 max_span=min(256,max_val-min_val+1)\colors tbl={} local n,len=0,0 while n&lt;width*height do local val,nxtval=sget(n%width,n\width),sget((n+1)%width,(n+1)\width) if nxtval==val and len&lt;(max_span-1) then len+=1 else v=val+len*colors add(tbl,v+min_val) len=0 end n+=1 end str=&quot;&quot; ch=0 for i=1,#tbl do val=tbl[i] nxtval=tbl[i+1] if i&lt;#tbl and nxtval&gt;47 and nxtval&lt;58 and val==0 then str..=&quot;\\000&quot; ch+=3 elseif val==0 then str..=&quot;\\0&quot; ch+=1 elseif val==10 then str..=&quot;\\n&quot; ch+=1 elseif val==13 then str..=&quot;\\r&quot; ch+=1 elseif val==34 then str..=&quot;\\\&quot;&quot; ch+=1 elseif val==92 then str..=&quot;\\\\&quot; ch+=1 else str..=chr(val) end end function cprint(s,y,c) ?s,64-#s*2,y,c end printh(str,'@clip') cprint('string posted to clipboard',52,11) cprint(1+max_val-min_val..' possible values',60,13) cprint(colors..' colors/pixel',68,13) cprint(max_span..' pixel max span length',76,13) cprint(#str..' characters total',84,12) cprint(#str-ch..' values total',92,6)</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <h3>Optimizing for encoding</h3> <p>To make the most of your data strings, you'll need to optimize your spritesheet. For example, here are the raw spritesheets for the demos I showed earlier (well, half of the frames for the Lemmings one).</p> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/42638/Jelpi_tweet_spritesheet_1.png" alt="" /> <p>-</p> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/42638/Lemmings_tweet_spritesheet.png" alt="" /> <p>-</p> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/42638/Pitfall_tweet_spritesheet.png" alt="" /> <p>While Jelpi uses colors from Pico-8's full palette and works better with RLE, the Lemmings and Pitfall Harry sprites only use 4 and 2 colors respectively, and both are stored more efficiently using direct pixel encoding. Because of the math involved, if you want to restrict your palette to save space, you'll need to draw the sprites using the lowest-numbered colors. With 4 colors we have to use colors 0-3, and with 2 colors, we use 0 and 1. It looks weird, but we'll fix it later.</p> <p>In addition to this, the Lemmings sprites aren't laid out horizontally as you might expect, but vertically. That's because they're only six pixels wide, so placing them side-by-side would take 1/3 more space than necessary. You'll also notice there aren't full frames of animation for Jelpi's run because there wasn't enough space. Because Jelpi's head is the same in each frame and only the position of the legs change, I just drew the head once and stored stacked animation frames of the 2-pixel high leg area, which will be displayed using the sspr(). Jelpi does move up and down a pixel during the run cycle, but that can be added at runtime by altering the vertical sprite position based on the current frame in the animation cycle using '%' and '\'. As you can see, even with efficient compression, it takes some thought and ingenuity to squeeze sprite graphics and animation down to a few hundred characters.</p> <h2>Sprite recoloring</h2> <p>If you restricted your sprites' color range to save space, you'll need to set the pixels back to the right colors. There are a few different ways to do this, but each one takes around a dozen characters or more, so experiment and compare how many chars it takes to recolor vs. just encoding the right colors in the first place.</p> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/42638/tweet_sprite_recolor_0.png" alt="" /> <p>Using the Lemmings sprites above as an example of recoloring indexed color sprites, I've come up with two main solutions for this. The first lets you recolor using Pico-8's standard palette, as you can see in the second lemming , and the second lets you use any mixture of colors from the standard and dark palettes, which can be a better fit, as seen in the third lemming.</p> <p>The standard color method uses a small extra string placed inside an ord() function to act as a lookup table. Place this into the sset() command in the decoder as the third input, with the pixel value <em>v\4^(i%3)%4</em> used as the string position input. It will intercept the pixel values of 0-3 which the output of the string produces, and instead of using it to color the pixels directly, it will use the small string as a lookup table for the corrected colors. Note that you only need 1 less than the number of colors in your palette, (e.g. 3 string characters for a palette of 4 colors). This is because there's no entry 0 in the string, so color 0 will remain unchanged and transparent, which we'll want. As for which characters to use, you can use any which are in the correct column of the character set, though I like to use chars 48-63 as shown in green below, because it makes things more intuitive for 10 out of the 16 colors. Using these characters, our lookup string will have characters from columns 13,11, and 15, or <strong>&quot;=;?&quot;</strong>.</p> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/42638/Recoloring_chars.png" alt="" /> <p>-</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>for i=0,380do v=ord(&quot;&quot;,i\3+1)-35 sset(i%6,i\6,ord(&quot;=;?&quot;,v\4^(i%3)%4))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>For recoloring using mixed standard and dark palette colors, the most compact way I've found is to declare a small table at the beginning of your code instead of using a lookup string. Like the standard color method, this won't effect color 0, just keep in mind that colors 1-whatever will have those new values wherever they are used. The dark palette colors are usually called by their color palette index number+128, so for medium blue we'd add 12 (light blue) and 128 for 140. I've found that the same effect can be had by just subtracting 16, though, instead of adding 128, which can save a character. So, to get medium blue, we can use 12-16= -4. Likewise, for medium green, we can use 11-16= -5.</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>pal({-4,-5,15},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>-<br /> Now, the Pitfall sprites are more of a special case. They're one bit, or just 0 and 1. This saves space and allows 6 on or off pixels per character for a 92-character range, or 7 if you're using a range of 221 characters, but by default everything will just be dark blue. I've come up with two main methods for dealing with this as well. The first is just setting every 'on' pixel to a certain consistent value, and the second recreates the look of Atari graphics by recoloring the 1-bit sprite on every scanline.</p> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/42638/tweet_sprite_recolor_1.png" alt="" /> <p>For a starting point, this is what the code looks like to paint Harry in basic dark blue.</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>for i=0,509do v=ord(&quot;&quot;,i\6+1)-35 sset(i%40,i\40,v\2^(i%6)%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>Changing the sprite color from dark blue to a single other color is very simple. Since every non-transparent pixel equals 1, just multiply the pixel value <em>v\2^(i%6)%2</em> by the color you want. In the case above, I used 11.</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>for i=0,509do v=ord(&quot;&quot;,i\6+1)-35 sset(i%40,i\40,v\2^(i%6)%2*11)end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>For colors that vary per scanline, we'll need another small lookup string, but this time we need more math. Specifically, we'll take the pixel value and multiply it another expression, (i+120)\80.</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>for i=0,509do v=ord(&quot;&quot;,i\6+1)-35 sset(i%40,i\40,ord(&quot;4?;;333&quot;,v\2^(i%6)%2*(i+120)\80))</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 80 here represents twice the width of pixels of all our sprites, which are 40 pixels wide, and the floor divide means this value will count up by 1 every time i increases by 80, or every two rows, so each character in our lookup string will color two rows of pixels. If we replaced 80 with 40, we'd be able to color each individual row with a string entry. An offset (120) is added to i here because if not, no color would be assigned until two rows had been completed, cutting of Pitfall Harry's head (yikes...). The offset here is 120 specifically because that means the pixels will be set to the color of the first symbol only for the first row, (80 to get to 1, plus 40 so the value will change to 2 after 40 pixels, or 1 row), which is helpful because his brown hair is only one pixel tall.</p> <p><em>Note, these recoloring methods should also with an RLE decoder, just make sure you have the right number of entries in any lookup strings and plug the pixel value of the decoder into them or multiply it by a constant in a similar way. The one possible exception is the per-scanline color trick, haven't tried that with RLE yet.</em></p> <h2>Animating Sprites</h2> <p>Finally, here are a few tips for animating your sprites in very few characters. First of all, since your animations will probably be just looping a set pattern of sprites, we can do that easily with the modulo operator (%). You just need a variable that increases or decreases every frame, what multiple of this you want the animation to update at, and a modulo value to make it loop through a certain number of animation frames. Here are a couple different ways of doing this for the Lemmings sprites, using this expression as the sprite number input in the spr() function.</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>t()\.1%8*16 </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 variable t() is an abbreviation for time(), and will give the time elapsed since startup. By itself this counts up tiny fractions of an integer every frame, and by 1 each second. Neither of these are useful, but floor dividing it by .1 means that the the animation frame will increase by the integer 1 every 10th of a second, or every 3 frames, which is a good speed. This expression is then run through %8, resulting in a sprite number that cycles from 0-7, but then we also need to multiply that by 16 to match up with the right sprite numbers (0,16,32,...), because the sprites are laid out vertically.</p> <p>Since it might be a good illustration and starting point, here's a complete, simplified version of the Lemmings tweet.</p> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/42638/46_tutorial_tweet_2_0.gif" alt="" /> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>pal({-4,-5,15},1)for n=0,380do v=ord(&quot;+%K%C&amp;S2_$?$7(2_C%K.[2S$_$?$:(&amp;2K-K&amp;S2S$S$3&amp;?$S&amp;C-K&amp;S2S$3&amp;3V7/_#+%K%C&amp;S23&amp;307(2_C%K.[2S$S$3&amp;:(&amp;2K-K&amp;S2S$S$3$?$S&amp;C-K&amp;S2S$?$?T7/_&quot;,n\3+1)-35sset(n%6,n\6,v\4^(n%3)%4)end poke(24364,3)::_::cls()spr(t()\.1%8*16,29,28)flip()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>-</p> <p>Next up, here's how the animation code works for Pitfall Harry.</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>spr(ˇ\3%5,ˇ%k-8,64,1,2)ˇ+=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>Here, we use a similar structure, an iterating variable run through a floor divide to determine animation speed, then a modulo to control the number of animation frames. Here, we have a new sprite used every 3 frames, and the there are 5 sprites in the run cycle. The same iterating variable is also used in the x-position, along with a modulo. 'k' here is an alias for the constant value of 139, and combined with a modulo, this is what makes Harry's horizontal position loop. The expression <strong>ˇ%k</strong>, which means <strong>position%139-8</strong> makes his horizontal position cycle from -8 to 130, so he keeps running by.</p> <p>As a side note, the symbol I'm using there, <strong>ˇ</strong>, is character 149 from Pico-8's character set, which you get by pressing shift+v, and looks like two little birds. I'm using it because it has some unique properties. It only counts as one byte in a tweet, but like the other glyphs, it has a default value before being assigned one (in this case it's -2624.5). Because we're running it through a modulo, it's exact value doesn't matter, so we don't need to intialize it, which saves 3 characters =).</p> <p>Finally, Here's the code for displaying the Jelpi demo sprites, showing some more advanced tricks.</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>k=ˇ\2%5... z=i%2sspr(0,z*(k*2+6),8,6-z*4,60,65-k\3+z*6)spr(32,i*8-ˇ%8-8,73,1,2)</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 start, k gives the animation speed (new sprite every 2 frames) and cycle length (5 sprites). With the variable z here I create a value that cycles between 0 (for the head), and 1 (for the body). This is for two reasons. First, it lets me co-opt the same loop that I'm using to set the sprite pixels, to also display all the sprites. The single sspr() function here draws, by turn, both the head and body. The horizontal spritesheet position starting is always the same, but vertical is adjusted by the z variable to be either 0, or cycle through the values 6,8,10,12,and 14. z is also used to cycle sprite height between 6 pixels for the head and 2 pixels for the legs. For vertical position, this is increased by 6 for the legs to put them just below the head, but both head and legs are also modified by <strong>-k\3</strong>. This is what creates the up and down motion for the animation. Because k cycles between 0 and 4, the value will be -1 when k is &gt;=3, so Jelpi will go up one pixel for the 4th and 5th animation frames. (It's so simple o_O).</p> <p>The spr() function draws the ground layer by setting several sprites side by side at 8-pixel increments, and it creates the looping effect by performing a, you guessed it, modulo operation on the position variable, represented by our bird glyph, while 8 is also subtracted to make sure there's never a blank space on the left edge of the screen.</p> <hr /> <p>Wow, we got pretty far in the weeds there, didn't we? Hopefully you were able to get through that and it made sense. Anyway, that's all for now. I hope that gave you some good tools and ideas, and that you have fun squeezing sprite graphics down to an absurdly small size. I look forward to seeing what you come up with. =)</p> https://www.lexaloffle.com/bbs/?tid=44375 https://www.lexaloffle.com/bbs/?tid=44375 Wed, 25 Aug 2021 06:20:22 UTC Floppy Bird (Tweet Tweet Jam 6) <p> <table><tr><td> <a href="/bbs/?pid=94162#p"> <img src="/bbs/thumbs/pico8_floppy_bird-4.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=94162#p"> floppy_bird</a><br><br> by <a href="/bbs/?uid=42638"> JadeLombax</a> <br><br><br> <a href="/bbs/?pid=94162#p"> [Click to Play]</a> </td></tr></table> </p> <p>This is a clone of the infamous Flappy Bird, complete with detailed graphics and 60fps gameplay, and scrunched down to under 560 characters. Any feedback about the controls or physics is welcome.</p> <p>Controls: Press any button to fly upward/restart</p> <p><strong>Version 1.1</strong> - Added high score and a brief pause before gravity kicks in on restart.</p> https://www.lexaloffle.com/bbs/?tid=43572 https://www.lexaloffle.com/bbs/?tid=43572 Mon, 28 Jun 2021 01:10:42 UTC