Making a 2D game with no art assets
In my last blog post I wrote about the game I'm working on with two of my friends. It now officially has a name, Afterlight Caves, and we're going to be showing it off at the WPI booth at PAX East, February 27 through March 1 2020. In this post I'll talk about how three computer science majors with no artistic ability between them were able to make a decent looking game.
Good looking particles add a lot of excitement and motion to a game, and they can be surprisingly simple to make. In our physics system, all entities have velocity, acceleration, and drag. Using these, we can create simple line-based particles very easily.
Each particle has a lifetime, after which it is automatically removed from the world, an initially high velocity, and high drag. It's drawn as a line with length as a function of its velocity, so it naturally shortens as it slows down until it is removed. This creates a nice spark-like effect that is computationally cheap and snappy.
Cole came up with a cool way to
give Afterlight Caves a glowing, neon look. The display manager
maintains a separate canvas, called the
half the dimensions of the main display canvas (so it's only a quarter
of the pixels). The
filter attribute of this canvas' is set to a string of filter functions:
const blurContext = blurCanvas.getContext("2d"); blurContext.filter = "blur(3px) brightness(200%)";
Each frame, the game world and all entities and particles are drawn onto
canvas. Then, the
canvas is scaled to half
its original dimensions and drawn onto the
lower resolution and filter string create the bright, glowing effect we
blurCanvas is drawn onto the
displayCanvas, the one that's actually visible to the user.
Next, all UI elements (menus, health bars, etc.) are drawn onto the
canvas. This prevents text elements from getting blurred.
canvas is drawn onto the
displayCanvas, which has its
set to "lighter," placing the regular game world and UI elements on top
of the glowing game world.
When enemies die, they create a nice splatter effect on the floor that permanently sticks around in the game world. This provides satisfying visual feedback for each enemy killed, and leaves a way to tell which areas of the world you've been to before.
These splatters are also generated programmatically, using a separate
splatterCanvas has dimensions equal to one
fourth of the display canvas, so it only has one sixteenth of the
pixels. When an enemy dies, it draws several random rectangles at its
location on the splatter canvas.
These rectangles are distributed according to the enemy's velocity before it died. If a shot (or bomb) deals more damage than the enemy has health, the extra damage is converted into velocity, creating a nice splatter effect.
Check out displaymanager.js and draw.js on GitHub to see how all these functions work, and try out the game online to see how it looks in motion.