Ahoy! Here's a little fishing game for you.
The main goal of this project was to experiment with a bunch of fun rendering effects that aren't super common in Pico-8...
...so hopefully the gameplay is worthwhile enough to justify its own inclusion.
- 3D character animation (with knees and elbows!)
- Spriteless animated fish rendering
- Water which visualizes a flow-velocity field
- Fullscreen "day to night" transition filter
- Realtime shadows, including soft shadows from the player
- "Windy grass" rendering
- Procedurally generated maps
- A shop with four gadgets
- Something unexpected, which I don't want to spoil for you
The version of the code that's included here is obfuscated to be illegible, but you can buy the real source code (formatted properly, with optional comments) on itch.io - the price is "$1 or more."
Thanks for reading - I hope you enjoy the game!
First update - fixed a bug in the minified version which broke all the item unlocks. Sorry about that!
Second update - didn't change the game, but the itch.io page is live, so I added a link above.
It's a frosted 3D donut, drawn in 265 chars of Lua!
I'm including the code here, with spacing and indents for legibility (instead of minimizing chars like in the cart).
X/Y/Z: Current sample position (moves along a camera ray), +Y is up
I/J: Screenspace position
U/V/W: Ray direction (normalized)
C: Output color of the current ray
K: Raymarch iterator
Q: Distance to the unextruded torus on XZ plane
L: Shortest distance to the surface of the extruded 3D torus
A: Angular position of sample pos around the torus (0-1, repeating)
(Both distance values are signed: a negative distance means that a point is inside a shape)
cls(2) ::_:: x=0 y=2 z=-3 i=rnd(112)+8 j=rnd(66)+40 u=i/128-.5 v=-(j/128) w=sqrt(1-u*u-v*v) c=2 for k=1,20 do q=sqrt(x*x+z*z)-1 l=sqrt(q*q+y*y)-.5 if (z>4 or y<-1) then break end if (l<.08) then a=t()/64+atan2(z,x) c=(-y*5-.3+sin(a*6)/4) break end x+=u*l y+=v*l z+=w*l end pset(i,j,max(c%16,1)) goto _
Material Capture, or "matcap" for short, is a really neat technique, and now that I've learned about it, I'm pretty surprised that it doesn't come up more often in gamedev conversations. It's great! Here's a pico8 implementation of the concept: it draws approximated realtime reflections on 3D meshes.
There are three settings that you can change while it's running:
Right/Left: Switch materials
Up/Down: Fast-mode / Slow-mode
O/X: Switch models
Fast-mode is kind of like a vertex shader in modern 3D engines (the material texture is only sampled along the edges of triangles). Slow-mode is kind of like a pixel shader (except there's no GPU to give it a speed boost)
Here's something I made this weekend - I recreated a pixel art image which was made by @Kldpxl:
I love his pixel art because it often has a really striking photographic look about it, so I tried to carry that effect over as much as I could.
- It's 100% code: all sprites are generated at load time
- Textured ground plane with perspective distortion
- Value noise with multiple octaves (used for building all textures)
- Raymarcher for generating sprites with lighting:
- Four types of plants
- Background mountains
- Horizontally-tiling clouds
- 3D-positioned plant billboards
- 3D extrusion for low grass and road lines
I think it even runs at 60 fps!
Hello there! This is an example project which is intended to help people learn about making platformers in Pico-8.
The game is free to play, but the source code for this version has been obfuscated, so it's not really practical to look through it. To read the normal-and-legible version of the source code (with or without comments), you can buy it for at-least-$1 on itch.io. As long as you make your own map, you can even sell games that use this code! If you didn't already know, itch.io has very nice support for Pico-8 games.
Anyway, it's a cute little platformer with a grappling hook (you get the hook about halfway through) and a big finale! The main goal was to make a piece of illustrative/educational content which was centered around a real and complete game. See, "Madness Interactive" taught me that reading source code for a game that's fun to play can be much more exciting than reading a code snippet in the middle of some online tutorial. Not sure if I succeeded, but I tried real hard!
Huge thanks to David Carney for helping me with the music, and also to everyone who volunteered to test the game! Y'all made the game better.
A first run seems to take 20-45 minutes or so, but it depends on the player, and a fast runthrough is around three and a half minutes. If you record a video of a run that's faster than that, I'd love to see it!
A particle effect that spawns streams based on the music that's playing!
The song is a chiptune cover of "STONEFIST" by HEALTH.
It never stops repeating once it starts, but the music loop is maybe 45 seconds long.
Here's an example of how to do some basic stuff that reacts to music:
// pick a channel - a number from 0-3 // (0 is the far-left channel in the music editor) channel=0 // get the sfx index that's playing in this channel // (the number at the top of an enabled music channel's column) sound=stat(16+channel) // get the current timeline position of this channel (0-31) row=stat(20+channel) // get the two bytes representing the channel's current note byte1=peek(0x3200+68*sound+row*2) byte2=peek(0x3200+68*sound+row*2+1) // now we can extract the note values! // all three of these return 0-7 volume=band(byte2,0b1110)/2 effect=band(byte2,0b1110000)/16 instrument=band(byte1,0b11000000)/64 instrument+=band(byte2,1)*4
More info about the audio memory layout is available here.
I made an animated self-portrait!
Some of it is rendered with drawing functions (the head shape, eyeballs, "ear beams" on the glasses, cheek-lines, etc), and other stuff done with sprites (frames of glasses, eyelids, most of the hair).
Had a lot of fun making this - I recommend making one of yourself, or of someone else!
I also added a fullscreen trail effect for some extra pizzazz, because it's an easy addition. Here's the code for that part, in case you want to use it in your own stuff - note that this will only allow you to "fade to black" over time, but you could modify it a bit to make it fade to a different color. It's...probably very difficult to control what colors it moves through as it approaches your target color, though, since it's abusing the two-pixels-per-byte format that pico8 uses for its screen buffer (which is also why it produces vertical stripes).
for i=1,1100 do local x=flr(rnd(64)) local y=flr(rnd(128)) local m=8192*3 poke(m+y*64+x,peek(m+y*64+x)*.6) end
A barebones implementation of the FABRIK algorithm ("Forward And Backward Reaching IK"). Move the mouse around to control the IK target point.
I think there's something kind of cute and coincidental about the way that it actually sorta looks like fabric.
FABRIK is a clever trick that's surprisingly straightforward to implement, and it gives some really natural and performant results. The general principle is that instead of doing gradient descent or other fancy math for IK, you just imagine that your IK chain is a string (for 2D strings, imagine that they're resting on a table, and you're viewing from above).
At each tick, you perform two loops through the chain: First, you "pull the string" by the end point to the target position (and some amount of the rest of the string will get pulled along with it). After you've done this, you do the same thing, but this time, you pull the root of the string to the anchor point. (If the IK chain is a person's arm, then the anchor point is the shoulder.)
The source code also includes a 2D-distance check that tries to avoid number-overflow (by sacrificing some precision) when you give it a large enough vector. Might not be tuned perfectly (I really just guessed about the "safe range"), but maybe some motivated party can math out a more rigorous version of the function!
A weird animated image generator, based on the screensaver "Electric Sheep" (except way less powerful).
Press Z to generate a new flame.
Press S to save the current flame.
Press X to view saved flames.
When viewing saved flames, press Up/Down to move the cursor between saved flames.
When viewing saved flames, press F to select/deselect a flame.
When viewing saved flames, press Z to load the selected flame (instead of generating a new one).
If you have flames selected and you close the saved-flame-view (by pressing X), then any new flames that are generated will be bred from the flames that you've selected (as parents).
For example: If you select one flame, close the selector, and generate new ones, they will all at least vaguely resemble the one that you selected. If you select more than one parent and generate new ones, then the new ones will inherit traits from all selected parents (plus some randomized mutations).
Post me your prettiest children in the comments!
A non-interactive view of a scene. It's roughly based on something I saw a few days ago, which reminded me of Virginia.
- Infinite random props
- "Immediate mode" rendering - no spawning/deleting/pooling props
- Smooth LOD on tree leaves (more leaves on nearby trees)
Source code is commented, but the least-intuitive part of it (infinitely looping random objects) isn't really explained in there, because it would be a huge comment. Instead, here we go:
First, think of the casino signs with a ring of lights around them. When they light up one at a time in sequence, it can appear like a "single light" is "moving around" the sign, even though it's really different lights which are blinking at choreographed times. Our trees in this demo work similarly, but we can also move the positions of the lights separately from changing their states. Also, instead of on-or-off, each tree is given a persistent random seed.
Other than that, it's all pretty normal, I think?