andrejtrindade [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=86005 Tiny Tactics Postmortem <h1>Tiny Tactics Postmortem</h1> <img style="margin-bottom:16px" border=0 src="/media/86005/24_1-title.png" alt="" /> <p>A few months ago I discovered PICO-8 and decided to make a game for it. It was a nice experience, and I'm proud of this little turn based, tactics / puzzle game. I'll try to summarize below how I made <strong>Tiny Tactics</strong>.</p> <p>I didn't have much spare time to devote to this project (maybe 5 to 10 hours a week), but I think it went pretty smooth. I spent exactly 3 months making the game (from purchasing a license for PICO-8 to exporting the final version of the cart).</p> <p>You can play the game and download the cart <a href="https://www.lexaloffle.com/bbs/?tid=55172">here</a>.</p> <p>I have also created a <a href="https://github.com/andrejtrindade/tiny_tactics/tree/main">project</a> on GitHub. It contains:</p> <ul> <li>source code before flattening / compression;</li> <li>spritesheet and map exports;</li> <li>a standalone HTML version; </li> <li>binaries for Windows, Mac, Linux and Raspberry Pi; </li> <li>a <strong>walkthrough</strong>: GIFs I recorded using PICO-8, showing my solutions for each level; </li> <li><strong>leaderboards</strong>: more GIFs, showing how to get <em>gold trophies</em> I'm aware are possible (first person to claim the record gets the credit).</li> </ul> <p>Note: <strong>Tiny Tactics</strong> was created using PICO-8 version 0.2.5g</p> <h2>1. What I set out to do</h2> <p>One of my main goals when making the game was learning PICO-8, so I decided to only use documented features while reading the PICO-8 Manual. This means no alternate palette, for example. I only used graphics functions in the most straightforward way possible (no 3D, lighting or other complicated techniques not directly supported by the PICO-8 graphics callbacks).</p> <p>I also decided right away to fit everything into a single cart: I liked the limitations imposed by PICO-8, and I feared going multicart would allow the scope to creeply get out of hand (as it tends to do), especially on my first project.</p> <p>On the other hand, I didn't want the game to feel like a vertical slice demo. I wanted it to feel somewhat complete, so I decided to cram as much levels into the cart as possible (no decompression or other advance techniques though, see the previous paragraphs). One of the earliest design decisions I made in <strong>Tiny Tactics</strong> was to devote all shared memory to the map.</p> <p>You can see below that i used 99.87% of the available tiles in the map (including shared memory).</p> <img style="margin-bottom:16px" border=0 src="/media/86005/tiny_tactics.map.png" alt="" /> <p>This left me with only two tabs for sprites. I also decided very early on that all enemies would use the player sprites, palette swapped. I experimented with different sprites for enemies, but the levels became more difficult to read so I abandoned the idea.</p> <p>Of course there are also sprites for drawing the map (including enemies starting postion), story elements etc.<br /> In the end I had just enough sprites to make a simple (yet pleasant) title screen and add a few &quot;easter eggs&quot; to the levels (dining rooms and offices, just to make the levels feel more lived-in).</p> <p>You can see below that I used all available sprites (first two tabs only).</p> <img style="margin-bottom:16px" border=0 src="/media/86005/tiny_tactics_sprites.png" alt="" /> <p>The UI was also very important from the start, as I feel this is part of what makes the game feel &quot;somewhat complete.&quot; I opted not to include transitions or other fancy UI animations, though. Instead, I focused on the quality of life settings the player can configure in the game's menus (customizable animations, controls, tips and so on).</p> <p>Also, I tried to &quot;do it only once&quot;. I didn't want to spend lots of time redesigning levels or reimplementing mechanincs. If it wasn't fun, I scrapped it ASAP. If it was fun, I finished it and moved on. This is my first project, it was not supposed to have a long development cycle.</p> <p>Finally, I quickly decided to use an external editor (Notepad++) to edit the code. The code section in tiny_tactics.p8 only contains 20 <code>#include</code> lines and a few comments, like the cart label ones.</p> <h2>2. What changed along the way</h2> <h3>2.1. Feel</h3> <p>The game started as a minimalist tactics game, but it ended up also feeling like a puzzle game. Which is fine by me, these are my two favorite game genres. What was set on stone from the very beginning was that I wanted the game to feel &quot;fair&quot;. The player and the enemies should be able to perform the same actions. Everyone should die in one hit. I wanted the player to feel he is overcoming all those enemies by being smarter than their simple AI, not because of some super powered armor or weapon.</p> <h3>2.2. Colors</h3> <p>The colors I used to palette swap the enemies changed a lot during development. I needed to have good contrast with the floor. The checkered white / light gray floor tile was set on stone very early on, but enemies' colors changed a lot along the way. When designing the last enemy types, the idea of using both hair and jacket colors to independently indicate different characteristics of their AI behaviour finally came to me.</p> <img style="margin-bottom:16px" border=0 src="/media/86005/enemies.png" alt="" /> <p>Also, the idea of palette swapping wall colors to make each secret base feel different from the last one only came when designing the final bases. For most of the development process, the map was all in shades of gray. In the end of the development process, I realized this made progress very monotonous. I tried to choose wall colors that don't sacrifice level readability and also don't distract you from the enemies you should be focusing on.</p> <h3>2.3. Levels</h3> <p>When I was designing the first levels, the plan was to make all levels 15x13 tiles (which is the maximum level size, as some screen space is reserved for status bars on top and bottom and for the EXIT text when the door is unlocked).</p> <p>Each level would consist of multiple rooms and, when a player moved from one room to another, enemies would enter the room from color coded doors. I quickly realized this made the code a lot more complex than it should... And also severely limited level design, which was the worst drawback.</p> <p>I changed the approach, making each level be a single room with x, y, width and height coordinates stored in a table. Player and enemies are positioned when the level starts. This is done through color coded floor sprites (invisible by palette swapping these colors to white when drawing the map).</p> <p>This brought much more freedom for the level design - and was much simpler to code.</p> <img style="margin-bottom:16px" border=0 src="/media/86005/map2.png" alt="" /> <h3>2.4. Menu</h3> <p>When I designed the first few levels I quickly realized the game felt a lot like a puzzle game. I remembered how much fun I had optimizing my solutions in <em>Sokoban</em> and <em>Hitman Go</em>, so I decided to add a turn counter and records very early on. Player records are persisted on cart data.</p> <p>On the other hand, I didn't want players to feel stuck so I included an option to unlock all levels (I also persisted that option on cart data). This helped a lot with development and testing.</p> <p>For a long part of development, the menu only had three options. </p> <ul> <li><strong>play</strong> - I wanted level names front and center, as I quickly found out they were important to make levels feel unique and keep them engaging. When you press <strong>play</strong> you only see level numbers, names and wether you've cleared them or not.</li> <li><strong>options</strong> - The only option at the time was to unlock all levels.</li> <li><strong>records</strong> - Where the player can compare their best score for each level with the <em>dev's record</em>. As the record chase is meant to be the endgame, I decided this would be the last option on the menu.</li> </ul> <h3>2.5. Controls</h3> <p>Using arrows to move and a button to shoot was obvious from the start, but what about the other button? Should it also be used? For what? In the beginning I thought about using it to let the player spin in place (without moving), but I had the intuition this would lead to less interesting, more bureaucratic puzzles - and more complex AI. </p> <p>I decided the second button would simply skip the turn for the player. This made the levels more claustrophobic - in a good way! Now the player has to consider if he has enough space to position himself so he can aim at enemies. This made for much more interesting puzzles.</p> <p>I know the community knows keyboard input mappings like the back of their hands, but I wanted to show the game to friends who never played a PICO-8 game, so I decided to ask the player if he is using a keyboard and change button / key labels accordingly. The game does this when it can't load cart data (first time the game is started) or at any time the player selects <strong>controls</strong> on the title screen.</p> <p>Based on the feedback I received, this was the right choice.</p> <img style="margin-bottom:16px" border=0 src="/media/86005/29_1-controls.png" alt="" /> <h3>2.6. Tips</h3> <p>Tips started as random hints that appeared when levels were small enough, so i had some screen space to show them. In the end, though, it was best to leave them in the main menu, so they are easier to access. </p> <p>I like that you have the basic info you need to play available in the game's menus, even if you don't read anything in a blog post. I wrote a lot more tips, but had to trim them down to the absolutely necessary so I could fit everything in a single cart.</p> <p><img style="margin-bottom:16px" border=0 src="/media/86005/30_1-tips1.png" alt="" /> <img style="margin-bottom:16px" border=0 src="/media/86005/31_2-tips2.png" alt="" /></p> <h3>2.7. Customizable animations</h3> <p>When I added animations to the game and tested levels with more enemies (like level 1-9), the testing process quickly became tedious. I decided to do what a lot of RPGs do: give players an option to skip animations. Then I decided to break that into more detailed options, like letting players set the <em>animation speed</em> and skip <em>move</em> and <em>idle</em> animations.</p> <p>I decided to let animations in mid speed by default and trust the player to find these options by himself. Many didn't. I noticed many people didn't read the instructions or even checked to see what was available in the <strong>options</strong>. I suspected this could happen, but didn't want to interrupt the player with yet another text screen. I'm not sure it was the best decision though.</p> <img style="margin-bottom:16px" border=0 src="/media/86005/32_1-options.png" alt="" /> <p>While testing with <em>move</em> / <em>idle</em> animations turned off, I noticed the game was letting only one enemy act in each frame. This made the game feel too slow when there were many enemies on a level. I changed the code to make sure the game lets more than one enemy act in a single frame when their animations are skipped.</p> <p>The game still isn't as responsive as I would like when <em>idle</em> and specially <em>move</em> animations are turned off. But I don't have the tokens to completely overhaul the animations, turns and controls. Besides, as I said before, this is my first project. &quot;Do it once and move on&quot; was my motto! In any case, the game still is pretty playable and enjoyable as it is, IMHO.</p> <h3>2.8. Pause menu</h3> <p>Restarting or quitting the level is possible through additional commands in the pause menu.</p> <img style="margin-bottom:16px" border=0 src="/media/86005/33_2-pause.gif" alt="" /> <p>I didn't want to assume player would be familiar with the pause menu, though. That's why the button / key used to access the pause menu are displayed in the <strong>controls</strong> screen.</p> <p>That's also why I added the ability to turn off sound from the title screen, even though you can do the same in the pause menu. Redundant? Yes. But if I didn't know I could do that for the first few weeks of development, why assume players will know about it? Many players are friends of mine who never played a PICO-8 game before...</p> <h3>2.9. Story</h3> <p>While designing levels and testing them, I felt the game was feeling like a simple pack of levels. Level names did make each level more unique, but I still missed some kind of overarching narrative. I believed the game needed a story, even if it was as simple as the story in the first <em>Super Mario Bros.</em> game. So I made a simple story referencing some sentences from that game, but using a Mission: Impossible / 007 setting - which better fitted the gameplay.</p> <p>Did you catch those references while playing the game? I even hightlighted the word substitutions in different colors to make them as identifiable as possible.</p> <p><img style="margin-bottom:16px" border=0 src="/media/86005/base_cleared.png" alt="" /> <img style="margin-bottom:16px" border=0 src="/media/86005/mario.png" alt="" /></p> <p>I liked the end result, even if it actually consists of just a few screens with text and very simple graphics with a different perspective (side view instead of top-down). It's simple, but I find it charming.</p> <h3>2.10. Trophies and alternative skin</h3> <p>I wanted to give players an additional challenge, and I wanted to reward them for it. So I added my personal records to the level coordinates table as the <em>dev's record</em>. I also added a screen to track records... And trophies! If the player matches my record for a level, he gets a silver trophy. If he breaks my record, he gets a gold one.</p> <img style="margin-bottom:16px" border=0 src="/media/86005/records-gold.png" alt="" /> <p><strong>Note</strong>: I won't update the <em>dev's records</em>, even if I break my own records after the game's release (it has already happened, in fact). That's what the <a href="https://github.com/andrejtrindade/tiny_tactics/tree/main/leaderboards">leaderboards</a> are for.</p> <p>I also added an alternative skin in the <strong>options</strong> if the player manages to get trophies for all levels (doesn't matter if they are silver or gold). It's been a week since I published the game on the BBS. As far as I know, nobody has unlocked the alternative skin yet... If you manage to do so, post a screenshot on the game's thread!</p> <img style="margin-bottom:16px" border=0 src="/media/86005/37_3-.png" alt="" /> <h3>2.11. Sound</h3> <p>I'll admit sound was an afterthough in this project. The game didn't have any sound for most of the development process. Adding sound effects was pretty straightforward, but composing music takes time. I decided to do a very simple theme for the menus, use looping sound effects for story screens and not have any music during levels (just sound effects). I used less than 25% of the available sound effects and music patterns, but that's OK.</p> <p>Maybe my next game will have more sophisticated sound, but the sound in <strong>Tiny Tactics</strong>, though simple, is serviceable and pleasent - at least to my ears. Also, it doesn't distract you from solving the puzzles, which is something I consider essential.</p> <h3>2.12. Tokens</h3> <p>I have used 99.86% of the available tokens and 99.55% of the compressed bytes limit.</p> <img style="margin-bottom:16px" border=0 src="/media/86005/39_tokens.png" alt="" /> <p>I broke the token limit a few times during the last few weeks. I had to use some tricks to optimize my token count. Here are the two main ones...</p> <ul> <li>The coordinates for each stage were combined into a single integer. As there are 81 levels, this saved me more than 1,000 tokens. For example, for stage 5-8 we have <code>0x1216.892e</code>. Let me break it down (all numbers are in hex): <ul> <li>12 and 16 are the x and y map coordinates of the topmost, leftmost tile of the level. </li> <li>8 is the level width in tiles. </li> <li>9 is the level height. </li> <li>Finally, 2e is the <em>dev's record</em> for the level.</li> </ul></li> <li>I used split() to create most of my tables, as each string only consume a single token. For example, the main menu is created with <code>split(&quot;play,controls,options,tips,records&quot;)</code>. You can do the same with numbers, split() will convert them for you.</li> </ul> <p>Something I wish I could do is to define constants without wasting tokens. Constants in lua are just variables, and you spent tokens to define them. I still created a lot of them to make the code more readable, but in the final weeks I just didn't have the tokens to spare.</p> <p>Sound effects constants, for example, are commented, and sfx numbers are hardcoded in the lua files. Side view character sprites for the story are also hardcoded for the same reason. I'm glad I managed to avoid this in most other situations, though.</p> <p>I also simplified or removed a few redundant, verbose comments from the code to keep everything under the compressed bytes limit. The code is still very readable though, I believe.</p> <h3>2.13. Release</h3> <p>Before posting the cart on the Lexaloffle BBS, I uploaded the whole project to GitHub. I wanted anyone to have easy access to the bynary apps (Windows / Mac / Linux / Raspberry Pi), the standalone HTML version and the uncompressed source code, even if the person doesn't have PICO-8 to export everything.</p> <p>I also created a walkthrough by recording GIFs, showing my solution for every level. After some time, it may be difficult to recall how exactly you finished a level in X turns. I know this from experience...</p> <h3>2.14. Updates</h3> <p>I updated the game a couple of days after releasing it. This first change was very minor: I addeed the level number to the clear screen, because my friends were sending me screenshots of broken records - and I had to ask which level they were playing.</p> <p>Then, a couple of days later, I found a bug (suprised no one complained!) where you could walk through the locked exit door before you eliminated all the enemies... So I updated the game again to fix this.</p> <p>I also added a leaderboards folder to the GitHub project. It contains GIFs showing how to get the gold trophies I'm aware are achieavable. First person to claim the record gets the credit (once I verify the new record is actually possible, of course).</p> <p>This game has 9 enemy types and 9 secret bases with 9 levels each. Right now there are 9 gold trophies on the leaderboards. Funny coincidence, huh?</p> <h2>3. How did it go?</h2> <p>It's been a week since I published the game on the BBS.</p> <p>I'm very happy to see my friends and family playing the game, finishing bases and even breaking my records! Two of them have already finished the whole game, all 81 levels! </p> <p>It's also very nice that several forum members tried the game and liked it enough to give it a star or leave a comment.</p> <p>I remember when I was a kid, drawing super heroes on my notebook. I didn't want to make money out of it, put my drawings in an art gallery or anything. I just liked drawing... Whenever I was proud of a drawing and my friends thought it was cool, that was my definition of success. </p> <p>That's how I feel now, decades later, about <strong>Tiny Tactics</strong>. I had fun making it! I'm thrilled people are also having fun playing it! It's not perfect, but I'm proud of it.</p> <p>Anyway, I hope you liked this writeup! And, if you still haven't played <strong>Tiny Tactics</strong>... <a href="https://www.lexaloffle.com/bbs/?tid=55172">Go try it!</a></p> https://www.lexaloffle.com/bbs/?tid=55244 https://www.lexaloffle.com/bbs/?tid=55244 Fri, 08 Dec 2023 15:54:35 UTC tiny_tactics <p> <table><tr><td> <a href="/bbs/?pid=138037#p"> <img src="/bbs/thumbs/pico8_tiny_tactics-4.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=138037#p"> tiny_tactics</a><br><br> by <a href="/bbs/?uid=86005"> andrejtrindade</a> <br><br><br> <a href="/bbs/?pid=138037#p"> [Click to Play]</a> </td></tr></table> </p> <h1>Tiny Tactics</h1> <p>A turn based, tactics / puzzle game for PICO-8</p> <img style="margin-bottom:16px" border=0 src="/media/86005/2-playing.gif" alt="" /> <h2>Controls</h2> <ul> <li>When you start the game for the first time it will show you the controls and ask if you are using a keyboard. Your answer will be saved, and appropriate button / key labels will be used on the menus. </li> </ul> <img style="margin-bottom:16px" border=0 src="/media/86005/1-controls.png" alt="" /> <ul> <li>Shorter levels (like the first few ones) will also show the controls at the bottom so you get used to them.</li> <li>If you want to change labels from keys to buttons or vice-versa later on, just select <strong>controls</strong> on the title screen.</li> </ul> <h2>Features</h2> <ul> <li>81 levels</li> <li>9 enemy types</li> <li>2 hours of gameplay (first playthrough estimate)</li> <li>Story with an actual ending</li> </ul> <img style="margin-bottom:16px" border=0 src="/media/86005/2-briefing.png" alt="" /> <ul> <li>Customizable animations</li> <li>Ability to unlock all levels if you get stuck</li> <li>Appropriate button / key labels wether you are using a keyboard or not</li> </ul> <p><img style="margin-bottom:16px" border=0 src="/media/86005/2-buttons.png" alt="" /> <img style="margin-bottom:16px" border=0 src="/media/86005/3-keys.png" alt="" /></p> <ul> <li>In-game tips detailing enemies AI behaviour</li> <li>Your settings and records are saved</li> <li>Get trophies if you match the <em>dev's records</em></li> <li>Unlockable skin if you get trophies for all levels</li> </ul> <h2>Playing Levels</h2> <ul> <li>Select <strong>play</strong> on the title screen.</li> </ul> <img style="margin-bottom:16px" border=0 src="/media/86005/1-bases.gif" alt="" /> <ul> <li>Clear a level to unlock the next one.</li> <li>You can quit or restart the current level from the <em>pause menu</em>.</li> </ul> <img style="margin-bottom:16px" border=0 src="/media/86005/2-pause.gif" alt="" /> <ul> <li>Notice the level name at the top, it may be a hint on how to solve it.</li> <li>Notice the turn counter and the turn indicator (<strong>player turn</strong> / <strong>enemies turn</strong>) at the bottom.</li> </ul> <h2>Options</h2> <img style="margin-bottom:16px" border=0 src="/media/86005/1-options.png" alt="" /> <ul> <li>You can adjust the <em>animation speed</em>.</li> <li>You can speed up the gameplay further by disabling <em>idle</em> and/or <em>move</em> animations.</li> <li>If you get stuck, you can <em>unlock all levels</em>.</li> <li>You can also change your <em>active skin</em> (once you unlock the <em>alternative skin</em>).</li> <li>Your settings are saved when you go back to the title screen.</li> <li>You can also <em>show FPS</em> (frames per second), which boringly stay at 30 at all times in my experience. This setting is intentionally not saved.</li> </ul> <h2>Tips</h2> <ul> <li>Select <strong>tips</strong> from the title screen for some in-game hints.</li> </ul> <p><img style="margin-bottom:16px" border=0 src="/media/86005/1-tips1.png" alt="" /> <img style="margin-bottom:16px" border=0 src="/media/86005/2-tips2.png" alt="" /></p> <ul> <li>Take your time to understand enemies AI behaviour, which is indicated by the color of their hair and jacket.</li> <li>Also note the order of activation during enemies turn.</li> </ul> <h2>Records</h2> <ul> <li>Your record is saved when you set a new personal record for a level.</li> </ul> <img style="margin-bottom:16px" border=0 src="/media/86005/1-record_saved.png" alt="" /> <ul> <li>Select <strong>records</strong> from the title screen to see the <em>dev's records</em> and compare them to yours.</li> </ul> <img style="margin-bottom:16px" border=0 src="/media/86005/2-records.png" alt="" /> <ul> <li>You earn a <em>silver trophy</em> for each level in which you tied the <em>dev's record</em>.</li> <li>It's possible that you are able to break the <em>dev's record</em> in some levels. In such case, you will earn a <em>gold trophy</em>.</li> <li>If you earn trophies for all levels you will unlock an <em>alternative skin</em>. It doesn't matter if your trophies are silver or gold.</li> <li>Once the <em>alternative skin</em> is unlocked, you can change your <em>active skin</em> in the <strong>options</strong>.</li> </ul> <img style="margin-bottom:16px" border=0 src="/media/86005/3-.png" alt="" /> <h2>Project</h2> <p>You can download <a href="https://github.com/andrejtrindade/tiny_tactics">the complete project</a> from GitHub, including:</p> <ul> <li>the separate .lua files before flattening;</li> <li>a <a href="https://github.com/andrejtrindade/tiny_tactics/tree/main/exports/html">standalone HTML version</a>;</li> <li><a href="https://github.com/andrejtrindade/tiny_tactics/tree/main/exports/binary%20apps">binary versions</a> for Windows / Mac / Linux / Raspberry Pi.</li> </ul> <h2>Walkthrough</h2> <p>I strongly suggest you try to tackle the levels in the game by yourself. If you get stuck, you can unlock all levels in the <strong>options</strong> and skip the level that's giving you trouble.</p> <p>The same can be said about records. You don't need to tie the <em>dev's record</em> for every level, unless you want to unlock the alternative skin. Even then, you don't need to do it straight away, you can always keep playing the next levels and come back for records later.</p> <p>But if you really want to see how the <em>dev's record</em> can be obtained for a specific level, I have recorded GIFs showing my solution for all levels in the game. The GIFs are on the GitHub repository, in the <a href="https://github.com/andrejtrindade/tiny_tactics/tree/main/walkthrough">walkthrough folder</a>.</p> <h2>Gold Trophies</h2> <p>On many levels, especially the simpler ones, the <em>dev's record</em> already seem to be the optimal solution, so don't expect to be able to get gold trophies on all levels.</p> <p>If you manage to get a gold trophy... Take a screenshot of the <em>level clear</em> screen! This screenshot will contain your entire solution so you (or anyone else) can replay it.</p> <img style="margin-bottom:16px" border=0 src="/media/86005/2-7 solution.png" alt="" /> <p>Please post your screenshot on this forum. I'll appreciate it, and I'll add your record to the leaderboards (see below), giving you the credit for being the first to discover said solution (to the best of my knowledge, naturally).</p> <h2>Leaderboards</h2> <p>On the GitHub repository there is a <a href="https://github.com/andrejtrindade/tiny_tactics/tree/main/leaderboards">leaderboards folder</a> with GIFs showing how to get the gold trophies that I'm aware are possible. First person to claim the record gets the credit (once I can verify the record is really achievable, of course).</p> <h2>Development</h2> <p>I wrote an extensive <a href="https://www.lexaloffle.com/bbs/?tid=55244">postmortem</a>. Go read it!</p> <h2>Feedback</h2> <p>This is my first PICO-8 game. It took exactly 3 months of my spare time (5 to 10 hours / week) to make, from purchasing a license to exporting the final version of the cart. Any feedback is appreciated.</p> <p>I hope you have fun playing <strong>Tiny Tactics</strong>!</p> https://www.lexaloffle.com/bbs/?tid=55172 https://www.lexaloffle.com/bbs/?tid=55172 Thu, 30 Nov 2023 12:46:00 UTC