Skip to main content

On Sale: GamesAssetsToolsTabletopComics
Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Twinbeard

120
Posts
5
Topics
921
Followers
43
Following
A member registered Feb 23, 2015 · View creator page →

Creator of

Recent community posts

Totally valid. I saw several playtesters continually accidentally reset or regroup, but I wasn't sure what to do about it with this control scheme. Pico-8 only gives you two buttons 😂

Wrote up some design notes/thoughts about design process here: https://twinbeard.itch.io/it2/devlog/1137791/it-2-design-notes

A Steve served cold

If you look at the patent for Tapper, they admit that it's basically just Space Invaders rotated 90 degrees

A very rad Steve

Powerful. We could all learn a thing or two from Annie's determination to better herself.

I love admitting guests

A very wholesome Steve

I got the funny ending. (I assume. I don't know if the other ending is also funny.)

More like "A Short Hike," amirite

A very uncomfortable Steve

A very good Steve

The feel good movie of the year

An excellent Steve

You're not stuck! This is an intentional puzzle.

Extremely convincing self-driving AI!

Glad to hear it! Thanks for playing!

Which screen was it? Your progress should be mostly saved!

Where was that? I just now uploaded a fixed for an out-of-bounds digging rightwards out of the dirt sac below the toilet nexus.

If you restart the cartridge, the save system should have kept almost all your progress!

Shipped It!

https://twinbeard.itch.io/it2

As you golf tokens to add features, the code complexity increases and the compressed code size goes up. It's the Token Golfer's Curse. I forgot to keep counting, but I'm at something like 1500 tokens golfed and I've been actually having to remove features/text to make new things fit.

I've spent the past couple of days implementing audio and music -- not very screenshottable -- and a secret ending --extremely screenshottable, except that I don't want to spoil it.

Anyway, please look forward to those things.

Pi! Co! Steve! Mo! Pi! Co! Steve! Mo! Pi! Co! Steve! Mo! Pi! Co! Steve! Mo!

Yeah I'm of two minds about it as well. I think the token constraint is a crucial aspect of Pico-8's design. It discourages feature creep and encourages a shipping mentality. But when you're at the token limit and you need to fix a bug or make a tweak, there's nothing stopping you from golfing just a few more tokens, until your code is an unmaintainable mess and and you realize that if you do it wrong, Pico-8 is actually harder and less fun to use than an ordinary game engine. 

(2 edits)

I am butting up hard against both the token and compressed code limits right now, 99.85% and 99.79%, respectively. About 1300 tokens golfed. I don't know why I assumed this game would be simpler than my previous PiCoSteveMo entry! (I'm at like 86% for sprite/map space, despite having fleshed out the map far beyond what I'd predicted would be feasible. Apparently this game's level design compresses really well.)

Pico-8 token golfing is a deep rabbit hole. 

A lot of token golf optimizations are just good changes, taking unnecessary complexity or verbosity and turning into it something simple. For example, in the initializer, I looped over the map, with a series of if-then statements to compare each map tile to a dozen different magic numbers that indicated a certain entity is supposed to spawn there, like this:

if t==1 then e = balloon(p)
elseif t==4 then e = boulder(p)
elseif t==20 then e = phone(p)

I have a function that initializes a dictionary using a string, so I created a tile to object mapping:

objs = dict"1,balloon,4,boulder,20,phone,37,target,34,stormdrain,39,checkpoint,2,button,48,gate,52,theythem,78,button"

So most of that series of if-thens gets replaced with this code that looks up the that object's initialization function in the global namespace dictionary:

if objs[t] then e = _ENV[objs[t]](p)

And I think that's a net good change, sacrificing simplicity for size and flexibility -- though the "actually good code" version would initialize the dictionary in a more readable way.  But if you want to really get the most out of your tokens, you get up to some wild shenanigans. For example, I've got this code as part of the routine that draws the title screen, several calls to the sprite blitting routine specifying what to draw where:

cspr(256,78,0,3,2)
cspr(259,110,0,2,2)
cspr(261,4,20,8,2)
cspr(288,68,20,7,2)

By Pico-8's count, that's 28 tokens. I added a wrapper to cspr that allows you to pass parameters in a string:

csprs"256,78,0,3,2"
csprs"259,110,0,2,2"
csprs"261,4,20,8,2"
csprs"288,68,20,7,2"

Which is apparently valid function call syntax?? And a mere 8 tokens.

One of the most recent things I did was to take all the state of the dialog tree system that used to be encapsulated inside its own object, and just dump it into the global namespace. This saved like 50 tokens throughout the codebase because nar_msg is one fewer token than nar.msg.

This is by far the ugliest code base of any of my Pico-8 games. Historically I've avoided using a minifier because I like to ship a relatively readable game, but even with manual optimization, readability is totally out the window at this point. For my next game I'm probably going to figure out how to use a minifier workflow so things stay readable on my end at least.

(4 edits)

I'd based my decision to switch from high memory video mapping to sprite caching on tests I ran where I disabled video remapping, and the same seemed to play fine. (Just with the wrong graphics.) After I actually did the switchover to sprite caching, and it still froze up, I revisited the no-remapping build and it also froze up. All three builds froze, after an unpredictable amount of time -- sometimes several minutes of gameplay.

In a shocking turn of events, the preceding investigation turned out to be a wild goose chase. The bug was happening when you input a diagonal rather than up/down/left/right, which is much easier to do accidentally on a touchscreen or d-pad than on a keyboard.

On the plus side, I get to keep all the tokens that I golfed to make room for the sprite caching library. ~1100 tokens golfed so far!

It 2 is currently playable start to finish in the Pico-8 IDE, in a Windows build, and in a web build on Windows Firefox and Windows Chrome. It crashes very early on in Android Firefox, Android Chrome, and in the Xbox Series Edge browser.

I've been using an undocumented feature of Pico-8 called "high memory video mapping" to switch between multiple banks of sprites. I had been warned that this feature might be unstable in a web build, so I'd been testing it -- but only on desktop, until now.

High memory video mapping was inspired by a library by pancelor that did the same thing by copying sprite data into video memory as needed. If I switch to using that library, I'll have to golf 184 tokens, which is nontrivial at this point -- I've already golfed the easy stuff, ~820 tokens worth -- but should be doable.

When you're right, you're right

Looking sharp!

Coneheads!

I've got an essay in me about how the correct API for playing looping sounds is something like "StartOrContinue(sound, volume, pitch, etc)" that you call every frame, and the sound engine stops playing the sound if that function isn't called.

Like a year ago I decided to run an experiment: I drank a shit-ton of water throughout the day, much more than was intuitive for me, for a few weeks. During that time, among other changes, I stopped wanting to drink coffee. I realized that my desire for coffee in the morning was almost certainly just a desire for hydration. Then I got lazy and returned to my usual amount of water drinking, but coffee hasn't regained its luster. So while the "8192" in that font is very appealing, I'm not sure what I could put in the mug??

I ran a couple playtests at a local event on Saturday. The most fun result of this was definitely that I needed to implement a fast travel system:


In less fun news, I've hit the token limit. From now on when I talk about token stats, it'll be how many I had to code golf in order to fit new features or fixes.

I've implemented nearly every feature that I had planned, including the ending. I've got a first draft of all the story scenes written.

Stats:

  • Sprite/map memory: 71.0% full.
  • Compressed code size: 96.1% full
  • Tokens golfed: 480

Trying to tie everything together to playtest at an event I'm going to this weekend. I've got the intro scene is finished so the whole title->intro dialog->gameplay sequence is in place.

Here's where I'm at for the cartridge constraints:

  • Sprite/map memory: 5184 bytes (47.3%)
  • Tokens: 7012 (86%)
  • Compressed code size: 11954 (77%)

Compressed code typically ends up being the limiting factor on dialog trees. Look Who's The Shining 2 had about 1000 words of dialog in it and I had to code golf to make room. (Code golfing compressed code size is much less fun/intuitive than code golfing tokens.) This will probably end up a simpler game mechanically so hopefully the code won't end up as dense, leaving more room for writing. I'm at about 400 words and I've got five more scenes planned out.

Was it Pyro 2?

I didn't know about passing non-integer values to the width and height parameters, that's a neat trick!

Wow you're done early, it's not even halfway through the month!

Hm yes, this could get v. interesting with different house designs

Working on story scenes:



Last year I deliberately set out to make a Sokoban-derived game where the interest came from a different place than being incredibly hard. Whenever I play one of those puzzle games, I'm like *this was fun for like ten levels, why can't the rest of the game be as easy and fun as the first ten levels?" 

This year, I happened on the Snakebird similarity accidentally. I would look to Snakebird for puzzle design inspiration, but I can't because it was too hard for me.

(3 edits)

Bev has a slingshot:

Eddie can swim. Everyone else floats:

Solving puzzles with water flow:


Tokens: 6610