Swift wrapper for the Ink narrative scripting language. Based on InkJS. This version requires JavaScriptCore (so for now no Linux support).
loadStory(json: String)
as well as Ink directly loadStory(ink: String)
;continueStory()
and choices chooseChoiceIndex(_ index: Int)
;moveToKnitStitch(_ knot: String, stitch: String? = nil)
;currentTags
variable;stateToJSON()
and loadState(_ jsonDataString: String)
;JXKit
branch has experimental support for Apple and Linux platforms using JXKit
(https://github.com/jectivex/JXKit). The tests pass on macOS and Linux. For now I'll keep the two branches seperate, but I will probably merge them in due time.Use 'File' -> 'Swift Packages' -> 'Add Package Dependency...' to add the package to your project.
Add InkSwift as a dependency to Package.swift
:
let package = Package(
name: "test_swiftpm", // choose your own name
platforms: [
.macOS(.v10_15),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
.package(url: "https://github.com/maartene/InkSwift.git", from: "0.0.2")
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "test_swiftpm",
dependencies: ["InkSwift"]),
.testTarget(
name: "test_swiftpmTests",
dependencies: ["test_swiftpm"]),
]
)
Start by creating a InkStory
let story = InkStory()
Then load a story from a Ink JSON (you can use Inklecate or Inky to convert an .ink file to a .json file.):
let storyJSON = ... //
story.loadStory(json: storyJSON)
Alternatively, you can load a story from Ink directly. Not however, that this might hinder performance for users.
story.loadStory(ink: "Hello, World!")
You can create a very basic command line 'player' using just a few lines of code:
// As long as the story can continue (either because there is more text or there are options you can choose)), keep the loop going
while story.canContinue || story.options.count > 0 {
// Print the current text to the console/terminal
print(story.currentText)
// If you can continue the story, we wait for input before continuing.
if story.canContinue {
print("Press 'enter' to continue")
_ = readLine()
story.continueStory()
}
// If there are options, show the options and wait for player to choose
else if story.options.count > 0 {
// print every option
for option in story.options {
print("\(option.index). \(option.text)")
}
print("What is your choice?")
// wait for input from player
if let choice = readLine() {
// try and convert input to an index.
if let index = Int(String(choice.first ?? "a")) {
// choose the selected option index
story.chooseChoiceIndex(index)
}
}
}
}
// no more content, story is done.
print("Story done!")
InkStory conforms to the ObservableObject
protocol. This makes using it in Combine possible and SwiftUI very easy. A simple example SwiftUI view that can play an Ink story would contain:
Add
import InkSwift
to ContentView.swift
Add the following property to your ContentView:
@StateObject var story = InkStory()
Note: change the filename to load to your own JSON file. Don't forget to add it to the project.
func loadStory() {
guard let url = Bundle.main.url(forResource: "test.ink", withExtension: "json") else {
fatalError("Could not find ink story file.")
}
guard let storyJSON = try? String(contentsOf: url) else {
fatalError("Could not load story file.")
}
story.loadStory(json: storyJSON)
}
var body: some View {
VStack {
Text(story.currentText)
if story.canContinue {
Button("Continue") {
story.continueStory()
}
}
ForEach(story.options, id: \.index) { option in
Button(option.text) {
story.chooseChoiceIndex(option.index)
}
}
}.padding()
.onAppear {
loadStory()
}
}
link |
Stars: 7 |
Last commit: 3 weeks ago |
InkSwift was stable for use for some time. But now InkJS has been updated to version 2.2.2. The compiler is now included, so you can load stories directly from Ink source code. Without needing to compile.
Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics