TinyBrainGames

horaciovaldes.com

Tiny Brain Games

Tiny Brain Games is a SwiftUI collection of quick, single-session mini-games that focus on reflexes, memory, and attention. Each game is designed to be finished in under a minute and tracks best scores per difficulty.

Games

Features

Requirements

Run

  1. Open TinyBrainGames.xcodeproj in Xcode.
  2. Select the TinyBrainGames scheme.
  3. Run on a simulator or device.

Tests

Project Structure

Adding Custom Art / Reskinning the App

This project uses a theme layer (TinyBrainGames/UITheme) so you can swap artwork without touching gameplay code.

Step-by-step

  1. Open TinyBrainGames/Assets.xcassets in Xcode.
  2. Add Image Sets with the exact names listed below.
  3. Drop your PNGs or a single-scale PDF into each Image Set.
  4. Build and run. Missing assets fall back to the current SwiftUI shapes/materials.

Exact asset names (match UIAssetRole raw values)

How the fallback system works

How to add a new theme/provider

  1. Create a new type that conforms to ArtProvider in TinyBrainGames/UITheme.
  2. Return images/colors/materials for any roles you want to override.
  3. Swap the theme at app launch, for example:
@StateObject private var themeStore = ThemeStore(
    theme: Theme(
        tokens: .default,
        primaryArt: AssetCatalogArtProvider(),
        fallbackArt: DefaultArtProvider()
    )
)

Global assets + per-game overrides

Use a global provider for shared art, then layer a per-game provider for a specific view.

Global provider at app launch:

@StateObject private var themeStore = ThemeStore(
    theme: Theme(
        tokens: .default,
        primaryArt: AssetCatalogArtProvider(),
        fallbackArt: DefaultArtProvider()
    )
)

Per-game override provider (example for Minesweeper):

struct MinesweeperArtProvider: ArtProvider {
    func image(for role: UIAssetRole) -> Image? {
        switch role {
        case .tileHidden:
            return AssetCatalog.imageIfExists(named: "ui/games/minesweeper/tile_hidden")
        case .tileRevealed:
            return AssetCatalog.imageIfExists(named: "ui/games/minesweeper/tile_revealed")
        case .tileHighlightGood:
            return AssetCatalog.imageIfExists(named: "ui/games/minesweeper/tile_highlight_good")
        case .tileHighlightBad:
            return AssetCatalog.imageIfExists(named: "ui/games/minesweeper/tile_highlight_bad")
        default:
            return nil
        }
    }
}

Apply the override only to that game:

MinesweeperView(highScoreStore: highScoreStore)
    .environmentObject(
        ThemeStore(theme: themeStore.theme.applying(overrideArt: MinesweeperArtProvider()))
    )

Notes:

How to override only one game’s art

  1. Create a focused ArtProvider that only returns assets for that game’s roles.
  2. Inject a local theme for that game’s view hierarchy:
GameView()
    .environmentObject(
        ThemeStore(theme: themeStore.theme.applying(overrideArt: MyGameArtProvider()))
    )

How to test art changes quickly

  1. Add or update the Image Set assets.
  2. Use AssetCatalogArtProvider in your theme (example above).
  3. Restart the preview or re-run the app to see changes immediately.