Skip to content

Commit

Permalink
broken stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
kru42 committed Oct 1, 2024
1 parent 9f1c378 commit d47c50b
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 35 deletions.
4 changes: 4 additions & 0 deletions SwiftVN.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
7859C39C2CA849C200051A60 /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = 7859C39B2CA849C200051A60 /* ZIPFoundation */; };
785C03A32CAB556400C27C66 /* HistoryOverlayNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 785C03A22CAB556000C27C66 /* HistoryOverlayNode.swift */; };
785C03A52CABE07800C27C66 /* sazanami-gothic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 785C03A42CABE07800C27C66 /* sazanami-gothic.ttf */; };
785C03A72CAC102600C27C66 /* ChoiceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 785C03A62CAC102500C27C66 /* ChoiceManager.swift */; };
788EC63B2CA848F1006A3562 /* ArchiveManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 788EC63A2CA848EF006A3562 /* ArchiveManager.swift */; };
788FBCEF2CA92DCD00B976A9 /* TextNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 788FBCEE2CA92DCA00B976A9 /* TextNode.swift */; };
78918ACB2CA8C28900632961 /* AudioManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78918AC72CA8C28900632961 /* AudioManager.swift */; };
Expand Down Expand Up @@ -79,6 +80,7 @@
7824DE3B2CA819E0003383A7 /* SwiftVN.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftVN.swift; sourceTree = "<group>"; };
785C03A22CAB556000C27C66 /* HistoryOverlayNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryOverlayNode.swift; sourceTree = "<group>"; };
785C03A42CABE07800C27C66 /* sazanami-gothic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "sazanami-gothic.ttf"; sourceTree = "<group>"; };
785C03A62CAC102500C27C66 /* ChoiceManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChoiceManager.swift; sourceTree = "<group>"; };
787942252CA99B4200C50CC1 /* TODO.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = TODO.md; sourceTree = "<group>"; };
787942262CA99B4700C50CC1 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
787942272CA9A3FA00C50CC1 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
Expand Down Expand Up @@ -195,6 +197,7 @@
78918ACA2CA8C28900632961 /* VNDS */ = {
isa = PBXGroup;
children = (
785C03A62CAC102500C27C66 /* ChoiceManager.swift */,
78918AC72CA8C28900632961 /* AudioManager.swift */,
785C03A22CAB556000C27C66 /* HistoryOverlayNode.swift */,
78918ACE2CA8C29200632961 /* NovelScene.swift */,
Expand Down Expand Up @@ -371,6 +374,7 @@
781741612CA89C9400D0B3B9 /* LoggerFactory.swift in Sources */,
78918ACB2CA8C28900632961 /* AudioManager.swift in Sources */,
78BA5B9E2CAA73E600EBDE6B /* TextManager.swift in Sources */,
785C03A72CAC102600C27C66 /* ChoiceManager.swift in Sources */,
78918ACD2CA8C28900632961 /* ScriptExecutor.swift in Sources */,
7824DE3C2CA819E9003383A7 /* SwiftVN.swift in Sources */,
);
Expand Down
11 changes: 6 additions & 5 deletions SwiftVN/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ struct ContentView: View {
if let scene = scene {
SpriteView(scene: scene)
.ignoresSafeArea()
.onTapGesture {
if (!showHistoryOverlay) {
scene.next()
}
}
.gesture(
DragGesture(minimumDistance: 0)
.onEnded { value in
scene.handleTap(at: value.location)
}
)
}

// Overlay for title and FPS
Expand Down
59 changes: 58 additions & 1 deletion SwiftVN/VNDS/ChoiceManager.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,64 @@
//
// Untitled.swift
// ChoiceManager.swift
// SwiftVN
//
// Created by Kru on 01/10/24.
//

import SpriteKit

class ChoiceManager {
private let scene: SKScene
private var choiceNodes: [SKNode] = []
private var onSelection: ((Int) -> Void)?

init(scene: SKScene) {
self.scene = scene
}

func presentChoices(_ options: [String], onSelection: @escaping (Int) -> Void) {
self.onSelection = onSelection

let choiceContainer = SKNode()
choiceContainer.name = "choiceContainer"

for (index, option) in options.enumerated() {
let button = SKSpriteNode(color: .blue, size: CGSize(width: 200, height: 50))
button.position = CGPoint(x: 0, y: -CGFloat(index * 60))
button.name = "choice_\(index)"

let label = SKLabelNode(text: option)
label.fontColor = .white
label.verticalAlignmentMode = .center
button.addChild(label)

choiceContainer.addChild(button)
choiceNodes.append(button)
}

choiceContainer.position = CGPoint(x: scene.size.width / 2, y: scene.size.height - 100)
scene.addChild(choiceContainer)
}

func handleTap(at position: CGPoint) -> Bool {
guard let choiceContainer = scene.childNode(withName: "choiceContainer") else { return false }

for (index, choiceNode) in choiceNodes.enumerated() {
if choiceNode.contains(scene.convert(position, to: choiceNode)) {
onSelection?(index + 1)
clearChoices()
return true
}
}
return false
}

func clearChoices() {
scene.childNode(withName: "choiceContainer")?.removeFromParent()
choiceNodes.removeAll()
}

var hasActiveChoices: Bool {
return !choiceNodes.isEmpty
}
}
7 changes: 7 additions & 0 deletions SwiftVN/VNDS/NovelScene.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ class NovelScene: SKScene, ObservableObject {

executor = ScriptExecutor(scene: self)
executor?.loadScript(named: "main.scr")

// Start the script
executor?.next()
}

func handleTap(at location: CGPoint) {
executor?.handleTap(at: location)
}

func next() {
Expand Down
105 changes: 79 additions & 26 deletions SwiftVN/VNDS/ScriptExecutor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
// Created by Kru on 29/09/24.
//

//
// TODO
// - Interpolate in most instructions, even choices?
//

import SwiftUI
import SpriteKit

Expand All @@ -15,17 +20,20 @@ class ScriptExecutor: ObservableObject {
private var globalVariables: [String: Any] = [:]
private var labels: [String: Int] = [:]

@Published var isWaitingForInput: Bool = true
@Published var isLoadingMusic: Bool = false
@Published var isLoadingMusic = false
@Published var isWaitingForInput = true
@Published var isWaitingForChoice = false

var skip = false

private let scene: NovelScene
private let archiveManager: ArchiveManager = ArchiveManager(zipFileName: "script.zip")
private let choiceManager: ChoiceManager
private let logger = LoggerFactory.shared

init(scene: NovelScene) {
self.scene = scene
self.choiceManager = ChoiceManager(scene: scene)
}

func loadScript(named scriptName: String) {
Expand Down Expand Up @@ -54,6 +62,11 @@ class ScriptExecutor: ObservableObject {
}

func next() {
if isWaitingForChoice {
// Do nothing, wait for choice selection
return
}

if isWaitingForInput {
isWaitingForInput = false
currentLine += 1
Expand All @@ -80,6 +93,10 @@ class ScriptExecutor: ObservableObject {
case "text":
executeText(components)
return
case "cleartext":
// Simulate `text ~`
executeText(["text", "~"])
return
case "choice":
executeChoice(components)
currentLine += 1
Expand Down Expand Up @@ -152,9 +169,9 @@ class ScriptExecutor: ObservableObject {
if components[1] == "~" {
scene.audioManager.clearMusic()
} else {
self.isLoadingMusic = true
//self.isLoadingMusic = true
scene.audioManager.playMusic(songPath: components[1]) {
self.isLoadingMusic = false
//self.isLoadingMusic = false
}
}
}
Expand Down Expand Up @@ -214,10 +231,28 @@ class ScriptExecutor: ObservableObject {
}

private func executeChoice(_ components: [String]) {
// Get components separated by "|"
// TODO: do
let choices = components.dropFirst().joined(separator: " ").components(separatedBy: "|")
variables["selected"] = 1 // Will be updated when user makes a choice

choiceManager.presentChoices(choices) { [weak self] selectedIndex in
guard let self = self else { return }
self.globalVariables["selected"] = selectedIndex
self.isWaitingForChoice = false
self.currentLine += 1
self.executeUntilStopped()
}

isWaitingForChoice = true
}

func handleTap(at position: CGPoint) {
if isWaitingForChoice && choiceManager.hasActiveChoices {
let choiceHandled = choiceManager.handleTap(at: position)
if choiceHandled {
isWaitingForChoice = false
return
}
}
next()
}

private func executeSetVar(_ components: [String], isGlobal: Bool) {
Expand Down Expand Up @@ -252,29 +287,27 @@ class ScriptExecutor: ObservableObject {

private func executeIf(_ components: [String]) {
guard components.count >= 4 else { return }

let varName = components[1]
let operation = components[2]
let value = components[3]
let comparisonValue = components[3]

let variableValue = (variables[varName] ?? globalVariables[varName]) as? String ?? ""
guard let variableValue = variables[varName] ?? globalVariables[varName] else {
logger.error("Variable \(varName) not found")
fatalError()
}

let condition: Bool
switch operation {
case "==":
condition = variableValue == value
case "!=":
condition = variableValue != value
case ">":
condition = (Int(variableValue) ?? 0) > (Int(value) ?? 0)
case "<":
condition = (Int(variableValue) ?? 0) < (Int(value) ?? 0)
case ">=":
condition = (Int(variableValue) ?? 0) >= (Int(value) ?? 0)
case "<=":
condition = (Int(variableValue) ?? 0) <= (Int(value) ?? 0)
default:
print("Unknown operation: \(operation)")
condition = false
if let intVariableValue = variableValue as? Int, let intComparisonValue = Int(comparisonValue) {
// Compare as integers if both are Ints
condition = evaluateCondition(intVariableValue, operation: operation, value: intComparisonValue)
} else if let strVariableValue = variableValue as? String {
// Compare as strings if the variable is a String
condition = evaluateCondition(strVariableValue, operation: operation, value: comparisonValue)
} else {
// Handle unsupported types
logger.error("Unsupported variable type for \(varName)")
fatalError()
}

if !condition {
Expand All @@ -295,9 +328,29 @@ class ScriptExecutor: ObservableObject {
}
}

private func evaluateCondition<T: Comparable>(_ variableValue: T, operation: String, value: T) -> Bool {
switch operation {
case "==":
return variableValue == value
case "!=":
return variableValue != value
case ">":
return variableValue > value
case "<":
return variableValue < value
case ">=":
return variableValue >= value
case "<=":
return variableValue <= value
default:
logger.error("Unknown operation: \(operation)")
return false
}
}

private func executeJump(_ components: [String]) {
guard components.count >= 2 else { return }
let scriptName = components[1]
let scriptName = interpolateText(components[1])
loadScript(named: scriptName)
currentLine = 0

Expand Down
12 changes: 9 additions & 3 deletions SwiftVN/VNDS/TextNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,20 @@ class TextNode: SKNode {
var isAnimating: Bool = false
var isAnimationComplete: Bool = true

private let logger = LoggerFactory.shared

init(fontSize: CGFloat = 16, maxLines: Int = 3, padding: CGFloat = 20) {
self.fontSize = fontSize
self.maxLines = maxLines
self.padding = padding

// let fontURL = SwiftVN.baseDirectory.appendingPathComponent("default.ttf")
let fontURL = Bundle.main.bundleURL.appendingPathComponent("sazanami-gothic.ttf")

logger.info("Loading font...")
var fontURL = SwiftVN.baseDirectory.appendingPathComponent("default.ttf")
if !FileManager.default.fileExists(atPath: fontURL.path) {
logger.info("Falling back to sazanami-gothic.ttf")
fontURL = Bundle.main.bundleURL.appendingPathComponent("sazanami-gothic.ttf")
}

// Load novel custom font
if let fontDataProvider = CGDataProvider(url: fontURL as CFURL),
let font = CGFont(fontDataProvider) {
Expand Down

0 comments on commit d47c50b

Please sign in to comment.