Portfolio

© Photo by Anas Alshanti on Unsplash
Current position - Freelancing

Preserve

Multi-Platform Console Porting for Grindstone

This was my first position in the Gaming Industry.

I independently ported the game Preserve to the Microsoft Store, Xbox Series X|S, and Nintendo Switch simultaneously, handling performance, optimizations, continuous updates, localization, and direct communication with Nintendo and Microsoft for compliance.

I also managed to integrate networking and an independent server setup, implementing a cross-play leaderboard using brainCloud, tailored to meet each console’s guidelines. Taking full responsibility for certification, I ensured all ports passed successfully without an external compliance company.

Through efficient time and project management, I navigated the complexities of multi-platform development, delivering a seamless gaming experience across different ecosystems.

Previously - Games Academy

Galaxy Gobbles

2nd student project - Mobile Game - Restaurant Game

Developed as a student project at Games Academy, Galaxy Gobbles is a 2.5D restaurant simulation with a dark twist—you serve alien customers while secretly orchestrating their demise (indirectly, of course).

Designed for Android, the game blends strategy, resource management, and quirky humor.

I was responsible for most programming aspects, including gameplay mechanics, architecture design, mobile optimization, Git administration (pull requests). Additionally, I handled the deployment process, ensuring a seamless deployment to Android.

Watch the development journey in this Youtube Playlist.

Previously - Games Academy

Lost Tails:
Luna's Legacy

1st Student project - Standalone PC Build

As my first student project, Lost Tails: Luna’s Legacy is a heartfelt 2D platformer where players embark on a journey as a fox mother searching for her lost cubs. The game blends emotional storytelling with engaging platforming mechanics.

I was responsible for character art and animation, ensuring seamless integration into Unity (excluding cutscene visuals). Additionally, I assisted the development team in UI implementation and physics mechanics, contributing to a well-rounded player experience.

Previously - Games Academy

Chasing Shadows: The Fox Nightmare

GameJam Project - Motto Dreams - Time: Weekend

Developed as a game jam project at the start of Games Academy, this Unity platformer brings the motto "Dreams" to subject.

Following the jam's theme—"Dreams"—the game depicts a fox hunting a child in his nightmare, blending eerie atmosphere with fast-paced platforming mechanics.

Despite limited experience at the time, the team created a simple yet engaging experience within the timespan of a weekend.

I was responsible for gameplay, movement mechanics, lighting design, and integrating the artists' animations.

Spare Time projects

Foxie MC

Rewrite of an AI Behaviour of the Minecraft Fox Entity - Modding
1// Source File: Foxie.java - 🔗 in Footer
2
3public class Foxie extends TamableAnimal {
4  public static final String ID = "foxie";
5    
6  // Dividing AI logic into multiple sub-controllers for 
7  // better readability, maintainablity and architecture
8  public final FoxieAIControl aiControl;
9  public final FoxieMouthControl mouthControl;
10  public final FoxieDataControl dataControl;
11  public final FoxieHungerControl hungerControl;
12  public final FoxieOwnerControl ownerControl;
13  public final FoxieHuntControl huntControl;
14    
15  ... (A lot more entity handling methods)
16    
17  // Reflecting that hunger is more important than obeying.
18  // If the owner doesn't feed his pet, the pet will not obey.
19  public void tick() {
20    super.tick();
21    this.hungerControl.tick();
22    this.ownerControl.tick();
23  }
24}
Code Spotlight: AI Controllers
A demonstration of how the AI behaviour is organized into different controllers.
link
public final class Pathfinder {
  public static BlockPos getClosestPathWhere(
    @NotNull Mob entity,
    int xzRange,
    int yRange,
    Predicate<BlockPos> predicate
  ) {
  
  ... (many assignments)

  for (var y = cy - yRange; y < cy + yRange; y++)
    for (var x = cx - xzRange; x < cx + xzRange; x++)
      for (var z = cz - xzRange; z < cz + xzRange; z++) {
        var i = new BlockPos(x, y, z);

        if (!navigation.isStableDestination(i)) continue;
        if (!predicate.test(i)) continue;

        var dist_manhattan = current.distManhattan(i);
        if (dist_manhattan > targetRange) continue;
        if (dist_manhattan == Math.floor(targetRange)) {
          var dist_sqrt = current.distToCenterSqr(x, y, z);
          if (dist_sqrt > targetRange) continue;
          targetRange = dist_sqrt;
        }

        var type = evaluator.getBlockPathType(level, x, y, z);
        if (entity.getPathfindingMalus(type) < 0) continue;

        target = i;
      }

    return target;
  }
    
  ... (more pathfinding utils)
}
    
// Example - Search within 25 Blocks (radius) and 5 Blocks height for
//  ... a navigable block where there's enough space and a roof above!
Pathfinder.getClosestPathWhere(mob, 25, 5, x -> !mob.level.canSeeSky(x));
Code Spotlight: Pathfinding Utils
Simple tools to check with lamdas for specific blocks while maintaining performance.
link
public class FoxieSearchForFoodGoal extends Goal {
    ...
    
    // Checking if the fox is in need for searching for food
    public boolean canUse() {
        if (!this._foxie.aiControl.canSearchForFood()) return false;
        if (!this._foxie.hungerControl.isHungry()) return false;
        var heldItem = this._foxie.mouthControl.getItem();
        if (this._foxie.hungerControl.isEdible(heldItem)) return false;
        if (!this._foxie.getNavigation().isDone()) return false;
        return !this._foxie.huntControl.foundFood();
    }
    
    public void tick() {
        if (this._foxie.getNavigation().isInProgress()) return;
        if (this._foxie.getRandom().nextFloat() > .04F) return;

        var boundary = this._foxie.getBoundingBox().inflate(20, 10, 20);

        this._foxie.huntControl.prey = this.findPrey(boundary);
        if (this._foxie.huntControl.prey != null) return;

        this._foxie.huntControl.berries = this.findBerries(boundary);
        if (this._foxie.huntControl.berries != null) return;

        // TODO: Search for edible items that lie arround to steal them

        var random = Pathfinder.getRandomPositionWithin(this._foxie, 20, 5, 3);
        if (random == null) return;

        this._foxie.runTo(random, 1.0F);
    }
    
    ...
}
Code Spotlight: AI Behaviour Example
One of many AI behaviours. This allows the fox to search for food or to stray around.
link

Inspired by the complex behaviors of foxes, I embarked on a mission to redesign the fox entity in Minecraft, transforming it into a more dynamic, intelligent and most importantly tameable creature.

This project served as a hands-on opportunity to learn AI programming in a gaming environment, while also deepening my expertise in Java, Modding, and Server-Client Architecture.To ensure clean and maintainable code, I integrated Codacy, a code quality backend API, refining my development practices.

My custom Foxie entity replaces the standard fox in world spawning, biome placement, and—most importantly—enhances its intelligence.

These foxes now experience hunger, engage in hunting, steal, tire over time, become tamable, follow commands, screech in distress, and react dynamically in various scenarios.

The mod is compatible with Minecraft versions 1.18.2, 1.19.2, and 1.20.1.

1// Source File: Foxie.java - 🔗 in Footer
2
3public class Foxie extends TamableAnimal {
4  public static final String ID = "foxie";
5    
6  // Dividing AI logic into multiple sub-controllers for 
7  // better readability, maintainablity and architecture
8  public final FoxieAIControl aiControl;
9  public final FoxieMouthControl mouthControl;
10  public final FoxieDataControl dataControl;
11  public final FoxieHungerControl hungerControl;
12  public final FoxieOwnerControl ownerControl;
13  public final FoxieHuntControl huntControl;
14    
15  ... (A lot more entity handling methods)
16    
17  // Reflecting that hunger is more important than obeying.
18  // If the owner doesn't feed his pet, the pet will not obey.
19  public void tick() {
20    super.tick();
21    this.hungerControl.tick();
22    this.ownerControl.tick();
23  }
24}
Code Spotlight: AI Controllers
A demonstration of how the AI behaviour is organized into different controllers.
link
public final class Pathfinder {
  public static BlockPos getClosestPathWhere(
    @NotNull Mob entity,
    int xzRange,
    int yRange,
    Predicate<BlockPos> predicate
  ) {
  
  ... (many assignments)

  for (var y = cy - yRange; y < cy + yRange; y++)
    for (var x = cx - xzRange; x < cx + xzRange; x++)
      for (var z = cz - xzRange; z < cz + xzRange; z++) {
        var i = new BlockPos(x, y, z);

        if (!navigation.isStableDestination(i)) continue;
        if (!predicate.test(i)) continue;

        var dist_manhattan = current.distManhattan(i);
        if (dist_manhattan > targetRange) continue;
        if (dist_manhattan == Math.floor(targetRange)) {
          var dist_sqrt = current.distToCenterSqr(x, y, z);
          if (dist_sqrt > targetRange) continue;
          targetRange = dist_sqrt;
        }

        var type = evaluator.getBlockPathType(level, x, y, z);
        if (entity.getPathfindingMalus(type) < 0) continue;

        target = i;
      }

    return target;
  }
    
  ... (more pathfinding utils)
}
    
// Example - Search within 25 Blocks (radius) and 5 Blocks height for
//  ... a navigable block where there's enough space and a roof above!
Pathfinder.getClosestPathWhere(mob, 25, 5, x -> !mob.level.canSeeSky(x));
Code Spotlight: Pathfinding Utils
Simple tools to check with lamdas for specific blocks while maintaining performance.
link
public class FoxieSearchForFoodGoal extends Goal {
    ...
    
    // Checking if the fox is in need for searching for food
    public boolean canUse() {
        if (!this._foxie.aiControl.canSearchForFood()) return false;
        if (!this._foxie.hungerControl.isHungry()) return false;
        var heldItem = this._foxie.mouthControl.getItem();
        if (this._foxie.hungerControl.isEdible(heldItem)) return false;
        if (!this._foxie.getNavigation().isDone()) return false;
        return !this._foxie.huntControl.foundFood();
    }
    
    public void tick() {
        if (this._foxie.getNavigation().isInProgress()) return;
        if (this._foxie.getRandom().nextFloat() > .04F) return;

        var boundary = this._foxie.getBoundingBox().inflate(20, 10, 20);

        this._foxie.huntControl.prey = this.findPrey(boundary);
        if (this._foxie.huntControl.prey != null) return;

        this._foxie.huntControl.berries = this.findBerries(boundary);
        if (this._foxie.huntControl.berries != null) return;

        // TODO: Search for edible items that lie arround to steal them

        var random = Pathfinder.getRandomPositionWithin(this._foxie, 20, 5, 3);
        if (random == null) return;

        this._foxie.runTo(random, 1.0F);
    }
    
    ...
}
Code Spotlight: AI Behaviour Example
One of many AI behaviours. This allows the fox to search for food or to stray around.
link
1int main()
2{
3    initializeScreenBuffer();
4    initializeConsole();
5    initializeTetrominos();
6    initializeField();
7
8    startGame();
9
10    clear();
11}
12
13// The good old game-loop
14void startGame() {
15    while (!bGameOver) {
16        doGameTiming();
17        doInputReading();
18        doGameLogic();
19        render();
20    }
21}
The good old game-loop
The architecture of a simple tiny command-line game engine.
link
1// Did you know they're called tetrominos? ;)
2
3void initializeTetrominos() {
4    // Initialize the buffer of one tetromino.
5    // Where . means space and X means solid.
6    tetromino[0].append(L"..X...X...X...X.");
7    tetromino[1].append(L"..X..XX...X.....");
8    tetromino[2].append(L".....XX..XX.....");
9    tetromino[3].append(L"..X..XX..X......");
10    tetromino[4].append(L".X...XX...X.....");
11    tetromino[5].append(L".X...X...XX.....");
12    tetromino[6].append(L"..X...X..XX.....");
13}
14
15// tetromino[0]  tetromino[1]  ...
16// ..X.          ..X.          
17// ..X.          .XX.
18// ..X.          ..X.
19// ..X.          ....
Hitboxes of Tetrominos
Using the tetrominos as a covered 4x4 pattern.
link
1// Hardcoded c++ keybinding's - WASD, arrow keys and R/Z/Space
2// Saving array lenght at first index for correct access.
3char* cKeyMapping[4]{
4    new char[3] { '2', '\x28', 'S' }, //                 Index 0  -  Down
5    new char[3] { '2', '\x25', 'A' }, //                 Index 1  -  Left
6    new char[3] { '2', '\x27', 'D' }, //                 Index 2  -  Right
7    new char[6] { '5', ' ', 'Z', 'R', 'W', '\x26' } //   Index 3  -  Rotate
8};
9
10// handle's movement and writes state's for later rendering
11void handlePlayerMovement() {
12    // Try move the tetromino down by player's choice.
13    y += (bKey[0] && !causesCollision(x, y + 1, r)) ? 1 : 0;
14    
15    // Try move the tetromino left/right. 0 if both are pressed.
16    x -= (bKey[1] && !causesCollision(x - 1, y, r)) ? 1 : 0;
17    x += (bKey[2] && !causesCollision(x + 1, y, r)) ? 1 : 0;
18    
19    // Try rotate the tetromino
20    r += (bKey[3] && !causesCollision(x, y, r + 1) && !bRotateDown) ? 1 : 0;
21    bRotateDown = bKey[3];
22}
C++ Keybindings
The way keybindings work in the console - and how to check for them.
link
Spare Time projects during apprenticeship

Console Tetris

A fun spare time project of writing tetris in C++ (CMD)
1int main()
2{
3    initializeScreenBuffer();
4    initializeConsole();
5    initializeTetrominos();
6    initializeField();
7
8    startGame();
9
10    clear();
11}
12
13// The good old game-loop
14void startGame() {
15    while (!bGameOver) {
16        doGameTiming();
17        doInputReading();
18        doGameLogic();
19        render();
20    }
21}
The good old game-loop
The architecture of a simple tiny command-line game engine.
link
1// Did you know they're called tetrominos? ;)
2
3void initializeTetrominos() {
4    // Initialize the buffer of one tetromino.
5    // Where . means space and X means solid.
6    tetromino[0].append(L"..X...X...X...X.");
7    tetromino[1].append(L"..X..XX...X.....");
8    tetromino[2].append(L".....XX..XX.....");
9    tetromino[3].append(L"..X..XX..X......");
10    tetromino[4].append(L".X...XX...X.....");
11    tetromino[5].append(L".X...X...XX.....");
12    tetromino[6].append(L"..X...X..XX.....");
13}
14
15// tetromino[0]  tetromino[1]  ...
16// ..X.          ..X.          
17// ..X.          .XX.
18// ..X.          ..X.
19// ..X.          ....
Hitboxes of Tetrominos
Using the tetrominos as a covered 4x4 pattern.
link
1// Hardcoded c++ keybinding's - WASD, arrow keys and R/Z/Space
2// Saving array lenght at first index for correct access.
3char* cKeyMapping[4]{
4    new char[3] { '2', '\x28', 'S' }, //                 Index 0  -  Down
5    new char[3] { '2', '\x25', 'A' }, //                 Index 1  -  Left
6    new char[3] { '2', '\x27', 'D' }, //                 Index 2  -  Right
7    new char[6] { '5', ' ', 'Z', 'R', 'W', '\x26' } //   Index 3  -  Rotate
8};
9
10// handle's movement and writes state's for later rendering
11void handlePlayerMovement() {
12    // Try move the tetromino down by player's choice.
13    y += (bKey[0] && !causesCollision(x, y + 1, r)) ? 1 : 0;
14    
15    // Try move the tetromino left/right. 0 if both are pressed.
16    x -= (bKey[1] && !causesCollision(x - 1, y, r)) ? 1 : 0;
17    x += (bKey[2] && !causesCollision(x + 1, y, r)) ? 1 : 0;
18    
19    // Try rotate the tetromino
20    r += (bKey[3] && !causesCollision(x, y, r + 1) && !bRotateDown) ? 1 : 0;
21    bRotateDown = bKey[3];
22}
C++ Keybindings
The way keybindings work in the console - and how to check for them.
link

As a fun side gig and a way to learn C++, I created a command-line version of Tetris.

It helped me gain experience in the fundamentals of game engines and C++, and it was an enjoyable challenge.

The project incorporates key aspects of a game engine, including tick timing, input handling, collision detection, and rendering—all implemented within the widely known game-loop.

TECVIA - Apprenticeship

Fahrschulmanager

German Apprenticeship - 3 years - Fullstack web Development

During my apprenticeship in Germany, I quickly immersed myself in real-world development.

Within the first few months, I was already working on Fahrschulmanager, a driving school management software used for bookkeeping, customer management, and general business operations.

My responsibilities included fixing, adding, and updating REST endpoints using ASP.NET, as well as refining database queries and Entity Framework statements.

On the client side, I contributed to the Angular web application, implementing features such as the EBICS banking system and an AI-powered taxation customer setup tool. I also tackled more complex tasks, including Single Sign-On for multiple in-house applications and build and deployment automation.

Collaboration was a key part of my role—I worked alongside testers, the support team, and fellow developers, gaining invaluable insights into what it truly means to be a Software Developer.

Got you convinced?

Let's work together!

I'm eager to help on your project!
Write me a message and let us talk.

Contact me

I usually respond within 24 hours.

Thank you! Your submission has been received!
Oops! Something went wrong.
Please try again or contact me on my socials.