Among Pico

Posted on 18/10/2020 in Gamedev

Among Pico is a project I made using the PICO-8 environement trying to reproduce some of the behaviour found in the the game Among Us, maintly, the fog of war like effect where wall to dynamically cast shadow hidding what may happen in different room than the one the player is currently is.

Summary

Amongpico 38

During the main of the Covid Pandemic, I started to look at project to work on to keep myself busy and I wanted to play around with the shadow effect found in the game Among Us which I was playing with friends at the time, and then trying to see how far I could push PICO-8 to have functionnality close to the original game.

You’ll find in the next section a copy from the original thread text:

Description

The name may not be clear, but the origin of the project started with Among Us in mind, and I first wanted play around the way your character move in AU and replicate that., So I made a inspired set of sprite and started to animate it on screen. Nothing really fancy and even if the bouncing is there, it don’t really look good, but well I was pleased enough at the time.

Amongpico 0

And then went, ok now, AU have multiples colours palette for players, let’s add that:

Amongpico 4

Nothing really fancy, but always fun to play with the palette to try to find nice combinations that works.

Reasonably satisfied with that, I went. Ok what I want to play with next. I came to the visibility shadow which is in the original game, as wall tend to cast shadow so there are area you don’t see what is in there.

I started to play around, trying to identify how to do that. First working on a poly fill:

Amongpico 6

which was way more buggy than I originally though ! (will fix is latter in many iterations)

Then trying to understand how to cast the shadow from a wall in the vision area:

Amongpico 7Amongpico 8

As you can see the projection somewhat work, but the polyfill is really buggy !

And I ran into the problem if the corner not getting filled:

Amongpico 12

And that’s about at that time I decided to look around on how other people solved that type of thing to find the blog post of the author of Dank Tomb that explain thoughtfully how he does his lighting effect, and it was quite interesting.

I decided to see if I could use some of his idea (and in the end used some of his code) for the shadow cast. It seemed to work reasonably fine, even not being fully satisfied with how it behaved, it felt good enough for the job:

Amongpico 21

It is also about when I found another issue with my polyfill:

Amongpico 16

Which was the result of a division by zero !

Then I’ ve continued doing test also adding the possibility to change the view radius on the fly:

Amongpico 20

Then decided to build some form of a room to see how the shadow react:

Amongpico 23

With some variants:

Amongpico 005

And decided it was time to play with a tilemap, and added one of top the wall and see how it behave:

Amongpico 26

It looks nice, but something is off. You are not supposed to see everything in rooms you are not in, but at least you should see the shape of non movable thing in there. And I remembered about a tweet from Zep about some POKE magic, and played around with it:

Amongpico 25

And I was really happy with that, it does not cost CPU time, works really well, the only drawback is you need to make sure to not draw thing in the room you don’t want the player to see, and choose palette correctly for thing will look in the shadow area.

And that’s when the first really laborious task of the project started. It was time to get a proper map to run around. So I went on google, search for the first AU map (the Sked) and found an image of it. Then resize it to roughly match my sprite size (so thing don’t feel too off), clean it to remove all art just keep the wall and floor, and map it in PICO-8. Yeah it actually fit in the normal tilemap (using the extended area) I was not expecting that at all! But it also come at the expense of limiting to only two tile banks, and well. That does not leave me with a lot of usable tiles in the end, but that’s another story for later.

All the tiles used for the drawing all walls:

Walltileset

So after a while I came to that:

Amongpico 28
(You can also notice that the moving animation is more smooth and bouncy than it was, I don’t remember exactly when, but I’ve done some tweak on it to make it looks better)

Also decided that the out of space was a bit dull so added a good old star effect:

Amongpico 29

Then came the second laborious task. mapping the wall to the actual map. I didn’t really wanted to do that by hand, way too many change of error, so needed to have a break and came back with a, I think, clever idea, I temporarily change the main sprite as a single dot, and moved with it around and used printh to map all the wall corner in each of the three wall loop that map have. It really worked fine and was perfect on the first try!

Just needed to add some code to automatically create the wall list from each loop list of point, and voila:

Amongpico 30

But that’s when I started to have to issues. First, I needed to cull all the wall not on the vision area, because I had a lot of drop from 60 to 30fps, and second even after culling there were still some drops (less but still some) and found that on some wall the shadow was absolutely not behaving the way it should:

Amongpico 007

the red poly is the actual casted shadow for the wall in green, and of course that is not valid. Can also see it in this test mode I implemented just for checking and debugging that issue:

Amongpico 32

I had to scratch my head a lot, and went into a complete rewrite of how I do extend the shadow, in a way which is still not perfect, there is still some overdraw and more than I really should draw:

Amongpico 34

But now does work in all conditions and in the expected way, and slightly unexpected bonus?

Amongpico 33

It now run at a constant 60fps! CPU use is still high, but that’s to be expected there are a lot of math and drawing involved. Thing probably could be more optimised, but it is good enough for now.

Casting shadow is fun, but being a ghost walking through wall is fun for some time:

Amongpico 37

It was clearly time to make sure you cannot clip through the wall. It took me some time because I wanted to make it in a clever way, took me a couple of day away from the project to clear up my mind and get into a working solution:

Amongpico 38

And that’s the current state of the project.

I’m happy if people are interested to explain how and where my shadow cast differ from @krajzeg solution, how my wall collision detection work, it is simple, probably not original, but I like how it works.

There are more thing to come with this project, including something it is way to early to talk about. I may stream working on that project on twitch at a later point. I will post a cart a bit later I just need to make sure it is good enough for a demo release.

Hope the reading was interesting!


The original thread about this PICO-8 cart can be found here: https://www.lexaloffle.com/bbs/?tid=39944