Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Help getting TheaterJS working in SugarCube 2

So in my continued quest to investigate different typing effect options, I've stumbled onto TheaterJS.

I've been trying to get this simple example to work in Twine 1.4 with SugarCube 2, but I've having some issues.

I thought it would be as simple as pasting the theater.min.js code into my script tagged passage, then putting the rest of the code in my start passage like so:
<div id="vader"></div>
<div id="luke"></div>

<<script>>
  var theater = theaterJS()

  theater
    .on('type:start, erase:start', function () {
      // add a class to actor's dom element when he starts typing/erasing
      var actor = theater.getCurrentActor()
      actor.$element.classList.add('is-typing')
    })
    .on('type:end, erase:end', function () {
      // and then remove it when he's done
      var actor = theater.getCurrentActor()
      actor.$element.classList.remove('is-typing')
    })

  theater
    .addActor('vader')
    .addActor('luke')

  theater
    .addScene('vader:Luke...', 400)
    .addScene('luke:What?', 400)
    .addScene('vader:I am', 200, '.', 200, '.', 200, '. ')
    .addScene('Your father!')
    .addScene(theater.replay)
<</script>>

But even without anything but theater.min.js in my script tagged passage, I'm getting a launch error of "cannot set property theaterJS of null" which I guess has to do with the start of theater.min.js:
! function(e, t) {
    "object" == typeof exports && "object" == typeof module ? module.exports = t() : "function" == typeof define && define.amd ? define([], t) : "object" == typeof exports ? exports.theaterJS = t() : e.theaterJS = t()
}

Comments

  • Wrapping the TheaterJS code within the following should clear up the exception you're running into:
    (function () {
    
    
    	/* TheaterJS code here. */
    
    
    }).call(window);
    


    You will likely also have an issue with what you're attempting to do with it. You're having it look for elements which, at the time, are not yet in the page. Worse, from the API docs, I do not believe they offer a way to provide a context, allowing you to use the render buffer—meaning, the elements have to be attached to the DOM for TheaterJS to be able to work with them.

    Ultimately, you're probably going to have to wrap each passage's theater code within something like the following, so that it gets executed after the elements have been added to the page:
    <<script>>
    postdisplay['sceneSetup'] = function (taskName) {
    
    
    	/* A passage's TheaterJS code here. */
    
    
    	// This must be a single-use task, so remove it.
    	delete postdisplay[taskName];
    };
    <</script>>
    
    Full example: (based on yours above)
    <div id="vader"></div>
    <div id="luke"></div>
    
    <<script>>
    postdisplay['sceneSetup'] = function (taskName) {
    
    
    	var theater = theaterJS();
    	theater
    		.on('type:start, erase:start', function () {
    			// add a class to actor's dom element when he starts typing/erasing
    			var actor = theater.getCurrentActor();
    			actor.$element.classList.add('is-typing');
    		})
    		.on('type:end, erase:end', function () {
    			// and then remove it when he's done
    			var actor = theater.getCurrentActor();
    			actor.$element.classList.remove('is-typing');
    		});
    	theater
    		.addActor('vader')
    		.addActor('luke');
    	theater
    		.addScene('vader:Luke...', 400)
    		.addScene('luke:What?', 400)
    		.addScene('vader:I am', 200, '.', 200, '.', 200, '. ')
    		.addScene('Your father!')
    		.addScene(theater.replay);
    
    
    	// This must be a single-use task, so remove it.
    	delete postdisplay[taskName];
    };
    <</script>>
    
  • And... magic! Thanks a lot!
Sign In or Register to comment.