It looks like you're new here. If you want to get involved, click one of these buttons!
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); }
@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 }
Comments
Beyond being terrible, the reason it doesn't work in SugarCube is that SugarCube hasn't used the fade() function internally in, literally, ages—even v1 doesn't use it.
The following macro requires SugarCube v2.5.0 or later. If you're using an older release of v2, a simple upgrade should get you on track.
Script: (goes in Story JavaScript) Styles: (goes in Story Stylesheet)
I had no idea it was that old either, although come to think of it, I was using Sugarcane back when I used it...
Thank you so much for making a clean version of it! However, I can't seem to get it to work.
Thanks again!
I have attached an Archive file containing a demo story, use the Import From File option added it to your Story List.
The updated version of the <<shake>> macro, including documentation, is available on SugarCube 2's site (under: Downloads > Add-ons).
So I just figured out why it wasn't working: debug mode. In debug mode, the only thing that shakes is the actual macro <<shake>> if 'debug view' is clicked. Not sure why? But if I actually "play" the story, then it works as intended. But the "Test Story From Here" little bug icon does not. Weird.
I'm just getting back into Twine after a 3-year hiatus, and boy has a lot changed! While I was a wizard back then, I feel I'm back to being a newbie in many ways.
Last thing, while I still have your godly Twine-weaving attention: Is there a way to apply <<shake>> to a single element, ie. an internal link or word/sentence/picture/etc, instead of the whole passage? Or would that require another batch of fancy JS?
I couldn't get this to download, or open in another page. I suspect I'm doing something dumb. I tried downloading/opening it with IE because sometimes Firefox gives me grief, but that didn't work either. Thanks anyway, though!
Thanks for doing that. One major problem I saw during Twine 1 days was how fractured the documentation and availability of macros were. I know it's still early days in some ways, but I really appreciate having those macros all in one place. Especially now that there are so many branches of Twine forking all over.
Is there a place on the forum or main website with a collection of stylesheets? I have an old stockpile of a bunch of custom stylesheets from before.
That said, SugarCube's Test Mode is just what it says on the tin. It's a testing mode meant for debugging problems. It can, and probably will, cause layout issues—the problem here. It is really not meant for normal play-testing. Use it when something isn't working as you think it should, to get a visual representation of what's going on.
The shaking animation comes completely from the CSS, so all that would be needed to set any element shaking, normally, is to apply the "shake" class to it. The only real issue is timing. If you only want it to shake for a finite period, then you'll need to remove the class after your duration has expired.
While I'm fixing the base <<shake>> macro, I'll look into adding an additional macro to make that easy.
That said, it's possible to do so right now with a little kitbashing of some of SugarCube's core macros (see: DOM (Classes) macros, <<timed>> macro). For example: I used HMTL markup there, but SugarCube's wiki-style markup could be used instead—it's just a matter of preference.
If using Windows then right mouse button click on the download icon and select then "Save Link As.." (or words to that effect) menu item. Use the equivalent option if using a different operating system.
As the related comment stated, once you have downloaded that Archive HTML file you use the Import From File option to add the story contained within it to your Story List.
The new package, including documentation, is available on SugarCube 2's site (under: Downloads > Add-ons).
I should probably replace this with a generic animation package at some point.