Projects
Once Upon A ___
A game made for a week-long game jam. All programming done by me, and all writing and player animations were done by my partner for the jam. Once Upon A ___ is a narrative-focused puzzle platformer where you rewrite the Prince's story as you play. Rearrange sentences to solve puzzles and watch as the Prince's story unfolds before your eyes. This was a particularly fun game to work on because of the dynamic text. I had to figure out how to measure the text glyph sizes and manually position the text. I also had to figure out how to make a system that would let me set up logic gates for what objects should be visible or activated depending on the state of the game. I also had a single race condition that would only present itself in an official build and not in the editor :( The game at the end of the game jam had no animations, and no dynamic text spacing. All that work was done after at a slightly more leisurely pace. I'm currently working on adding a page turn animation made by capturing the last frame of the current level and rendering that onto a page-turn animation. I didn't want to do any actual 3D rendering in the game (yes, I know Unity 2D is just 3D but with a fixed camera but whatever) so I pre-rendered the UVs and lighting and use a shader to mix between the current level and next level. It actually works out really nicely, since I can use the R and G channels for UV coordinates as is standard. Then I can use the B channel to indicate whether it should use the current or next level, and the A channel stores the brightness multiplier for shading.
Nomai Pebble Watchface
This was just made purely for fun; I really like Outer Wilds (enough so that I've done a few speedruns of the game), and wanted to make a watchface that reflected that. I traced the Nomai mask from a game screenshot, and modeled the time display after the oxygen/fuel gauges in the suit's HUD
Bad Apple!! for the Pebble Smartwatch
This was a really fun project. The Pebble smartwatch is quite limited on space, the oldest model only allows 128KB of app resource files total, and all newer models allow 256KB. Of course I could just stream the animation from the phone and display it on thw watch, but where's the fun in that? I had to figure out how to fit 2,629 frames into that small space. At first I tried XORing each frame and run-length encoding the resulting data stream, but it was far too big still. After much experimenting, I eventually settled on encoding each frame as a quadtree, storing a 1 if the cell should be split into 4 or a 0 followed by a 1 for white and 0 for black. This afforded me enough granularity in the encoding that I could sacrifice some quality for the oldest platform and still fall under the 128KB limit. I've started working on the project again, some of the newer watches have a speaker so I wrote a MIDI parser and now it can play the song at the same time! I've also been experimenting with compressing the animation as a ZIP file, and decompressing it on the watch. The official DEFLATE spec (the compression algorithm I'm using for my ZIP files) dictates that data blocks can backreference blocks of data up to 32KB prior, which is simply infeasible to keep in memory on the Pebble. So now I'm currently experimenting with streaming a DEFLATE-compressed file with a custom backreference limit so I only have to hold ~2KB of data in memory while decompressing.
Crochet Stitch Counter
I made this because I learned how to crochet and wanted some way to keep track of my progress in the pattern. I made the initial prototype in Godot, then decided that the web builds for Godot were not suitable for anything that requires text input. So I switched to a purely web build. I had recently learned React and discovered that while it was nice to use as a dev, I really didn't like the... slowness of it. I foudn a lightweight reactive library called VanJS that provides basic data binding, and I re-write it using VanJS. I'm especially pleased with the system for saving and loading patterns from the URL, and the way it saves your progress in the background.
Gartic Autodraw
A program that uses a greedy gradient-descent algorithm to draw ellipses, rectangles, and lines in the online Gartic Phone application to approximate an arbitrary target image.
Crystal Forest
Made for Artistic Game Development I at WPI, this explores the use of stylised paint-stroke-like geometry. I made this by first modeling the base geometry in Blender, then making a procedural geometry nodes system to instantiate plans on the surface of the object for paint strokes. I also made a spritesheet of a few different paint strokes to use as an alpha matte, and I baked out low-resolution textures for each object that set the colour of each paint stroke. Using a custom shader, I set the alpha of the plane using the paint texture, and colour from the colour texture, using two different sets of UVs for each plane.
WPI Humanities Practicum
Exploration in art with light, using projection mapping onto a 3D-printed sculpture.
Haybaler
A game made in a few days for a WPI game development class.
Color Tiles
This is a game recreated from the UNDERTALE colored tile puzzle.
K-Means
Implements a simple K-means clustering algorithm to try to classify clusters of points. Currently increases the number of clusters based on a simple heuristic using the relative size of the largest and smallest clusters.
Inverse Kinematics
Implements an iterative 2D inverse kinematics algorithm to connect two targets with a linkage.
Get Canvas Assignments
Uses the public Canvas API to pull assignments into a checklist in a local Markdown file.
Trim Video
Lightweight WPF application with an intuitive UI for quickly cutting video files to the desired length.
Convert Workday Class Schedule
Reads the data in an Excel file and creates an iCalendar file to easily import class schedules.
Parse Pearson Expressions
Uses context-free grammar structures to convert from a proprietary mathematical expression format to a more commonly used format.