the sartrean knight is a short interactive story blending medieval fantasy with existential philosophy. inspired by the works of Jean-Paul Sartre, the experience invites you to navigate a reflective journey about meaning, freedom, and the consequences of choice.
you play as a weary knight facing a mysterious gatekeeper. through dialogue and memories, you will determine your own path and conclusion, featuring multiple unique endings and full support for both English and Portuguese.
i developed the sartrean knight in one week during the initial phase of my experience at the Apple Developer Academy. the project was an opportunity to explore interactive storytelling and the design of meaningful choices.
i learned a lot about using JSON to build a game's narrative structure, as well as honing my skills in SwiftUI and Combine. it was also a rudimentary way to implement localization for an app, paving the way for me to later learn about using string catalogs.
design choices
palette
mist#F1F1F1ink#000000paper#FFFFFF
typography
MedievalSharp/antiquity and authenticity
The quick fox jumps over the lazy dog
Jacquard 24/gothic decorative touch
The quick fox jumps over the lazy dog
rationale
the design of the sartrean knight was inspired by the aesthetics of medieval manuscripts, reflecting the philosophical and historical theme of the narrative.
the choice of MedievalSharp and Jacquard 24 fonts aims to evoke a sense of antiquity and authenticity, while the soft color palette and old paper textures complement the game's contemplative atmosphere.
in terms of story development, the choice to include images at each stage of the narrative was made to enrich the player's experience, providing a visual context that helps immerse them in the medieval setting.
the images were created to reflect the themes and emotions present in each part of the story, reinforcing the connection between the player and the plot.
the image frames were designed to resemble a decorated illustration that could be seen in an old book.
the images themselves do not follow a specific artistic style, although they have certain gothic tendencies, but seek to capture the essence of the setting and characters in an evocative way.
tech stack
SwiftUI
UI framework
Combine
reactive state
JSON / Codable
narrative engine
Icon Composer
asset creation
code snippets
Story data loading optimization
swift
private func loadStory() { guard let url = Bundle.main.url(forResource: "story", withExtension: "json"), let data = try? Data(contentsOf: url) else { return } do { let decoded = try JSONDecoder().decode(StoryData.self, from: data) for page in decoded.screens { pages[page.id] = page } orderedPages = decoded.screens currentPageID = decoded.screens.first?.id } catch { print("Failed to decode story.json: \(error)") }}
Custom typography parser
swift
func parseFigureSegments(_ input: String) -> [FigureSegment] { var segments: [FigureSegment] = [] let parts = input.components(separatedBy: "[figure]") for part in parts { if part.contains("[/figure]") { let subParts = part.components(separatedBy: "[/figure]") if subParts.count >= 1 { segments.append(FigureSegment(text: subParts[0], isFigure: true)) if subParts.count > 1 && !subParts[1].isEmpty { segments.append(FigureSegment(text: subParts[1], isFigure: false)) } } } else if !part.isEmpty { segments.append(FigureSegment(text: part, isFigure: false)) } } return segments}
Reactive localization system
swift
class AppLanguage: ObservableObject { enum Language: String { case english = "en" case portuguese = "pt" } @Published var current: Language = .english func toggle() { current = (current == .english) ? .portuguese : .english }}