top of page

Check it out!!!

Golfella

Overview

Golfella is a Sonic-inspired golfing game where you hit a golf ball through various levels as fast as possible. 

I worked on the game's systems, golf mechanics, UI, and more. Learn more in the My Contributions Section.

Accomplishments

  • Won the Best Gameplay award at 2D Con (MN’s Largest Games Expo) and at Stout Game Expo 2023

  • Reached #3 on New and Trending and peaked #77 in the Popular tab on Itch.io

  • Our game was selected for the MysteryFunHouse 2024 tournament, streamed on GamesDoneQuick Twitch channel with over 2 Million Followers!

  • We got pirated! Check it out here

​​

ROLES:

Mechanics/Systems/UI Developer

DURATION:

4 Months

TEAM SIZE:

3 Programmers & 3 Artists

ENGINE:

Godot

PLATFORMS:

Web, Windows

Best Gameplay

AwardSGX_02.png

Best Gameplay

My Contributions 

  • Programmed the player's golfing moveset. Learn more about this below!

    • e.g. the ground and air hits, bullet time hit, slide hit, and slide hop.​​

  • Developed the game's menus while ensuring proper resizing on all screen sizes.

    • ​This includes the Main Menu, Level End Menu, Pause Menu, Level Select, and Options Menu

  • Added core systems using Scriptable Data Objects

    • Including the Sound Manager, Scene Changer, Options system, Level Objective

  • Developed many level mechanics including the bouncy tees, windmill buttons, level goals, 

  • Added complete controller support with input icons that switch responsively based on which input type is being used (Keyboard, Xbox, Playstation) Learn more on this below!

  • Added polish to the game with shaders, tweens, freeze frame, and more

  • Made a prototype for a multiplayer mode that was cut for scope reasons (still playable in the game)

Scroll down for a deep dive on the

and the

It's worth it! I promise ;)

ezgif.com-crop.gif

Deep Dive on My Work!

Slide_edited.jpg

Input Switcher

For Golfella, I created a system that dynamically swaps input icons at runtime based on the input method currently in use. Although initially straightforward, the system was continually improved to accommodate more than what we initially expected. Let’s delve into the details of how I achieved this!

ezgif.com-crop.gif

The Problem

In Golfella, our goal was to support a diverse range of input devices, including mouse and keyboard, Xbox controller, and PlayStation controller.

 

However, this presented challenges for player tutorialization. We needed to teach players various golfing moves throughout the game, some of which involve simultaneous multiple inputs (e.g., holding up on the joystick and pressing ‘X’).

 

On top of that, Xbox and PS4 controllers have distinct button icons, which would have cluttered a single text box if combined (see gif for proof).

GolfellaOptimizedControlsShowcase.gif

The Solution

I devised a solution that dynamically selects the proper input icons to our text boxes based on the detected player controller.

We first use a small free plugin to detect the player's input device, even accommodating a switch in input device in the middle of gameplay. 

Then when the text is about to be displayed to the user, we scan the string for a specific tag marked by a % on either side. The content within this tag represents an input action, such as ‘jump’ or ‘slide.’ 

 

Our system then cross-references the current input map and determines the appropriate input scancode. Finally, it retrieves the corresponding icon from our input folder and seamlessly integrates the rich text image tag into our text string!

What Went Well?

It's User-Friendly! Our dialogue text is directly accessible on the dialogue nodes, making modifications a breeze. Adding tags to our existing level dialogue took me just 5 minutes. Plus, anyone—artists included—can add tags without needing to touch any code.

It's Responsive! Leveraging an external plugin (not developed by me), our input icons seamlessly switch between controller and keyboard within the same dialogue instance based on the most recently used input device.

It's Polymorphic! Originally designed for one purpose, this system proved versatile. We successfully employed it for unexpected tasks, such as swapping out various interact icons.

It's Compatible with Cutscenes! During our opening cutscene and tutorial dialogue (powered by the Dialogic plugin), we needed the system to work for teaching players input actions. By delving into the plugin code, utilizing Dialogic’s event and variable systems, and extensive testing, I managed to replace the dialogue proceed icon and incorporate input icons into the cutscene text.

It's Dynamic! Rather than binding icons directly to input buttons, we associated them with specific actions. This flexibility allowed us to change inputs for actions and even consider re-mappable controls.

So... It's Perfect?

NO!

Even though the system served its purpose, it definitely isn't perfect. Here are some issues with the Input Swapper:

Complexity: As the project evolved, the system became unwieldy as more functionality was added with less and less time remaining. Given more time, I would have subdivided the class into multiple smaller classes:

  • A class to manage input action requests, handling cases with multiple inputs and concatenating multiple image tags.

  • A class responsible for retrieving the correct input action from the dictionary.​

Dialogic Integration Challenges: While I’m proud I could integrate it with our Cutscene plugin Dialogic, the implementation was fiddly and overcomplicated. Sending out events with input swap counts and adding specific conditional checks became necessary. Simplifying this process would have been ideal if time allowed.

Icon Alignment: The input icons couldn’t be vertically aligned with the line of text it appears in. Godot 4.0 offers this feature for image tags, but unfortunately, we were using an older version. I attempted to address this by scripting a custom rich text parameter to slightly raise the surrounding line of text, but the results weren’t consistent.

Final Notes

I consider this tool one of the most impressive and valuable creations I’ve developed for a game project. What makes it particularly remarkable in mt eyes is that I couldn’t find any Godot-specific tutorials on this topic. Despite that, I built the entire system from scratch within a week, all while juggling many other project tasks.

This tool reflects my unwavering commitment to game polish, my user-centric approach to tools development, and my ability to create solutions for difficult problems.

Interestingly, I recently stumbled upon a plugin that achieves something very similar to my solution. However, it was created a couple of months after I implemented my own version. If you’re curious, you can find it here!

GolfellaHit_edited.jpg

Golfing Moveset

I implemented an intricate golf moveset to ensure that players could effortlessly control the ball without feeling overly restricted. To achieve this, I employed a de-coupled state machine architecture. Let's see how!

GolfellaMoveset.png

Our Plan

After extensive design discussions, we arrived at a plan for the hit mechanics. As depicted in the diagram to the right (created by our talented programmer, Dom Mei), we developed a diverse set of moves that offered a range of vertical and horizontal trajectories at varying speeds.

While our move set could be broken down many different ways, I thought it best to separate golfing moves into 3 distinct states:

  • Regular State: This is the most common state. It allows full character movement and provides the widest variety of shot options.

  •  Slide State: When the character is sliding, they are locked at a fixed speed along the ground and automatically hit the ball upon contact. They can also jump to perform a slide jump and get a boost of speed.

  • Focus State: During this state, time slows down, and the player uses the Mouse or Joystick to aim the ball with more precision.

The Hows and Whys of my implementation

LOVE state machines, so it was a given that I would implement our golfing move set using one. I also made a point to create decoupled architecture, something I've never done for a state machine.

 

To handle state switching, shared references, and shared functions, I introduced a general Golf class. This manager class ensures that the states do not need to directly reference each other. Instead, each state can focus solely on the functionality relevant to it. The beauty of this approach is that adding or removing a state becomes much easier. Moreover, the organized structure simplifies the process of locating and fine-tuning specific golf hits.

GolfellaOptimizedHitShowcase.gif

Take a Look!

bottom of page