Posts

Showing posts from December, 2025

Customizing the playing experience with special ball effects

Customizing the playing experience My original vision for BallBuilder was strict equality. Players would unlock balls through coins earned by playing, and every ball would be functionally identical—just cosmetic variety. Everyone competes on equal footing. Through discussions with my development partner and general brainstorming, I realized this approach left significant potential on the table. The ball system could offer much more than cosmetic choices. It could become a customization layer that changes how players approach puzzles. The concern with giving some balls mechanical advantages is obvious: pay-to-win dynamics. But I concluded that advantages can exist without breaking competitive integrity, as long as skill remains the primary differentiator. A better ball might make a puzzle easier, but it won't solve it for you. Passive Effects: The Core Concept Each ball in BallBuilder now has a passive effect that activates when equipped. These effects range from subtle ad...

Solving Aspect Ratio Problems For Good!!

The Problem: Inconsistent Gameplay Across Devices BallBuilder is a physics puzzle game. Levels contain various components—triangles, rectangles, fans, portals—that players interact with to guide a ball to the goal. Consistency matters. A puzzle that's solvable on one device must be solvable on another, using the same approach. Early in development, I was building on an iPhone. When I used Xcode's device emulator to see how the game looked on an iPad, I was immediately disappointed. The layouts were wrong. Components appeared in different relative positions. The carefully crafted levels didn't translate. This was a fundamental problem that I needed to solve. First Attempt: Percentage-Based Positioning My initial approach used fixed pixel coordinates. This was obviously wrong—devices have different pixel counts, so a component placed at pixel 100 would appear in completely different locations across devices. The first real improvement was switching to percentage-b...

Implementing a Gacha system

Design Goal: A Configurable Player Experience BallBuilder is a physics puzzle game where players launch balls to complete objectives. I wanted to create a system where players could deeply customize their experience through unique ball effects. Each ball would have passive abilities that influence gameplay—some subtle, some significant. Once I committed to unique ball effects, the next question was progression. Should each ball be a binary unlock? That felt flat. Instead, I designed a multi-level upgrade system where each ball can be leveled up, making its effect incrementally stronger. This creates longer-term engagement and more meaningful choices about which balls to invest in. What is a Gacha System? For readers unfamiliar: a gacha system is a randomized reward mechanism common in mobile games. Players spend currency to "pull" or "summon" from a pool of possible rewards, with different rewards having different probabilities. The name comes from Japanese ...

Duplicated Configuration Data Solution

The Problem: Duplicated Configuration Data I ran into a fundamental architectural problem while building BallBuilder: configuration data was duplicated between the frontend (Swift/iOS) and the backend (AWS). Consider a simple example: an upgrade costs 100 gems. For that transaction to be secure, the backend must validate the cost—it cannot trust whatever value the client sends. This means the cost has to exist in both places: hardcoded in Swift for the UI, and stored on the backend for validation. This creates an error-prone system. Every time you change a value, you must update it in two locations. Miss one, and the game breaks. Observing the Problem in Practice I noticed this pattern while using Claude to write code. Claude would make a change to a configuration value in the Swift codebase, then we'd update the mocked API call, which also required the same change. Watching this happen repeatedly made it clear: this approach is unsustainable. Two sources of truth for the...

Implementing Mock API Layer for Backend Integration

Problem Statement During initial development of the iOS application, I implemented data management using hard-coded values directly within Swift files. While this approach enabled rapid prototyping and validation of core functionality, it created technical debt that would complicate the transition to production-grade cloud storage. The application needed to evolve from in-memory state management to persistent cloud storage using AWS DynamoDB, requiring a systematic approach to prevent disruption during the migration. The challenge involved two interdependent concerns: Finalizing a comprehensive data model that would scale to production requirements Implementing an abstraction layer that would enable seamless transition from mock to production APIs without requiring extensive client refactoring Data Model Architecture Strategic Decision: Manual Schema Design I mad...

Designing a Scalable Community Content System

Problem Statement During development of the Ballistics puzzle game, I built a comprehensive level editing toolset for creating physics-based puzzle levels. This toolset enables efficient placement of game objects, configuration of gameplay parameters, and rapid iteration on level design. The natural progression was to democratize this capability—enabling players to create and share their own levels while maintaining quality standards and preventing abuse. The core challenge involved designing a system that would allow user-generated content while addressing several critical constraints: Ensuring published levels meet quality standards (solvability requirement) Preventing statistical inconsistencies when levels are modified post-publication Implementing efficient content discovery with multiple query patterns Mitigating cost concerns through strategic resource gating Pr...