Featured Projects
Super Bionic Bash International Game Jam

It was such an incredible honor to participate in Limbitless Solutions' Super Bionic Bash International Game Jam with the University of Skövde! My Minigame, "Bysen Says", contains my own original music and multiple systems I coded and helped to code. this game will be polished and incorporated into the Super Bionic Bash video game.
Learn MoreInk.exe

"Ink.exe" is a 2D wave-based hack and slash game with level progression. This game was made with a smaller team of coders to showcase a use of XML/JSON, C# object functionality, and creativity.
Learn MoreCreature Circus/Carnival

"Creture Circus" is a 3D Platformer with three level made by a team of 9 people within a short window. This showcases my ability to lead and direct a large team while contributing significantly to the project.
Learn MorePROJECTS
Illumen Horizons LLC

"Illumen Horizons LLC" is a first-person horror survival game, where the enemy has randomized behavior on each load. All the code in this game was written by me, showcasing my technical know-how and expertise working with NPC behavior.
Learn MoreGo Stumpy!

"Go Stumpy" is a 2D platformer that I collaborated with a team to create. All the code in this game was written by me, showcasing my extensive expertise in Unity C# development.
Learn MoreBlast Space

"Blast Space" is a 2D minigame where you must beat a high score. This was a solo project showcasing my mastery of 2D Unity functionality and development.
Learn MoreBird Burglars

"Bird Burglars" is an original card game where you must outplay your opponents' hands. This was a group project where I worked to create and design the mechanics of the game, showcasing my proficiency in creating and implementing gameplay mechanics.
Learn MoreCorporate World Dominion
"Corporate World Dominion" is a modified version of Risk, with an added economy system.
Learn MoreFACES COMMANDERS
"FACES COMMANDERS" is an original card game using a deck of cards and many types of dice.
Learn MoreEDUCATIONAL PROJECTS
Desert Scene
C# SCRIPTING
This is some code to create a scene using Unity's primitive creation code and random values.
Code
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using JetBrains.Annotations;
using Unity.Mathematics;
using UnityEngine;
public class DesertScene : MonoBehaviour
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
GameObject baseObject = GameObject.CreatePrimitive(PrimitiveType.Plane);
baseObject.transform.position = new Vector3(0, 0, 0);
baseObject.AddComponent();
baseObject.GetComponent().material.color = Color.yellow;
GameObject forest = new GameObject("Forest");
int x = UnityEngine.Random.Range(5, 10);
for (int i = 0; i < x; i++)
{
int objectType = UnityEngine.Random.Range(0, 2);
GameObject tree;
float height = UnityEngine.Random.Range(0.8f, 2);
if (objectType == 0)
{
tree = GameObject.CreatePrimitive(PrimitiveType.Cube);
tree.transform.parent = forest.transform;
tree.transform.position = new Vector3(UnityEngine.Random.Range(-4, 0), height/2, UnityEngine.Random.Range(-4, 0));
tree.transform.localScale = new Vector3(UnityEngine.Random.Range(0.1f, 0.6f), height, UnityEngine.Random.Range(0.1f, 0.6f));
tree.AddComponent();
tree.GetComponent().material.color = UnityEngine.Random.ColorHSV(0.33f, 0.33f, UnityEngine.Random.Range(0.3f, 0.5f), UnityEngine.Random.Range(0.6f, 1));
}
else
{
tree = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
tree.transform.parent = forest.transform;
tree.transform.position = new Vector3(UnityEngine.Random.Range(-4, 0), height, UnityEngine.Random.Range(-4, 0));
tree.transform.localScale = new Vector3(UnityEngine.Random.Range(0.1f, 0.6f), height, UnityEngine.Random.Range(0.1f, 0.6f));
tree.AddComponent();
tree.GetComponent().material.color = UnityEngine.Random.ColorHSV(0.33f, 0.33f, UnityEngine.Random.Range(0.3f, 0.5f), UnityEngine.Random.Range(0.6f, 1));
}
}
StartCoroutine(GeneratePyramid());
}
IEnumerator GeneratePyramid()
{
GameObject pyramid = new GameObject("Pyramid");
for (int i = 0; i < 5; i++)
{
switch (i)
{
case 0:
for(int j = 0; j < 5; j++)
{
for(int k = 0; k < 5; k++)
{
yield return new WaitForSeconds(0.2f);
GameObject brick = GameObject.CreatePrimitive(PrimitiveType.Cube);
brick.transform.localScale = new Vector3(0.85f, 0.85f, 0.85f);
brick.transform.parent = pyramid.transform;
brick.transform.position = new Vector3(k, 0.425f, j);
brick.AddComponent();
brick.GetComponent().material.color = Color.red;
}
}
break;
case 1:
for(int j = 0; j < 4; j++)
{
for(int k = 0; k < 4; k++)
{
yield return new WaitForSeconds(0.2f);
GameObject brick = GameObject.CreatePrimitive(PrimitiveType.Cube);
brick.transform.localScale = new Vector3(0.75f, 0.75f, 0.75f);
brick.transform.parent = pyramid.transform;
brick.transform.position = new Vector3(k + 0.5f, 1.25f, j + 0.5f);
brick.AddComponent();
brick.GetComponent().material.color = Color.yellow;
}
}
break;
case 2:
for(int j = 0; j < 3; j++)
{
for(int k = 0; k < 3; k++)
{
yield return new WaitForSeconds(0.2f);
GameObject brick = GameObject.CreatePrimitive(PrimitiveType.Cube);
brick.transform.localScale = new Vector3(0.65f, 0.65f, 0.65f);
brick.transform.parent = pyramid.transform;
brick.transform.position = new Vector3(k + 1, 2f, j + 1);
brick.AddComponent();
brick.GetComponent().material.color = Color.green;
}
}
break;
case 3:
for(int j = 0; j < 2; j++)
{
for(int k = 0; k < 2; k++)
{
yield return new WaitForSeconds(0.2f);
GameObject brick = GameObject.CreatePrimitive(PrimitiveType.Cube);
brick.transform.localScale = new Vector3(0.55f, 0.55f, 0.55f);
brick.transform.parent = pyramid.transform;
brick.transform.position = new Vector3(k + 1.5f, 2.64f, j + 1.5f);
brick.AddComponent();
brick.GetComponent().material.color = Color.blue;
}
}
break;
case 4:
yield return new WaitForSeconds(0.2f);
GameObject topBrick = GameObject.CreatePrimitive(PrimitiveType.Cube);
topBrick.transform.localScale = new Vector3(0.45f, 0.45f, 0.45f);
topBrick.transform.parent = pyramid.transform;
topBrick.transform.position = new Vector3(2, 3.22f, 2);
topBrick.AddComponent();
topBrick.GetComponent().material.color = Color.white;
break;
}
}
yield break;
}
}
Credit: Gavin Schmidt and Jadyn Englett
DND Character Using Classes And Structs
C# SCRIPTING
This is some code to create a DND character using inputs from the inspector, using classes and structs.
Code
using UnityEngine;
using System.Collections.Generic;
public class SolutionTwo : MonoBehaviour
{
public bool Tough;
public bool HillDwarf;
public bool RolledHP;
public string charClass;
public int inLevel;
public int CON;
public string name;
private int hp;
private StructVariable myChar;
// Start is called before the first frame update
void Start()
{
myChar = new StructVariable(HillDwarf, RolledHP, Tough, charClass, inLevel, CON, name);
if (!StructVariable.classes.Contains(myChar.className) || myChar.level < 1 || myChar.level > 20 || myChar.con < 1 || myChar.con > 30 || myChar.charName == "")
{
Debug.Log("Invalid input");
return;
}
myChar.SetHP((int)CalcHP());
Debug.Log(DisplayMessage());
}
public float CalcHP()
{
float maxHP = 0;
maxHP = StructVariable.hitDie[myChar.className];
maxHP += StructVariable.ConMod[myChar.con - 1];
if (myChar.level > 1)
{
for (int i = 0; i < myChar.level; i++)
{
if (myChar.isRolledHP) maxHP += Random.Range(1, (int)StructVariable.hitDie[myChar.className] + 1);
else maxHP += ((StructVariable.hitDie[myChar.className] + 1f) / 2f) + 0.5f;
}
}
if (myChar.hasTough)
maxHP += 2 * myChar.level;
if (myChar.isHillDwarf)
maxHP += myChar.level;
return maxHP;
}
public string DisplayMessage()
{
return $"My character {myChar.charName} is a level {myChar.level} {myChar.className} with a CON score of {myChar.con} and {(myChar.isHillDwarf ? "is" : "is not")} a Hill Dwarf and {(myChar.hasTough ? "has" : "does not have")} the Tough feat. I want the HP {(myChar.isRolledHP ? "rolled" : "averaged")}. HP: {myChar.hp}";
}
}
[System.Serializable]
public struct StructVariable
{
public bool hasTough;
public bool isHillDwarf;
public bool isRolledHP;
public string className;
public int level;
public int con;
public string charName;
public int hp;
//Dictionary of classes and their hit die
public static readonly Dictionary hitDie = new Dictionary()
{
{ "Artificer", 8f },{ "Barbarian", 12f },{ "Bard", 8f },{ "Cleric", 8f },{ "Druid", 8f },
{ "Fighter", 10f },{ "Monk", 8f },{ "Ranger", 10f },{ "Rogue", 8f },{ "Paladin", 10f },
{ "Sorcerer", 6f },{ "Wizard", 6f },{ "Warlock", 8f }
};
//List of classes
public static List classes = new List()
{
"Artificer", "Barbarian", "Bard", "Cleric", "Druid", "Fighter", "Monk",
"Ranger", "Rogue", "Paladin", "Sorcerer", "Wizard", "Warlock"
};
//Array of Con Mods
public static float[] ConMod = { -5, -4, -4, -3, -3, -2, -2, -1, -1, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10 };
public StructVariable(bool isHillDwarf, bool rolledHP, bool hasTough, string charClass, int level, int con, string name)
{
this.isHillDwarf = isHillDwarf;
this.isRolledHP = rolledHP;
this.hasTough = hasTough;
this.className = charClass;
this.level = level;
this.con = con;
this.charName = name;
this.hp = 0;
}
public void SetHP(int hp)
{
this.hp = hp;
}
}
Credit: Gavin Schmidt, Miguel Pineda, Samuel Drastal, and Brandon Wahl
Two Person Microgame
MODIFIED TUTORIAL GAME
This 2D top-down shooter microgame was collaboratively developed by myself and Egor Nikiforov. The game features moving enemies, NPC dialogue, and environmental hazards. Detailed credits for our individual contributions can be found in the README file.
Download Partner MicrogameCredit: Projectile Particles, UI, In-level Sounds, Ammo System, Level Design: Gavin Schmidt Scenery, Win/Lose Screen Music/UI, Damage Zones: Egor Nikiforov
Unity Tutorial: FPS
ORIGINAL MUSIC
My objective was to compose a triumphal gladiatorial melody, subsequently interspersed with elements of uncertainty and foreboding. Given the game's dark and enigmatic nature, I meticulously crafted both the atmospheric design and the music's darker harmonies to evoke an enduring sense of dread.
Credit: Sound Design, VFX, Prop Placement: Gavin Schmidt Game Design, Level Design, Scenery: Unity
Breadth First Search
PROBLEM SOLVING CODE
Problem:
The first line of input contains two space separated integers, r (2 ≤ r ≤ 1000) and c (2 ≤ c ≤ 1000), representing the number of rows and number of columns in the grid, respectively.
The following r lines contain c characters each. The ith line of these lines contains the contents of the ith row of the grid, from left to right.
It is guaranteed that exactly one of the grid characters will be ‘*’ and exactly one of the grid characters will be ‘$’. All grid characters that represent regular squares will be labeled with the character ‘.’. All forbidden squares will be represented with the grid character ‘!’. All other squares will be capital letters, representing various teleportation squares. If a letter appears in the grid, then it will appear in at least two separate grid squares.
The Output (standard console output): If Gustavo can get out of the maze, output a single integer representing the fewest number of moves it will takehim to get out. If he can’t get out, output “Call 911”.
Code
import java.util.*;
class Main {
final public static int[] DR = {-1,0,1,0};
final public static int[] DC = {0,-1,0,1};
public static int r;
public static int c;
public static char[][] maze;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
r = in.nextInt();
c = in.nextInt();
maze = new char[r][c];
for(int i=0; i < r; ++i){
maze[i] = in.next().toCharArray();
}
int start = find('*');
int result = bfs(start, '$');
if (result == -1)
System.out.println("Call 911");
else
System.out.println(result);
}
public static int bfs(int s, char e){
LinkedList q = new LinkedList();
q.offer(s);
int[] dist = new int[r*c];
Arrays.fill(dist, -1);
dist[s] = 0;
while(q.size()>0){
int curr = q.poll();
int currR = curr / c;
int currC = curr % c;
char currL = maze[currR][currC];
if (currL == e) return dist[curr];
for (int i=0; i < DR.length; i++) {
int nR = currR + DR[i];
int nC = currC + DC[i];
if (!inbounds(nR, nC)) continue;
if (maze[nR][nC] == '!') continue;
if (dist[nR*c+nC] != -1) continue;
dist[nR*c+nC] = dist[curr] + 1;
q.offer(nR*c+nC);
}
if('A' <= currL){
if(currL <= 'Z'){
int letterPlus = find((char)(currL + 1));
int letterNeg = find((char)(currL - 1));
if(letterPlus != -1){
int nR = letterPlus / c;
int nC = letterPlus % c;
if (dist[letterPlus] != -1) continue;
dist[letterPlus] = dist[curr] + 1;
q.offer(letterPlus);
}
if(letterNeg != -1){
int nR = letterNeg / c;
int nC = letterNeg % c;
if (dist[letterNeg] != -1) continue;
dist[letterNeg] = dist[curr] + 1;
q.offer(letterNeg);
}
}
}
}
return -1;
}
public static boolean inbounds(int x, int y) {
return x >= 0 && x < r && y >= 0 && y < c;
}
public static int find(char s){
for (int i=0; i < r; i++)
for (int j=0; j < c; j++)
if (maze[i][j] == s)
return i*c + j;
return -1;
}
// FOR TESTING
public static void printMaze(){
for(int i=0; i < r; ++i){
for(int j=0; j < c; ++j){
System.out.print(maze[i][j]);
}
System.out.println();
}
}
}
Dijkstra's Algorithm
PROBLEM SOLVING CODE
Problem:
The first line of input contains 3 space separated integers, C (2 ≤C≤105), R (C-1 ≤ R≤ min(105, n(n-1)/2), S (1 ≤ S ≤ N), representing the number of cities, number of roads, and the city number that represents the capital, respectively.
Then the next R lines contain the descriptions of the roads. Each of them contains 3 space separated integers vi, ui, wi (1 ≤ vi, ui ≤ n, vi ≠ ui, 1 ≤ wi ≤ 1000), where vi, ui are numbers of the cities connected by this road and wi is its length. The last input line contains integer L (0 ≤ l ≤ 109) — the distance from the capital to the places where the treasures are located. It is guaranteed that:
• between any two cities no more than one road exists.
• each road connects two different cities.
• from each city there is at least one way to any other city by the roads.
The Output (standard console output): Print two numbers — the number of treasures in the cities and the number of treasures on the roads in Monster land.
Code
import java.util.*;
class Main {
//global variables
public static int C;
public static int R;
public static int CAPITAL;
public static int[][] graph;
public static int L;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
//getting num of cities, roads, and where capital
C = in.nextInt();
R = in.nextInt();
CAPITAL = in.nextInt() - 1;
//setup adjacency matrix
graph = new int[C][C];
//integers to setup up matrix
int tempC1;
int tempC2;
int length;
//build matrix
for(int i = 0; i < R; ++i){
tempC1 = in.nextInt() - 1;
tempC2 = in.nextInt() - 1;
length = in.nextInt();
//into matrix
graph[tempC1][tempC2] = length;
graph[tempC2][tempC1] = length;
}
//getting L
L = in.nextInt();
//close input
in.close();
Dijkstra();
}
public static void Dijkstra() {
//three lists to track during algorithm
PriorityQueue minHeap = new PriorityQueue(C, new City());
int[] D = new int[C];
Set S = new HashSet();
//three lists to track treasure
int[] roadT = new int[C];
int tCity = 0;
int tRoad = 0;
//start all distances at INF
Arrays.fill(D,Integer.MAX_VALUE);
//start with capital
minHeap.add(new City(CAPITAL, 0));
D[CAPITAL] = 0;
int prevD;
while (S.size() != C){
//visit next node in minHeap
int next = minHeap.poll().c;
if(S.contains(next))
continue;
//add to visited list
S.add(next);
for(int i = 0; i < C; ++i){
if(graph[next][i] > 0 && i != CAPITAL){
//if treasure is on road
//System.out.println(next + ": " + D[next] + " " + i + ": " + D[i]);
if(D[next] < L && (D[next] + graph[next][i]) > L){
roadT[next] = L - D[next];
if(roadT[next] != roadT[i] || roadT[next] != graph[next][i] / 2){
//System.out.println("adding");
tRoad++;
}
}
//if smaller, update D, add to minHeap
if(D[i] > (D[next] + graph[next][i])){
prevD = D[i];
D[i] = D[next] + graph[next][i];
minHeap.add(new City(i, D[i]));
//treasure found
if(D[i] == L)
++tCity;
if(prevD == L && D[i] != L)
--tCity;
}
//System.out.println(next + ": " + D[next] + " " + i + ": " + D[i]);
}
}
}
System.out.println("In city: " + tCity);
System.out.println("On the road: " + tRoad);
}
}
//object for minheap
class City implements Comparator{
public int c;
public int d;
public City(){
}
public City(int c, int d){
this.c = c;
this.d = d;
}
@Override
public int compare(City node1, City node2) {
if (node1.d < node2.d)
return -1;
if (node1.d > node2.d)
return 1;
return 0;
}
}
Dynamic Programming
PROBLEM SOLVING CODE
Problem:
The first line of the input contains a single integer n (1≤n≤100000) that represents the number of students in each row.
The second line of the input contains n integers p1,1,p1,2,...,p1,n,(1≤p1,i≤109), where p1,i is the number of problems solved by the ith student in the first row.
The third line of the input contains n integers p2,1,p2,2,...,p2,n,(1≤p2,i≤109), where p2,i is the number of problems solved by the ith student in the second row.
The Output (standard console output): Print one number — the maximum possible total problem solved by the selected group of students.
Code
import java.util.*;
public class Main {
public static int[][] candidates;
public static int size;
public static void main(String [] args){
Scanner in = new Scanner(System.in);
size = in.nextInt();
candidates = new int[size][2];
for(int i = 0; i < size; ++i)
candidates[i][0] = in.nextInt();
for(int i = 0; i < size; ++i)
candidates[i][1] = in.nextInt();
System.out.println(DP());
}
public static int DP(){
int[][] dp = new int[size][2];
dp[0][0] = candidates[0][0];
dp[0][1] = candidates[0][1];
for (int i = 1; i < size; ++i){
dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] + candidates[i][0]);
dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0] + candidates[i][1]);
}
return Math.max(dp[size-1][0], dp[size-1][1]);
}
}