David Karr Johnston

David Karr Johnston

Software Engineer

Hi! I'm a software engineer currently living in Brooklyn, NY. I love math, literature, Nuts4Nuts, writing implements and Prince. I get excited about tiny things. My life's goal is to raise a child near Keita Takahashi's eventual playground.

Work

  • Gameplay Programmer – Tuque Games
    June 2016-May 2017

    • Worked on a team of nine on an unannounced UE4 roguelike shooter.
    • Had primary ownership of player controls, moment-to-moment gameplay, and UI programming using UMG.
    • Developed and maintained tools in Excel for more efficient management, balancing, and analysis of game data. This touched room generation, character stats, and item pools.
    • Contributed to secondary systems such as item effects, metagame, rendom events, and more.
    • Stayed ever-vigilant with artists, designers, and other programmers to measure and maintain good performance.

  • Junior Programmer – Tuque Games
    May 2015-August 2015

    • Worked on a team of four on an unannounced UE4 roguelike shooter.
    • Worked closely with the lead programmer to design, implement, and tune all kinds of gameplay features from the basic shooting to the item unlocking metagame.
    • Rearchitected and ported the UI from Slate to UMG.

  • Tutor / TA – Champlain College
    Sept 2013-April 2014 & Sept 2015-Dec 2015

    • Tutored students in C++ for the Introduction to Programming, Advanced Programming and Data Structures and Algorithms classes at Champlain College.
    • In the fall 2015 semester, assisted a professor with her section of Introduction to Programming, grading assignments and helping students one-to-one.

Projects

  • Ripples
    August 2015-May 2016

    • Worked on an eight person team developing a rhythm-based local multiplayer action game using Unity, C#, and Git.
    • Lead technical side of the production, fleshing out core design with lead designer and managing priorities throughout production.
    • Researched and developed custom beat matching algorithm so that users can play to their own music.

Education

  • Champlain College (University Level)
    2012-2016

    BS in Game Programming – Minor in Mathematics
    GPA: 3.753
    President's List one semester, Dean's list six semesters
    Trustee Scholar
    Inspiration Scholar
    Recipient of the Mt. Mansfield TV Award

References available on request.
Buncha Nonsense logo

Buncha Nonsense

I periodically write a blog / newsletter about projects I'm working on called Buncha Nonsense. Check it out!




Rigid Motors

Live, Die, Repeat

Rigid Motors is a mobile game I worked on with an artist, producer, and two designers. It is a mobile puzzle-platformer game made using Flash with the Citrus engine. In Rigid Motors you play as an infinite supply of robot minions, trying to find treasure in ancient catacombs. The catacombs are treacherous, filled with spikes, lava, and all manner of other nasty traps. Fortunately, when one robot dies it leaves its corpse behind to be used as a platform for later minions. The odds of any given robot getting the treasure are small, but together they will prevail.

This project taught me a lot about thinking about platform. In targeting mobile devices, I worked with the designer to design controls and levels that felt good, and with the artist to get around the graphical limitations of the platform.

Controls

For the controls of Rigid Motors, we wanted to keep it simple. The team all agreed that mobile games work best when they use simple touch controls. That being said, we wanted to provide deep platforming gameplay. We decided that the game worked best as a sort of finite-runner. We would keep the level format, but we would have the robots constantly run. This let us trim down the control scheme. In the final implementation, the controls are simply tap to jump (when the robot is against a wall it does a wall jump and turns around) and swipe to self-destruct. We found that self-destruction was a crucial mechanic in letting the player forge a unique path through each level.

Infection

Human Resources

Infection was developed in the fall of 2015 by a team of two programmers, an artist, a producer, and a designer. It's a two player asymmetrical abstract strategy game, with drafting. One player plays as human immune system cells, and one player plays as invasive agents, such as bacteria and viruses. Each team has five pieces, which all have unique abilities. In the first stage, players snake-draft three pieces, and place them in their starting zones. Then they are given two low power pieces (like pawns), and they start the tactics stage where they fight over the board. The immune cells' goal is to wipe out the invaders, while the invaders' goal is to infect a certain percentage of the board.

Teaching the Player

Working on infection taught me a great deal about presenting information to the player. We were trying to make an elegant abstract strategy game, and in doing so we focused on making every bit of information clear, yet inconspicuous. We worked a lot on non-textual cues. For instance, we repeatedly found in testing that players were having problems knowing whose turn it was, and which pieces could move. We didn't want to throw around popups every second saying exactly what was happening, but we did want it to be clear. In the final form of the game, just about everything related to each player lights up when it's their turn, and pieces have two different effects indicating that they can move. By the end of production, players were cruising through turns easily.

Ripples

Martial Dance

Ripples was developed in 2016 by a team of two designers, three producers, an artist, and three programmers. It is an elegant, stylish action game for one or two players. Players play as mathematical symbols, like Theta and Delta, dueling on a watery plane. Each encounter is set to a musical track. The characters jump to the beat of the track, and dance around in simultaneous defence and offense. When the characters land, they create a ripple in the surface of the water. If you hit your opponents ripple, you take damage. The characters have unique abilities based on their common mathematical usage. For example, Delta usually stands for rate of change, so the Delta character has a special ripple that she can shrink and expand at will.

Chill Out and Freak Out

In developing Ripples, we discovered that there are two distinct types of players that are attracted to the game. The first type of player, who most of the developers identify with, wants to have an intense action game experience. This was our initial goal in concepting, prototyping, and developing Ripples. The second type of player, who we didn't expect at all, wants to chill out with the game, get in the zone, and relax with the sweet tunes. Though we weren't designing the game for this purpose, we realized that Ripples really lends itself to this type of experience through its minmal, engaging graphics and stylish music. We did not anticipate this duality in the audience of Ripples, but ever since we found it we have fought to keep it. We have done this through careful balance and a focus on the aesthetics of the game.

Vicious Orb

Speed Kills

Vicious Orb is a pet project of mine (hence the Tim sprites). Vicious orb is about leaping into the air, grabbing a ball made of a highly instable material, and blasting it at your friend before your feet touch the ground. Vicious orb is about playing basketball with a nuclear bomb. Vicious orb is what CERN scientists do during their lunch hour. In Vicious Orb I am trying to make a hilariously fun, competitive, local multiplayer game, becuase those are the kinds of games I like to play.

Making it Juicy

Vicious Orb is meant to be a very visceral game. It is a competitive action game, I want it to feel good. To do that, I have been spending a lot of time tweaking the feedback of the game. My goal is to make it so that every graphical and aural effect is scaled to the tension of the current game state. I've learned a lot in doing this. Getting to be the designer of the game as well as programming it has made me think more about what designers really need to make the games they want to make. This has also encouraged me to work on more small projects. I have been working on this in my spare time for a little while now, but I finished the first prototype in a few hours.

Business Cards

Bite Size Puzzles

In anticipation of GDC 2016, I was scrambling around for a business card idea. This would be my first personal business card, so I wanted to make it special. I wanted my business card to reflect my personality; my love of math, games, and little programs. I wanted the cards to have some kind of function or game, so that people recieving them would have a reason to not immediately discard them. I came across Moo's offer of up to fifty different card backs for no extra charge, and knew that I needed to make some sort of randomly generated game.

Graph Theory

I got to thinking about the possible games one could fit on a business card, and decided an abstract puzzle sort of thing would be best given the strict restraints of the platform. A few facts from graph theory popped into my mind and, bam, I had my randomly generatable puzzle game. The idea is that I would randomly generate graphs with Euler circuits, Euler paths, and Hamiltonian circuits, give each graph a unique id number, and provide little instructions for how the graph can be traversed. The methods for generating these graphs are fairly simple, it all comes down to the number of connections between nodes, here's how it works:

  • If no nodes have an odd number of connections, the graph contains an Euler circuit.
  • If exactly two nodes have an odd number of connections, the graph contains an Euler path.
  • If we take the line graph of a graph with an Euler circuit, it will contain a Hamiltonian circuit.
  • Note: If more than two nodes have an odd number of connections, the graph has none of these properties! (Also, it is impossible for only one node to have an odd number of connections.)

For my program, we always generate an Euler circuit graph then, depending on the type of graph we desire, we either leave it alone, prune (or add) an edge (to get an Euler path), or take its line graph (to get a Hamiltonian circuit). From there we place nodes randomly, attempting to give them as much space as possible within the business card dimensions, then we draw edges between the nodes. Finally, we simply take a screen shot of the generated graph, instruction text, and id number, and export it to a png for use as a potential card back.

Raymarching Primitives

Out of Thin Wires

I have long been fascinated by the work of the demo scene. From crazy demos that don't run on any machine I have access to, to demos that push the limits of what we can do in very little space, to tiny proofs of concepts that run on a website, I am fascinated by turning code into beautiful art for the sake of art. When one looks around at graphics demos these days, one finds raymarching all over the place. It is a powerful, widely applicable technique, that allows for a ton of creativity. After seeing so many demos featuring raymarcing, I figured that I should understand how it works, so I set about creating a very basic scene through raymarching primitives. My work can be found here on Shadertoy.

Shadows

After the initial implementation of the sphere, torus, and array of rounded boxes in that scene, I took a break from the project for the day. I woke up the next day with an idea in my head for how I could easily do shadows given the basic shapes and raymarching algorithm I already had. Once I find the shape in the scene, I thought, I could march from that shape to the light source(s) and if I ended up intersecting any shapes on the way, I could shade the original shape accordingly. I implemented this on an approximately fifteen minute bus ride. This was a great confirmation to me of the power and potential for creative expression in raymarching.

The Hudson River Undergraduate Math Conference

A few months after finshing up this project, I was given the opportunity to speak at the Hudson River Undergraduate Math Conference (HRUMC). I decided to speak on raymarching, using the knowledge I gained in researching the topic for this project, and the project itself as a simple example.

Roulette CV

Finding an Edge

In the summer of 2017 I read the fascinating story of Claude Shannon and Edward Thorp making the first wearable computer, designed to predict roulette spins. The user would press a discreet button each time the roulette ball passed a certain point on the inner wheel of the roulette wheel and, given the time differences between the button presses, the computer would calculate the speed of the ball relative to the inner wheel. From there the computer would predict the final resting pocket of the ball. A signal indicating the pocket would be sent to the user and they would bet on that pocket and the other pockets nearby. The predictions were not perfectly accurate of course, but they were easily accurate enough to give the user an edge over the house.

I was really enjoying working with OpenCV at the time, and I thought roulette would be another interesting thing to do with the library. Shannon and Thorp's method relied on a user sending the computer timing information by pressing a button. There are myriad ways that a user could accidentally mistime their button press. I thought, what if I used OpenCV to track the motion of the ball and inner wheel in video of a roulette wheel, and gathered timing data that way? Of course, one can't just go to a casino with a laptop and a webcam and post up at the roulette table to gather data. Fortunately, with the proliferation of online live dealer casinos, I could easily gather data from real roulette wheels online. This added another dimension to the project, as my program would have to deal with the stream that an online casino provided me, but I took that as a fun challenge. My program can be found on Github here.

Counterplay

Ultimately, I decided to stop working on the project before what I would call the finish. I needed to focus on other things, and I felt that I got a lot out of the work I had done. One interesting piece of data I got to gather relates to a form of counterplay that casinos have at their disposal against someone using this kind of program. In researching and developing the program, I found that there are three main requirements for gathering good data from the roulette table:

  • The stream must be smooth and of decent quality.
  • There must be a good and consistent view of the roulette wheel.
  • There must be ample time between the ball being launched into the wheel and bets closing.

All of the online casinos that I looked at provided a smooth and high quality stream. After all, regular users would be turned off by a bad stream. The other two requirements were a bit harder to find, and nearly impossible to find together. Generally casinos offer two genres of live dealer roulette games: Standard Roulette and Immersive Roulette. Standard Roulette tables offer a good and relatively consistent view of the wheel, but the ball hardly makes two orbits around before betting closes. In Immersive Roulette the ball is allowed a few more orbits, but the streamed view is constantly rotating between different angles of the table and the dealer's face. I crossed both of these off as options. I found one game which seemed to have all three qualities in spades: a great stream, an unchanging overhead view of the wheel, and even more time before bets closing than Immersive Roulette. The only issue is that it was auto-roulette.

Auto-roulette wheels don't require a dealer to spin the inner wheel and launch the ball. Instead, the inner wheel is controlled by a mechanical rotor and the ball is launched with a puff of air. In research I found that this kind of auto-roulette wheel has what they call Active Rotor Control. A feature which makes the inner wheel slow down or speed up subtly after betting closes. This is subtle enough that a human player wouldn't notice and suspect foul play, but any predictions made by a computer based on the inner wheel speed before betting closes would be rendered useless. I wanted to see if my program could observe this changing rotor speed and was happy to see the rotor very clearly changing speed after bets closed.

Between changing rotor speed, rotating camera angles, and limited betting windows, online casinos have many ways to defend against a player with a roulette prediction program. Still, the program was fun to write and I learned a lot.

Make a Face

Painting with Randomness

In 2016, inspired by the work in painting with genetic algorithms by many other programmers, I set about creating a hardware accelerated version of the idea. Unfortunately, I didn't fully understand what made the other programs genetic algorithms at the time, but I tried to recreate the idea simply by trying to reproduce the results. I developed the prototype of my version on Shadertoy. That prototype can be found here.

There were a few limitations that I ran into in the prototype version. The biggest one is that Shadertoy limits shaders to sixty FPS, and I wanted Make a Face to run faster. Besides that I wanted to create a better way to change the settings of the program (in the Shadertoy version they are defines you can comment and uncomment) and I wanted to try to more closely recreate the effect shown in the cpu genetic painting programs. In the summer of 2017 I worked on the standalone version, which can be found on GitHub.

Dear ImGui

For the GUI of the standalone version I used Dear ImGui, an immediate mode GUI library for C++. I saw a demonstration of Dear ImGui at GDC 2016 and was really impressed. I had been looking for an excuse to try it out, so when it came time to write the controls for Make a Face I thought it would be a great use case. My main goal for Make a Face was to be able to experiment and iterate as much as possible, so I focused on making the UI code simple and flexible. The program would be mainly used by me, and is not commercial so aesthetics were not very important.

Where am I?

Right now I'm in Brooklyn, NY!

Reaching me

email@dkj.io

What's up?

I'm always looking for cool things to do. Don't be shy about emailing me.

David Karr Johnston / email@dkj.io