Objectives
Advancing Computer Science
Boards Presentation
Example 1: SIP - PortalOps
This project started as a way to manage my multiple Linux based servers without needing to manually log into each one and as a way to demonstrate any console-based applications I've written with in-browser playable versions. Once the concept had been nailed down, I worked on creating a basic state diagram and program flow diagram.
Once working through the code for a bit, I realized the networking was getting too complicated to work on from memory, so I stopped and created a flowchart showing the network interactions between the user, server, agent, and executing application to make everything easier to understand.
This project was kept on track by tracking tasks and progress in Jira, and using Git branches to segregate different tasks and merge them in once completed.
Example 2: Mock Game Company
This is a mock Game Company that was created by designing the database first using an Entity Relationship (ER) Diagram. This diagram displayed Primary key and Foreign key relationships as well as field constraints. The diagram was added to gradually week by week, and tested using SQL queries. This project was realized in a web-based application available here.
Example 1: SIP - PortalOps
PortalOps is a suite of software, with one application running on a web server and serving as the gateway for users to the applications. And with the second application running as an agent on the device that contains the software that needs to be executed by the web software.
The web application is written using C# with .Net 8 and using SignalR technology to enable real-time updates with the end-user without requiring a postback.
The agent application was written using Rust and communicates with the web application using UDP packets containing JSON data.
Example 2: Pong for Dreamcast
This game was written using C++ and the KallistiOS Unofficial Development Kit to interface with the Sega Dreamcast hardware. This requires a specifically set up development environment using Linux and GCC and requires interfacing with uncommon hardware, like the PowerVR graphics processor found in the Dreamcast hardware.
Example 3: Rustbound Odyssey
This is a text-based adventure game, written in Rust. This game relies on data files loaded in containing data written in JSON for room information, enemy information, and treasure information.
The below video is a full technical overview of the game, including footage of it running.
Example 1: Mock Game Company
The Mock Game Company website, found here, was designed through an ER Diagram and realized into a small C# application. Screenshots of both the ER Diagram and the Schema Diagram from MySQL Workbench are shown above.
Example 2: Portfolio Analytics
The analytics data my portfolio stores was very basic when I first added the feature to the site. It mainly stored the IP and some basic data from the request sent to the server. I refactored the database to normalize the data somewhat, and add additional data in the form of geolocation data that can be looked up for each IP that visits.
This data normalization makes it easier to analyze the data and ban IP Addresses, or even entire Internet Service Providers, that are attempting to "hack" into my portfolio. Images above show the before and after schemas from the refactor.
Example 1: PortalOps Agent Application
This application was designed and written specifically to be able to run on multiple platforms. I have tested it to be functional on both Windows and Linux systems. While subtle, the screenshots above show the agent running on both Windows and Linux. The "PS" before the command prompt in the top screenshot comes from PowerShell 7 running on Windows, while the bottom screenshot shows the default bash terminal for a Debian Linux system.
Example 2: Tank Game
This game was written in Unity using C# as the scripting language. Unity is designed to allow games written in it to run on multiple platforms so long as no platform specific code is used... and even then if implemented correctly the game would still be able to run with reduced features on multiple platforms. Above you'll find the video for "Milestone 5" demonstrating the final features of the game, which was done in Linux. Next to it, you'll find a quick demonstration showing the same code running on a Windows machine.
Example 3: Rustbound Odyssey
This application was created in Rust with no platform specific libraries. This enables it to very easily run on multiple platforms without any code changes. The above video demonstrates the game running on both Windows and WSL Debian.
Example 1: Fantastic Frenemies
While this project is not a software project, it does demonstrate the use of agile development processes. For this project we used Agile to plan out the boardgame, split the work to multiple team members, keep track of who was responsbile for what, and track estimated time for each task.
Discord was used to communicate between team members, hold agile rituals, and schedule meetings.
Excel spreadsheets, stored in Google Drive, were used to track Product Backlog and Sprint Backlogs.
Example 2: SIP - PortalOps
For my SIP project, task planning was completed in Jira. Screenshots above show the Sprint Board and Issues pages.
Code was stored in GitLab, using Git Flow pattern for branch management. Branches were named to reflect the associated Jira card to make it easy to track the specific issue or task that was being worked on.
Additional planning was carried out in the form of a state diagram, a flow diagram, and a UML diagram documenting the intended network flow for the application.
Example 1: Data Structures - Binary Search Tree
This small project demonstrates a Binary Search Tree, built from scratch in C++. It utilizes randomly generated data and builds a tree. From there it removes those values, and tracks the time in nanoseconds those operations take.
Example 2: Data Structures - Insertion Sorting
This small project demonstrates Insertion Sorting, built from scratch in C++. It utilizes randomly generated data, inserts that data into a double linked list, then sorts it. The application was built to benchmark the speed the computer could complete this sorting for 99, 500, 5000, 50000, and 100000 records.
Example 3: Data Structures - Double Linked List
This small project demonstrates a double linked list, built from scratch in C++. It utilizes a known sequence of numbers, inserts them into the list, then prints out the address value for the head and tail, then steps through each node and prints the value. Functions to find a node with a specific value, delete a node, and get the current length were also built.
Game Programming
Boards Presentation
Example 1: Pong for Dreamcast
This is a 2D game created to run on physical Sega Dreamcast hardware. It is a 2 player game, with each player controlling the corresponding paddle.
This game was written in C++ utilizing the KallistiOS Development Toolkit without using a commercial engine.
Example 2: A-Maze-ing
This 3D game was completed using Unreal Engine 5, combining the use of Blueprints and C++ scripts.
In this game you are trying to navigate several mazes of increasing difficulty, while fending off enemies with only your stun ability to protect you.
Features implemented in the game include; jumping, doors with two locks, a mini-map, an expandable number of max stuns, color changing health meter (dependent on value), and an automatically hiding UI when values are full.
Example 3: The Attack
The Attack is a 2D vertical shooter made in Unity using C# scripts. It boasts several advanced C#/Unity features, including Object Pooling, LINQ, JSON data export and import, interfaces, and coroutines. It was also designed to allow the use of any XInput compatible controller, such as the Xbox One/Series controller, to provide a more enjoyable experience.
Example 4: Tank Game
This 3D tank game was written in the Unity game engine using C# for scripts. In this game your objective is to destroy all the other tanks.
This game included 3D art for the models and levels, and 2D art for the user interface and floating health bars.
Example 1: A-Maze-ing Maze Game
This 3D game was completed using Unreal Engine 5, combining the use of Blueprints and C++ scripts.
The game includes a main menu that includes a settings screen where a player can set the master volume or individual volumes for sound effects and music. The game can also be exited from this main menu.
It also includes a level select screen with the levels being selectable once unlocked in the game, which is done when the player reaches the goal for each maze.
In game, there is a pause menu, a win screen with selectable options, and a lose screen in the case that the player loses all their health. In each of these menus are several buttons allowing the player to return to the main menu or continue with the game.
Example 2: The Attack
The Attack is a 2D vertical shooter made in Unity using C# scripts.
The game includes a main menu with options to start the game, view highscores, set option values, or quit. The options menu includes the ability to change the master volume, and individual volumes for music and sound effects.
On player death, or when the player reaches the end of the current set of levels, the player is prompted to enter their name to be added to the high score table. This high score table is written to disk in JSON format, and retrieved when the game starts, allowing high scores to be persistent.
Example 3: Pong for Dreamcast
This is a 2D game created to run on physical Sega Dreamcast hardware. This game was written in C++ utilizing the KallistiOS Development Toolkit without using a commercial engine.
The game includes a main menu screen with options to start a new game, adjust game options, or view the credits. The options include the ability to adjust the volume for music or sound effects, and adjust the number of points needed to win the game.
In game, it features a pause menu that can be called be either player, with the calling player in control of the menu. This pause menu allows the player to either resume playing or quit the game.
When either player wins, a win screen appears letting the players know which player won the game and allowing them to return to the main menu by pressing any button.
Example 1: Tank Game
The Tank Game is a 3d tank shooter written in Unity with C#. This game requires that you defeat all other tanks and the big boss tank at the end!
This game features procedural room generation in both random and map of the day modes. Patrol type AI generates its list of waypoints at game start using a random length of points and constructing a loop using those points. Spawn points and controllers are stored in Lists.
Example 2: The Attack
The Attack is a vertical space shooter! Destroy the aliens and go for the high score!
This game features the use of scriptable objects to hold level data, enemy data, and enemy settings. This game also makes use of object pooling for efficient loading of game resources like enemies and bullets. LINQ is used to efficiently sort high scores to ensure they are displayed in the properly sorted order on the high score screen. High scores are serialized in JSON and stored on disk so they will persist between plays.
Example 3: Rustbound Odyssey
Rustbound Odyssey is a text-based adventure game! You find yourself in a dimly lit dungeon and must escape! Enemies and traps get in your way as you navigate through the dungeon!
This game features procedurally generated maps, each playthrough is a unique combination of rooms. Data for rooms, items, enemies, and dialog are stored in JSON files and loaded in. Useful items and treasure are stored in Vectors. This game also features a rudimentary command parsing system.
As shown in the above screenshot, with the "print_map" function uncommented the game will display a text representation of the generated map for debug purposes. The numbers 1-9 represent regular rooms which at generation can randomly contain an enemy and/or a treasure chest. The @ symbol represents a pitfall, if you move into this room you will fall to your death. The - symbol represents a wall, you cannot move in the direction of a wall. And the S represents a store where you can purchase healing items.The size of the map is randomly decided at generation as well, ranging from 7 to 18 rooms in either direction.
Example 4: Data Structures
During the Data Structures class I created projects that contain Binary Search Trees, Insertion Sorting, Graphs (both Node Based and Adjacency Based), and Double Linked Lists.
These examples were written in C++, and output a series of test data that is usually randomly generated.
Example 1: Pong for Dreamcast
For this game, the main challenge was learning how to use the KallistiOS development kit and how to render sprites and polygon primitives using the PowerVR graphics chip.
Learning a new development kit was the easier challenge, as KallistiOS has been around for 20 years now and there is a ton of documentation and examples available to follow, but what really gave me trouble was drawing polygons. A polygon's vertexs need to be drawn in a specific order or nothing would render to the screen at all. This means that verticle and horizontal lines need to be drawn in slightly different ways... and a diagonal line has to be drawn in yet a 3rd way. So to draw lines, I made a nice abstraction for myself to use which allows you to pass in just the two points that need to be drawn and it determines if the line is horizontal, vertical, or diagonal and calls the correct function to render it properly.
Now with lines out of the way, you'd think maybe other objects can be drawn easier right? Like a circle or a box should just be built in functions right? Wrong! For a box, you can have two different types filled and hollow. To draw a filled box, it's pretty easy; you basically run the draw line code but instead of adding 1 to the x or y dimension, you add the height and width. To draw a hollow box though, you can't really do it by drawing a series of linked vertexes like you can to draw a filled box... because that fills the box. Instead I gave the "DrawRect" function a flag to determine if the box should be filled, and if not I called my "DrawLine" function 4 times with the different vertexes of the box which gives you the empty box you wanted!
Lastly, drawing a circle (to create the ball using only primitives) combined a new function called "DrawPoint," which secretly just draws a rectangle 2 pixels by 2 pixels, 360 times using some math to determine the screen coordinates to draw the points at.
It all works! The entire game field, the ball, the paddles, and the score display is drawn as series of lines, boxes, and points drawn directly with primitives.
Example 2: Knockout Arcade Character Editor
While creating the editor it became apparent, after changes were made a few times that broke existing data, that we needed some way to automatically upgrade the character data in case of a future breaking change.
To that end, I implemented character data versioning. To ensure that the version number was always readable, I created a parent class for the character data that contained only extremely important information such as the file version, a unique identifier for the character data, the last modified date, and who did it.
Next I implemented a check when opening a character data file, it checks the version of the file against a constant called "CurrentVersion" that would be set to the currently in use version of the character data, if it did not match it would call the "Upgrade" extension method, which would run the appropriate upgrade functions one after another until the file had rearranged itself or set new defaults to work with the current version.
This process then returns an "UpgradeResults" object that can contain breaking change warnings if something could not be upgraded automatically and allows the user to cancel the upgrade in the case that such an upgrade would lose them important data.
Since implementing this solution, 3 major breaking changes have been made and several more refinements to data that required new default values to function properly. Every upgrade has gone through without a hitch!
Example 3: SIP - PortalOps
My SIP project is an application suite that allows you to run command-line based tasks, both interactive and non-interactive, on a remote computer while providing the input and viewing the output in a web browser. The primary challenge here was, how do you know when control is returned to the user?
When running a command-line based application directly, no one has to worry when control is passed to the user. Generally some sort of prompt is written to the screen and the user then knows to type something in. But, when capturing the input and output for a program you don't get the luxury of being able to view and interpret what is being displayed to the screen. In fact, if you don't purposely stop reading the output before the target application requests input, your application will hang indefinitely preventing you from requesting new input from the user. So how do you know?
The trick is to know exactly what the output for each prompt in an application will be. For an application you wrote, this can be easy as you can just look in the code to see how you formatted your prompts. For an application you did not write though, this requires running and noting the output for each prompt. Once you know the prompts, it becomes easy to just check each line for that prompt, and requesting input from the client once you see it. While not implemented yet, future versions of the agent will be set to allow regular expressions for the prompts as well, to make it easier to support prompts with phrases like "enter 1-5" in them.
Example 1: Pong for Dreamcast
The thing that really sets this project apart, is that it was developed without the use of a commercially available engine. It was created entirely from scratch in C++ using only the KallistiOS Dreamcast Development Toolkit. Rather than use static sprites for the ball and paddles, I learned how to draw primitives directly to the PowerVR graphics chip in the console.
This game is designed to be 2 player only, with each player controlling one of the paddles. Players can play directly on real Dreamcast hardware (provided the hardware is old enough to allow the use of burned CDs), with the control stick controlling the paddle.
Example 2: A-Maze-ing
This 3D game was completed using Unreal Engine 5, combining the use of Blueprints and C++ scripts. It has been tested to run on Windows PCs.
Features implemented in the game include; jumping, doors with two locks, a mini-map, an expandable number of max stuns, color changing health meter (dependent on value), and an automatically hiding UI when values are full.
Example 3: The Attack
The Attack is a 2D vertical shooter made in Unity using C# scripts. It boasts several advanced C#/Unity features, including Object Pooling, LINQ, JSON data export and import, interfaces, and coroutines. It was also designed to allow the use of any XInput compatible controller, such as the Xbox One/Series controller, to provide a more enjoyable experience.
This game is designed to work on Windows PCs, but should be exportable to work on other platforms as well.
Example 4: Knockout Arcade!
Knockout Arcade is a 2D fighting game, that harkens back to the amazing 2D fighters of the past. It was developed in GameMaker Studio, and coded using GameMaker Language (GML). It is designed to run on Windows PCs. It also supports both keyboard and gamepad control, allows players their choice in taking on their opponents.
Example 1: Knockout Arcade!
I worked as part of the team for Knockout Arcade for 15 weeks during my Production Studio. I took on the role of Programming Lead where I established code style guidelines, mandated the use of branches within Git, required reviews before merging code into the repository, and was in charge of getting any new programmers picked up between terms up to speed so they could start contributing as soon as possible.
While the project lead was ultimately in charge of what tasks were to be worked on, during our lead meetings I would recommend certain tasks be worked on to reduce our future workload. This ultimately lead to me working with one of the new programmers during the second term to completely map out the existing code and update it to meet our code style standards.
During the course of my time on this project, I worked directly with the project lead to implement loading character data from external stores, reducing the amount of hard-coded data for the characters and making it much more simple to add new characters or modify an existing one.
Example 2: Knockout Arcade! Character Editor
Though my main role was as the Programming Lead for the project as a whole, I was also in charge of designing and producing a character editor to use for creating and editing the data. This project consumed the majority of my time during the 15 weeks, but at the end we were able to create a character, edit the palettes, and store each of the animations for the moves.
Once my time was done, and I had moved on to other classes, I continued to assist on this project. Notably, for the first few weeks of the next semester I continued my role as Programming Lead and brought the new programmers up to speed on how this tool worked, how to add to it, and how to ensure it could upgrade previous character data to fit any changes made. After they were fully up to speed, I continued to stay in contact with them and provide guidance when needed to ensure the tool was a success.