↖️ Blog Archive

Pinwheel Game, Part One

Bradley Gannon

2025-09-11

TL;DR: I made a little game with macroquad, a Rust game library. I call the game Pinwheel, and it’s a clone of a game my wife found on the at-table point-of-sale device at an Applebee’s. You can play my version in your browser here or view the code here. There’s only one level, and it doesn’t even tell you when you’ve won or lost (it just stops), but it technically works and was a good motivator for learning.

Desired Gameplay

A hand
ready to tap a small touchscreen showing a colored circle with several pins sticking out of it, all
on top of a restaurant table
The game I tried to clone

The game is pretty simple. It’s a game of skill where the goal is to tap the screen at the right time to fire colored pins onto a spinning circle. The circle is divided into various colored sectors, and the colors of the pins must match the colors of the sectors where they land, or the game is over. To increase difficulty as gameplay progresses within a level, the game also ends if any two pins collide, regardless of color. Sometimes the spinner will start with black pins, which act as initial obstacles. If the player can get rid of all the pins in a level, they proceed to the next one. Otherwise, the level restarts.

The essential parts of the game are:

The level design can become somewhat interesting by setting the number of pins near the maximum number that can fit in the given sectors, increasing the spinner speed, decreasing the pin flight speed, and probably other stuff I haven’t thought of. It seems to me like the upper bound for replayability is somewhat low, but that isn’t a problem in the original scenario (i.e., a customer waiting 10–30 minutes for their food to arrive).

macroquad

One of my goals with this project is to build up a basic game development workflow. I started out thinking I’d use Godot or Bevy, but I was unhappy with the idea of relying on such relatively heavy systems and feeling too far from the underlying game state and graphics. macroquad is a much better fit by this metric because it calls itself a game library, not an engine. This seems to mean that it doesn’t provide any “higher-level” conveniences for game development and is mostly a cross-platform way to draw pixels to the screen. There are definitely plenty of graphics-related conveniences, like being able to draw text, but macroquad doesn’t prescribe or even provide a specific game engine framework.

This is harder if your goal is, first of all, to ship a game that isn’t too complex. Pinwheel is well within the capabilities of basically any game engine, and if that was my goal I’d be taking on unnecessary work by using macroquad. However, in my case I was deliberately looking for the least amount of help possible as a way to learn more and have some fun building out my own somewhat wonky game engine-ish system.

It’s annoyed me for a while now that drawing to a computer screen is so difficult on current systems, particularly in a cross-platform way. macroquad is built on miniquad, which appears to have been built to solve this problem. I’ll definitely use it again on future projects that need to just open a window and paint on it.

By the way, another big advantage to macroquad is that it compiles trivially to WebAssembly, which is how I was able to publish Pinwheel to the web so easily. The other game engines I mentioned can do that too, but I was pleased to see it available in the much smaller and simpler library as well.

Drawing Circular Sectors

When the time arrived to start building rendering logic for Pinwheel, right away I found that I didn’t know how to draw the spinner. macroquad makes it easy to draw circles, but there isn’t a built-in way to draw a circular sector, so I had to build it. This turned out to be easy once I understood the basics of how to interact with the graphics API. (The function is here if you want to see the code.)

First, you have to get an InternalGlContext, which is just a function call. Since there’s some churn about the thread safety of this context struct, I call it once at the top level of the program and pass it down as a mutable reference where I need it. Then we get into the real algorithm. It turns out that you can render a circular sector by splitting it into triangles, kind of like a hand fan. All the triangles share the center of the circle as one point, and then they fan out towards the circumference, approximating it with line segments. If you divide the sector into enough segments, it looks convincing on the screen.

To actually do this with macroquad, you have to build up two vectors. One is for vertices, the actual points that will form the corners of the triangles, and the other is for indices. You only list each vertex once, and the indices tell the graphics system how to look up the vertices to form triangles. The index vector is just a Vec<u16>, but I guess its length always has to be a multiple of three. Anyway, in this case you build up these vectors by iterating from some starting and ending angle and do trigonometry to figure out where the points should go. Then you push that all into the graphics machinery and out comes a lovely filled sector.

Next Time

I was going to write a lot more about my duct-taped game engine that I made up as I went along, but I ran out of time this week. When this project comes around again next month I’ll try to get some detail in here on that. Hopefully I’ll be able to improve it by then, too, along with adding more than one level, maybe sound, scoring, collision improvements, etc.