Notice: You can get Jumpsmith here
For many years, lighting effects have been almost standard in games. There are many tricks that developers have used over the years. If you play Super Meat Boy, you’ll see shadows change as platforms in the level appear, disappear, and move. In Monaco, they used ray tracing to shade all the areas that are not in a player’s line of sight. In Limbo, there are layers of fog that partially obfuscate the silhouettes of the game. These methods are awesome, and they can make a game look very polished and professional. However, they tend to require certain capabilities from your graphics library. Today’s blog post is about how to fake some 2d lighting with very simple tricks- no shaders, no raytracing, no alpha blending. Just pure, solid, pixels.
If you think about it, a perfectly dark room would be… well…. black. While making a playable game with a 100% black screen might be a fun challenge, we’ll probably want to make the players and the space around the players have lighting. It would be possible to do this Dragon Warrior 1 style, where the player would be at the center of a 100% lit rectangle, and the rest of the area on the screen is black. The problem with this method is that it looks pretty unnatural to have a perfectly straight line between lit and dark areas.
Lucky for us, there’s an old pixel art method that we can use to “smooth out” transitions. It’s called dithering. Wikipedia defines dither as “an intentionally applied form of noise used to randomize quantization error, perventing large-scale patterns such as color banding in images.” Yikes. In the context of this post, think of dithering as gradually increasing the number of black pixels. This is what dithering looks like:
If we make the screen all black except for the area around the player, and then use dithering to smooth the transition of the visible area, we’re most of the way there. This is pretty much what I did in the underground levels in Super Pooper, only I had an alpha-blended border instead of a dithered border:
However, how are we supposed to handle multiple light sources in the same room? The lighting is not very dynamic if you are just drawing the exact same black rectangle with the exact same dithered hole all the time. Also, if we just pasted two of those rectangles on top of each other, the illusion would be quite broken when they intersected.
Never fear, though. I found a sweet way to fake this and make it look awesome. Every frame, make a black rectangle. Next, you’ll need a dither pattern that you can draw onto the black rectangle. The pattern needs to be made up of solid pixels, and they need to all be the same color. Any color is fine, EXCEPT black. I use an ugly pinkish color, with the RGB value of 255, 0, 255. Every frame, draw the “visibility holes”, i.e. dither patterns, onto the black surface in the appropriate areas.
At this point you should have a big rectangle of pixels. Each pixel should be either black, or the other color. Now, tell your game to not draw the pixels of the non-black color on that surface of pixels. In SDL and SDL2, this is called a “Color Key”. Bam! Now, you can have cleanly interconnecting visibility holes in your black room.
You can take it another step further if you use a few different sized dither patterns. This gives you a bit of a flickering effect. In Jumpsmith, I have 5 slightly different dither patterns that the game cycles through every frame.
But…. what if you don’t want the whole room to be dark? What if you want the room to be relatively lit, but with some dark corners? Of course, it is possible to just draw a layer of darkness over everything, but there is one more trick that I used in Jumpsmith that is simple and easy to emulate.
The game has a feature that I call “Doodads”. These are animated things that can be put in a room. The players cannot interact with them, they do not affect the gameplay, but they do add some visual ambience to the game, and they keep the rooms from looking super bland and static. They were really easy to implement, the game just grabs six 32×32 pixel squares from the tile sheet, and cycles through them. I used them to make little fluttering flags, waterfalls, and pistons.
One day, I realized I could make a doodad that was just a dither pattern of black pixels. The pattern would just move up and down a few pixels each frame. When I want a room to feel semi-lit, I just put rows of dither doodads on the top and bottom of the screen.
So, if you want to have some neat lighting in a 2d game and you don’t want to bother learning shader languages, you can do a few lighting effects with a basic 2d software renderer. Dithering, color mods, and simple animation can make a basic game look pretty awesome.
If you have any questions or comments, you can leave a reply here or contact me on Twitter @foundtimegames or email me at firstname.lastname@example.org
Notice: You can get Jumpsmith here ….You can troll your friends in local multiplayer, create levels with your controller, use custom tilesets and characters, and play levels created by the community.