/** Play is the Director for the regular game-play. Lauch dolls from the Launchers. Aim with the mouse, and click to launch. If you knock over a Fragile item, you lose. If a Doll gets zapped by Plasma, you lose. Knock over all of the bowling Pins, collect all of the Targets and ring all of the Bells to win. The count of these are storing in [objectives]. There are also Collectables : grow, shrink, slowDown and speedUp. You do not NEED to collected them to finish the level, and some are actually bad to collect, because they make the level harder (or even impossible)! There can be more than one Launcher. In which case, press the corresponding number key to select. AutoLaunchers fire Dolls at given intervals, out of the control of the player. Menu (a subclass of Play) is also use on the menu scenes, as they have AutoLaunchers, for visual effects only. */ class Play : DollsHouseDirector() { /** * Set to true by SceneComplete role when it's animation is finished. * That animation is started from within [objectivesComplete]. */ var sceneComplete = false /** * Set when the first Doll is launched. Used for scenes with a time limit. */ var started = false /** * Set to true when the time is up, or you have failed in other ways. */ var lost = false /** * The number of remaining objectives till the scene is complete */ var objectives = 0 /** * The currently selected launcher. */ var launcher: Launcher = null /** * A list of all launchers in the scene. Populated when the scene begins by looking for all Actors with Roles * of type Launcher. */ val launchers = listOf() /** * The Arrow role, which has the aimActor, which follow the mouse. This is use to aim the Dolls. * Set when the scene begins. */ var arrow: Arrow = null var inputContinue: Input static var instance : Play init { instance = this } override fun begin() { super.begin() inputContinue = findInput( "continue" ) var launcherCount = 0 for ( launch in mainView.stage.findRolesByClass( Launcher ) ) { if (launcher == null ) { launcher = launch } launcherCount++ launch.number = launcherCount launchers.add(launch) } arrow = mainView.stage.findRoleByClass(Arrow) startTime = Game.instance.seconds if (launcher != null) { ensureVisible( launcher.actor ) } } override fun tick() { super.tick() // When paused, the Pause Role won't animate without this. if (Game.instance.paused) { glassView.stage.findRoleByClass( Pause ).tick() } } override fun onKey( event : KeyEvent ) { if (inputContinue.matches(event) == true) { if (sceneComplete) { nextScene() } else if (lost) { startScene( Game.instance.sceneName ) } return } super.onKey( event ) } /** * When the left mouse button is pressed, ask the current Launcher to create a Doll * (unless the scene is complete, in which case, go to the next scene). * When the middle or right button is pressed and dragged, pan the scene. */ override fun onMouseButton(event: MouseEvent) { if (event.state == ButtonState.PRESSED) { if (event.button == 0) { if (arrow != null && !arrow.hidden) { if (!started) { val countdown = glassView.stage.findRoleByClass(Countdown) if (countdown != null) { countdown.go() } started = true } launcher.launch(arrow.aimActor.position) event.consume() return } } } super.onMouseButton( event ) } fun objectiveComplete() { objectives -- if (!lost && objectives <= 0) { objectivesComplete() } } fun objectivesComplete() { sceneComplete = true for ( role in glassView.stage.findRolesByClass( SceneComplete ) ) {role.go() } for ( role in glassView.stage.findRolesByClass( Countdown ) ) { role.stop() } DollsHouseProducer.sceneCompleted( Game.instance.sceneName, Game.instance.seconds - startTime ) } /** * Called from Countdown, when the countdown reaches zero. */ fun timeIsUp() { if (!sceneComplete) { lost = true for( role in glassView.stage.findRolesByClass( TimeIsUp ) ) { role.go() } for( role in glassView.stage.findRolesByClass( YouLose ) ) { role.go() } } } /** * Called from Fragile when it is knocked over, also when a Doll is zapped by Plasma */ override fun knockedFragile() { if (!lost && !sceneComplete) { lost = true for( role in glassView.stage.findRolesByClass( YouLose ) ) { role.go() } } } fun nextScene() { Game.instance.startScene(menuName) } override fun onDollHit( doll : Doll, hard : bool ) { doll.actor.event(if (hard) "hitHard" else "hit") } override fun onDollZapped( doll : Doll ) { knockedFragile() } }