screen positions were stage positions all along

This commit is contained in:
2023-03-30 08:13:51 -06:00
parent 250b092192
commit 5da0f4f79e
10 changed files with 106 additions and 138 deletions

View File

@@ -3,4 +3,12 @@
(defAlias &ident Right "Right")
(defAlias &ident RightBehind "Right2")
(defAlias &ident FacingLeft (TowardsPosition "OffScreenLeft"))
(defAlias &ident FacingRight (TowardsPosition "OffScreenRight"))
(defAlias &ident FacingRight (TowardsPosition "OffScreenRight"))
// Screen positions
(defAlias &ident UpperLeft "ScreenUpperLeft")
(defAlias &ident UpperCenter "ScreenUpperCenter")
(defAlias &ident UpperRight "ScreenUpperRight")
(defAlias &ident Center "ScreenCenter")
(defAlias &ident LowerLeft "ScreenLowerLeft")
(defAlias &ident LowerCenter "ScreenLowerCenter")
(defAlias &ident LowerRight "ScreenLowerRight")

View File

@@ -12,6 +12,7 @@ import flixel.tweens.FlxTween;
import hollywoo.Movie;
import hollywoo.Scene;
import hollywoo.Director;
import hollywoo.StagePosition;
import hollywoo_flixel.FlxMovie;
import flixel.util.FlxColor;
import flixel.text.FlxText;
@@ -29,7 +30,7 @@ import openfl.geom.Rectangle;
import openfl.geom.Point;
@:build(kiss.Kiss.build())
class FlxDirector implements Director<FlxSprite, FlxScreenPosition, ActorFlxSprite, FlxSound, String, FlxSprite, FlxSound, FlxCamera, FlxLightSource> {
class FlxDirector implements Director<FlxSprite, ActorFlxSprite, FlxSound, String, FlxSprite, FlxSound, FlxCamera, FlxLightSource> {
public static function blackAlphaMaskFlxSprite(sprite:FlxSprite, mask:FlxSprite, output:FlxSprite):FlxSprite
{
sprite.drawFrame();

View File

@@ -1,6 +1,6 @@
(prop :FlxActionDigital continueAction)
(prop actionManager (new FlxActionManager))
(prop &mut :Movie<FlxSprite,FlxScreenPosition,ActorFlxSprite,FlxSound,String,FlxSprite,FlxSound,FlxCamera,FlxLightSource> movie)
(prop &mut :Movie<FlxSprite,ActorFlxSprite,FlxSound,String,FlxSprite,FlxSound,FlxCamera,FlxLightSource> movie)
(defAlias &ident flxMovie (cast movie FlxMovie))
(loadFrom "hollywoo-flixel" "src/hollywoo_flixel/Aliases.kiss")
@@ -17,7 +17,7 @@
(set actionManager.resetOnStateSwitch NONE)
// TODO characters will be in front of every prop layer -- characters need their own group layer
(doFor i (range LAYER_MAX)
(doFor i (range (+ 1 LAYER_MAX))
(let [g (new FlxTypedGroup<FlxSprite>)]
(spriteLayers.push g)
(FlxG.state.add g))))
@@ -265,75 +265,32 @@
(var PROP_MIN_WIDTH 200)
(var PROP_MAX_WIDTH 500)
(method :Void quickShowPropOnScreen [:FlxSprite prop :FlxScreenPosition position :Continuation cc]
(let [left (/ FlxG.width 6)
right (- FlxG.width left)
upper (/ FlxG.height 6)
lower (- FlxG.height upper)
centerX (/ FlxG.width 2)
centerY (/ FlxG.height 2)
[x y]
(case position
(Center [centerX centerY])
(UpperLeft [left upper])
(UpperRight [right upper])
(LowerLeft [left lower])
(LowerRight [right lower])
(LowerCenter [centerX lower])
(UpperCenter [centerX upper])
(otherwise (throw "screen position not implemented")))]
(let [width (min (max prop.width PROP_MIN_WIDTH) PROP_MAX_WIDTH)]
(prop.setGraphicSize width)
(prop.updateHitbox)
// if the prop is too tall, shrink it heightwise
(when (> prop.height flxMovie.DIALOG_Y)
(prop.setGraphicSize 0 (Std.int flxMovie.DIALOG_Y))
(prop.updateHitbox))
(set prop.x (- x (/ prop.width 2)))
(set prop.y (- y (/ prop.height 2)))
(let [propBottom (+ prop.y prop.height)]
(case position
// if a prop meant to be centered would block the dialogue box, bump it up
(Center
(when (> propBottom flxMovie.DIALOG_Y)
(-= prop.y (- propBottom flxMovie.DIALOG_Y))))
// If a prop meant to be on the lower half of the screen goes below the edge, bring it up
((or LowerLeft LowerCenter LowerRight)
(when (> propBottom FlxG.height)
(-= prop.y (- propBottom FlxG.height))))
(otherwise)))
(FlxG.state.add prop)))
(cc))
(prop &mut :FlxSprite _canvas null)
(method :FlxSprite canvas []
(unless _canvas
(set _canvas (new FlxSprite 0 0))
(_canvas.makeGraphic FlxG.width FlxG.height FlxColor.BLACK))
_canvas)
(method :Void smartShowPropOnScreen [:FlxSprite prop :Int layer :RelativePosition rpos :Continuation cc]
(assert (<= 0 layer LAYER_MAX) "Layer $layer is out of range 0-$LAYER_MAX")
(SpriteTools.scaleStampOn prop (canvas) rpos)
(let [[x y] (SpriteTools.positionOn prop (canvas) rpos)]
(set prop.x x)
(set prop.y y)
(if (= layer LAYER_MAX)
// In front of everything:
(FlxG.state.add prop)
(.add (nth spriteLayers layer) prop)))
(cc))
(method :Void showPropOnScreen [:FlxSprite prop :FlxScreenPosition position :Continuation cc]
(method :Void showProp [:FlxSprite prop :StagePosition position :Continuation cc]
(set prop.cameras [flxMovie.screenCamera])
// TODO give the prop reveal some time to land (add a delay to the cc)
(ifLet [(FullControl layer rpos) position]
(smartShowPropOnScreen prop layer rpos cc)
(quickShowPropOnScreen prop position cc)))
(let [width (min (max prop.width PROP_MIN_WIDTH) PROP_MAX_WIDTH)]
(prop.setGraphicSize width)
(prop.updateHitbox)
// if the prop is too tall, shrink it heightwise
(when (> prop.height flxMovie.DIALOG_Y)
(prop.setGraphicSize 0 (Std.int flxMovie.DIALOG_Y))
(prop.updateHitbox))
(set prop.x (- position.x (/ prop.width 2)))
(set prop.y (- position.y (/ prop.height 2)))
(let [propBottom (+ prop.y prop.height)]
// if a prop would block the dialogue box, bump it up
(when (> propBottom flxMovie.DIALOG_Y)
(-= prop.y (- propBottom flxMovie.DIALOG_Y)))
// If a prop goes below the edge, bring it up
(when (> propBottom FlxG.height)
(-= prop.y (- propBottom FlxG.height))))
(let [layerNum position.z]
(assertEquals layerNum (Std.int layerNum))
(.add (nth spriteLayers (Std.int layerNum)) prop)))
(cc))
(method :Void hideProp [:FlxSprite prop cc]
(FlxG.state.remove prop)

View File

@@ -11,37 +11,10 @@ import hollywoo_flixel.ActorFlxSprite;
import kiss_flixel.SpriteTools;
import openfl.Assets;
/*
enum FlxStagePosition {
Left;
Right;
LeftBehind;
RightBehind;
// Specify the layer and position relative to screen size, or in absolute coordinates, etc.
// AND don't move the object automatically for any reason
FullControl(layer:Int, pos:RelativePosition);
}
*/
enum FlxScreenPosition {
// Shortcuts
UpperLeft;
UpperRight;
LowerLeft;
LowerRight;
LowerCenter;
UpperCenter;
Center;
// Specify the layer and position relative to screen size, or in absolute coordinates, etc.
FullControl(layer:Int, pos:RelativePosition);
}
/**
* Model/controller of a Hollywoo-Flixel film, and main execution script
*/
class FlxMovie extends Movie<FlxSprite, FlxScreenPosition, ActorFlxSprite, FlxSound, String, FlxSprite, FlxSound, FlxCamera, FlxLightSource> {
class FlxMovie extends Movie<FlxSprite, ActorFlxSprite, FlxSound, String, FlxSprite, FlxSound, FlxCamera, FlxLightSource> {
// Think of HollywooFlixelDSL.kiss as the corresponding Kiss file for this class!
public function new(director:FlxDirector, lightSourceJsonFile:String, positionsJson:String, ?voiceLinesAssetPath:String) {

View File

@@ -64,6 +64,19 @@
(defAlias &ident flxDirector (cast director FlxDirector))
(prop &mut :FlxSprite _canvas null)
(method :FlxSprite canvas []
(unless _canvas
(set _canvas (new FlxSprite 0 0))
(_canvas.makeGraphic FlxG.width FlxG.height FlxColor.BLACK))
_canvas)
(method :StagePosition FullControl [:Int layer :RelativePosition rpos]
(assert (<= 0 layer FlxDirector.LAYER_MAX) "Layer $layer is out of range 0-$FlxDirector.LAYER_MAX")
(localVar pixel (new FlxSprite))
(pixel.makeGraphic 1 1 FlxColor.BLACK)
(let [[x y] (SpriteTools.positionOn pixel (canvas) rpos)]
(new StagePosition x y layer)))
(preload
(unless uiCamera
(set uiCamera (new flixel.FlxCamera))
@@ -105,4 +118,18 @@
ACTOR_Y,
STAGE_BEHIND_DY
));
}#)
}#
(let [left (/ FlxG.width 6)
right (- FlxG.width left)
upper (/ FlxG.height 6)
lower (- FlxG.height upper)
centerX (/ FlxG.width 2)
centerY (/ FlxG.height 2)
layer 5]
(stagePositions.put "ScreenCenter" (new StagePosition centerX centerY layer))
(stagePositions.put "ScreenUpperLeft" (new StagePosition left upper layer))
(stagePositions.put "ScreenUpperRight" (new StagePosition right upper layer))
(stagePositions.put "ScreenLowerLeft" (new StagePosition left lower layer))
(stagePositions.put "ScreenLowerRight" (new StagePosition right lower layer))
(stagePositions.put "ScreenLowerCenter" (new StagePosition centerX lower layer))
(stagePositions.put "ScreenUpperCenter" (new StagePosition centerX upper layer))))

View File

@@ -12,7 +12,7 @@ TODO explain Director
You must add the type parameter in many places:
* Movie.hx (on class Movie)
* Movie.kiss (on prop director)
* Scene.hx (on typedef Scene) (if scenes will contain it)
* Movie.kiss (on properties director and scenes, and method _showScene)
* Director.hx (on class Director AND field movie)
* YourMovieType.hx, YourMovieType.kiss and YourDirectorType.hx, YourDirectorType.kiss in your Hollywoo director implementation

View File

@@ -24,8 +24,8 @@ typedef AutoZConfig = {
frontLayer:Int
};
interface Director<Set:Cloneable<Set>, ScreenPosition, Actor, Sound, Song, Prop, VoiceTrack, Camera, LightSource:Jsonable<LightSource>> {
var movie(default, default):Movie<Set, ScreenPosition, Actor, Sound, Song, Prop, VoiceTrack, Camera, LightSource>;
interface Director<Set:Cloneable<Set>, Actor, Sound, Song, Prop, VoiceTrack, Camera, LightSource:Jsonable<LightSource>> {
var movie(default, default):Movie<Set, Actor, Sound, Song, Prop, VoiceTrack, Camera, LightSource>;
function autoZConfig():Option<AutoZConfig>;
function showSet(set:Set, time:SceneTime, perspective:ScenePerspective, appearance:Appearance, camera:Camera, cc:Continuation):Void;
function hideSet(set:Set, camera: Camera, cc:Continuation):Void;
@@ -47,8 +47,7 @@ interface Director<Set:Cloneable<Set>, ScreenPosition, Actor, Sound, Song, Prop,
function hideTitleCard():Void;
function showBlackScreen():Void;
function hideBlackScreen():Void;
function showPropOnScreen(prop:Prop, position:ScreenPosition, cc:Continuation):Void;
// TODO showPropOnStage
function showProp(prop:Prop, position:StagePosition, cc:Continuation):Void;
function hideProp(prop:Prop, cc:Continuation):Void;
function rollCredits(credits:Array<CreditsLine>, cc:Continuation):Void;

View File

@@ -45,4 +45,4 @@ enum CreditsLine {
* Model/controller of a Hollywoo film, and main execution script
*/
@:build(kiss.Kiss.build())
class Movie<Set:Cloneable<Set>, ScreenPosition, Actor, Sound, Song, Prop, VoiceTrack, Camera, LightSource:Jsonable<LightSource>> extends AsyncEmbeddedScript {}
class Movie<Set:Cloneable<Set>, Actor, Sound, Song, Prop, VoiceTrack, Camera, LightSource:Jsonable<LightSource>> extends AsyncEmbeddedScript {}

View File

@@ -18,7 +18,7 @@
(prop &mut :DelayHandling delayHandling AutoWithSkip)
// Mutable representation of frames in time:
(prop :FuzzyMap<Scene<Set,ScreenPosition,Actor,Prop,Camera>> scenes (new FuzzyMap<Scene<Set,ScreenPosition,Actor,Prop,Camera>>))
(prop :FuzzyMap<Scene<Set,Actor,Prop,Camera>> scenes (new FuzzyMap<Scene<Set,Actor,Prop,Camera>>))
(prop :FuzzyMap<Bool> shownScenes (new FuzzyMap<Bool>))
(prop :FuzzyMap<Bool> shownCharacters (new FuzzyMap<Bool>))
@@ -116,13 +116,13 @@
(makeCC
// hide current scene props, etc.
(_ccForEach
currentScene.propsOnScreen
->[:ScreenProp<ScreenPosition,Prop> p :Continuation cc]
currentScene.props
->[:StageProp<Prop> p :Continuation cc]
(director.hideProp p.prop cc)
cc))))))
(cc)))
(method _showScene [:Scene<Set,ScreenPosition,Actor,Prop,Camera> scene :Appearance appearance :Camera camera :Continuation cc]
(method _showScene [:Scene<Set,Actor,Prop,Camera> scene :Appearance appearance :Camera camera :Continuation cc]
(director.showLighting scene.time .elements (lightSources.get sceneKey) camera)
// Show current scene background
(director.showSet scene.set scene.time scene.perspective appearance camera
@@ -133,17 +133,25 @@
->[:String key :Continuation cc]
(director.showCharacter (dictGet scene.characters key) (appearanceFlag shownCharacters key) camera cc)
(makeCC
// hide current scene props, etc.
// show current scene props, etc.
(_ccForEach
scene.propsOnScreen
->[:ScreenProp<ScreenPosition,Prop> p :Continuation cc]
(director.showPropOnScreen p.prop p.screenPosition cc)
scene.props
->[:StageProp<Prop> p :Continuation cc]
(director.showProp p.prop p.position cc)
cc))))))
(method resolvePosition [:Dynamic position]
(typeCase [position]
([:String positionKey]
(stagePositions.get positionKey))
([:StagePosition position]
position)
(otherwise (throw "Not a position or position key: $position"))))
(defNew
[
// "View" in the Model-View-Controller architecture:
&prop :Director<Set,ScreenPosition,Actor,Sound,Song,Prop,VoiceTrack,Camera,LightSource> director
&prop :Director<Set,Actor,Sound,Song,Prop,VoiceTrack,Camera,LightSource> director
:String lightSourceJsonFile
:LightSource defaultLightSource
:String stagePositionsJson
@@ -233,8 +241,8 @@
(.clone (dictGet sets setKey))
characters
(new FuzzyMap<Character<Actor>>)
propsOnScreen
(new FuzzyMap<ScreenProp<ScreenPosition,Prop>>)
props
(new FuzzyMap<StageProp<Prop>>)
camera
camera
]
@@ -297,16 +305,14 @@
{
(doFor =>name otherCharacter .characters (_currentScene)
(when (and (= position.x otherCharacter.stagePosition.x) (= position.y otherCharacter.stagePosition.y) (= position.z otherCharacter.stagePosition.z))
(moveCharacter name (object x position.x y position.y z (+ otherCharacter.stagePosition.z zPerLayer)) otherCharacter.stageFacing cc)
(moveCharacter name (new StagePosition position.x position.y (+ otherCharacter.stagePosition.z zPerLayer)) otherCharacter.stageFacing cc)
(return)))
(cc)
}
(cc)))
(hollywooMethod addCharacter false [actorName :Dynamic position :StageFacing facing :Continuation cc]
(let [position (typeCase [position]
([:String pKey] (stagePositions.get pKey))
(otherwise position))
(let [position (resolvePosition position)
character (object stagePosition position stageFacing facing actor (dictGet actors actorName))]
(autoZProcess position
(makeCC
@@ -324,12 +330,9 @@
// INSTANTLY move a character:
(hollywooMethod moveCharacter false [actorName :Dynamic newPosition :StageFacing newFacing :Continuation cc]
(let [newPosition (typeCase [newPosition]
([:String pKey] (stagePositions.get pKey))
(otherwise newPosition))]
(removeCharacter actorName
(makeCC
(addCharacter actorName newPosition newFacing cc)))))
(removeCharacter actorName
(makeCC
(addCharacter actorName newPosition newFacing cc))))
// INSTANTLY swap characters
(hollywooMethod swapCharacters false [actorNameA actorNameB :Continuation cc]
@@ -356,13 +359,14 @@
(assert isLoading)
(dictSet props name prop))
(hollywooMethod addPropToScreen false [name :ScreenPosition position :Continuation cc]
(let [prop (dictGet props name)]
(dictSet .propsOnScreen (_currentScene) name (object screenPosition position prop prop))
(director.showPropOnScreen prop position cc)))
(hollywooMethod addProp false [name :Dynamic position :Continuation cc]
(let [prop (dictGet props name)
position (resolvePosition position)]
(dictSet .props (_currentScene) name (objectWith position prop))
(director.showProp prop position cc)))
(hollywooMethod removeProp false [name :Continuation cc]
(.remove .propsOnScreen (_currentScene) name)
(.remove .props (_currentScene) name)
// TODO (propsOnStage.remove name)
(director.hideProp (dictGet props name) cc))

View File

@@ -33,16 +33,15 @@ enum SpeechType<Actor> {
Custom(type:String, actor:Actor, args:Dynamic);
}
typedef ScreenProp<ScreenPosition,Prop> = {
screenPosition:ScreenPosition,
typedef StageProp<Prop> = {
position:StagePosition,
prop:Prop
};
typedef Scene<Set:Cloneable<Set>, ScreenPosition, Actor, Prop, Camera> = {
typedef Scene<Set:Cloneable<Set>, Actor, Prop, Camera> = {
set:Set,
characters:FuzzyMap<Character<Actor>>,
propsOnScreen:FuzzyMap<ScreenProp<ScreenPosition,Prop>>,
// TODO props on stage
props:FuzzyMap<StageProp<Prop>>,
time:SceneTime,
perspective:ScenePerspective,
camera:Camera