drakeblue [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=47206 Making PICO Space <h1>Making PICO Space</h1> <p>This is a rambling description of some of what went into making <a href="https://www.lexaloffle.com/bbs/?tid=42279">PICO Space</a>. I've tried to write it for most readers to follow - there's some basic stuff and nothing very advanced. Hopefully it's not too dull and might help someone.</p> <img style="" border=0 src="/media/47206/space_77.gif" alt="" /> <h2>When You Wish Upon a Starfield</h2> <p>Coming up to Christmas of 2020 I had been spending most of my dev time trying to squeeze image data into PICO-8 to make a Dungeon Master clone (I promise I will return to this at some point). I'd got a bit tired of writing compression and encoding routines and feeling like I was fighting PICO-8 rather than playing nicely with it. I'd seen some other nice star-fields and particles in other peoples' games and wondered how much it would take to do my own.</p> <p>I'd also read about the CAMERA function and suspected that would help - using CAMERA to transform the &quot;view window&quot; once instead of transforming the positions of every single particle many times seemed like it'd be a big win in terms of performance.<br /> I knocked up the following while the girlfriend was watching a Christmas movie to try it out. Ironically, the stars in the final game don't benefit from the CAMERA function at all - although the other particles and everything else do.</p> <p> <table><tr><td> <a href="/bbs/?pid=90118#p"> <img src="/bbs/thumbs/pico8_drakeblue_camerastars-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=90118#p"> drakeblue_camerastars</a><br><br> by <a href="/bbs/?uid=47206"> drakeblue</a> <br><br><br> <a href="/bbs/?pid=90118#p"> [Click to Play]</a> </td></tr></table> </p> <p>There's not a lot to it: use directions to &quot;fly&quot; the red line around (there's nothing there, but the star field). But this is the basis of how the ship flies in PICO Space.</p> <p>I wrote a post about the stars and fade effect here: <a href="https://www.lexaloffle.com/bbs/?tid=41149">https://www.lexaloffle.com/bbs/?tid=41149</a> </p> <p>I considered a rotate and thrust method, like in games like Thrust, Oids etc. but decided to keep it simpler, friendlier to those who didn't grow up in the 80s and allow the game to be more dynamic. Left, right and thrust would have saved a precious PICO-8 button though...</p> <p>In the final version, there's a constant deceleration added to the velocity components of the ship (which gets wiped out if you hold down the controls) - and a very low minimum velocity. Why?</p> <h2>Not Just a Triangle; Not Even a Triangle</h2> <p>The ship (and the NPC ships) are all drawn in the game using a combination of lines and a sprite to cover the hole in the middle (yes, really - I had some triangle drawing code sat in the p8 file for weeks without ever actually using it in the end so it got cut). The vertices used for the lines are calculated from a normalised vector of the ship's velocity. If the velocity gets too close to zero then this calculation, the vertex calculations and the lines don't come up with anything sensible and the ship doesn't draw correctly.</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>----------------------------------------------------------------------------------------- -- draws the player or an npc ship function draw_ship(s) ship_pal(s) -- calc some vertices based on current heading angle -- 0 -- (0) -- 2 1 local z,an=s.z&lt;1 and -1 or 1,s.an local s0,s1,s2,c0,c1,c2=sin(an)*z,sin(an-0.15)*z,sin(an+0.15)*z,cos(an)*z,cos(an-0.15)*z,cos(an+0.15)*z local svx0,svy0,svx1,svy1,svx2,svy2=3.5*c0,3.5*s0,-3.5*c1,-3.5*s1,-3.5*c2,-3.5*s2 line(svx0*1.2,svy0*1.2,svx1*1.2,svy1*1.2,2) line(svx0*1.2,svy0*1.2,svx2*1.2,svy2*1.2) line(svx1,svy1,svx2,svy2) line(svx0,svy0,svx1,svy1,8) line(svx0,svy0,svx2,svy2) line(0,0,svx1,svy1) line(0,0,svx2,svy2) line(0,0,svx0,svy0) spr(unpack_split'0,-4,-4') -- cockpit reset_dr_pal() 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>ship_pal sets up the correct colours for whatever ship is being drawn - there's a pair of values for every brighter colour apart from the blue used for the cockpit.</p> <p>The z variable deals with the &quot;flip&quot; ability that the ship has so you can face backwards - otherwise, while the ship does have some inertia it will always be drawn to point in the direction it's moving.</p> <p>I'll explain more about &quot;unpack_split&quot; in another post.</p> <p>Here's the ship without the cockpit sprite:</p> <img style="" border=0 src="/media/47206/space_72.gif" alt="" /> <p>reset_dr_pal is a function that acts like a call to pal with no arguments, but doesn't affect the screen palette. I've used it for a few projects now:</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>function reset_dr_pal() poke4(0x5f00,0x0302.0110,0x0706.0504,0x0b0a.0908,0x0f0e.0d0c) 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 latest PICO-8 letting consecutive values be multiple pokes at a time has let me optimise this so it's a bit opaque even to me. IIRC it dumps the equivalent of 0,1,2,...,15 into the correct part of PICO-8's memory to reset the draw palette and whatever magic needs to be done for palt too(?), but doesn't hit the screen palette range of memory.</p> <p>Feel free to lift this for your own code if you think it'll be useful - no warranty expressed or implied ;)</p> <p>I tweaked the ship drawing code a few times, but it never varied much. Once I had a ship flying about I needed somewhere for it fly to so I made a &quot;planets&quot; table that was populated with random coordinates, drew a circular planet sprite and hit go. That's gone now - it was handy to have as a placeholder, but I don't miss it.</p> <h2>Start of a Solar System</h2> <p>Once I had planets it made sense to me to add a sun/star, but I wanted it to be bigger than the planets. I'd already used 64x64 of the sprite sheet with the planet sprite so I wondered what I could do with PICO-8's circfill command.</p> <p>It turns out that circ and circfill let you draw pretty large circles for not a great deal of perf cost. I tried various sizes and settled on an 800 pixel radius circle for the sun with some extra circles around it. One is a border, the others are there just because I like how they look. My &quot;game design&quot; excuse is that they give some warning to the player that they're about to fly into a star - not v healthy for their ship.</p> <img style="" border=0 src="/media/47206/space_70.gif" alt="" /> <p>I have another cart that draws a partial circle within another circle to show the sun on the scanner, but the token count was too much. In the end, the sun on the scanner is drawn by generating lots of points then checking if they are within both the circle of the sun and the circle of the scanner; then drawing a circle of radius 1.</p> <p>Originally I had yet another circle for the edge of each system - but as the systems got busier the performance cost was just too high so I needed something a bit more &quot;sophisticated&quot;. I noticed that the edge circle was so large that it never looked like anything else but a straight line on the little PICO-8 screen so in the game I do a little bit of maths to work out two intersection points with the edge circle and draw a line between them i.e. the edge circle segment is approximated with a line.</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>--edge of system if g_dist_to_sun&gt;g_edge-23 then -- approximate with drawing tangent line at angle through ship's coordinates -- since ship is so far from centre and edge circle is so large -- edge is a circle around 0 -- get angle to ship local an,ed=atan2(S.x,S.y),g_edge+rnd'16' -- get tangent angle at 90deg and coords of point on edge (with some jitter) local an2,ca,sa=an-0.25,cos(an)*ed,sin(an)*ed -- get vector of line using tangent angle local ca2,sa2=cos(an2)&lt;&lt;7,sin(an2)&lt;&lt;7 line(ca-ca2,sa-sa2,ca+ca2,sa+sa2,p%8+8) end </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <img style="" border=0 src="/media/47206/space_74.gif" alt="" /> <p>I use g_dist_to_sun to conditionally draw the sun when needed as well.</p> <p>Having a circular edge seemed like a nicer way to stop the ship flying too far out of the game than just clamping to a rectangle or wrapping the coordinates. I had a really fancy bit of code that would turn the ship around from anywhere outside the system and force it back. In the end just adding a vector pointing towards the centre of the system to the ship's velocity is what makes it behave like a stuck blue bottle behind glass in the game.</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre> g_dist_to_sun=dist_trig(S,g_sys.sun) if g_dist_to_sun&gt;g_edge then local avx,avy=get_dir(S,g_sys.sun) vx+=avx vy+=avy end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <h2>Trigonometry for Distances</h2> <p>(As any fule kno) the distance between a point A and B is the square root of the sum of the squares of the coordinate distances i.e. d = sqrt(dx<em>dx+dy</em>dy) -- for 2D</p> <p>Except not in my game.</p> <p>In a fit of madness I decided to make the systems pretty large, 10240 pixels in radius, in fact. PICO-8 numbers are a 16-bit fixed point type with a range of -32768.0 to 32767.9999847412109375 (0x8000. 0000 to 0x7fff). Which means I was fine until I needed to calculate a large-ish distance and had to square numbers over 1000 e.g.</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>dist({0,0},{9000,8000}) = sqrt(9000*9000 + 8000*8000) = sqrt(81000000 + 64000000)</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Um...</p> <p>Weirdly, I got a really long way into coding before this actually became a problem and I'm not quite sure how that happened - especially since I was expecting it all along, I'm no stranger to the limitations of number types or even to fixed point floats.</p> <p>One method I tried to get round this was to divide every value (bit shift in fact) before the squaring operation and then shift back afterwards. I'd lose precision, but in theory it'd work fine i.e. something like:</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>dist = sqrt( (dx&gt;&gt;4)*(dx&gt;&gt;4)+(dy&gt;&gt;4)*(dy&gt;&gt;4) )&lt;&lt;4</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Most of the time I'd only needed the shifted squared value. But I had real trouble getting it to work well - possibly because of other code around it. And sometimes I wanted the true distance (with the sqrt) anyway.</p> <p>I'd been doing some experimentation with the SIN and COS functions and I'd noticed that they're very fast on PICO-8 and I wondered about whether this might be another solution.</p> <p>A bit of trig later and I had a candidate:</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>-- distance with trig -- to avoid large numbers -- not v accurate, but seems good enough. -- also seems v fast on pico-8 function dist_trig(a,b) local x,y=abs(b.x-a.x),abs(b.y-a.y) if x&lt;y then x,y=y,x end -- accuracy goes down massively if x is much smaller than y so swap them :) return x/sin(atan2(y,x)) 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 discovered the accuracy problem mentioned in the code a bit later - it manifested as the ship spontaneously diving into the sun if you flew too close to the top or bottom of it - and only those two points. The code to stop the ship escaping the edge of the system was firing and pushing the ship into the centre of the system because the distance calculation was so bad it thought the ship was at the edge not right by the sun!</p> <p>Anyway, this function gets used all over the place now and was favourably comparable in accuracy and speed to any of the shifted distance functions that I tried.</p> <h2>Galaxy Generation</h2> <p>Of course, the more sensible solution would probably have been to make the star systems smaller and &quot;zoom&quot; the coordinates only for drawing, but I'd already done most of the work on galaxy creation and drawing and didn't really want to change it too much. I think I actually tried it for 30 minutes, made a mess and then gave up.</p> <p>When you choose a new game or load from a saved game in PICO Space it generates the whole galaxy from an integer seed (your captain's name is a different value; otherwise they couldn't travel to other galaxies...).</p> <p>The stars are all generated from the galaxy seed plus a fraction part e.g. the fourth star has something like id=galaxy_id+4*0.0001. This means there are potentially 65535 galaxies (I think, or at least 32767) with every system having a unique id/seed &quot;in the gaps&quot;.</p> <p>Apart from star number 1 which is always at (0,0), the stars are given random positions within a fixed distance from that star with the condition that they can't be too close to an already existing star. This is v fast.</p> <p>Then the code links the galaxies with wyrmholes (called gates in the code). First it makes a minimum spanning tree with wyrmholes:</p> <ul> <li>find the star with minimum distance from star 1</li> <li>add wyrmholes to link the two</li> <li>add the new star to star 1 in a &quot;found&quot; set</li> <li>find the closest star to any star in that set</li> <li>link with wyrmholes</li> <li>repeat last 3 steps until every star is in the &quot;found&quot; set</li> </ul> <p>This way I know that every system is connected to the galaxy as a whole. Without this some systems aren't reachable (I had considered having a jump drive upgrade that let you jump between groups of stars - maybe next time).</p> <p>Unfortunately my algorithm to calculate the minimal spanning tree gets v slow after relatively few iterations (checking the closest star in an n-size set of stars has a pretty bad O value) and acts as a mechanical limit to how big the galaxies can get.</p> <p>I'd be more worried about it, but for two things:</p> <ol> <li>The loading view covers it well. It looks like the stars are being generated, but it's actually showing the stars being added to the minimum spanning set.</li> <li>It's fast enough that even with 70 stars it's not that slow and I think 70 stars is probably enough.</li> </ol> <p>--controversial?--I've noticed in a lot of procedurally generated games there's a whole load of repetitious content where there doesn't really need to be - it doesn't add much to the game and feels a bit like it's there just because the developers could. Now PICO Space is still pretty guilty of this - there's a lot of space in PICO Space and 70 systems is probably still way more than most players will ever visit. The systems don't have that much variety - I really wanted to put in more and kinda of heart-breakingly PICO-8 is easily <em>fast</em> enough to allow it. But there's not much cart space and I just couldn't find the tokens. There were a lot of things I would have added without the token limit and even some stuff I had to cut before release. I never found myself wanting to add more star systems. In fact, for a lot of dev time I reduced the number to make testing faster.--/controversial--</p> <p>Anyway, long story short: I didn't waste any more time (or tokens) optimising this, instead I slapped in a logo and a few star spr calls and pretended it was a deliberately designed intro sequence...</p> <p>Once that's done, there are a few iterations after the spanning tree search looking for short distances between stars and adding more gates between them so that there are &quot;loops&quot; and it's a bit easier to get about. This is pretty fast too.</p> <img style="" border=0 src="/media/47206/space_76.gif" alt="" /> <h2>Generating Systems</h2> <p>Then the systems themselves are fleshed out. Originally I generated each system in the galaxy only when the player entered them. In fact, all I had was the current system and some wyrmholes in it. When the player entered a wyrmhole I took the seed value associated with it and generated the new system. I even added a wyrmhole back to the previous system using its seed to give the illusion of persistence. For the galaxy map I was going to run this generation on the fly when it was opened to a certain depth of wyrmholes and that way I'd have a near to infinite galaxy and tiny memory footprint!</p> <p>Typing it out now it still seems like it might have worked, especially as I know the scope of what's in the game. At the time though, I ditched that idea since I didn't. The final straw was wanting to put &quot;missions&quot; into the game.</p> <p>Each system has wyrmholes and planets which also may have space stations orbiting them. The wyrmholes, only really have a position, a destination id and a draw function. They are called wyrmholes because I was hoping to have &quot;space wyrms&quot; in the game. Sadly, that never happened.</p> <h3>Planets</h3> <p>Planets have radii and colours and are added in distance &quot;slots&quot; (with the wyrmholes) radiating out from the sun - this way there shouldn't be any collisions between them, even as the planets orbit around the star. Yep, the planets do orbit in the game, but their positions only update when entering a system. I had them update along with everything else for a long time though.</p> <p>As mentioned elsewhere in this post, the scale of each system is quite large. The planets orbit in circles determined by sine and cosine functions combined with their distance from the star (I balked at setting up stable systems with realistic gravity calculations if only because I'd disappeared down enough wyrmholes already). Unfortunately, the precision of these functions isn't high enough to allow smooth movement when any distance from the sun. It caused the planets to &quot;jump&quot; between positions on their orbit. Unperturbed I wrote a routine to interpolate between the imprecise positions so that the planets would still orbit smoothly. It worked really well and I was sad to have to cut it to regain the tokens it needed.</p> <p>I was able to leave the scribbly planetary rings in place though, which are drawn by generating a bunch of vertices using sine and cosine values (with random jitter) and drawing lines between pairs of them. Draw the back half of a ring first, draw the planet, then draw the front half of the ring.</p> <p>Like the planet interpolation, I designed them in a separate test cart first:</p> <p> <table><tr><td> <a href="/bbs/?pid=90118#p"> <img src="/bbs/thumbs/pico8_drakeblue_rings-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=90118#p"> drakeblue_rings</a><br><br> by <a href="/bbs/?uid=47206"> drakeblue</a> <br><br><br> <a href="/bbs/?pid=90118#p"> [Click to Play]</a> </td></tr></table> </p> <p>The code in the game is very similar. Knocking up little test carts is nice in PICO-8 since it's v lightweight to get going. Doing this also means less messing up of existing code, especially if you change your mind and it means less flying about trying to find the thing you want to test.</p> <h3>Space Stations</h3> <p>The space stations do orbit as you fly, around the planets. A planet has a station entry in its table so there's only one per planet (early in dev I had up to 4!) and the space station positions get updated with everything else that updates. When you're docked the ship has to match this (that was a fun bug).</p> <p>The space stations have three different sprites, a few circles and a pal call in their draw function to provide some cosmetic variety. I had written a little cart which would allow me to specify shapes, sprites and map commands in a string that was interpreted at runtime to give many more looks for them, but tokens and performance stopped me using that. And I hit the compressed size limit quite badly too.</p> <p>At one time there was a ship's garage with mechanic NPCs in every station but alas tokens...</p> <h2>Missions</h2> <p>(kinda)</p> <img style="" border=0 src="/media/47206/21_space_57.gif" alt="" /> <p>I wanted to add a whole different variety of these, but eventually I only made the passengers on the noticeboards at the stations - the simplest missions I could think of. They're even more basic than fetch quests (find something <em>and</em> bring it back - sounds complicated!) or even deliveries (plausibly you only have room for one passenger in your small ship so I only needed to track one mission at a time). I ran out of tokens before I could attempt adding any more types.</p> <p>To make the passenger missions work I needed to have some knowledge of not just the name of the destination system, but also of the objects in the system; specifically the space stations. I'd hoped to have docks on planets, but, again, the token limit got the better of me.</p> <p>It was so much easier to have the destination systems pre-created and in memory for this. PICO-8 has a generous 2MB for such data (my first computer had 64KB and David Braben and Ian Bell made do with a fraction of that). PICO-Space only ends up using about half of that at any time (when it's working correctly).</p> <p>The game takes a seed of the current space station id and the progress that the player has made through the game and uses that to generate a number of notices with destinations and a seed for the animal wanting a ride. That way, if you return to the notice board it keeps the same notices, at least until you complete a mission.</p> <p>When you finish enough journeys a progress global is increased, an upgrade is awarded, different news &amp; NPC messages are unlocked and more dangerous weevils may appear. There's an upper limit to how many journeys are needed for each progress point (four I think) so every player should progress reasonably quickly.</p> <h2>Silly Names</h2> <p>Nonsense word generators are something I've written a few times in the past. They're very effective (and entertaining) for something so easy to do. If you've never written one I highly recommend it, especially for newer programmers.</p> <p>There is a single list of syllables and a single function that generates all the names in PICO Space. If I had more space/tokens then having different syllable sets etc. per species or system or something might have been fun, but I never felt like this was a weak part of the game and garnered an embarrassingly large amount of amusement out of some of the silly things it came out with.</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>------------------------------------------------------------------------------------------ -- generate some wacky random names function gen_name(s) stash_n_set_seed(s) local n,nm=rnd_spl_str&quot;1|2|2|2|3|3|3&quot;,'' for i=1,n do if i&gt;1 and rnd(15)&lt;1 then nm..=' ' end nm..=rnd(g_syls) end unstash_seed() return nm 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 gist of this is:</p> <ul> <li>choose length for the name in number of syllables</li> <li>for each syllable up to thate length choose a syllable string and append it</li> <li>occasionally append a space instead of a syllable</li> </ul> <p>The stash_n_set_seed function is my hack to get around the trials and tribble-ations of working with a random number generator for procedural generation (as opposed to a noise function). See below for more about this.</p> <p>Here's the syllables:</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>split&quot;ca,bal,da,gar,non\-en,pol,der,arp,bun,duc,kit,poo,v\-evee,zir,buf,v\-evil,xan,frak,ing,out,re,far,do,tel,tri,cry,quack,er,dog,pup,sno,ger,bil,pa,n\-ena,jan\-en,es,on&quot;,--g_syls</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 more serious names, don't put in such silly syllables e.g. poo.</p> <img style="" border=0 src="/media/47206/space_66.gif" alt="" /> <h2>Ms and Ws</h2> <p>The eagle eyed amongst you may have noticed that PICO Space has &quot;wide&quot; 5x5 pixel M and W letters instead of the usual 5x3 characters that PICO-8 has by default. My other games, e.g. P8C-BUN have similar wide Ms and Ws too. In those games, I have a custom print function that iterates through whatever string is to be printed and when it finds an M or W it replaces it with a sprite that has the wide version of the letter. I added this after I got some negative feedback about the legibility of the text in a game.</p> <p>Originally PICO Space used the same function, but I found it was a bit of a performance problem. PICO-8 has a much more &quot;spiky&quot; processing time per frame than my other games have had.</p> <p>Fortunately, zep's addition of P8SCII in the newer version of PICO-8 came at exactly the right moment and allowed me to replace my routine with these magic codes:</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>m=&gt; n\-en [print an n then shift the cursor back 2 pixels (\-e) and print another n] w=&gt; v\-ev [u\-eu looks okay too]</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>As long as a find/replace is done for those characters in a string to be printed then it &quot;just works&quot; and I was able to ditch my custom print routine at last. This can be done &quot;offline&quot; even. The only tricky part was trying to centre text when the width was no longer as predictable - I do have a mostly working solution for that. Ask me if you're interested.</p> <h2>Taming RND</h2> <p>PICO-8 has no noise function, but it does have RND and a seed set function SRAND. I considered writing a noise function, but I suspected I'd want the tokens for something else and I was concerned about performance. I'd already used RND for the first hacky progress in the game when I thought about this so I gave up on noise and set up a function that saved the current random number (or at least whatever RND returned at that moment) and called SRAND with a value I'd passed to it. Then I was careful with the order I called RND in and did a lot of testing to make sure that I got consistent or random results as appropriate.</p> <p>For a particular seed, RND always returns the same sequence of subsequent results so, for instance, setting the seed before choosing portrait sprites and generating a bunch of names using RND means you'll always get the same output. That's why there's always the same animal minding each station and the same notices each time you look on a station's noticeboard (at least until you ferry another passenger). I'd restore a &quot;random&quot; seed after using RND in this way so that, for example, the NPC generation stayed unpredictable.</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>-- set seed and store a random number for later function stash_n_set_seed(seed) g_old_seed=rnd() srand(seed) end -- restore &quot;randomness&quot; function unstash_seed() srand(g_old_seed) 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 works pretty well all considered and I never felt I was having performance problems from it. I call the time function for the galaxy seed and pilot id just to mix it up even more.</p> <h2>Animals</h2> <p>I needed characters for the game and I considered identikit faces like Elite 2 uses for a bit. In the end, I drew some animals as placeholders and then never looked back.</p> <p>Animals feature in my games. Get over it.</p> <p>I wanted the portraits to move so initially I was going to add animation frames, but horizontally flipping was easier and meant I could have more unique pictures. I figured it was &quot;good enough&quot;.<br /> <table><tr><td width=128> <img src="https://www.lexaloffle.com/bbs/gfxc/47206_0.png" width=128 height=128> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_47206_0"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/47206_0.txt", function (retdata){ var el = document.getElementById("gfxcode_47206_0"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [32x32]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_47206_0" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> </p> <p>There are 59 animals in total.</p> <h2>News and NPCs</h2> <p>The Beeb News was my first attempt to communicate some story in the game and add a bit of narrative colour (alongside the colour colour). The news stories develop as the player progresses in the game - there's a different set after each upgrade is achieved. I used a <em>very</em> basic template filling function to generate a bit of customisation for each game - e.g. the galaxy name and the president's name change depending on which galaxy you're in.</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>------------------------------------------------------------------------------------------ -- substitutes values (#n) into a string for the corresponding entry in data (data[n]) function template_fill(t,data) local i,out=1,'' while i&lt;=#t do local c=sub(t,i,i) if c=='#' then i+=1 out..=data[tonum(sub(t,i,i))] elseif c=='m' then out..='n\-en' elseif c=='w' then out..='v\-ev' else out..=c end i+=1 end return out 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>You'll notice the M and W substitutions in this - in the last week of development I had to add this to reduce the size of the strings used for the news and NPC chat in order to fit the game under PICO-8's compressed size limit. Fortunately, it works very well and turned out to be quick enough.</p> <p>The news is drawn using the same scrolling message system that is used for the upgrades and notice board, just with different colour parameters.</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>---------------------------------------------------------------------- -- draws a bar of scrolling text function draw_scroller(scroller,y,x,c,bc) clip(x,y,128,y+6) rectfill(x,y,128,y+6,bc) print(scroller.message,x-scroller.x,y+1,c) clip() scroller.x+=1 if scroller.x-x&gt;scroller.len then scroller.x=-64 return 1 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> <h2>NPCs</h2> <p>The other attempt at story telling comes from the NPC ships. These will send you random messages when they're on-screen. Like the news, the template function adds a bit of customisation e.g. for the current system and there are different sets of messages for each stage of progress in the game.</p> <p>The NPCs are (obviously) drawn in the same way as the player ship, but on top of basic attributes like position, velocity, colour etc. they also have a target that they head towards; either a station or a wyrmhole. They're spawned from a station or from a random position (with hyperspace particles) to pretend that they've just jumped in. I'd love to have more persistent NPCs, but I probably spent too many tokens, performance and cart space on them already.</p> <p>One of the more interesting problems to solve was how to stop NPCs spawning in a position then flying towards a target on the other side of the system's sun without them hitting it. I don't check them for collisions so they'd just fly right on through blissfully unaware of any problem. Given the player can't do that it was a bit non-ideal to witness ships emerge from the superhot plasma if you happened to be flying close to the sun at the time. It got even more obvious when I stopped pausing the simulation in the System Map since you could watch the NPCs sun-diving:</p> <img style="" border=0 src="/media/47206/space_20.gif" alt="" /> <p>I tried various clever solutions with trigonometry and mathematics, but they never worked very well. In the end, I solved this problem with a hack. Whenever an NPC is generated their journey is quickly simulated, start to finish, but with coarser framerate. If they get too close to the sun then that journey is ditched and the NPC journey is generated again until a valid journey is produced. This does make for the occasional performance spike, but on the whole works quite well and for few tokens.</p> <p>There's a cap on the number of NPCs per system that takes into account the number of weevils to try and make sure there's quite a bit of performance headroom, just in case.</p> <h2>Enemies</h2> <p>To be honest, I was having so much fun making a pretend universe that I left it quite late to add in a challenge to the game. Eventually I admitted that I needed villains so I drew on personal history.</p> <p>A few years ago we found weevils in our kitchen. All over our kitchen. Eventually we tracked them back to a bag of birdseed that now moved and crackled by itself...</p> <p>The next hours and days consisted of rooting out weevil and destroying it - weevils became a kind of bogeyman in our house. Nothing is more evil than weevil in our home.</p> <p> <table><tr><td width=128> <img src="https://www.lexaloffle.com/bbs/gfxc/47206_1.png" width=128 height=128> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_47206_1"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/47206_1.txt", function (retdata){ var el = document.getElementById("gfxcode_47206_1"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [32x32]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_47206_1" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> </p> <p>I wanted to make each weevil unique, but in the end they are all based on the same code with varying attributes. As the game goes on more and more dangerous weevils are generated ahead of the ship within a random circle depending on how dangerous the system is and the difficulty level of the game. Some weevils can hit the ship and damage it with their collision, all weevils fire missiles at the ship at different rates and for different amounts of damage.</p> <h3>Space is Big, even PICO Space</h3> <p>One of the biggest problems with the weevils was how to make them possible to fight on the tiny 128x128 PICO-8 screen without making them too slow to stop a player just flying past them. I didn't want to slow down the player either, since getting between locations was taking long enough already. Besides, when I tried slowing the ship, it just felt... bad.</p> <p>I think the weevils are still a bit too fast to be fair - I'm not convinced that I really solved this problem entirely.</p> <p>WARNING SPOILERS - DO NOT READ IF YOU WANT TO LEAVE THE ENDING AS A SURPRISE<br /> <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> <h2>Weevil Queen</h2> <p>I wanted an ending and a &quot;boss&quot; and so I did some research into big weevils (as you do). It turns out that there are some big ones out there and there are even some that live like ants with a queen. Not to the same scale as ants though.<br /> Add a bit of poetic licence and I came up with the weevil queen that's in the game.<br /> What do you mean: &quot;there isn't one?&quot;<br /> Are you saying you've not completed enough missions to gain the Prototype Scanner upgrade, located the Weevil Base and jumped into the system to fight the Weevil Queen and save the galaxy?<br /> At time of writing, I'm not sure anyone has except me (many testing times). If you have I'd really like to know (please?).</p> <p>The Weevil Queen is generated in a system that has only one wyrmhole in it (a leaf node in the galaxy &quot;tree&quot;) and is by default hidden in the Galaxy Map (and the wyrmhole to it is hidden in the system containing it too). Some of the changes for the weevil system happen during galaxy generation. Most of it is done on entry. There are no space stations or NPC ships and the weevil queen is added. She behaves a lot like a normal weevil, but she has hitboxes at the back of her that don't take damage and she moves more slowly. She fires the most deadly missiles, most frequently. She may also teleport randomly if hit.<br /> The weevil queen is drawn using several sprites together and she gyrates at a speed according to how close to destruction she is.<br /> <table><tr><td width=128> <img src="https://www.lexaloffle.com/bbs/gfxc/47206_2.png" width=128 height=128> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_47206_2"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/47206_2.txt", function (retdata){ var el = document.getElementById("gfxcode_47206_2"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [32x32]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_47206_2" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> <table><tr><td width=128> <img src="https://www.lexaloffle.com/bbs/gfxc/47206_3.png" width=128 height=128> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_47206_3"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/47206_3.txt", function (retdata){ var el = document.getElementById("gfxcode_47206_3"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [32x32]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_47206_3" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> </p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>function(q) pal(15,0) local en=5-q.life/10 local sn48,cs48,sn32,cs32=sin(p/48*en),cos(p/48*en),sin(p/32*en),cos(p/32*en) q.x+=sn32 circ_orig(p%96,g_sys.sun.pl[q.life\10+1]) spr(135,-25+sn48,-10+cs48,2,2) -- right front leg spr(135,11-sn32,-10-sn48,unpack_split'2,2,1') -- left front leg spr(135,-29,cs32-52,2,2,nil,1) -- right back leg spr(135,13,cs48-52,unpack_split'2,2,1,1') -- left back leg spr(137,12+sn48,-26+sn32,unpack_split'2,2,1,1') -- left back leg spr(137,-27-cs32,-26+cs48,2,2,nil,1) -- right back leg spr(128,sn48-15,unpack_split'-50,2,4') -- right wing spr(130,-sn48,unpack_split'-50,2,4') -- left wing spr(132,cs48-13,unpack_split'-29,3,4') -- thorax spr(139,-10+cs48,-8-sn32,3,3) -- head reset_dr_pal() 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>When she is destroyed, she is changed into the Intergalactic Wyrmhole that leads to the next (harder) galaxy, the weevil system loses its weevil flag and all the weevils are destroyed.</p> <p>I spent a lot of time getting all this to work, all the time wondering if anyone will ever see it.<br /> </div></div></div></p> <h2>Tables and &quot;Objects&quot;</h2> <p>I'm not much of an object oriented zealot (learning to program in BASIC in the 80s does that to you), but for the entities in PICO Space I used tables as objects of a kind.<br /> Things like planets, stations, weevils (called aliens in the code) and NPC ships generally have &quot;standard&quot; attributes (x,y for position, bounding box for draw culling etc.) and functions (update and draw).<br /> On entering a system an &quot;updateables&quot; and a &quot;drawables&quot; table is populated with appropriate things from those tables in the current star system and the update and draw functions loop through these and call them as appropriate. Using the CAMERA function I set the origin for drawing to reflect the object's position then the draw function draws from there. Things with a map function get drawn on the System Map etc. It works quite well and feels a bit like adding components to entities.<br /> I had a lot more separate lists and loops for these early on just to get going - I find doing things &quot;the dumb way&quot; first and improving it later works well for me (along with, if it ain't broke don't fix it...).</p> <p>Some things e.g. particles are kept separate still, for speed.</p> <h2>Particles</h2> <p>There are two big types of particle in PICO Space. Points and circles. There's a function to add both of these in a single line each. They have a lifetime, position and update functions.</p> <p>Points have two update functions - a typical velocity update one and a more abstract randomly swapping x and y velocity update. The former is used in the explosions. The latter is most obvious in the hyperspace cloud at the very start of the game.<br /> Circle particles draw at a different size corresponding to the life left of the particle.</p> <p>Why do they look the way they do? It's the screen fade effect.</p> <p>See <a href="https://www.lexaloffle.com/bbs/?tid=41149">https://www.lexaloffle.com/bbs/?tid=41149</a> for more information.</p> <h2>Menus</h2> <p>All the menus use the same code and are driven by data passed to them. There's nothing amazingly clever about them (or that), but I found it was much nicer in every respect to work with them once I took this approach. So I suggest writing generic menu routines soon if you find you're needing more than one of the things in a project - don't put it off.</p> <h2>Memory and Performance</h2> <p>PICO-8 makes both of these things really easy - Ctl/Cmd P along with a constant print of stat(0) if it went above a threshold value (usually 1024).<br /> The latter helped me find a nasty problem very near release. For a long time I'd paused the game except when flying the ship in space, but particles were drawn and deleted in the draw function. When I enabled the game to update, even while in the maps and docked, I was generating particles (NPC ship engines, NPC hyperspace, sun flares), but never deleting them. So I'd run out of memory. Sometimes after a very long time. It happened much faster when I moved the cursor about in the map views so I spent ages debugging those to no joy only to eventually realise that I was running out of memory due to the ship engines firing a bunch of particles out into my dwindling memory...</p> <h2>Loading and Saving</h2> <p>I was very worried about getting the load and save functions to work, especially with the web player, but in the end it was very easy. Dump some values into cartdata to save, read them back when loading. I'm presuming the browser cache gets these when playing in a browser(?).<br /> One slight downer is the paste codes don't work on the web. They seem to work fine in &quot;native&quot; PICO-8 though and the &quot;binary&quot; versions. It's the only thing that doesn't work there.</p> <p>The best thing about having save games was for testing during development. I built up a text file with a long list of different saves that allowed me to test different stages in the game, different galaxies and systems etc. I could edit them a bit to quickly test some things as well.<br /> I'd highly recommend implementing something like this if you have a longer game and want to test it - especially since it's something your players might be able to use too.</p> <img style="" border=0 src="/media/47206/space_37.gif" alt="" /> <h2>Tokens</h2> <p>As you may have gathered if you read this far, I ran out of tokens.<br /> Procedural generation produces content from code in preference to pre-defined content in storage so it wasn't overly surprising. I've seen others struggle with memory for proc gen, but I found the 2MB limit wasn't ever a problem.</p> <p>A large amount of the end of development involved trying to save tokens.</p> <p>Look out for my followup post about that, working title: &quot;A desperate programmer's attempts to squeeze galaxies into a PICO-8 cart&quot;</p> <p>--<br /> If you have any questions about the above post or anything else to do with PICO Space please ask them below and I'll try to answer them (or maybe even extend this article even further).</p> https://www.lexaloffle.com/bbs/?tid=42353 https://www.lexaloffle.com/bbs/?tid=42353 Fri, 09 Apr 2021 15:46:00 UTC PICO Space <h1>PICO Space</h1> <p> <table><tr><td> <a href="/bbs/?pid=89915#p"> <img src="/bbs/thumbs/pico8_drakeblue_picospace-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=89915#p"> drakeblue_picospace</a><br><br> by <a href="/bbs/?uid=47206"> drakeblue</a> <br><br><br> <a href="/bbs/?pid=89915#p"> [Click to Play]</a> </td></tr></table> </p> <p><em>v0.9b</em><br /> Defend the animals of the galaxy from the space weevil invasion in your grandad's space taxi!</p> <p>Check the notice boards at space stations for prospective passengers. Gain rewards when they're delivered safely and discover how to defeat the weevil menace.</p> <p>The galaxy is quickly becoming a more and more dangerous place so be careful out there - with 50-70 systems and some questionable government policies an animal needs to look after themselves!</p> <p><strong><em> Please report any bugs or if something is unclear below. Feedback helps me improve and is always welcome :) </em></strong></p> <h2>Controls</h2> <img style="" border=0 src="/media/47206/spacecontrols.png" alt="" /> <h3>Main Menu</h3> <ul> <li>Use Up, Down and X to select options in the menus. </li> <li>Return/Start/P will always take you to the Main Menu</li> <li>Hold Return/Start/P to access the normal PICO-8 menu.</li> </ul> <p>I recommend a gamepad if you have one, but keys work fine too. Holding the X and O buttons together is useful to use the ship flip ability successfully. On mobile, I've found swiping my thumb backwards and forwards between the X and O buttons works okay, but it does seem easier to play with keys or a gamepad (to me at least).</p> <h2>Starting the Game</h2> <img style="" border=0 src="/media/47206/space_46.gif" alt="" /> <p>Use the up and down directions to highlight an option and X to select it.</p> <ul> <li>Begin New Game - starts a new game with the currently show captain in a new galaxy (Captain Magerquack by default).</li> <li>Change Captain - chooses a new captain and galaxy with which to start a new game using the Begin New Game option. This doesn't affect the currently stored game or any game from a pasted code.</li> <li>Continue Last Game - this retrieves the previously auto-saved game from your browser's cache or PICO-8's cartdata. The game is saved at the Dock Menu and on entering a system via a hyperjump.<br /> If you want to preserve further game states beyond this then use the next option.</li> <li>Load From Pasted Code - every time the game is saved PICO Space places a save game code into the clipboard. By pasting this code into a text file or similar then multiple game saves can be maintained. To restore from one of these codes:<br /> &gt; - copy the code into the clipboard from the application you've used to store it<br /> &gt; - switch back to PICO Space running in PICO-8 and paste it<br /> &gt; - Use X to select the Load From Pasted Code option in the menu</li> </ul> <p>NOTE: THIS DOESN'T SEEM TO WORK IN THE BROWSER - YOU WILL NEED TO DOWNLOAD THE STANDALONE PICO-8 CONSOLE VERSION TO LOAD FROM SAVE CODES OR ACCESS THE GAME THROUGH SPLORE<br /> THE GAME WILL BEHAVE UNPREDICTABLY (PROBABLY CRASH) IF A MALFORMED CODE OR OTHER DATA IS PASTED INTO IT</p> <ul> <li>Set Difficulty - Adjusts how dangerous the galaxy is in the game. This option affects new games only so needs to be set before choosing &quot;Begin New Game&quot;.<br /> &gt; - Easy - for casual or inexperienced players, but still with some challenge<br /> &gt; - Normal - a reasonable challenge, success is not guaranteed on each journey<br /> &gt; - Hard - a difficult game likely to require multiple reloads</li> </ul> <p><strong><em> Please tell me if you think these ratings aren't very correct so I can try to tweak them </em></strong></p> <h2>How to Get Around the Galaxy</h2> <p><em>(the following is an extract from the dog-eared manual you found in the glove compartment of your grandad's ship)</em></p> <p>Congratulations on your purchase of a Farwilre P1C0 Star Taxi!</p> <img style="" border=0 src="/media/47206/space_47.gif" alt="" /> <p>Your ship will enable you to fly anywhere within a system's boundary by directing it with the arrow keys or control stick (if fitted). Be careful of flying into a system's sun as there may be undesirable explosive consequences.</p> <ul> <li>The Short Range Scanner is useful to see what's close to you and is located in the bottom right of the viewscreen.</li> <li>The current system or current target (with distance in standard galactic units) is shown in the top left.</li> <li>Your ship's remaining shield energy is displayed in the bottom left. If this is depleted then it will flash to indicate that you should dock at the nearest space station for recharging.</li> <li>To locate space stations or other objects within a star system press Return, Start or P to bring up the main menu.</li> </ul> <h2>Main Menu (Pause)</h2> <img style="" border=0 src="/media/47206/space_48.gif" alt="" /> <p>Select the System Map (with Up, Down and X) from the options shown.</p> <h3>System Map</h3> <img style="" border=0 src="/media/47206/space_53.gif" alt="" /> <p>Solar systems are large so to avoid excessive journey time it is advised to utilise your ship's hyperdrive from the System Map (where traffic laws permit).</p> <p>To do this:</p> <ul> <li>Locate the cursor where you wish to jump to by using the direction keys</li> <li>Press O, Z or V to execute a hyper jump</li> <li>Press X to target the nearest system object. The target is shown in the top left and also indicated by a red marker.</li> </ul> <p>Note: be sure to peruse the System Map in a safe location to avoid possible accidents while it has your attention. Last year 45% of ship accidents happened while pilots were viewing their map screens - don't let the next one happen to you!</p> <p>Systems in PICO Space are linked by Hyperspace Wyrmholes (of as yet unknown origin). These can be used to traverse between stars even in ships that are unequipped with an interstellar-capable drive. Thus to travel to another system simply fly into the centre of a wyrmhole and your ship will travel through hyperspace to a point in the system indicated in the wyrmhole's name.</p> <p>If you know which adjacent star you wish to travel to, it is easiest to find where the wyrmhole to it is by using the System Map.</p> <p>To navigate about the greater galaxy and hence determine which wyrmholes to use it is advisable to examine the ship's Galaxy Scanner.</p> <h3>Galaxy Scanner</h3> <img style="" border=0 src="/media/47206/space_50.gif" alt="" /> <p>The Galaxy Scanner will open centred on your current location - shown by the ship icon and expanding circle indicator. Adjacent stars (i.e. those which are connected by a pair of wyrmholes) have lines drawn between them. Systems adjacent to your current location have green lines drawn to them. Corresponding wyrmholes should be visible on the System Map.</p> <p>The view and cursor in the centre may be moved using the direction keys. The currently highlighted system will be the closest to the cursor position.</p> <p>The galaxy is quite large so for optimal viewing it may be necessary to zoom the view in or out by holding the X key and using the Up and Down directions to change the scale of the view.</p> <p>If your ship is fitted with an Interstellar Drive then it is possible to hyperjump (without traversing a wyrmhole) to adjacent systems by highlighting them with the cursor in this view and pressing O, Z or C.</p> <h3>Status</h3> <p>At any time your current status can be checked from the Main Menu by selecting this option.</p> <img style="" border=0 src="/media/47206/space_55.gif" alt="" /> <p>The screen shows:</p> <ul> <li>You, the captain of the ship and your combat rating</li> <li>Any current message</li> <li>Your current passenger if one is present and to where they wish to be taken.</li> <li>Information about any upgrades that have been added to your ship</li> <li>The energy level remaining for you ship's shields</li> <li>The danger level of this galaxy</li> </ul> <h2>Weaponry</h2> <p>Should you be unfortunate enough to encounter a hostile threat on your travels your P1C0 Space Taxi is fitted with a standard P3W Blaser; a small but adequate defensive weapon.</p> <ul> <li>Tap X (and release) and the P3W will fire</li> <li>Hold X to charge multiple shots that will rapidly fire on releasing the trigger.</li> <li>Note: while energy is diverted to charging the P3W your shields are unable to recover strength.</li> </ul> <h2>Dock Menu</h2> <p>When docked at a space station the following standard options will be available:</p> <img style="" border=0 src="/media/47206/space_56.gif" alt="" /> <h3>Notice Board</h3> <p>Waiting passengers are listed here for an enterprising space taxi owner to transport to their desired destination.</p> <img style="" border=0 src="/media/47206/space_57.gif" alt="" /> <p>Use the Up, Down and X keys to select a passenger that you wish to transport. Be careful to choose a journey you can complete - an animal never backs out of a deal!</p> <h3>New Paint</h3> <p>Choose from a range of desirable colour schemes to customise your Farwilre pride and joy!</p> <h3>Launch to Space</h3> <p>The station will launch you back to space so you may continue on your journeying.</p> <p><em>extract ends</em></p> <h2>Tips</h2> <ul> <li>Choose your passengers wisely - some wish to travel further than others. Check on where they want to go via the Galaxy Map before committing to a journey you aren't sure you want to take.</li> <li>Plan your journey before leaving the safety of the space stations.</li> <li>If your shields are damaged it may be wise to stop at a station on the way to your destination to recharge them.</li> <li>Charge your weapon before encountering enemies, but don't hold X constantly as it stops your shields recharging as you fly.</li> <li>Use your hyperspace ability within systems to save on journey time or to escape a tough spot, especially as the galaxy becomes more and more dangerous.</li> <li>Note that the game is only paused in the Main Menu, other screens don't freeze time.</li> </ul> <p>If you are not sure what to do:</p> <ul> <li>try ferrying passengers</li> <li>later in the game, try reading the Beeb News or listening to what the NPC ships say to you.</li> </ul> <p>Good Luck, Captain!</p> https://www.lexaloffle.com/bbs/?tid=42279 https://www.lexaloffle.com/bbs/?tid=42279 Sat, 03 Apr 2021 16:56:27 UTC Fading Stars <h1>Fading Stars Demo</h1> <p> <table><tr><td> <a href="/bbs/?pid=86396#p"> <img src="/bbs/thumbs/pico8_fading_stars-5.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=86396#p"> fading_stars</a><br><br> by <a href="/bbs/?uid=47206"> drakeblue</a> <br><br><br> <a href="/bbs/?pid=86396#p"> [Click to Play]</a> </td></tr></table> </p> <p>Demo showing the combination of the stars and fade effect I used in PICO Space: <a href="https://www.lexaloffle.com/bbs/?tid=42279">https://www.lexaloffle.com/bbs/?tid=42279</a>.</p> <p>[UPDATE 2021-4-12: 8bit and 16bit cached modes (explanation below and in code), some other small tweaks]</p> <h2>Stars</h2> <p>The stars are just simple particles that have x,y,z coordinates.</p> <p>In this demo I use a couple of sin functions to give them some movement combined with a divide by the z coord for a bit of parallax. In game, I feed in the player's position.</p> <p>Then I clamp the resulting x,y values to the screen with the modulus operator so they're always visible (%128). It does mean that the same stars go past constantly, but otherwise I was processing a lot of particles that don't get seen very often (not aiming for realism here).</p> <h2>Fade Effect</h2> <p>This works by mapping the colour of every pixel on the screen to another colour that tends to a target e.g. 0/black.<br /> You can use a similar mapping with the pal(x,1) function to e.g. do fades to black between screens etc. but that fades everything including anything drawn that frame.</p> <p>In this demo I process the pixels already in screen memory so that the screen is faded by a step, then draw fresh stars on top of that.</p> <p>It's pretty expensive to do the whole screen (IIRC about 90% of performance at 60fps) so I've set it up to do every fourth scan line, starting from a different point each frame. Effectively a quarter of the screen is faded at a time. It takes 4 frames to fade the whole screen one step.</p> <p>I initially tried fading in quarter strips top to bottom, but the tearing on bigger objects like planets looked pretty bad.</p> <p>Using the order 0,2,1,3 for the scanlines does some rough dithering to make the effect look a bit more uniform. A random value flr(rnd(4)) works quite well too, but is messier looking.</p> <p>Since I found using poke4 to work on 8 pixels at a time was fastest (not surprising really) dithering horizontally is limited and isn't in the demo. Nevertheless, I keep meaning to try a &quot;Z&quot; pattern i.e.</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre> 0000000011111111 2222222233333333</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'm concerned it might cost too much more in performance/tokens for too little visual improvement.</p> <p>[edit]<br /> Of course, as soon as I write about it the old subconscious starts working away and it takes 5 minutes to implement just that - a reverse N pattern as it turns out. Same performance, same tokens. See the new cart.</p> <h3>Pros of Effect</h3> <ul> <li>You can draw whatever you want really and the effect essentially &quot;just works&quot; as a replacement for a cls().</li> <li>Cross-fading out from a scene just happens &quot;free&quot;.</li> <li>very simple particles look much more complicated than they really are</li> </ul> <h3>Cons</h3> <ul> <li>You can't draw anything that moves without the fade effect &quot;catching&quot; it. It can be mitigated by drawing around your objects (e.g. black borders), but if the view moves more than the width of the border you're out of luck.</li> <li>Conversely, the effect only works where you don't draw that frame - so if your game has e.g. a full-screen scrolling background that's drawn every frame then you won't see any effect at all. For a <em>space</em> game this isn't a huge problem, but it's still visible here and there. </li> <li>If nothing moves then there's no effect - try hacking the stars to be still in the demo.</li> <li>Performance cost is approx 21% at 60fps.</li> <li>Obv costs some tokens.</li> </ul> <h2>Caching</h2> <p>The effect works fine by extracting each pixel's colour value via shifting and masking then dumping the mapped values back onto the screen, but it's still pretty performance heavy.<br /> When I was writing PICO Space I'd read a few times that procedurally generated content used a lot of memory so I didn't want to try anything like the following, but now I have a much better idea of the game's memory requirements I thought I'd give it a go.</p> <h3>8-bit Mapping</h3> <p>Pixels in PICO-8's screen are determined by a 4-bit value, but peeking and poking only works with 8-bit granularity at best i.e. a pair of pixels or more at once. The mappings I have contain 16 values for each possible colour of a pixel.</p> <p>Considering pairs of pixels instead of single pixels, there are 16 * 16 = 256 possible combination of colours that need to be mapped. Why not store a table with each of these values - it can't be that large, right?</p> <p>Turns out it isn't, especially when compared to the 2MB of space lua is given in PICO-8. In fact the demo seems to only use about 2K or so (which is still a lot more than the 256 bytes it <em>should</em> take, but still pretty small).</p> <p>This means that a lot of masking and shifting isn't as necessary inside the inner loop. It even takes fewer tokens. The performance improvement is enough that half or even all of the screen being processed per frame isn't too bad.</p> <h3>16-bit Mapping</h3> <p>The next step was obviously to try mapping 4 pixels at a time using 16-bit values.</p> <p>This would need a table of 16^4 = 65536 entries which isn't very big for a modern machine, but is pushing it pretty far for PICO-8. It's possible - take a look at the code. It also takes up a <em>lot</em> more memory: about 1200KB it seems. That's well over half of the total space available and for my purposes in PICO Space is enough to give me sporadic out of memory errors as it stands (PICO Space takes about 600-900KB depending on the size of the current galaxy and how much is going on in it at any particular moment). For other games it may be absolutely fine and it's tempting since there's about a 2x speed-up compared to my original implementation of the effect using this technique. </p> <h3>A bit too far</h3> <p>PICO-8's number format is 16bit.16bit fixed point so every value I've been storing so far is actually 32 bits in size whether I use all of those bits or not. Why not use them all?</p> <p>Storing mappings for 8 pixels isn't going to work: 16^8 = 4,294,967,296 - a bit too much for PICO-8.</p> <p>Instead, the last implementation that I've tried (so far) stores two 16-bit values in each number in the cache table so that the same amount of mapping values as in the previous section takes half the entries and hence half the space. The upper 16 bits take the even values; lower 16 bits the odd values.</p> <p>This brings the memory usage down to about 600KB or so, which is fairly reasonable.</p> <p>Unfortunately, the two mapping values packed into a single PICO-8 table value need to be unpacked to be used in the inner loop of the effect. By the time shifts and masks are applied to do this I couldn't get the performance to really be any better than the original effect (without any caching of values), never mind faster than the 8 bit or 16 bit table. So using this would be spending about 600K for no real benefit.</p> <p>If you have any other ideas or know of optimisations I've missed then I'd love to hear about it below.</p> https://www.lexaloffle.com/bbs/?tid=41149 https://www.lexaloffle.com/bbs/?tid=41149 Tue, 12 Jan 2021 15:57:44 UTC Demystifying the Christmas Tree <p> <table><tr><td> <a href="/bbs/?pid=85468#p"> <img src="/bbs/thumbs/pico8_demystify-3.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=85468#p"> demystify</a><br><br> by <a href="/bbs/?uid=47206"> drakeblue</a> <br><br><br> <a href="/bbs/?pid=85468#p"> [Click to Play]</a> </td></tr></table> </p> <h1>Demystifying the Christmas Tree</h1> <p>Help your kitten destroy as many decorations as you can before the tree is fully decorated or their energy runs out and they nap.</p> <p>Try to destroy multiple decorations within a short time to get combo bonuses and improve your score. Use your energy wisely, young feline.</p> <p>Play as Philly or Frankie on their own or with a friend against each other. See who can cause the most chaos!</p> <h2>Controls</h2> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>Action Frankie (Player 1) Philly (Player 2) jump up E run left/right S, F descend down D poke O(Z) W swipe/hit X Q Return menu, including music on/off and restart.</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>(These are the standard PICO-8 controls so some other keys work too)</p> <h2>Background</h2> <p>Demystifying the Christmas Tree recreates a real event from a Christmas past, although in real life the kittens not only broke decorations, but also took out parts of the tree itself. They also didn't run out of energy (as anyone who has had kittens would know).</p> <p>If you like this game, find a problem or have any suggestions then please comment below.</p> <p>Please consider trying my other games or following me for news on new projects.</p> <p>Happy Holidays :)</p> <p><strong>1.0.1 update:</strong> after testing with the owner of the kittens (my girlfriend's mother aka &quot;mother-outlaw&quot;) I've added an option to change the speed that the arms decorate the tree.</p> <p><strong>1.0.2 update:</strong> added fade effect to intro. Because I felt like it.</p> <p><strong>1.0.3 update:</strong> added combo indicator after user feeback.</p> https://www.lexaloffle.com/bbs/?tid=40826 https://www.lexaloffle.com/bbs/?tid=40826 Wed, 16 Dec 2020 13:32:01 UTC Silly Snow <h1>Silly Snow</h1> <p> <table><tr><td> <a href="/bbs/?pid=84926#p"> <img src="/bbs/thumbs/pico8_db_silly_snow-3.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=84926#p"> db_silly_snow</a><br><br> by <a href="/bbs/?uid=47206"> drakeblue</a> <br><br><br> <a href="/bbs/?pid=84926#p"> [Click to Play]</a> </td></tr></table> </p> <p>(update: added 2 new methods that incorporate gusts of wind)</p> <h2>Controls</h2> <p>UP/DOWN chooses different behaviour for the snow flakes<br /> X changes the colour of the falling snow so you can see the &quot;trick&quot; a bit easier<br /> O/Z toggles drawing the non-snow bits of the graphics each frame on and off</p> <h2>What it is</h2> <p>--</p> <p>TL;DR<br /> Only track falling snow, add lying snow to the background.</p> <p>--</p> <p>As it's that time of year again, I thought I'd write some winter-themed stuff.</p> <p>This is my take on ye olde faithful falling snow demo, which I'm using for the intro screen for another cart (on its way soon). I've cleaned it up a bit, added way more comments than I normally do and added some options to show what's happening a bit and show some variations. Click &quot;Code&quot; below the display above if you're interested.</p> <p>I first typed in a version of this demo from a magazine back in the mid 80s on an Atari 800XL. In the 35ish years since then I'm not sure I've ever implemented it again though.</p> <p>The gist of how it works:<br /> Falling snow is represented by a collection of simple particles that are represented by a position (x,y). Each frame that position is updated (mostly downwards i.e. y+=some_dist).<br /> If the snow flake encounters an obstacle (i.e. a pixel that isn't empty or the bottom of the screen) then the snow flake has landed. </p> <p>Tracking snow flakes after they've landed isn't practical (even with PICO-8 and it certainly wasn't with an 800XL) and is also a bit pointless since once a snow flake has landed, it aint going anywhere. Well, at least not in this demo. Instead, the particle is destroyed and the pixel where it landed is set to white and becomes part of the background (in this demo that means it has a colour greater than 1).<br /> This is an incredibly basic version of how a lot of &quot;physics&quot; engines work: updating only moving or otherwise interesting parts of the simulation and &quot;parking&quot; the rest. Usually they'd check the stationary particles in some way for whether they need to be activated. If you wanted to simulate collapsing drifts etc. there's nothing really to stop you keeping a record of where the snow has fallen or scanning for white pixels and perhaps checking to see if a condition to collapse has been met. Then you could find all the snow pixels affected by the collapsing pixel and &quot;wake&quot; them up. You would probably need to check at a slower than per frame rate for performance reasons.</p> <p>As with most sims the fun is in playing about with it, hence the 9 method variations in the cart e.g.</p> <ul> <li>the exact behaviour of the flakes in the air</li> <li>whether they land or slide to the side on encountering the background can be tweaked.</li> <li>wind gusts...</li> </ul> <h2>Blustery Blizzards</h2> <p>Methods 8 and 9 add a wind factor to the updated position for each flake generated by a value derived from complex and deep trigonometric knowledge (aka trial and error). The nice thing about this is it's only calculated once per frame and only added per snow flake so it's very cheap. Adding sin values per flake based on the flake's position gives some odd results.</p> <h2>Limitations</h2> <ul> <li> <p>for there to be stationary, landed snow relies on not clearing the screen. If you clear the screen then you're pretty snow drifts all disappear. You can still have snow flakes falling, but they will disappear a frame after they land...</p> </li> <li> <p>The methods in this cart are fairly non-destructive of the background, but it's fairly easy to make a version that &quot;eats&quot; into what's already on the screen (acid snow!). I've included an option to re-draw the background each frame. As long as your background doesn't move then it works fine (remember, no screen clear).</p> </li> <li>&quot;tunneling&quot; through thin parts of the background varies in frequency depending on your method. Generally, the more random the snow flake movement, the more problems you'll have.</li> </ul> <p>On the Atari ST there was a game based around this that I got from a magazine cover disk called &quot;Downfall&quot;. I could only find one video of it and the uploader doesn't seem to really understand how to play it sadly.<br /> You were supposed to compete against a friend to draw lines to funnel snow from your side out of a hole at the bottom that would then be sent to their side (and vice versa). You could also funnel snow to the sides to give you energy for &quot;special powers&quot; that let you e.g. draw lines on your opponent's side.</p> <p>I expect that explanation's as clear as a blizzard; hopefully the code isn't as bad.</p> <p>Happy holidays :)</p> <p><object width="640" height="400"><param name="movie" value="https://www.youtube.com/v/SHZB9nIzZ64&hl=en&fs=1&rel=0"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="https://www.youtube.com/v/SHZB9nIzZ64&hl=en&fs=1&rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="400"></embed></object></p> https://www.lexaloffle.com/bbs/?tid=40631 https://www.lexaloffle.com/bbs/?tid=40631 Wed, 02 Dec 2020 12:47:35 UTC The Pico Mermaid <h1>The Pico Mermaid</h1> <p> <table><tr><td> <a href="/bbs/?pid=84034#p"> <img src="/bbs/thumbs/pico8_thepicomermaid-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=84034#p"> thepicomermaid</a><br><br> by <a href="/bbs/?uid=47206"> drakeblue</a> <br><br><br> <a href="/bbs/?pid=84034#p"> [Click to Play]</a> </td></tr></table> </p> <p>Use (X) to control the Pico Mermaid as she fetches pearls from the bottom of the sea back to the surface. Avoid the piranhas that will swim faster and faster as the mermaid retrieves more pearls.</p> <p>This is my entry into Tweet Tweet Jam 5 and so the code fits into 560 characters (two tweets).</p> <h3>Features:</h3> <ul> <li>Single-button controls (X)</li> <li>Animated and multi-colour pixel art sprites*</li> <li>air and water physics*</li> <li>Two particle systems*</li> <li>Difficulty ramp*</li> <li>Score effect*</li> <li>Death effect*</li> <li>start animation*</li> <li>current score and high score display*</li> <li>in-game instructions*</li> </ul> <p>(* kinda)</p> <p>Here's the code:</p> <div> <div style="max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre>P=pset::A::x=64y=0v=-9t=0w=127e=0d=.6s=0for z=0,29do poke(z\6*x+z%6+1,'0x'..sub('e0e800800880ce0800444404e008002444043b0000444480b000004088',1+z*2,2+z*2))end::B::P(69,e&lt;1and w or y,7)H=max(s,H)e=y&gt;119and 1or e ?'tAP❎ gET●:'..s..' hI:'..H v+=.5C=cls if(y&gt;8)v-=max(btnp(❎)and 2or.4,v-.6) flip()C(1)rectfill(0,0,w,9,12)t=(t+d)%w y=min(120,y+v)spr(0,x,y,1,1,t&amp;8&lt;1,e&lt;1)for i=3,14do d=-d t=-t h=40*i-t-4&amp;w pal(4,i)k=i*8k+=7*sin(h/w)if((h+4)\8==8and 4&gt;abs(k-y-2))C(8)goto A spr(1,h,k,1,1,d&lt;0)P(rnd(8)+x,h*d%y+3)P(k*d/.7,h\d)end if(y&lt;9and e&gt;0)e=0s+=1d*=-1.2C(7) goto B</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=40311 https://www.lexaloffle.com/bbs/?tid=40311 Mon, 09 Nov 2020 11:37:59 UTC P8C-BUN on Itch.io <p>P8C-BUN is now uploaded to itch.io here: <a href="https://drake-blue.itch.io/p8c-bun"><a href="https://drake-blue.itch.io/p8c-bun">https://drake-blue.itch.io/p8c-bun</a></a><br /> <object width="640" height="400"><param name="movie" value="https://www.youtube.com/v/QmOxLX-82RY&hl=en&fs=1&rel=0"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="https://www.youtube.com/v/QmOxLX-82RY&hl=en&fs=1&rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="400"></embed></object></p> <p>I've also been working on something else that I really want to share a preview of soon, but I need to clean it up just a little more first.</p> https://www.lexaloffle.com/bbs/?tid=40116 https://www.lexaloffle.com/bbs/?tid=40116 Mon, 02 Nov 2020 14:36:10 UTC P8C-BUN <h1>P8C-BUN</h1> <p> <table><tr><td> <a href="/bbs/?pid=83276#p"> <img src="/bbs/thumbs/pico8_drakeblue_p8cbun-2.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=83276#p"> drakeblue_p8cbun</a><br><br> by <a href="/bbs/?uid=47206"> drakeblue</a> <br><br><br> <a href="/bbs/?pid=83276#p"> [Click to Play]</a> </td></tr></table> </p> <p>Help your chosen bunny cover each level with poo then escape down a rabbit hole. Don't get caught by the fox or anything else that's out to get you!</p> <p>Finish all 16 levels without restarting to achieve &quot;Iron Bun&quot; or just try to post a high score. Start at whatever level you like.</p> <h3>Controls</h3> <ul> <li>Use the d-pad/arrow keys to direct your bunny.</li> <li>z/c/(O) to show where you haven't pooed yet.</li> <li>x to paws and return to the title screen.</li> <li>You can toggle the music or return to the title screen from the menu as well.</li> </ul> <h3>Tips</h3> <ul> <li>The buns will keep running in the direction you choose until there's no clear path in front of them so there's no need to hold down the arrow keys.</li> <li>If you choose a new direction before a junction or corner they'll remember that and turn immediately so corner early for maximum speed.</li> <li>The bananas will give you a speed boost, but leave skins behind that you (or the fox) may slip on.</li> <li>Macaroon is too tough to be caught by the fox or anything else so if you just want to play through the levels (or practice) choose to play as her. Real-life Macaroon has seen off cats and kills blankets on a regular basis.</li> <li>The fox gets faster and the red kite will fly over as you cover more levels so choose which level you start from wisely if you're aiming for Iron Bun.</li> <li>Manipulate the fox, especially using the rabbit holes, to make your life easier.</li> </ul> <p><object width="640" height="400"><param name="movie" value="https://www.youtube.com/v/5PR46S5bCCA&hl=en&fs=1&rel=0"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="https://www.youtube.com/v/5PR46S5bCCA&hl=en&fs=1&rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="400"></embed></object></p> <p>1.1 Update: text legibility and efficiency improvements<br /> 1.1.1: restored kite spawn to be after a few levels and not right from the beginning.</p> <p>This is my first PICO-8 game (in fact, my first full game for anything) so any feedback is welcome. More info about P8C-BUN is here: <a href="https://drakeblue.com">DrakeBlue.com</a>.<br /> This game was inspired by our real-life pet rabbits (especially Oreo, who does tend to poo everywhere) and exists thanks to the patience of my gf (who runs the rabbit-oriented website mentioned on the title screen <a href="https://rabbitretail.co.uk">RabbitRetail.co.uk</a> and uses it to help donate to rabbit charities and rescues as well as feed ourselves and our own bunnies).</p> <p>Purchase to download and support more development and bunnies here: <a href="https://rabbitretail.co.uk/products/p8c-bun-game"><a href="https://rabbitretail.co.uk/products/p8c-bun-game">https://rabbitretail.co.uk/products/p8c-bun-game</a></a></p> <p>Or here: <a href="https://drake-blue.itch.io/p8c-bun">Drake Blue on Itch.io</a></p> https://www.lexaloffle.com/bbs/?tid=40018 https://www.lexaloffle.com/bbs/?tid=40018 Sat, 24 Oct 2020 11:46:09 UTC