public
Last active

This Twine macro lets you make the screen shake! Tested in Chrome and Firefox. Should work in Opera and IE 10+. Uses CSS3 animations. #TwineHacks

  • Download Gist
README.md
Markdown

This Twine macro lets you make the screen shake! Tested in Chrome and Firefox. Should work in Opera and IE 10+. Uses CSS3 animations, taken from this CSS Reset tutorial.

See a demo in action here.

How to set it up

IMPORTANT NOTE: Due to a bug in Twine 1.3.5, macros do not work on the Start passage. If you want to use this code (or any other macro) on your starting passage, you should put your start passage in a new passage called "ActualStart" and then put the following code in the Start passage:

<<display ActualStart>>

This will warp you directly to ActualStart when your game starts up.

  • Paste the contents of the stylesheet.css file below into a new passage. Call the passage whatever you want, and add the tag "stylesheet" to it.
  • Paste the contents of the script.js file below into a new passage. Call the passage whatever you want, and add the tag "script" to it.
  • Paste the contents of the twineCode file below into your 'ActualStart' passage described above. This will make the screen shake for 5 seconds!

How to use it

Put the following in any passage where you want the screen to shake:

<<screenShake [milliseconds]>>

This tells the screen to shake for a certain number of milliseconds. For example, if you want the screen to shake for 1.5 seconds, put this in your passage:

<<screenShake 1500>>

1000 milliseconds = 1 second, so 1500 milliseconds = 1.5 seconds.

If you set the milliseconds to 0, the screen will shake forever (until the reader moves to a new page)!

script.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
function screenShake(time) {
console.log(document);
var el = document.getElementsByClassName('content');
baz = el;
console.log(baz[0]);
el[0].className = el[0].className + ' shake';
if (time > 0) {
setTimeout(function () {
el[0].className = 'content';
}, time);
}
};
 
// the screenShake macro. Adapted from Emmanuel Turner's article on creating Twine macros. http://eturnerx.blogspot.com/2012/12/how-to-create-custom-macros-in-twine.html
try {
version.extensions['screenShakeMacro'] = {
major: 1,
minor: 0,
revision: 0
};
macros['screenShake'] = {
handler: function (place, macroName, params, parser) {
var time = parseInt(params[0]);
if (typeof time !== 'number') {
time = 1000;
}
// we're overriding the fade function. It behaves as usual except it runs screenShake() if time >= 0.
fade = function (el, options) {
var current;
var proxy = el.cloneNode(true);
var direction = (options.fade == 'in') ? 1 : -1;
 
el.parentNode.replaceChild(proxy, el);
 
if (options.fade == 'in') {
current = 0;
proxy.style.visibility = 'visible';
} else current = 1;
 
setOpacity(proxy, current);
var interval = window.setInterval(tick, 25);
 
function tick() {
current += 0.05 * direction;
 
setOpacity(proxy, Math.easeInOut(current));
 
if (((direction == 1) && (current >= 1)) || ((direction == -1) && (current <= 0))) {
console.log('swapping fader proxy out');
el.style.visibility = (options.fade == 'in') ? 'visible' : 'hidden';
proxy.parentNode.replaceChild(el, proxy);
delete proxy;
window.clearInterval(interval);
 
if (options.onComplete) options.onComplete();
 
if (time >= 0) {
screenShake(time);
time = -1;
}
 
}
};
 
function setOpacity(el, opacity) {
var percent = Math.floor(opacity * 100);
 
// IE
el.style.zoom = 1;
el.style.filter = 'alpha(opacity=' + percent + ')';
 
// CSS 3
el.style.opacity = opacity;
};
};
},
init: function () {},
};
} catch (e) {
throwError(place, "screenShake Setup Error: " + e.message);
}
stylesheet.css
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
@keyframes shakeit {
0% { transform: translate(2px, 1px) rotate(0deg); }
10% { transform: translate(-1px, -2px) rotate(-1deg); }
20% { transform: translate(-3px, 0px) rotate(1deg); }
30% { transform: translate(0px, 2px) rotate(0deg); }
40% { transform: translate(1px, -1px) rotate(1deg); }
50% { transform: translate(-1px, 2px) rotate(-1deg); }
60% { transform: translate(-3px, 1px) rotate(0deg); }
70% { transform: translate(2px, 1px) rotate(-1deg); }
80% { transform: translate(-1px, -1px) rotate(1deg); }
90% { transform: translate(2px, 2px) rotate(0deg); }
100% { transform: translate(1px, -2px) rotate(-1deg); }
}
 
@-o-keyframes shakeit {
0% { -o-transform: translate(2px, 1px) rotate(0deg); }
10% { -o-transform: translate(-1px, -2px) rotate(-1deg); }
20% { -o-transform: translate(-3px, 0px) rotate(1deg); }
30% { -o-transform: translate(0px, 2px) rotate(0deg); }
40% { -o-transform: translate(1px, -1px) rotate(1deg); }
50% { -o-transform: translate(-1px, 2px) rotate(-1deg); }
60% { -o-transform: translate(-3px, 1px) rotate(0deg); }
70% { -o-transform: translate(2px, 1px) rotate(-1deg); }
80% { -o-transform: translate(-1px, -1px) rotate(1deg); }
90% { -o-transform: translate(2px, 2px) rotate(0deg); }
100% { -o-transform: translate(1px, -2px) rotate(-1deg); }
}
 
@-webkit-keyframes shakeit {
0% { -webkit-transform: translate(2px, 1px) rotate(0deg); }
10% { -webkit-transform: translate(-1px, -2px) rotate(-1deg); }
20% { -webkit-transform: translate(-3px, 0px) rotate(1deg); }
30% { -webkit-transform: translate(0px, 2px) rotate(0deg); }
40% { -webkit-transform: translate(1px, -1px) rotate(1deg); }
50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); }
60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); }
70% { -webkit-transform: translate(2px, 1px) rotate(-1deg); }
80% { -webkit-transform: translate(-1px, -1px) rotate(1deg); }
90% { -webkit-transform: translate(2px, 2px) rotate(0deg); }
100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); }
}
 
@-moz-keyframes shakeit {
0% { -moz-transform: translate(2px, 1px) rotate(0deg); }
10% { -moz-transform: translate(-1px, -2px) rotate(-1deg); }
20% { -moz-transform: translate(-3px, 0px) rotate(1deg); }
30% { -moz-transform: translate(0px, 2px) rotate(0deg); }
40% { -moz-transform: translate(1px, -1px) rotate(1deg); }
50% { -moz-transform: translate(-1px, 2px) rotate(-1deg); }
60% { -moz-transform: translate(-3px, 1px) rotate(0deg); }
70% { -moz-transform: translate(2px, 1px) rotate(-1deg); }
80% { -moz-transform: translate(-1px, -1px) rotate(1deg); }
90% { -moz-transform: translate(2px, 2px) rotate(0deg); }
100% { -moz-transform: translate(1px, -2px) rotate(-1deg); }
}
 
.shake {
-webkit-animation-name: shakeit;
-webkit-animation-duration: 0.8s;
-webkit-transform-origin:50% 50%;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
-moz-animation-name: shakeit;
-moz-animation-duration: 0.8s;
-moz-transform-origin:50% 50%;
-moz-animation-iteration-count: infinite;
-moz-animation-timing-function: linear;
-o-animation-name: shakeit;
-o-animation-duration: 0.8s;
-o-transform-origin:50% 50%;
-o-animation-iteration-count: infinite;
-o-animation-timing-function: linear;
animation-name: shakeit;
animation-duration: 0.8s;
transform-origin:50% 50%;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
.shake{
display:inline-block
}
twineCode
1 2 3
THIS PASSAGE IS SHAKING FOR TWO SECONDS, WHOAAAAA!!!!
 
<<shakeScreen 2000>>

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.