Graphics Programming!

I learned 3D graphics programming in college with OpenGL, maybe getting back into that

When I was in college, I was pretty sure I was learning computer science so that I could spend the rest of my days writing video games. That didn't pan out, as it's been like 24 years since I graduated college, and I played around with video games for a few months while college was still fresh.

We didn't learn anything about web programming in college, and what I picked up doing my own websites (the very beginning of this site, as the domain name was registered in like 2000 or so), Perl programming on my school's Unix server, a class about databases, is what I ended up doing for the past 24 years.

But video games have always been an interest. And I recently got back into graphics programming, albeit a tiny bit, albeit on a <canvas> object with javascript, and albeit, not interactive in any way! But it was fun and I kinda still have the urge.

On my word game, rangram.com, the win screen was very boring. It would just switch to a win / game over state, and that was it. Nothing. I was thinking about how I would make it a bit more flashy.

This is the result
 

It pops up when the game over screen shows, and thousands of colored blocks shoot out from ¼ of the way across the screen, and ¾ the way across. I had played with multiple different start points, including the four corners, bottom two corners, and top two corners, before coming to this as the solution.

It was very fun to program!

To start something like this, I usually start out with the function signature, and then provide implementation details. This is the signature

function confetti(size, count, velocity, colors, duration, bounce)

Where size is the pixel size (1 usually), count is how many, velocity is the speed, colors is an array of colors that are compatible with the canvas context's “fillStyle” property (I name them simply like “red”, “blue”, “pink” etc), the duration which I pretended was a timer, but really is just the upper bounds of the for loop, and bounce, whether the pixels should bounce when reaching the end of the screen.

In graphics, in animation, there are really two states that are important. The update state, and the draw state. In update, you update the state of the world, and in draw, you just draw it. There's no business logic in draw, and there's no draw logic in update. The separation of concerns is crucial to writing readable code and keeping bugs down to a mild roar.

This is the main loop. It might not look like a loop, but in web / canvas graphics programming, you call “requestAnimationFrame” with a callback, and that's a recursive call if you didn't notice :) Check if we're past the duration, otherwise draw points then update points. It should probably be update then draw, but the initial state is fine to draw.

The update state alone won't make any sense without the setup code. So here's the draw state.

Onto a canvas, given the list of points.

Simple as can be. In graphics and games, things have a concept of “dead”, this sounds morbid but it's just the term that these things use. Pixels are given a random lifecycle in my code, and reaching the end of that lifecycle, they become dead. This is to introduce more randomness. This is all about randomness. So they don't all reach the end of the screen, some die before, and I think it looks fine.

This is the initial state. Let's go over a few things!

starts is our starting points. This puts them at the bottom of the canvas, ¼ of the way across, and ¾ the way across. For all of the points that we want to display (the number in count which can be like 3000), we pick a random start point and a random color. variation is very important, or all of the pixels would just shoot out in a straight line. This isn't what I wanted. The radians plus variation give it a nice random spread across the screen. But without something else, they would just shoot across the screen in an arc. All in a line but a rounded line. We create a vector that gives it its direction, and a small variation of speed, either the base speed or like 1 or 2 faster. The delay is what gives it the extra variation to not shoot them all out at the same time. I give a random delay value, and wait until the “time” is at that value before I even start doing anything with that particular pixel. So this gives it the nice effect that I was looking for. And then a random lifetime which is guaranteed to be less than the duration.

Finally, the updatePoints method. This just applies all of the math, sets properties like “dead”, and updates the vector appropriately if we want pixels to bounce.

And we are done! That code is located here - https://www.rangram.com/static/js/confetti.js

I call it like this:

    confetti(3, 3000, 2, ["red", "green", "lime", "aqua", "dodgerblue", "blue", "orange", "pink", "purple", "fuschia"], 800, false)

So I go with 3 pixel size, 3000 pixels, 2 speed, all of those colors, and a duration of 800 with no bounce. You'll have to beat today's rangram to see how it behaves :)

But anyway, now I'm all into graphics programming. I'm watching videos on game programming, reading up on graphics libraries, thinking of a game idea that I once had. I will be deep into this stuff for a while!

Happy coding!

EDIT: An update. So I did end up swapping update and draw, so it updates first, then draws. This is just canonical. Then the update method didn't need to return the list of pixels. In javascript, this is passed by reference, so it updates in place, and I don't need to return it. I was looking at the code and noticed I “continue”'d after setting the pixel to dead, which wouldn't update points[i] lower in the method, but it wasn't needed anyway.