Files
hollywoo-flixel/src/hollywoo_flixel/FlxDirector.kiss
2021-12-04 00:12:13 -07:00

162 lines
6.3 KiB
Plaintext

(prop :FlxActionDigital continueAction)
(prop actionManager (new FlxActionManager))
(prop &mut :Movie<String,FlxStagePosition,FlxStageFacing,FlxScreenPosition,ActorFlxSprite,FlxSound,String,FlxSprite> movie)
(defNew []
(set continueAction (new FlxActionDigital "Continue" onContinue))
// TODO allow configuring continue keys -- any key, specifically mapped keys, etc.
(continueAction.addKey SPACE JUST_PRESSED)
(continueAction.addMouse LEFT JUST_PRESSED)
(actionManager.addAction continueAction)
(FlxG.inputs.add actionManager)
(set actionManager.resetOnStateSwitch NONE))
(prop &mut :SceneFlxState currentState)
(method :Void showScene [:Scene<String,FlxStagePosition,FlxStageFacing,FlxScreenPosition,ActorFlxSprite,FlxSprite> scene :Appearance appearance :Continuation cc]
// Close the last scene state
(when currentState
(currentState.close))
// TODO on the first appearance, give a super (for some scenes but probably not others... hm....)
(set currentState (cast scene SceneFlxState))
(FlxG.state.openSubState currentState)
(cc))
(var STAGE_LEFT_X 150)
(var STAGE_RIGHT_X (- 1280 150))
(var ACTOR_Y 500)
(var ACTOR_WIDTH 300)
(method :Void showCharacter [:Character<FlxStagePosition,FlxStageFacing,ActorFlxSprite> character :Appearance appearance :Continuation cc]
// TODO on the first appearance, show name and description (maybe? also probably not for all?)
// TODO also allow for manually defined flipped frames so text doesn't mirror
(set character.actor.flipX ?!(= character.stageFacing character.actor.defaultFacing))
(character.actor.setGraphicSize ACTOR_WIDTH)
(set character.actor.x
(- (case character.stagePosition
(Left
STAGE_LEFT_X)
(Right
STAGE_RIGHT_X)
(otherwise (throw "unsupported stage position")))
(/ character.actor.width 2)))
(set character.actor.y ACTOR_Y)
(currentState.add character.actor)
(cc))
(method :Void hideCharacter [:Character<FlxStagePosition,FlxStageFacing,ActorFlxSprite> character :Continuation cc]
(currentState.remove character.actor)
(cc))
(prop &mut :Null<Continuation> nextCC)
(method onContinue [:FlxActionDigital continueAction]
(whenLet [cc nextCC]
(set nextCC null)
(cc)))
(method :Void startWaitForInput [:Continuation cc]
(set nextCC cc))
(method :Void stopWaitForInput []
(set nextCC null))
(var DIALOG_X 300)
(var DIALOG_WIDTH (- 1280 ACTOR_WIDTH ACTOR_WIDTH))
(var DIALOG_Y 500)
(var DIALOG_HEIGHT (- 720 DIALOG_Y))
// TODO these could be customizable to the Actor
(var DIALOG_BOX_COLOR FlxColor.BLACK)
(var DIALOG_COLOR FlxColor.WHITE)
(var DIALOG_SIZE 24)
(var &mut :FlxSprite dialogBox)
(var &mut :FlxText dialogText)
(var &mut :FlxText speakerNameText)
(method showDialog [:String speakerName :SpeechType<FlxStagePosition,FlxStageFacing,ActorFlxSprite> type :String wryly :String text :Continuation cc]
// TODO handle text messages, wrylies, off-screen, from-phone, etc. via (case type)
// TODO attribute on-screen dialogue to the character's stageposition
// Make a dialog box
(unless dialogBox
(set dialogBox (new FlxSprite DIALOG_X DIALOG_Y))
(dialogBox.makeGraphic DIALOG_WIDTH DIALOG_HEIGHT DIALOG_BOX_COLOR))
(currentState.add dialogBox)
(dialogBox.revive)
// show the dialog
(unless dialogText
// TODO use FlxTypeText to reveal dialog gradually
(set dialogText (new FlxText DIALOG_X DIALOG_Y DIALOG_WIDTH "" DIALOG_SIZE)))
(currentState.add dialogText)
(set dialogText.text text)
// TODO actually clip the dialogue instead of sizing it down:
// TODO this is downsizing everything:
(when (< 720 (+ dialogText.y dialogText.height))
(-= dialogText.size 6))
// show the speaker name
(unless speakerNameText
(set speakerNameText (new FlxText DIALOG_X DIALOG_Y DIALOG_WIDTH "" DIALOG_SIZE)))
(currentState.add speakerNameText)
(if speakerName
{
(set speakerNameText.text "${speakerName}:")
(speakerNameText.revive)
(set dialogText.y (+ DIALOG_Y speakerNameText.height))
}
(set dialogText.y DIALOG_Y))
(dialogText.revive)
// wait for input or delay
// TODO customize the delay in a more sophisticated way to the dialog length or voice-over length,
// or rely on FlxTypeText to add breathing room
(movie.delay (+ 5 (* 0.5 .length (text.split " ")))
->{
(dialogText.kill)
(speakerNameText.kill)
(dialogBox.kill)
(cc)
}))
(method :Void playSound [:FlxSound sound :Float volumeMod :Bool waitForEnd :Continuation cc]
(let [originalVolume sound.volume
restoreOriginalVolume ->(set sound.volume originalVolume)]
(*= sound.volume volumeMod)
(set sound.onComplete
(if waitForEnd
->{(restoreOriginalVolume) (cc)}
restoreOriginalVolume)))
(sound.play)
(unless waitForEnd (cc)))
(prop &mut :FlxSound music)
(prop MUSIC_FADE_SEC 1)
(prop MUSIC_FADE_STEPS 10)
(method :Void playSong [:String song :Float volumeMod :Bool loop :Bool waitForEnd :Continuation cc]
(set music (FlxG.sound.play song 0 loop null true (if waitForEnd cc ->{})))
(.start (new FlxTimer)
(/ MUSIC_FADE_SEC MUSIC_FADE_STEPS)
->:Void _ (+= music.volume (/ volumeMod MUSIC_FADE_STEPS))
MUSIC_FADE_STEPS)
(set music.persist true)
(unless waitForEnd (cc)))
(method :Void stopSong [] (when music (music.stop)))
(var PROP_MIN_WIDTH 200)
(var PROP_MAX_WIDTH 500)
(method :Void showPropOnScreen [:FlxSprite prop :FlxScreenPosition position :Continuation cc]
// TODO assign the other possible positions
(let [[x y]
(case position
(Center [(/ 1280 2) (/ 720 2)])
(otherwise (throw "not implemented")))]
(let [width (min (max prop.width PROP_MIN_WIDTH) PROP_MAX_WIDTH)]
(prop.setGraphicSize width)
(set prop.x (- x (/ prop.width 2)))
(set prop.y (- y (/ (* prop.height prop.scale.y) 2)))
(currentState.add prop)))
// TODO give the prop reveal some time to land
(cc))
(method :Void hideProp [prop cc]
(currentState.remove prop)
(cc))