class Bell : ActionRole(), Draggable, Scalable { @Attribute( about="How much higher up is the ceiling?", isRelative=true ) val ceiling = Vector2() @Attribute( about="How much imact is needed to ring the bell" ) var requiredImpact = 50 var front: Actor var clanger: Actor /** * I call it a rope, but it's more like a bar. Used to connect the bell to the ceiling. */ var rope: Actor // Used to test when the clanger is hit hard enough. var oldClangerSpeed = Vector2(0, 0) var alreadyHit = false override fun scale( by : Vector2 ) { actor.scale *= by front.scale *= by clanger.scale *=by } override fun mass() = actor.body.mass + clanger.body.mass override fun createAction() : Action { // Front is a copy of the bell, without the "back" part. // The zOrders are : Bell, the clanger, and then the "front". front = actor.createChild("front") front.scaleXY = actor.scaleXY (front.role as Follower).following = actor // Create the "rope", which is more like a solid bar, which is just a visual to attach the bell to the ceiling. // It doesn't have any physics properties. rope = actor.createChild("rope") rope.scaleXY = actor.scaleXY rope.tiledAppearance.size.y = ceiling.y / actor.scaleXY TicklePinJoint(actor, rope, actor.position) clanger = actor.createChild("clanger") clanger.scaleXY = actor.scaleXY val joint = TicklePinJoint(actor, clanger, actor.position - Vector2(0.0, -20.0 * actor.scaleXY)) joint.collideConnected = true val hitTest = UntilAction( this:>isHit ) then EventAction( actor, "ring" ) return if (DollsHouseDirector.instance is Play) { Play.instance.objectives++ hitTest then ( Fade(actor.color, 1, 0, Eases.easeIn) and Fade(rope.color, 1, 0, Eases.easeIn) and Fade(front.color, 1, 0, Eases.easeIn) and Fade(clanger.color, 1, 0, Eases.easeIn) ) thenOnce Play.instance:>objectiveComplete then (Kill(actor) and Kill(rope) and Kill( clanger ) and Kill( front ) ) } else { (hitTest then Delay( 1 )).forever() } return hitTest } /** Return true when the bell has been rung, by testing the change in speed of the clanger. Note that the clanger does NOT interact with dolls, but it does interact with the bell, so large changes in speed indicates the clanger hit the bell. */ fun isHit(): bool { val newClangerSpeed = clanger.body.linearVelocity val impact = (newClangerSpeed - oldClangerSpeed).length() oldClangerSpeed.set(newClangerSpeed) return impact > requiredImpact } }