This is a clone of the infamous Flappy Bird, scrunched down to under 560 characters. I wanted to see if I could fit a game with actual graphics within the limit, and I'm happy to say that it worked. Any feedback about the controls and physics is welcome.
Controls: Press any button to fly upward/restart
This is the full level 1-1 from Super Mario Bros., graphics and all, contained in 3 tweets, or 840 bytes. The first 280 bytes contains the actual level data (including level-specific graphics), and the next two contain the rendering engine and the main tileset. I'm thinking about making some more add-on levels, which should each fit in a single tweet.
I've made a number of Tweetcarts, and also worked on systems to efficiently compress graphics and level data to fit more on a PICO-8 cart, so this is kind of the logical combination of both. I'm not going to try and fit a full NES game in tweet form, but it's a neat demo that helped me learn some new optimization strategies.
Version 0.2-- Reconfigured repeating pattern object types for adjustable pattern size, added level delete option to editor menu, and changed a few design elements to improve usability
This is a graphical map editor that allows creation of large game worlds hundreds of screens in size that fit in a single Pico-8 cart. It does this using a version of metatiles, a compression technique used commonly with retro systems like the NES. Basically, levels are stored more efficiently by being built from groups of tiles instead of single tiles, just as images are stored more efficiently when built from tiles rather than single pixels.
To give you an idea of how efficient the scheme is, I built a playable demo of all Super Mario Bros. level maps with an earlier version, and they fit in just 3.9KB, about 1/3 of the storage space the system makes available.
I've worked hard to minimize the system's footprint so it's easy to add to game carts. It's very CPU-efficient and well-suited to 60fps games since map decompression is done only when loading a new level, and the core functions take about 650 tokens and 9% of compressed file size with comments, or about 6% without. You can use it in any project you want and modify the code to fit your application, just be sure to include attribution somewhere in your cart. Hopefully this will enable people to make some cool larger-scale games like platformers and action-adventures.
The editor lets users create levels from metatile "objects", like a tree, a hill, or a building, each of which is basically a reference to a rectangle of tiles in Pico 8's map area. In the editor, levels are stored as lists of objects in string form, but when exported to a separate cart, these are condensed into raw binary data and stored in its spritesheet and map areas. Meanwhile, three strings are output to the clipboard, ready to be pasted into the code area--compressed sprite and map area data strings, and a string-based lookup table for the location of each level's data in cart memory.
When the destination cart is run, the binary level data is transferred to a table in Lua RAM and the spritesheet and map area data are decompressed to the proper areas in cart memory. On loading a level, a second table is created to contain its map, and this is filled using instructions from the main table. A portion of the level table slightly larger than one screen is then copied to the top right corner of Pico-8's map area once each frame and mapped to the display. This allows each level to be any width or height, and up to 256 screens in size.
Left Mouse btn.-----Select or place object/bring up object placement preview
Right Mouse btn.---Click and hold to drag view (turns off object placement preview)
Directional keys----Move view
Scroll Wheel--------Select object number
Z--------------------Toggle object editor screen
X--------------------Delete object when mousing over its top left corner (a white 'x' will appear)
--Editor shortcut keys
V-------------------Change variance type (when in obj.editing mode)
M-------------------Change mapping pattern type (when in obj.editing mode)
S-------------------New level string submenu
Q-------------------Previous level map
W------------------Next level map
E-------------------Export level map to cartridge
A-------------------Export all level maps to cartridge
Directional keys---Move camera
Z-------------------Previous level map
X-------------------Next level map
Using the editor
Creating a new level
Once you've started the editor, if you want to create a new level string, open the menu and click on the 'new level map' icon. Select your desired background color, level type (work in progress), level width and height in screens, and press the checkmark icon to create the new level string.
Since your maps will be made from tile patterns in Pico-8's map area, you'll need to draw each object type there before you can use it. Due to the way the system works, you'll need to keep a couple of limitations in mind.
To create objects to populate your level map, select the object category using the icons on the top right, then the object number either by clicking the thumbnail and selecting a slot from the drop down menu, or by using the mouse wheel. To create an object, go into object editing mode by pressing 'Z' and outline the rectangle of tiles that defines the object's default (minimum) size.
Each object type can be made to have a variable size. This is done by changing two properties, its variance and mapping pattern. These are represented by icons in the lower right corner of the editor, next to the object's ID number.
An object's variance type tells how its size can be altered when it's being placed in a level.The box that's highlighted defines the default (or minimum) size of an object, but if its size is variable along an axis, the size can be extended up to 15 tiles larger than the default size in that direction. Fixed-size objects take 2 bytes each, while ones whose size can vary on one or two axes take 2.5 and 3 bytes respectively (though it'd be possible to limit this to 2.5 bytes max via lookup tables if you only need certain types in a given level).
This property controls the pattern of how map tiles are used to build objects in your level. This can allow objects to be made much larger than their representations in Pico-8's map area while still keeping their intended traits.
To change these settings for an object, go into the object editing mode and click on the buttons in the bottom right hand corner, or press the 'V' key to cycle through variance types and the 'M' key to cycle through mapping types.
The system continuously outputs the level you're working on and the list of definitions for all the objects you've defined to the clipboard as strings. To save these to the cartridge, just paste the contents of the clipboard over the current strings in the "data strings" tab, and save the cart.
Once you've made some levels, you can export them to a separate viewer cartridge, suitable to be incorporated into a game. To do this, first open a new cart and paste the functions from the "Game Cart Functions" tab in the editor there, and uncomment them. Then save the cart with the same name as the "export_cart_name" variable in the editor cart's _init() function, and save and close the new cart.
Next, run the editor, open the system menu, and click on one of the cartridge icons to export either the current level map, or all level maps to your new cart. Now open the viewer cart, make sure "puny font mode" is enabled by pressing Ctrl+P, and paste the contents of the clipboard into it. Now you can run the cart and view your levels.
As this is an early version of the editor, it's missing a few features and may have some kinks to work out, and the code's kind of messy. Please let me know about any issues you encounter, as well as any improvements you might think of. Thanks.
I've lately been working with image compression routines which output strings, and I've been able to increase efficiency and versatility by using as wide a range of characters to store data as possible. I've grown a bit frustrated at times, though, because any strings which use Puny font characters don't show up correctly unless I go into Puny Font mode. There have been a number of times I couldn't get things to work, and spent time debugging my code, only to realize that the problem was that I forgot to press Ctrl+P.
I know it's not a big issue, and it can be worked around, but it's kind of inconsistent how strings can be created with Puny characters at any time, but you have to enter a certain mode to view the output correctly. Is it possible this could be changed without breaking some other feature? I mean, is there any way to let the program know that a string has been created by Pico-8 and therefore display it as intended?
Version 1.1 -- added ability to clear output string by pressing Z
Version 1.2 -- Removed characters 0-15 as Pico-8 0.2.2 made these unusable and problematic, tweaked appearance
This is a little tool for easily selecting and outputting characters from Pico 8's extended character set. You can build strings of any length and paste them as text using Ctrl+V or a right mouse click (on the BBS, you have to press Ctrl+C as well). I had some fun making it look like a version of the Pico-8 code editor with text characters as the icons, and since it's a pretty small program, I squeezed it down to fit in a tweet =).
Arrow buttons---Select character
X button--------Add character to output string
Z button--------Clear output string
Version 1.1 - Reworked code and squeezed in invader animation
Version 1.2 - Invader shots now target player, tweaked barriers, fixed disappearing score glitch
This is a port of the original arcade Space Invaders in just over half a kilobyte. I had to simplify a few things, like only having one invader type, cutting the UFO, and rethinking the lives system a little bit, but most of the major elements are there, and I think it plays fairly well.
- Score system
- Level Progression
- Enemy Animation
- Enemy Fire with homing shots
- Destructible barriers
- Increasing invader speed and fire rate as number destroyed increases
- Damage system (your laser cannon changes colors after taking a hit, and will be destroyed after 3)
L/R----Move laser cannon
This is something I've been working on here and there for a while, but the jam was finally an excuse to finish it. It's a simple space invaders clone in a single tweet. There's no enemy fire or shields, but the invaders do speed up as you destroy more of them, and it's tricky to take the last few out.;)
Version 1.1 - new enemy wave begins when current wave is destroyed
Version 1.1 -- Updated for TweetTweetJam5, added square brush feature and tweaked appearance
This is a fully-functional painting program with image save capability in just 277 characters. It's built entirely around mouse controls, and requires a mouse with a scroll wheel for full functionality. Hope somebody enjoys playing around with it.
Left mouse button ---- Paint
Right mouse button --- Select paint color (hold and move mouse L/R)
Middle Mouse button -- Save drawing to cart
Scroll wheel --------- Change paintbrush size
X key (hold) --------- Use square brush
This is a compact and efficient system that enables recoloring of sprite graphics. For just 76 tokens, plus any function calls and data strings, you can easily change the color palettes of level tiles or characters based on an arbitrary number of conditions, and even animate them using color cycling. These kinds of techniques were used extensively in games for consoles like the NES to increase graphical variety while conserving limited memory resources. The cart explains the syntax of the data strings and includes a simple demo of what the system can do.
This is a little exercise in code optimization, a fully-functional analog clock in just 196 characters. I'm thinking I might add some features in the future while still keeping it under the 280-character limit, but for now it works just fine.
This is a demo for a system I developed that can store console-size game worlds on a Pico-8 cart. It contains every level and sublevel map from the original Super Mario Bros., and you can run and jump through all of them. There's no level progression, sound, or things to interact with besides platforms, but the map data includes placeholders for enemy spawn points and interactive objects, just uncomment a line in the init() function to make these visible. I'm not planning to release the finished game, as I don't want it to be taken down for copyright reasons, but I wanted to show some definitive proof that large-scale games are possible on Pico-8.
Cart Technical Info:
- Uses standard map() and sprite flag functions (w/special camera offsets)
- 60fps w/ CPU usage between 11-25%
- 1352 tokens, including streamlined platformer engine and graphics/map decompression systems
- 35% of compressed storage limit
- All maps contained in 3.9KB of binary data in map area
- No data stored in the 8KB spritesheet
The big thing is the last point on the list. Instead of storing the nearly-incompressible level data in strings, I instead store the spritesheet in a string because it compresses over 2:1, leaving a full 12KB of potential level storage space. This means that while leaving the majority of compressed data capacity and token count unused, 3 copies of every Super Mario Bros. level could fit on the cart! By my estimates, the worlds of mid-sized NES games like Megaman, Ninja Gaiden, Castlevania, Zelda, and even SMB2 (or original ones with similar scope and detail) could fit within that 12KB limit with some optimization. For instance, I estimate that Zelda 1's whole world could fit in around 6KB.
This demo was built entirely in Pico-8, using a graphical level editor that I plan to release in the near future. It's currently a bit limited due to being tailored to the quirks and limitations of SMB, but I intend to add some more features and make it easy for anyone to build their own large game worlds using a simple point-and-click interface. Here's a little preview =).
Version 2.0 --New system with much-improved ease-of-use and flexibility in one tiny, 74-token function!
With Pico-8's small spritesheet, many game makers who want a nice title screen are forced to either give up valuable sprite space for a custom-drawn logo, or use a tiny one and zoom in so it but looks very pixelated. Occasionally, someone will use a more advanced method to store images, such as Zep's PX9 or dw817's compression programs. These work well, but the minimum cost of 1000+ characters and 280+ tokens for decompression plus prite sheet rewriting, and/or screen-filling compressed strings can be overkill for many projects, so I came up with my own alternatives.
Version 1.0 encodes logos as 1bpp images into 7 bit-per-character strings, then renders graphical features such as shadows, color gradients, and outlines in real time, without using the sprite sheet. A logo drawing function built with it takes between 85-130 tokens and achieves high levels of compression, though it's limited only to logos, and large ones with outlines can use ~50% of cpu cycles at 30fps.
Version 2.0 uses a version of Run-Length-Encoding (RLE) to compress full-color graphics into strings. It's based on this system here, originally devised by @spellcaster, but I was able to shrink the core functionality down to a fraction of the size and token count while adding a few new features. Like version 1.0 it doesn't use the sprite sheet at all and can handle images of any pixel dimensions. It offers a slightly less compact data footprint, but is far simpler to use, uses less CPU, and can handle any kind of graphics you want. There are 3 versions:
- Core version --the one demonstrated in the cart (74 tokens)
- Version with pre-conversion of strings to tables (104 tokens, lowers CPU usage about 40% further on average --could be useful for 60fps games)
- Version with pre-conversion and real-time vertical and horizontal flipping (161 tokens)
Both 1.0 and 2.0 include instructions to encode your own logos or images, but version 2.0 is much simpler to use, just import or paste an image into the top left corner of the spritesheet, specify its size in pixels, run the cartridge, and follow the icons to encode the image and output a compressed string.
Lately I've heard bits here and there about a new function called unpack that seems to have some significant benefits, but after searching the BBS, the Pico 8 Wiki, and Google, I've barely been able to come up with any solid infomation on it or how to use it.
If someone could point me in the right direction, I'd much appreciate it.
Yes, this is yet another version of Space Invaders, but with this one I'm going for a direct port of the original arcade game. It's mostly complete, with functional gameplay and a working high score save system, but it needs some gameplay tweaks and a few graphical elements, and the sound effects are very much unfinished (I'm working on a version of the 4-tone march using subtones, but haven't ironed out the glitches yet). Anyway, in addition to going for authenticity, I also tried to code this very efficiently, and the whole game (including all graphics and sound), takes under 3KB and only about 1100 tokens.
Any constructive criticism and general feedback is welcome, thanks.
Version 1.1-- Managed to shrink code to under 560 characters, making this a tweettweetcart
Version 1.2-- Fixed game over glitch, improved HUD
Join Squirt as he jumps and bounces in the sky through varying times of day, on his way to Cloud Land.
This is the deluxe version of my single-Tweet platformer Cloud Bounce. The gameplay is essentially the same, but in just two tweets it has a lot of important game features added, including:
- Animated title screen
- Game over screen with restart
- Lives system
- An improved ending (the original was by necessity super abrupt)
There's no sound or music, and no enemies, but overall I'm pretty happy with how much of a full game I managed to fit in a little over half a Kilobyte. I'm interested to see how complete a game I could fit in 2 or 4KB using some of the optimization techniques I've learned.
This is a fully playable version of Tetris in fewer characters than a moderate-length email, including:
- Line removal
- Level progression (speed increases after every 10 lines cleared)
- 'Lines cleared' display
- Soft drop button (with slight delay when next piece appears)
Fitting everything in this small a space was really tough, but I made it. I had to cut a few corners, for instance there's no next piece preview, only one rotation direction, and there wasn't space for logic to allow movement of blocks once they land, so overhangs are a nuisance. With all that said, though, I worked hard trying to make this an actually decent version of tetris and not just a technical curiousity, so hopefully somebody actually enjoys playing it instead of just staring at the indecipherable souce code. Shoutout to 2dArray, whose Tweetjam Tetris and its genius piece indexing system I built on for this project.
Version 0.2 - Now has definite fail state with timer stop, and recolored graphics
You are a ground-based defense drone at a top-secret research base inexplicably located by a mountain prone to avalanches. When a tidal wave of snow and ice rushes toward you, you must use your cannon to vaporize it, keeping it at bay for as long as possible so the base staff can get to safety. How long can you hold out?
This is the unintended result of trying to cram a minimalistic space invaders clone into 280 characters. I couldn't figure out how to fit code for individual enemies, but an advancing amorphous mass was just doable. Hopefully it turned out alright on its own terms, and I welcome any feedback or criticism. Warning, though, this can get a bit nerve-wracking. o_O
After discussing base64 encoding in a recent thread, I decided to try my own version of it for storing level strings, but after some experimentation I started wondering how much of a storage benefit it really offers vs. hexidecimal. I also came across an old post from user Overkill from 2016, in which he concludes that unfavorable interaction with Pico-8's built-in compression basically negates base64's byte-per-character advantage.
I decided to perform a test of my own to measure the difference precisely. To do this, I used some web-based tools to generate random strings, using both hexidecimal and my own base64 character set, which uses as many 1-byte characters as possible (59, to be specific -- certain characters like small caps and glyphs use 2 bytes). I generated very large strings and pared them down just enough to fill the compressed data limit to 100.00% using each character set. I performed 3 trials each, recording how many characters would fit for each encoding type, then averaged these amounts for a general comparison. Results are as follows:
Base64: 15846 characters max.
Hex: 23230 characters max.
Base64: 15776 characters max.
Hex: 23261 characters max.
Base64: 15757 characters max.
Hex: 23275 characters max.
Base64: 15793 characters max. -- 11,845 bytes
Hex: 23255 characters max.-- 11,628 bytes
From these trials, the difference in byte capacity vs. compressed size appears to be about 2%, which suprised me. While there could be cases in which custom encoding offers various benefits, in general I think I'll stick with hexidecimal. For me, a negligible increase in storage efficiency is more than offset by much easier conversion to and from byte values and some degree of readability.
Join Squirt as he jumps and bounces in the sky through varying times of day, on his way to Cloud Land.
Features character and level animation, 60fps gameplay, over 150 unique screens of platforming, and a simple ending-- all in under 280 characters!
This is the first game I made for Pico-8 (or for any platform, for that matter...). I wasn't originally planning to try and fit a game in this small a size, I was just working on a platformer game test, but then I came across the concept of tweetcarts and things went in an unexpected direction. I planned to upload the release version a long time ago, but wanted to fit a couple more things in.
Hello, first post here.
I just got started with Pico-8 recently, and have learned about the usefulness of storing data in strings to get around token limits. I was wondering, can I build a data string using a p8 program, then output that string as text that can be fed into another p8 program without it being reformatted? I'm working on a graphical level-editor program that will output level data strings usable by another cart.
I tried using printh(), but when I opened the text file it mangled up the extended character glyphs and didn't preserve the 4x3 font lower-case letters I had in the string. My goal is to have all 121 characters available so I can store about 7 bits per character, instead of the 4 possible with hexadecimal, if this is possible.
View Older Posts