Skip to content

sjvandy/SwiftGame

Repository files navigation

SwiftGame

A game framework written entirely in Swift, rendering with Metal — the MonoGame model of game development, designed the way Apple designs its modern Swift frameworks.

The goal: the complete 2D engine, in one box. Everything you need to take a 2D game from empty folder to finished and shippable — sprites, text, audio, input, effects, animation, particles, tilemaps, UI, saves — built into the framework, with APIs you guess right on the first try. Where the MonoGame world reaches for third-party libraries, SwiftGame just keeps going. See Docs/ROADMAP.md for the scorecards and phase plan.

import SwiftGame
import SwiftGameMetal

@main
final class MyGame: Game {
    var position = Vector2(100, 100)

    func update(_ time: GameTime, _ context: GameContext) {
        position.x += 120 * time.deltaSeconds
    }

    func draw(_ time: GameTime, _ context: GameContext) {
        // SpriteBatch arrives in workstream 1e.
    }
}

Status

Phase 1 (Mac 2D core) is complete — everything needed to build and ship-quality-prototype a 2D game on macOS works today:

  • ✅ SwiftPM package, Swift 6 strict concurrency
  • ✅ Math: vectors (SIMD-backed), Angle, Color, Rect, 2D matrices
  • ✅ Game loop: fixed timestep with MonoGame-exact catch-up semantics (isRunningSlowly, 500 ms stall clamp), or variable timestep
  • ✅ macOS window host (AppKit + CADisplayLink)
  • ✅ Metal backend behind a backend-agnostic GPU seam
  • Texture2D + Assets loading (PNG/HEIC/JPEG from bundles, cached)
  • SpriteBatch: sort modes, blend/sampling enums, tinting, rotation, source rects, flips — 10,000 sprites at 120 fps in SpriteGallery
  • ✅ Input: keyboard, mouse, and gamepads as per-frame snapshots with built-in edge detection (input.wasJustPressed(.space)) — no previous-state bookkeeping in game code
  • ✅ Prototype shapes: Rect, Circle (anti-aliased), Triangle, Line — one fill/line/stroke call to draw, contains/intersects to collide, so a game is playable before any art exists
  • ✅ Text: sprites.draw("Score: \(score)", font: .system(24, weight: .bold), at: p) — CoreText glyph atlas, Retina-sharp, kerning/emoji/fallbacks handled, font.measure(_:) for centering
  • ✅ Audio: sound.play(volume:pitch:pan:) fire-and-forget on a pooled AVAudioEngine, makeInstance() for loops, context.audio.music for streaming — plus composed audio before any files exist: SoundEffect.tone(880, duration: 0.06) and SoundEffect.melody(.c(5), .e(5), .g(5)) with per-note durations
  • ✅ iOS/iPadOS (Phase 2): UIKit host with lifecycle pause/resume, touch input as snapshots (input.primaryTouch, touches/previousTouches), and Examples/PongApp — an Xcode project that builds Pong as a real app (verified on the iPad Simulator)
  • ✅ Virtual resolution: config.resolution = .fixed(width: 960, height: 540) declares the game's world size once — SwiftGame scales and centers it on any screen or window (letterboxed), text re-rasterizes to stay crisp, and touch/mouse input arrives already converted to world coordinates
  • ✅ Touch controls without art: makeSymbolTexture("pause.circle.fill") rasterizes any SF Symbol into a tintable texture, sprites.draw(icon, in: rect) fits it to a layout rect, and input.wasTapped(in: rect) is the whole button — tap or click, edge-detected
  • 🚧 Next — Phase 3, graphics completeness: render targets (render-to-texture), built-in + custom shader effects, and scissor clipping; then Phase 4's shipping essentials (text input, fullscreen, rumble, save data). Full plan in Docs/ROADMAP.md.

See Docs/ARCHITECTURE.md for how it fits together and Docs/ROADMAP.md for where it's going.

Requirements

  • macOS 14+ or iOS/iPadOS 17+
  • Xcode 16+ / Swift 6

Starting your own game

Three ways to a running project:

  1. TutorialDocs/TUTORIALS/01-your-first-game.md starts from an empty folder: create a SwiftPM package, add SwiftGame as a dependency, build a complete game learning each feature as you go.
  2. Template — copy Templates/StarterGame, point its Package.swift at SwiftGame, swift run.
  3. VS Code — install Tools/vscode-swiftgame and run SwiftGame: New Game Project. (API autocomplete comes from the official Swift extension; ours adds scaffolding and game-idiom snippets.)
  4. XcodeDocs/TUTORIALS/02-xcode-setup.md: open the package folder directly, or build an App project via File ▸ Add Package Dependencies. ./Tools/install-xcode-templates.sh adds a SwiftGame section to the New File chooser.

Running the examples

swift run Pong                  # W/S, arrows, or gamepad; P pauses
swift run SpriteGallery         # 10,000-sprite batching stress test
swift run CoinChase             # the "your first game" tutorial result
swift run Pong --frames 300     # exits after 300 frames, prints avg fps (CI mode)

New to SwiftGame? Start with Docs/TUTORIALS/01-your-first-game.md — a complete game in ~60 lines.

Testing

swift test                   # all suites; GPU tests skip without a Metal device
swift test --filter GameLoopClock   # one suite

Design principles

  • Depth before breadth. Mac-first, 2D-first: a complete 2D engine — MonoGame's capabilities plus what its ecosystem leaves to third-party libraries (animation, particles, tilemaps, UI) — before 3D or new platforms. The framework absorbs the boilerplate other engines make every game rewrite (edge detection, letterboxing, save paths).
  • The first guess compiles. A Swift developer's naive guess at the call site should be the actual API — wasJustPressed, wasTapped(in:), SoundEffect.melody are the bar.
  • Imperative core, declarative sugar. The update/draw loop is the ground truth; a SwiftUI-flavored scene layer (SwiftGameScene) is optional and experimental until Phase 3.
  • Enums over configuration objects. Blend modes, sampling, and time steps are Swift enums with associated values.
  • The GPU seam stays honest. The core framework depends on SwiftGameGPU protocols only. Metal lives in SwiftGameMetal; a future console backend is a new module, not a rewrite.

License

MIT — see LICENSE.

About

A game development framework made for Xcode using Swift

Resources

License

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors