Building Shape Popper: A Kid-Friendly iOS Game with SwiftUI & Claude Code
Suneet Malhotra
Jan 6, 2026
Building Shape Popper: A Kid-Friendly iOS Game with SwiftUI & Claude Code
A step-by-step case study on building Shape Popper โ a high-performance, accessible iOS game designed for children ages 4-6. Learn how Claude Code, SwiftUI's Canvas API, and MVVM architecture come together to create smooth 60fps animations and an engaging gameplay experience.
๐ก Key Insight: Using SwiftUI's Canvas API instead of traditional VStack layouts enables high-performance shape rendering at 60fps, making it perfect for interactive games that need to maintain smooth animations.
TL;DR: Key Takeaways
- Target Audience: Ages 4-6, designed with accessibility and kid-friendly UX in mind
- Performance: 60fps animations using SwiftUI Canvas API for optimal rendering
- Architecture: Folder-by-Feature structure with MVVM pattern for SpriteKit/SwiftUI coordination
- Accessibility: Full VoiceOver support, Dynamic Type, and color-blind friendly design
- Development: Built with Claude Code for rapid iteration and clean code generation
- Tech Stack: SwiftUI, SpriteKit, MVVM, Canvas API, iOS Accessibility APIs
The Challenge: Building a Game Kids Actually Want to Play
Creating a game for young children (ages 4-6) requires balancing multiple constraints:
- Performance: Smooth 60fps animations to keep kids engaged
- Accessibility: VoiceOver support, Dynamic Type, and intuitive touch interactions
- Educational Value: Progressive difficulty that grows with the child
- Kid-Friendly Design: Large touch targets, clear visual feedback, and simple interactions
Shape Popper solves all of these challenges using modern SwiftUI patterns and Claude Code for rapid development.
The Tech Stack
| Technology | Purpose | Why It Matters |
|---|---|---|
| SwiftUI | UI Framework | Declarative, modern iOS development with built-in accessibility |
| SpriteKit | Game Engine | High-performance 2D graphics and physics for shape animations |
| MVVM | Architecture | Clean separation between game logic (ViewModel) and UI (View) |
| Canvas API | Rendering | 60fps shape rendering without layout overhead |
| Claude Code | Development | Rapid iteration and code generation for game mechanics |
| iOS Accessibility | Inclusivity | VoiceOver, Dynamic Type, and assistive touch support |
| Swift | Language | Type-safe, performant code with modern concurrency |
Architecture: Folder-by-Feature with MVVM
The project follows a Folder-by-Feature structure, organizing code by game features rather than by technical layers. This makes the codebase more maintainable and easier to navigate.
ShapePopper/
โโโ Features/
โ โโโ Game/
โ โ โโโ GameView.swift
โ โ โโโ GameViewModel.swift
โ โ โโโ GameModels.swift
โ โโโ Shapes/
โ โ โโโ ShapeRenderer.swift
โ โ โโโ ShapeViewModel.swift
โ โ โโโ ShapeTypes.swift
โ โโโ Score/
โ โโโ ScoreView.swift
โ โโโ ScoreViewModel.swift
โโโ Core/
โ โโโ Canvas/
โ โ โโโ CanvasRenderer.swift
โ โโโ Accessibility/
โ โโโ AccessibilityManager.swift
โโโ Resources/
โโโ Assets.xcassets
โโโ Sounds/
Why MVVM for SpriteKit/SwiftUI Coordination?
MVVM (Model-View-ViewModel) was chosen specifically to bridge SpriteKit's imperative game engine with SwiftUI's declarative UI framework:
- ViewModel: Manages game state, shape positions, and score logic
- View: SwiftUI components that observe ViewModel state
- Model: Pure data structures for shapes, scores, and game configuration
This separation allows SpriteKit to handle high-performance rendering while SwiftUI manages the UI layer, with the ViewModel coordinating between them.
Canvas-Based Rendering: The Performance Secret
The game uses SwiftUI's Canvas API for rendering shapes instead of traditional VStack layouts. Here's why:
๐ก Deep Dive: Canvas renders directly to Core Graphics, bypassing SwiftUI's layout system. This means:
- No Layout Overhead: Shapes are drawn directly, not positioned through Auto Layout
- 60fps Guaranteed: Direct rendering path maintains frame rate even with 50+ shapes
- Memory Efficient: No view hierarchy means lower memory footprint
- Perfect for Games: Designed for high-frequency updates and animations
Canvas Rendering Implementation
struct ShapeCanvas: View {
@ObservedObject var viewModel: GameViewModel
var body: some View {
Canvas { context, size in
// Render all shapes in a single draw pass
for shape in viewModel.activeShapes {
context.fill(
Path(shape.path),
with: .color(shape.color),
style: FillStyle(eoFill: false, antialiased: true)
)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.onReceive(viewModel.timer) { _ in
viewModel.updateShapes()
}
}
}
TimelineView for Smooth Animations
For time-based animations, TimelineView ensures smooth frame updates:
TimelineView(.periodic(from: .now, by: 0.016)) { timeline in
ShapeCanvas(viewModel: viewModel)
.onChange(of: timeline.date) { newDate in
viewModel.updateAnimationFrame(at: newDate)
}
}
This creates a 60fps update loop (1/60 โ 0.016 seconds per frame) that keeps animations buttery smooth.
Progressive Difficulty System
The game adapts to the child's skill level with a progressive difficulty system:
| Level | Shapes | Speed | Time Limit | Target Score |
|---|---|---|---|---|
| Level 1 | 5 shapes | Slow | 30 seconds | 10 points |
| Level 2 | 8 shapes | Medium | 25 seconds | 20 points |
| Level 3 | 12 shapes | Fast | 20 seconds | 35 points |
| Level 4 | 15 shapes | Very Fast | 15 seconds | 50 points |
| Level 5+ | 20+ shapes | Adaptive | 10 seconds | 75+ points |
Adaptive Algorithm: The game tracks success rate and automatically adjusts difficulty:
- High Success Rate (>80%): Increases speed and shape count
- Low Success Rate (<50%): Reduces speed, adds more time
- Balanced (50-80%): Maintains current difficulty
Key Features
๐จ 60fps Animations
Using Canvas API ensures consistent 60fps rendering, even with multiple animated shapes on screen. The game maintains smooth performance across all iOS devices.
โฟ Accessibility First
- VoiceOver Support: Full screen reader compatibility
- Dynamic Type: Text scales with system accessibility settings
- Color Blind Friendly: Uses shape patterns, not just colors
- Large Touch Targets: Minimum 44x44pt touch areas for small fingers
- Haptic Feedback: Tactile responses for shape interactions
๐ถ Kid-Friendly Design
- Simple Gestures: Single tap to pop shapes
- Clear Visual Feedback: Immediate animations on interaction
- No Text Required: Icon-based navigation for pre-readers
- Parental Controls: Time limits and difficulty settings
- No Ads or In-App Purchases: Pure gameplay experience
Building with Claude Code
Claude Code accelerated development significantly:
- Initial Scaffold: Generated complete MVVM structure from a single prompt
- Canvas Implementation: Provided optimized rendering code with performance tips
- Accessibility Integration: Added VoiceOver and Dynamic Type support automatically
- Game Logic: Implemented progressive difficulty algorithm with clear documentation
Development Time: ~3 hours from concept to playable prototype using Claude Code.
What I Learned
Shape Popper was a rewarding educational exercise in modern iOS development that reinforced several key principles:
- Performance Matters:
CanvasAPI is essential for smooth game animations - Accessibility is Non-Negotiable: Every interaction must work with VoiceOver
- Progressive Difficulty: Adaptive algorithms keep kids engaged longer
- MVVM Bridges Frameworks: Clean architecture makes SpriteKit + SwiftUI work seamlessly
- Claude Code Accelerates: Rapid iteration with AI assistance enables faster prototyping
View the Project
๐ฆ GitHub Repository โ View the complete source code
๐ฎ Demo Video โ Watch gameplay in action
Built by Suneet Malhotra with Claude Code | Sr. Manager, Test Engineering at Motorola Solutions | Exploring AI-driven development for mobile games
Share this post
You Might Also Like
Build a Project Management App with Claude Code in 15 Minutes
A step-by-step guide to building Flowstate with Claude Code, Next.js, and Supabase. Learn how to use /frontend-design for a custom Editorial Brutalism aesthetic and deploy a fully functional project management app in 15 minutes.
Engineering LeadershipMastering Claude Code: From Core Mechanics to God Mode
A deep dive into Claude Code CLI: Context engineering, automation hooks, and scaling AI-driven development. Learn how to leverage planning mode, thinking mode, panic buttons, and post-hook type-safety loops to become a power user.
Quantitative TradingA Retry Is Not a Trading Decision
A rejected order is a decision. Retrying it without preserving the reason can turn a risk control into a duplicate trade.
Agentic AIThe Log Is Part of the Agent's Interface
An agent that can act but cannot leave a useful decision record is not autonomous. It is an opaque process with write access.
Latest Blog Posts
A Retry Is Not a Trading Decision
A rejected order is a decision. Retrying it without preserving the reason can turn a risk control into a duplicate trade.
The Log Is Part of the Agent's Interface
An agent that can act but cannot leave a useful decision record is not autonomous. It is an opaque process with write access.
The Market Is Closed Is Not a Trading Rule
A backtest can know the exchange hours and still schedule a trade into a holiday, an early close, or a stale session. Calendar state is market data.
Related Tools & Demos
The QA Field Manual to Language Models
A free 24-chapter book. Start at โwhat is AI, really?โ and finish with a small language model you built yourself โ one that reads a failing Playwright test and proposes a fix you can run. Read it in your browser, or download the PDF or the Mac app.
View Source Code โMulti-Model LLM Harness
One interface to call any AI model โ capability routing, fallback chains, budgets, circuit breakers, and a quality feedback loop. A practical architecture pattern write-up.
Automated Trading System
Multi-engine trading platform with real-time risk management, regime-based strategy selection, and automated order execution.
View Source Code โ
Stay in the Loop
Get weekly insights on AI-driven QA, engineering leadership, and automation strategies.
No spam, ever. Unsubscribe anytime.