TinyCat [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=56596 Eight Mages <p> <table><tr><td> <a href="/bbs/?pid=166523#p"> <img src="/bbs/thumbs/pico8_eightsages-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=166523#p"> eightsages</a><br><br> by <a href="/bbs/?uid=56596"> TinyCat</a> <br><br><br> <a href="/bbs/?pid=166523#p"> [Click to Play]</a> </td></tr></table> </p> <p>check out the music video here!<br /> <a href="https://churchbasement.org/#music/eight-mages/">https://churchbasement.org/#music/eight-mages/</a></p> <p>Used Pico8 as the visuals for a music video. Getting TIME() to be actually accurate was the main problem i ran into. Had to sampling beeps from Pico8 using TIME() to trigger them every second, record that into Reaper, ratio the sampled time with the time it should have been, averaging all the ratios, multiplying TIME() with the ratio we found, witch happened to be 1.0007962696777</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>-- 0x1.0034 is as close as Pico8 -- can get to the fration -- 1.0007962696777 local ratio = 0x1.0034 local oldt = 0 local t = 0 function _update() t = (time()*ratio)%1 if t &lt; oldt then sfx(0) end oldt = t end function _draw() cls() circfill(64,64,t*10,7) end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>this was the lua code used to calculate the ratio. we used love2d to run it to get more bit accuracy.</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>--[[ Samples from Reaper's recording of Pico8 Time Pico8 beep 8:00.00 8:00.422 8:30.00 8:30.424 7:30.00 7:30.370 7:45.00 7:45.376 8:15.00 8:15.419 3:30.00 3:30.146 4:00.00 4:00.190 6:00.00 6:00.281 8:00.00 8:00.381 10:00.00 10:00.472 12:00.00 12:00.563 14:00.00 14:00.654 16:00.00 16:00.754 18:00.00 18:00.845 20:00.00 20:00.936 ]] --[[ calculating times in minutes print(30.146 / 60) print(.190 / 60) print(.281 / 60) print(.381 / 60) print(.472 / 60) print(.563 / 60) print(.654 / 60) print(.754 / 60) print(.845 / 60) print(.936 / 60) ]] local samples = { 8.0070333333333333, 8.50706666666667, 7.50616666666667, 7.75626666666667, 8.25698333333333, 3.50243333333333, 4.0031666666666667, 6.0046833333333333, 8.00635, 10.0078666666666667, 12.0093833333333333, 14.0109, 16.012566666666667, 18.014083333333333, 20.0156, } local targets = { 8, 8.50, 7.50, 7.75, 8.25, 3.5, 4, 6, 8, 10, 12, 14, 16, 18, 20, } local average = 0 for i,sample in ipairs(samples) do local ratio = sample / targets[i] print('sample '..i,ratio) average = average + ratio end print('average',average/#samples) --[[ This program prints out... sample 1 1.0008791666667 sample 2 1.000831372549 sample 3 1.0008222222222 sample 4 1.0008086021505 sample 5 1.0008464646465 sample 6 1.0006952380952 sample 7 1.0007916666667 sample 8 1.0007805555556 sample 9 1.00079375 sample 10 1.0007866666667 sample 11 1.0007819444444 sample 12 1.0007785714286 sample 13 1.0007854166667 sample 14 1.0007824074074 sample 15 1.00078 average 1.0007962696777 ]]</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>mabye i'll edit this post once all the stuffs uploaded :)</p> https://www.lexaloffle.com/bbs/?tid=148805 https://www.lexaloffle.com/bbs/?tid=148805 Mon, 05 May 2025 02:06:26 UTC 招き烏 <p> <table><tr><td> <a href="/bbs/?pid=157729#p"> <img src="/bbs/thumbs/pico8_maneki_karasu-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=157729#p"> maneki_karasu</a><br><br> by <a href="/bbs/?uid=56596"> TinyCat</a> <br><br><br> <a href="/bbs/?pid=157729#p"> [Click to Play]</a> </td></tr></table> </p> <p>this was based off of a dream i had.</p> <p>the dream was of a sokoban like game.<br /> you couldn't move the boxes like normal though.<br /> you could only move them like you can in this game.</p> <p><strong>your goal is to squish all the red blocks.</strong> : <strong>you can not squish stacks of blocks.</strong></p> <p><img loading="lazy" style="margin-bottom:16px" border=0 src="/media/56596/howItWorks01.gif" alt="" /> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/56596/23_howItWorks02.gif" alt="" /></p> <p>the name is a play on words of &quot;maneki-neko&quot;.<br /> publishing this quick, i have a new project i need to focus on.</p> <h2>controls</h2> <p>z - land<br /> x - reset cart<br /> arrow keys - move crow</p> <p>find links to this project and others on this website -&gt; <a href="https://churchbasement.org/games/maneki-karasu/">church basement website</a></p> https://www.lexaloffle.com/bbs/?tid=145401 https://www.lexaloffle.com/bbs/?tid=145401 Wed, 20 Nov 2024 05:59:45 UTC Obscurist's Cave <p> <table><tr><td> <a href="/bbs/?pid=146982#p"> <img src="/bbs/thumbs/pico64_obscurists_cave-3.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=146982#p"> obscurists_cave</a><br><br> by <a href="/bbs/?uid=56596"> TinyCat</a> <br><br><br> <a href="/bbs/?pid=146982#p"> [Click to Play]</a> </td></tr></table> <br /> <del>load #obscurists_cave</del> Loading it this way does not seam to work for some reason? You can just use the png download.</p> <h3><strong>NOTICE</strong></h3> <p><strong>As of writing this, key() does not work in the web player. You can use arrow keys and right mouse button as substitutes for WASD and space. Otherwise, I would recommend playing on your own Picotron if you can</strong></p> <h2>CONTROLS - (requires mouse and keyboard)</h2> <ul> <li>WASD - left clump of buttons</li> <li>space - left lone button</li> <li>mouse - track ball</li> <li>left mouse button - right lone button</li> </ul> <h2>HISTORY</h2> <p>This is a port of a physical game/machine called Obscurist's Cave. Obscurist's Cave was made by Lynn Mathewson over the course of 2 years from 2005-2007 as one of his many side projects. Lynn would keep the device in the basement of his house for the next 9 years. After becoming hospitalized in 2016, Lynn would have the device donated to The Media Archaeology Lab, the local computer museum. Lynn insisted that a cassette of Negative Frequencies(1) be available to listen to as visitors played the game, saying that no other piece of music could better describe his mental state during the creation of Obscurist's Cave. Lynn died a later that year, on June 22nd. The device has required repairs, but is still in working condition as of 2024.</p> <p>(1) - <a href="https://urashima.bandcamp.com/album/negative-frequencies">Negative Frequencies can be found here on bandcamp</a></p> <h3>Lynn Mathewson</h3> <p>Lynn Mathewson was born 1953 Feb 13 in Bolder Colorado. At the age of 19 he began his studies in computer science at the Colorado School of Mines. He worked as a computer technician and repair man at the University of Colorado Boulder from 1975-2001. In 1993 Lynn bought a house with Suzanne Benson, a professor of forest ecology. In 2001 Suzanne would leave to Candida to follow her studies. Lynn said that his favorite places were the Into The Wind kite shop, and the street he grew up on as a kid.</p> <h3>The Device</h3> <p>The device is made from recycled computer parts, as well as other custom made componentry. It weighs close to 100 pounds because of two car batteries that allow the device to be played continuously, for about a week without recharge. Otherwise the device can last quite a long time without user input. While no user input is being given, the device will stop making certain calculations, putting itself into a stasis. After 30 minutes the device will completely shutdown, and can be awakened by pressing any of its buttons. After the 9 years it had been in the basement of Lynn's house, the device able to stay active for a couple minutes before it had to be recharged. The screens are custom made e-ink, helping with this low power consumption. The device does not have a power switch, and the state of the game is always being backed up. When The Media Archaeology Lab received the device, the player was in a very strange position within the game world. It took a while to figure out how to reset the game to its &quot;starting&quot; positions. The volunteers weren't sure if there was even a supposed starting position.</p> <h3>Interpretations</h3> <p>The interface and puzzles of Obscurist's Cave have been described as needlessly obtuse, while still being a playable experience. As for what meaning could be drawn from the game, some have said its just a strange puzzle game, while others have sworn by the game's ability to whisk them away, putting them into an unsettling headspace.</p> <h3>DEV'S NOTE - Elijah Bennett</h3> <p>I work as a volunteer at The Media Archaeology Lab, that's how I was introduced to Obscurist's Cave. Found this game to be overly cryptic for how much &quot;secret&quot; it had to reveal. I'll spoiler it for those who care -&gt; It requires that you know...<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;">...how ASCII works, and how negative numbers are represented in integers.</div></div></div> Usually i find its best if the whole &quot;puzzle&quot; is self contained. I did however find it quite an interesting game to deconstruct and re-program to work on Picotron. I learned a lot about how 3d math is done at a low level: collision, fish-eye camera, matrix multiplication for rotations.</p> <h2>FISHEYE</h2> <p>The fisheye rendering is done in the following steps.</p> <ul> <li><em>TRANSFORM</em> the points, offset by the camera's position and rotated by the camera's rotation.</li> <li><em>NORMALIZE</em> this new vector.</li> <li><em>IGNORE THE Z</em> component of the vector, just use x and y for screen position.</li> <li><em>RENDER THE CURVES</em> between each point in the tri </li> </ul> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/56596/19_Untitled.png" alt="" /> <p>Rendering the tri is definitely the hardest part. First, lets figure out what the shape of the tri is.</p> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/56596/21_Screenshot_2024-04-19_18-54-38.png" alt="" /> <p>Here you have the tri's main points, <em>Red, Green, Blue</em> creating a clockwise triangle. We can define this initial curve as such...</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>curve = { { v = vec(tri[1].x, tri[1].y, tri[1].z), next_i = 2 }, { v = vec(tri[2].x, tri[2].y, tri[2].z), next_i = 3 }, { v = vec(tri[3].x, tri[3].y, tri[3].z), next_i = 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>The between points are what make the fish-eye effect all nice and curvy. These midpoints are made in the following steps.</p> <ul> <li>Get the mid-point between a point and its next point.</li> <li>Normalize this mid-point, this is what creates the curve.</li> <li>Check if the distance (is screen space) between our first point and this normalized mid-point is smaller than a certain threshold. If it is, we move on to the next point in our chain. If not, we repeat this process.</li> </ul> <p>Now I only had to deal with wire-frame. I just draw lines between the points. If we wanted to rasterize these convex shapes maybe something like this would work -&gt; <a href="https://www.youtube.com/watch?v=SO83KQuuZvg">Coding Adventure: Rendering Text</a></p> <h3>thanks for reading :)</h3> <p>All of the stuff in the history section is of course fictional. Just some ARG fun.</p> https://www.lexaloffle.com/bbs/?tid=141831 https://www.lexaloffle.com/bbs/?tid=141831 Sat, 20 Apr 2024 14:51:38 UTC cat in snow <p> <table><tr><td> <a href="/bbs/?pid=0#p"> <img src="/bbs/thumbs/pico8_catinsnow-4.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=0#p"> cat in snow</a><br><br> by <a href="/bbs/?uid=56596"> TinyCat</a> <br><br><br> <a href="/bbs/?pid=0#p"> [Click to Play]</a> </td></tr></table> </p> <p>a cozy lill' walk through some snowy woods<br /> this game is mostly about atmosphere, so no objectives here. just walk around till you feel done :)</p> <p><img loading="lazy" style="margin-bottom:16px" border=0 src="/media/56596/8_catinsnow_cover_image.gif" alt="" /> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/56596/13_game_preview_2.gif" alt="" /></p> <h1>the trees</h1> <p>i'm real happy about how natural the tree generation feels so i figured i'd talk about it.<br /> the trees start out like this.</p> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/56596/15_Untitled.png" alt="" /> <p>the main thing that helps sell the forest is the random tree placement. but if we just did something like..</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>tree.x = x + RND(8) - RND(8) tree.y = y + RND(8) - RND(8)</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>..then each time we re-spawn the trees for a area they would be in different spots then before. basically we need a function that returns a sudo random value <code>y</code> from value <code>x</code>. thats were this function comes in...</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>FUNCTION ConstRnd(_𝘹,_𝘳) IF _𝘳 == NIL THEN _𝘳 = 1 -- r meaning range END RETURN (COS(_𝘹*.6)+SIN(_𝘹*4.9)+SIN(_𝘹*.01)+COS(_𝘹*7.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>here's a part of the function on desmos..</p> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/56596/function.png" alt="" /> <p>so while not totally random, it looks random enough :)<br /> so instead we do something like this</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>tree.x = x + ConstRnd(y) tree.y = y + ConstRnd(x)</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 reversal of x and y is important, otherwise we get this banding effect..</p> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/56596/bad_trees.png" alt="" /> <p>beyond that, its just a matter of scaling the top of the tree with <code>SSPR</code>, placing some random sets of branches, and doing some random flipping of the tiles.</p> <img loading="lazy" style="margin-bottom:16px" border=0 src="/media/56596/finished tree.png" alt="" /> <h2>links</h2> <p>an archive of the dev files can be found on <a href="https://es5000.itch.io/cat-in-snow">the itch.io page</a><br /> was made as part of the <a href="https://itch.io/jam/secret-santa-2023">2023 Secret Santa game jam</a></p> https://www.lexaloffle.com/bbs/?tid=55449 https://www.lexaloffle.com/bbs/?tid=55449 Sun, 24 Dec 2023 01:16:05 UTC