[Twine 2][Sugarcube 2.21.0] Typewriter effect with an optional skip

0 votes
asked Aug 9 by piffposh (160 points)

Hi all! Posting on forums is usually my last resort, but I'm totally stumped here.

I'm working on a game where there's a typewriter effect on every single page. That's the kind of look that I really wanted. However, my test players have reported that it's annoying to have to sit through the animation every time. I'd like a way to skip to the end of the typewriter animation by pressing a button on the keyboard, but only after the page has already been visited once. Currently, I'm using TME's modified version of this code from this forum post:

(function(){postrender.typewriter=function(b){if(this.tags){var r=/\bt8n-typewriter-(\d+)(?:-(\d+))?\b/g;
var t=r.exec(this.tags.toString());if(t){typeout(b,+t[1],+t[2]);}}return b;};var typeout=function(c,t,d){
var Furl=function(current){this.n=current;this.out=false;this.data=current.nodeValue;current.nodeValue="";
this.kids=[];var cn=current.childNodes;if(current.style && current.style.display==="none"){return;}while(cn.length>0)
{var f=new Furl(cn[0]);current.removeChild(cn[0]);f.out=true;this.kids.push(f);}};var nodes=new Furl(c);
var unfurl=function(furled,o){var n=furled.n;if(furled.out){o.appendChild(n);furled.out=false;}if(furled.data){
n.nodeValue+=furled.data[0];furled.data=furled.data.slice(1);return true;}for(var j=0;j<furled.kids.length;j++)
{var ret=unfurl(furled.kids[j],n);if(ret){return true;}}return false;};var title=state.active.title;if(d)
{setTimeout(function(){var intr=setInterval(function(){if(state.active.title!==title||!unfurl(nodes,null)){
clearInterval(intr);}},t);},d);}else{var intr=setInterval(function(){if(state.active.title!==title||!unfurl(nodes,null))
{clearInterval(intr);}},t);}};})();

If needed, I can post a version of this code that I attempted to clean up a bit, to make it more readable. I chose to use this over typed.js due to the latter's issues with links and macros. If there's another typewriter effect out there with a "skip" feature built-in, or something, I would greatly appreciate that too.

Thank you for your time.

1 Answer

+1 vote
answered Aug 9 by TheMadExile (50,290 points)
selected Aug 9 by piffposh
 
Best answer

The following version of the module will finish the typing if the spacebar is pressed while not interacting with the UI.  It will also, as requested, only allow short circuiting on passages which have been visited previously.

In case someone wants it without the visited requirement, try the t8n-typewriter module for SugarCube v2 Gist.

JavaScript:

/*! t8n-typewriter module for SugarCube v2 */
!function(){"use strict";function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor))throw new TypeError("Cannot call a class as a function")}var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||!1,descriptor.configurable=!0,"value"in descriptor&&(descriptor.writable=!0),Object.defineProperty(target,descriptor.key,descriptor)}}return function(Constructor,protoProps,staticProps){return protoProps&&defineProperties(Constructor.prototype,protoProps),staticProps&&defineProperties(Constructor,staticProps),Constructor}}(),Furl=function(){function Furl(current,append){if(_classCallCheck(this,Furl),Object.defineProperties(this,{node:{value:current},childNodes:{value:[]},value:{writable:!0,value:""},append:{writable:!0,value:!!append},abortTyping:{writable:!0,value:!1}}),this.node.nodeValue&&(this.value=this.node.nodeValue,this.node.nodeValue=""),!this.node.style||"none"!==this.node.style.display)for(var childNodes=this.node.childNodes;childNodes.length>0;)this.childNodes.push(new Furl(childNodes[0],!0)),this.node.removeChild(childNodes[0])}return _createClass(Furl,[{key:"finish",value:function(){for(this.abortTyping=!0;this.unfurl(););}},{key:"unfurl",value:function(parent){if(this.append&&(parent&&parent.appendChild(this.node),this.append=!1),this.value)return this.node.nodeValue+=this.value[0],this.value=this.value.slice(1),!0;for(var current=this.node,i=0,len=this.childNodes.length;i<len;++i)if(this.childNodes[i].unfurl(current))return!0;return!1}}],[{key:"typeout",value:function(content,typeDelay,startDelay){function typer(){if(!furled.abortTyping)var current=passage(),typerId=setInterval(function(){!furled.abortTyping&&passage()===current&&furled.unfurl()||clearInterval(typerId)},typeDelay)}var furled=new Furl(content);return startDelay?setTimeout(typer,startDelay):typer(),furled}}]),Furl}(),tagRe=/^t8n-typewriter-(\d+)(?:-(\d+))?$/;postrender["t8n-typewriter-handler"]=function(content){$(document).off("keypress.t8n-typewriter");for(var current=this.title,tags=this.tags,i=0;i<tags.length;++i){var match=tagRe.exec(tags[i]);if(null!==match){if("break"===function(){var furled=Furl.typeout(content,Number(match[1]),Number(match[2]));return $(document).on("keypress.t8n-typewriter",function(ev){32!==ev.which||ev.target!==document.body&&ev.target!==document.documentElement||!State.passages.slice(0,-1).some(function(pn){return pn===current})||(ev.preventDefault(),$(document).off("keypress.t8n-typewriter"),furled.finish())}),"break"}())break}}}}();

 

commented Aug 9 by piffposh (160 points)
Thank you so much!! You are a life-saver!
Welcome to Twine Q&A, where you can ask questions and receive answers from other members of the community.

You can also find hints and information on Twine on the official wiki and the old forums archive.

See a spam question? Flag it instead of downvoting. A question flagged enough times will automatically be hidden while moderators review it.
...