Hey guys, Connor here. I just wanted to talk a little about how Perspectrum’s elements work. As I’ve said before, Perspectrum started with me wanting to figure out how to do a palette swap shader. In doing this, I learned a lot about shaders and how they work and started experimenting some more. I realized it was cool to have a circular area that changed the palette, and to change it across the whole world, among other things.
So that’s how I realized it would be fun to toy around with it. Mechanically, it’s more complicated. First, I’ll talk about the visuals. There is a vertex shader, which is basically code that runs on the graphics card using and manipulating vertex data. In this case, it is the vertices of the sprites I draw to the screen. This shader does very little, all it does is basically pass its coordinates to the fragment shader for use later. The fragment shader is where the real magic happens.
A fragment shader uses info taken from the vertex shader and from things like textures to determine the color of pixels on the screen. My fragment shader utilizes a list of “nodes” which contain an element, a size, and a location to help determine colors. These nodes help determine which palette to choose from. The palettes are very simple, they are just very small images of 6 pixels, each a color to choose from. Once the shader knows what palette to choose from, it uses the red channel of the rgba color in the sprite’s texture to pick a color from the palette image.
Because of this method of choosing a color, the majority of sprites in Perspectrum will appear mostly black when opened anywhere else. This is because They are all saved with blue 0, green 0, and red 0-5. However, any color other than red 0-5 will appear normal in Perspectrum. We tried to use colors that don’t change sparingly since they don’t cooperate well with our core mechanic, but you can see them in some grey bricks and stone.
That covers the visual side, next is how it actually affects gameplay. Much like the visual side, I have a list of all the nodes on screen. However, collisions are not really pixel perfect, so I can’t work the same way shaders do. For the most part, collisions behave the same way regardless of element. In that case I use simple axis aligned bounding boxes. However, in some cases, like when a tile is cut in half by an element node, I have to do collisions on only part of that tile.
In those cases, first I check if the player is colliding with the tile. If they are, I check if the player is colliding with the circle around every node in the level. I run collisions against the circle next, and run some checks on those numbers, like whether or not it pushes you farther than that tile could possibly push.
Put all that together and you get a cool effect that we built our game on! It looks neat and behaves how it looks, but it does have a lot of moving parts. This doesn’t cover the whole game, and some things interact with elements in ways not addressed here, but in general this is the basic concept.