Projects

D&D Combat Tracker

For personal use in both D&D and Starfinder campaigns, I started development on a combat tracker.  As a player, I typically keep lots of notes regarding the current stats and events of the players and monsters during combat.  Information about what hits a monster and how much they are hit for are recorded.  I will compute the recorded damage in my head for estimated stats to know how close an enemy is to being eliminated.

I started working on a JavaScript app with Vue.js.  The goals are to be able to easily switch to the next active combatant and enter attack information, then view current information on all of the combatants.  Information entry will create a history record of the events in the battle as well as provide data for generating estimated stats of unknown monsters.  It’s developed with JavaScript to be able to easily viewed on both laptops and cell phones at the table.  I plan on adding some server and live polling support to let other active players be aware of the same data.

Vulkan Renderer

vulkanTo get back into C++ and graphics programming, I decided to start trying out the new graphics API by The Khronos Group.  I found that it’s much more verbose than OpenGL, and it took me around 800 lines to get a triangle displayed in a swapchain.  I currently have simple .obj model loading, a FPS camera, and a couple of fixed lights.  My goal is to implement many of the features I did in my Direct3D renderer years ago, but go for Forward+ instead of deferred lighting.

Word Count Analyzer

For a company’s interview process, I worked on a tool that would recursively search through directories for text and zip files, count the words, then display a histogram relating file counts and word counts.

The requirements were vague and open-ended.  I wanted something that worked on multiple platforms and where I didn’t need to spend a lot of time learning something new.  I decided that the easiest way for me to display a graph and potentially be interactive would be to use web technology.  I needed file access as well.  nw.js was a nice solution that allowed me to fulfill my requirements.  I got the WebKit renderer for display and Node.js for file access.

When I tested my tool, I encountered many anomalies when searching my user directory.  There were a few files that would have tons of words.  With a 2D histogram, I couldn’t even see the bar.  I created a fake 3D display to make it pop better.  The user was able to hover over a bar and see accurate counts as well.  I also wanted to see more detail on the non-anomaly sections, so I allowed the user to click and navigate through sub sections of the histogram.

I implemented several integration tests that could spit out results to the screen.  I had one large active graph and several small inactive graphics displayed underneath.  I received feedback on a potential problem and was able to include a new text once I fixed it.

I was running into an issue with JavaScript being single-threaded.  Since I displayed multiple graphs, I wanted the user to be able to interact with the program without it hanging while other graphs were being generated in the background.  JavaScript’s design kept locking up the program.  I switched from synchronous to asynchronous file and directory reads, but that only worked well until the word counting began.  I then tried to do a job system with time slicing, but it was a bit ineffective with the asynchronous file read callbacks triggering at any time.  I ended up just spawning a child thread to do the work.  I wanted to avoid that for a challenge, but I didn’t want to take forever on the project.

I added the option for the analyzer to check file headers to determine if a file is readable as text.  This is obviously a lot of extra work to be done, so I defaulted the analyzer to be “lazy” and only check file extensions for quicker demonstrations.

Puzzle Game

I worked on an unpublished puzzle game side project doing account management and payment processing.  I got experience with Unity, Node.js, AWS, Facebook API, and a third-party backend service.

I did all of the account display and interactions in our Unity project by implementing MonoBehaviours on persistent GameObjects and using UI Canvas components for display.  I took my experiences with JavaScript and implemented a deferred system (similar to goog.async.Deferred in the Google Closure library) to make asynchronous network communications more readable.  I implemented payment processing on the client with a third-party Unity plugin.  The latest Facebook Unity plugin was integrated as well and tested with Unity’s WebGL build output.

The third-party backend service had all of the necessary storage and retrieval capabilities for high-bandwidth products, something we wanted to worry less about.  To allow more flexibility with server requests, we set up the client to talk through our own lightweight backend written using Node.js.  I used Express.js to help set up a routing table.  The third-party backend service had a client-side JavaScript API that did not allow multiple users.  To make it easier for updates to the API in the future, I used their API builder to reconstruct their client-side API to work on our custom server.  I managed to get rid of the single-user authentication scheme that they implemented.

I used Python to help solve problems with setting up an environment on AWS efficiently and consistently.  Cloud Formation is a tool with AWS that allows the user to specify how a VPC should be constructed with an XML blob.  Due to problems with hand-editing an XML blob, I used a Python library to help construct the Cloud Formation XML.  Instead of letting the long Cloud Formation process break after several minutes of running, I could have instant feedback with a Python script.  I spent quite some time learning about all the different parts I needed with AWS and how to create them with Cloud Formation.  I learned later that Elastic Beanstalk would have simplified the entire process.

To ensure that the backend service was testable and reliable, I used Mocha.js to set up many unit tests.  I also mixed in several functional tests that would go out to both the third-party backend and Facebook to create test users.

Collaborative Drawing with HTML5 Canvas & Socket.io
pikachu-edited

I created a simple app for desktop and mobile browsers in a few days for several users to be able to paint and chat together in real-time. I used Node.js and Socket.io to distribute text commands to connected clients. Each client processes the commands and renders to an HTML5 canvas. The Node.js server renders to its own canvas for a persistent image and sends that image to newly connected clients.

Opacity on the paint brushes is included, but there is an obvious problem with painting multiple transparent lines from sets of each user’s previous mouse position to their current. A method to solve this would be to have a layering system. When a user starts a line of transparent paint, it’s rendered fully opaque to a separate semi-transparent canvas. New paint lines can be rendered to layers above. When the user is finished with a line, that canvas can be added to the base canvas. A simple solution is to only stroke the complete path of the painted line, but then each update would require a redraw. I shall test which method results in faster performance.

I was able to record commands for playback, but they quickly filled up the allocated space for HTML5 storage.

HTML5 Shmup

I spent a day with a friend to help him learn more about JavaScript, so we created a simple shmup in a 2D canvas.  We implemented classes with inheritance for rendering different objects and covered the basics of an update and render loop for a game.

Graphics

red_hawk_x2

I used Direct3D and HLSL to produce multiple graphical effects in a single demo. My first goal was to create a deferred shading system which I did with 3 render targets (depth, normal, material/specular power). I also rendered the ambient lighting of objects to the back buffer at the same time I wrote to the G-buffer. My lights have an inner radius, outer radius, and falloff instead of normal attenuation as suggested by a friend. This controls each light’s radius much better than relying on attenuation. I encountered a problem when oversaturating the color on lights when doing attenuation normally and using my previous light radius calculations. I implemented Killzone 2’s method of optimization which included using the stencil buffer on medium to large lights (relative to the screen) to render only the pixels effected by the light. This can get rid of rendering any pixels for lights in the middle of a room that don’t touch anything. The process is not cost effective on small lights.

Once the G-buffer from deferred shading was in place, I had access to a normalized depth buffer, and I was able to create crepuscular rays from light sources at far distances. I followed the CryEngine2’s method and did 3 radial blurs of 8 samples each (for 256 virtual samples) on the depth buffer to produce this effect. I was also able to create a depth of field effect with the depth from the deferred rendering’s G-buffer.

Since I was first doing this graphics demo for lighting, I also tried out volumetric light, quickly discovering the amount of sampling required to produce good effects. Essentially it uses plane-sliced sections of the light volume, but each pixel can have a different starting offset and a different number of samples. I also put functionality for rotating spot lights along their look direction and a “cookie” mask for projecting colorful textures. This allowed me to create a disco scene, which pleased me very much.

Networked Games

Server

Server(s)

Client

Client

Tanks

I used Winsock to make a reliable UDP network for a tank game. The game would continue sending important messages, like if a shot was fired, until it received a conformation for that message. Things that updated often and were sent, like position, did not need to be sent reliably. This was taken into consideration to lower the bandwidth used. The receiving client would predict the current position of networked players based on current information and new information received. Servers broadcasted out to clients, and there was also a pre-game chat available.

Asteroids

With a team of four, I helped create a networked asteroids game with multiple servers.  Each server owned their own space and would pass ownership of objects to other adjacent servers when the object crossed a boundary’s threshold.

“Smart Objects”

For an AI class final project, I worked with a teammate to create a simulation with “smart objects”. These were essentially objects in a scene which would have information inside them to describe both how they would satisfy an AI user and how the user should use or operate the object. We used a bit of fuzzy logic to have each AI determine action it would take, which each AI unit having a list of needs and a quantifier for how much they needed something. With all the surrounding objects, each unit would calculate the benefit of using a particular object. When the unit reached the object, the object would instruct the AI what to do. In our simulation, we had 2 teams of 8 against each other with cover points and randomly spawned health packs. Each unit had one of three weapons. The sides would battle each other, while taking cover and sometimes picking up health, picking up a better weapon, or switching to a better cover point that was free of units.

A* Pathfinding

I implemented A* pathfinding with “rubberbanding” and Catmull-Rom splines. “Rubberbanding”, as coined by professor Steve Rabin, takes 3 nodes on the final path and removes the middle node if there are no obstructions in the rectangle spanned by the first and last node. This process removes unnecessary nodes created by A*. The Catmull-Rom spline then adds detail and smoothing to the path for the character movement.

Graphics Optimizations

View frustum culling

View frustum culling

PVS culling

Potentially visible set (PVS) culling

Raycasting with KD-tree

Raycasting with k-d tree

Hierarchical occlusion map culling

Hierarchical occlusion map culling

Painter's algorithm with BSP tree

Painter’s algorithm with BSP tree

Other

Linked outline generation with marching squares

Linked outline generation with marching squares

Random Terrain Generation

In my senior year of high school, I spent time learning the basics of Direct3D 9.  I implemented a simple recursive midpoint subdivison terrain generator and rendered it with a simple fixed function pipeline.  I was also interested in the idea of generating sections separate from each other and then splicing the terrains together without looking like it was too blended.  I did not get around to that.  For some odd reason, I also loaded a character model that would be fixed to the camera.

terrain7