Update: Twine 1.4 now has an easier method of using Tag CSS, so this script code is no longer necessary.
Obsolete script removed: use Twine 1.4
CSS Syntax
The selector syntax for passages with specific tags is [data-tags~=
tagname]
.
So, if you tag a bunch of passages with "dream", you can then apply specific CSS to just those passages like this:
[data-tags~=dream] { color: aqua; text-shadow: aqua 0 0 3px; }The preceding code will affect both the passage div and the body element. To select those elements separately, use syntax like this:
body[data-tags~=blood] { background-color:red; color: black; } .passage[data-tags~=blood] { border: 5px solid white; font-size: 110%; width: 30em; }Some variations on the selector syntax exists that you might find useful:
[data-tags*=swamp]
for a passage whose tags contain "swamp" (such as "grayswamp" or "swampfort").:not([data-tags~=gold])
for a passage which does not have the tag "gold".And, of course, you can select elements of a matching passage <div> by combining selectors with ".body", ".body .internalLink" and such:
.passage[data-tags~=cave] .body .internalLink {
color: gold;
}
Caveat: all of this won't work for passage text displayed with the << display >> macro unless you use something like addtag.
Selector recap:
* To apply CSS to the body element, use "body[data-tags~=tag]
", "body:not([data-tags~=tag])
" etc.
* To apply CSS to the passage-class element, use ".passage[data-tags~=tag]
", ".passage:not([data-tags~=tag])
" etc.
* To apply CSS to both, use "[data-tags~=tag]
" etc.
If you like this code, consider using these macros that let you control tags inside the game.
*This is really just a workaround until browsers support CSS selector subjects. Ideally you could just do !body .passage[data-tags:]
, but alas, not this year.
Version history:
Update: this converter is now built into Twine 1.4 (in the "Import Compiled HTML file" menu item), so this page is no longer necessary.
Someone on my Twitter feed reported that they'd lost the source code of a Twine game of theirs, and wanted to know if they could convert the HTML back to a usable format. So, I decided to quickly knock up a utility that could do that. Here it is - it extracts the passages from a HTML twine game and converts them to Twee source code, which Twine can import using the "Import Source Code" menu option. I hope it works for you.
This is version 1 of the hacked copy of the "Jonah" story format that I used in Capri Toot, which I have unimpressively called "Journal". (I'm unaware of what naming pattern the prepackaged Twine formats use, so I cannot follow it.)
Just move the Journal folder inside this zip file into the "targets" folder of your Twine installation to add this to the Story Format menu.
You can also see this example program (modified from 'Town' by Anna Anthropy)
An explanation of some of the CSS and JS is as follows:
#passages {
white-space:nowrap;
width:auto;
height:auto;
overflow-x: scroll;
overflow-y: hidden;
}
white-space:nowrap
keeps the passage divs from wrapping when they reach the edge of the #passages div. overflow-x: scroll
permits the #passages div to extend to accommodate the addition of passage divs, using a scrollbar.
.passage {
display:inline-block;
vertical-align: top;
white-space:normal;
background-color: #eee;
font-size: 1.3em;
line-height: 175%;
margin: 1em;
width: 33%;
min-width: 35em;
height: 56em;
padding: 2em;
border-width: 1px;
border-style: solid;
border-color: #333;
box-shadow: 0.2em 0.2em 0.2em;
}
display: inline-block
ensures that the passage divs are arranged horizontally. vertical-align: top
ensures that their tops are aligned if they are different sizes.
Do note that Journal by default sets the height of passages to 56em, and the width of passages to 33% of the #passages div. This produces the satisfying look of consistent rectangular pages, but of course limits the text you can put in a passage. Feel free to add CSS to extend the height or the width if you wish.
function scrollDivTo(Q, E) {
var D = Q.scrollLeft;
var G = J(E) - Q.offsetLeft;
var C = Math.abs(D - G);
var B = 0;
var I = (D > G) ? -1 : 1;
var F = window.setInterval(H, 25);
function H() {
B += 0.05;
Q.scrollLeft = D + I * (C * Math.easeInOut(B));
if(B >= 1) {
window.clearInterval(F)
}
}
function J(N) {
var O = A(N);
var P = O + N.offsetWidth + N.offsetRight;
var K = Q.scrollLeft;
var L = Q.clientWidth;
var M = K + L;
if(O < K) {
return O - N.marginLeft
}
else {
if(P > M) {
if(N.offsetWidth < L) {
return(O + N.offsetRight - (L - N.offsetWidth))
}
else {
return O
}
}
else {
return O
}
}
}
function A(K) {
var L = 0;
while(K.offsetParent) {
L += K.offsetLeft;
K = K.offsetParent
}
return L
}
};
This is a horizontal replacement for the scrollWindowTo() function in Jonah. Although it takes two arguments, the additional first argument is simply the #passages div. You could probably rewrite it as a drop-in replacement for scrollWindowTo() by just removing the first argument (and adding " var Q = $('passages'); " to the other var definitions) and changing its name to "scrollWindowTo". However, since this was designed to encapsulate scrolling a div, the change of name was necessary in this case.
Update: Twine 1.4 has a reworked transition engine, so this script code is no longer applicable.
If you want more types of transitions, see also this code for an alternative transition engine for Sugarcane (more versatile but not compatible with this script).
Previously I was experimenting with alternatives to Twine's default fade-in animation. Now, I've figured out how to make such alterations with a single block of JavaScript insertion that you can drop into your story.
Here's a block of code that, when inserted into a Sugarcane formatted Twine game, changes the passage transition to a dissolve, where the previous passage fades out at the same time as the next passage fades in.
[Note: This will not work with the one-page Jonah format.]
addStyle(".passage { position:absolute !important; } ");History.prototype.display=function(d,b,a){var c=tale.get(d);this.history.unshift({passage:c,variables:clone(this.history[0].variables)});this.history[0].hash=this.save();var e=c.render();if(a!="offscreen"){var f=document.getElementById("passages").firstChild;if(f){fade(f,{fade:"out",onComplete:function(){document.getElementById("passages").removeChild(document.getElementById("passages").firstChild);}});}document.getElementById("passages").appendChild(e);if(a!="quietly"){fade(e,{fade:"in"});}}if((a=="quietly")||(a=="offscreen")){e.style.visibility="visible";}if(a!="offscreen"){document.title=tale.title;this.hash=this.save();document.title+=": "+c.title;window.location.hash=this.hash;window.scroll(0,0);}return e;};History.prototype.watchHash=function(){if(window.location.hash!=this.hash){if((window.location.hash!="")&&(window.location.hash!="#")){this.history=[{passage:null,variables:{}}];document.getElementById("passages").style.visibility="hidden";if(!this.restore()){alert("The passage you had previously visited could not be found.");}document.getElementById("passages").style.visibility="visible";}else{window.location.reload();}this.hash=window.location.hash;}};
Just put this in a vacant passage tagged with "script".
Note that in order to do this, it will set the passage divs to use the style "position: absolute", so keep that in mind if you're using CSS that requires a different positioning.
What this actually does is replace the Twine engine's History.prototype.display function with an alternative version that sets the previous passage to fade out and then be removed, instead of just immediately removing it. Since the passage divs are set to absolute positioning, they're drawn one top of the other while they simultaneously exist, instead of being vertically arranged.
This also replaces History.prototype.watchHash, which controls the Back button behaviour. Again, this is simply to keep the previous passage(s) from being removed immediately, and instead letting History.prototype.display do it. (If you're using a hack that modifies History.prototype.watchHash, you will probably have to do some tweaking to this or the other to get this to work.)
See attachment for an example (applied to "Town" by Anna Anthropy).)||(a==
This is the inline CSS I used in my Twine game, Capri Toot. Of course, I had to write some other CSS for my special horizontal hacked variant of Jonah, but this below is where almost all of the visual style of Capri Toot comes from.
----------------
#passages {
background-color: #000;
overflow:hidden;
}
----------------
"overflow: hidden" hides the horizontal scrollbar in the passages DIV, which is useful because backtracking isn't possible in Capri Toot.
----------------
@keyframes borderkeyframe
{
0% {box-shadow: 0 0 2.5em 2.5em }
50% {box-shadow: 0 0 0.5em 0.5em }
100% {box-shadow: 0 0 2.5em 2.5em }
}
@-moz-keyframes borderkeyframe
{
0% {box-shadow: 0 0 2.5em 2.5em }
50% {box-shadow: 0 0 0.5em 0.5em }
100% {box-shadow: 0 0 2.5em 2.5em }
}
@-webkit-keyframes borderkeyframe
{
0% {box-shadow: 0 0 2.5em 2.5em }
50% {box-shadow: 0 0 0.5em 0.5em }
100% {box-shadow: 0 0 2.5em 2.5em }
}
@-o-keyframes borderkeyframe
{
0% {box-shadow: 0 0 2.5em 2.5em }
50% {box-shadow: 0 0 0.5em 0.5em }
100% {box-shadow: 0 0 2.5em 2.5em }
}
----------------
CSS Keyframes: These define the animated pulsing glow behind the passages. There are four definitions because each browser has its own syntax (except IE, which doesn't support this). These define some timeline events which the browser tries to smoothly interpolate between. When the animation is 50% complete, the box-shadow is retracted to a size of 0.5em. When the animation starts and finishes, it's at its full size of 2.5em. Defining both a 0% and 100% point ensures that it loops smoothly, if an element uses it as a looping animation.
----------------
.passage:nth-child(8n+7) {
text-shadow: 0 0 0.6em hsl(0,100%,60%);
color: hsl(0,100%,50%);
background-color: hsl(0,100%,5%);
}
.passage:nth-child(8n) {
text-shadow: 0 0 0.6em hsl(45,100%,60%);
color: hsl(45,100%,50%);
background-color: hsl(45,100%,5%);
}
.passage:nth-child(8n+1) {
text-shadow: 0 0 0.6em hsl(90,100%,60%);
color: hsl(90,100%,50%);
background-color: hsl(90,100%,5%);
}
.passage:nth-child(8n+2) {
text-shadow: 0 0 0.6em hsl(135,100%,60%);
color: hsl(135,100%,50%);
background-color: hsl(135,100%,5%);
}
.passage:nth-child(8n+3) {
text-shadow: 0 0 0.6em hsl(180,100%,60%);
color: hsl(180,100%,50%);
background-color: hsl(180,100%,5%);
}
.passage:nth-child(8n+4) {
text-shadow: 0 0 0.6em hsl(225,100%,60%);
color: hsl(225,100%,50%);
background-color: hsl(225,100%,5%);
}
.passage:nth-child(8n+5) {
text-shadow: 0 0 0.6em hsl(270,100%,60%);
color: hsl(270,100%,50%);
background-color: hsl(270,100%,5%);
}
.passage:nth-child(8n+6) {
text-shadow: 0 0 0.6em hsl(315,100%,60%);
color: hsl(315,100%,50%);
background-color: hsl(315,100%,5%);
}
----------------
These are used to colour each of the zone tiers differently. When you click on a link in Jonah (as compared to Sugarcane) a new passage div is added to the end of the #passages div as a new child node. The nth-child() selector allows you to apply specific styles to an element depending on which child it is. nth-child(8n)
means that every eighth child should have this style (starting with the first). nth-child(8n+1)
means that every eighth child, plus 1 position over, gets this style. So, with these eight definitions, a looping cycle of eight colours is produced. This is kind of overkill for Capri Toot since you can only ever go 8 passages deep, but w/e.
Also, a note: if you don't specify a colour for box-shadow, then it falls back to using the text colour. Hence, we use a colour style here to change the animated shadow's colour without having to set up eight different keyframes (x 4 browsers).
----------------
.passage {
margin-left: 33%;
margin-right: 33%;
min-width: 33%;
margin-top: 3em;
margin-bottom: 3em;
border-radius: 8em;
border-color: white;
border-width: 2px;
box-shadow: 0 0 2.5em 2.5em;
animation: borderkeyframe 3s infinite;
-moz-animation: borderkeyframe 3s infinite;
-webkit-animation: borderkeyframe 3s infinite;
-o-animation: borderkeyframe 3s infinite;
}
----------------
The margin and min-width definitions mean that only one passage is ever visible at one time. The border-radius definition produces the delightful rounded rectangle edges. The animation definitions bind the aforementioned keyframe to this element, give it a speed (3 seconds) and tell it how many times to loop (infinite). Again, 4 definitions because each browser (except IE) has different syntax.
----------------
.passage .body .internalLink {
font-style: italic;
font-size: 1.5em;
color: white;
text-shadow: 0 0 0.6em silver;
}
.passage .body {
color: white;
text-shadow: inherit;
}
.passage .title {
margin-top: 0.2em;
font-style: italic;
font-size: 2em;
color: white;
text-align: center;
}
----------------
Fairly straightforward. Setting .body's text colour to white overrides the previous colour definition for .passage (which as I mentioned is being used for the box shadow).
----------------
.toolbar {
display:none;
}
----------------
This single-handedly hides the Jonah "rewind / bookmark" prompts for each passage. Quite convenient.
Update: embedded images in Twine 1.4 do not need to be preloaded, so this is not necessary if you are using those.
If you use a lot of images in your Twine game, it would be very good of you if you preloaded them at the start of the game - having to wait for images to load during a story, even momentarily, can be distracting.
Now you could bother to convert them all to inline Base64, but there's other, less intrusive ways. You could, rather, put every image in your story in invisible img tags in the Start passage:
<html> <img src=" [url of an image ] " style="display:none;" > ... </html>
(function(){var r="";var s=Wikifier.formatters;for(var j=0;j<s.length;j++){if(s[j].name=="image"){r=s[j].lookahead; break;}}var div=document.getElementById("storeArea").firstChild.nextSibling;while(div){if(r){k(new RegExp(r,"mg"),4); }var b=String.fromCharCode(92);var u=b+"s*['"+'"]?([^"'+"']+(jpe?g|a?png|gif|bmp))['"+'"]?'+b+"s*"; k(new RegExp("url"+b+"("+u+b+")","mig"),1);k(new RegExp("src"+b+"s*="+u,"mig"),1); div=div.nextSibling;}function k(c,e){do{var d=c.exec(div.innerHTML);if(d){var i=new Image(); i.src=d[e];}}while(d);}}());
That's all.
Update 17/2/13: This now works with images in HTML <img> tags as well.
Update 12/2/13: This will now also preload images used in CSS url( ... )
values. It will search for such values in every passage, include the stylesheet passages, script passages, and inline JavaScript.
Version history:
Playing through some of these games has given me a spirit for klik n play and I really like these releases. Some people aren't fortunate to have the windows 16 bit working and I like to pass games along to my ug for them to enjoy to get a real sense of appreciation for a good short game and the beautiful klip art many of these entries possess. The tracks are sweet, sometimes they need a little nudge with the right soundfont, and they carry the game to its completion.
Alright, let's try that again.
jump with shift, bananas are not allowed
Talk about haunting, this one just plays just right, no surprise breaking, just enjoy. Lovely everything about it, and don't touch the bananas if you can help it obviously.
So yeah, play away, click on the image to link to the game, and if you like them, leave a comment.. user comments are what keeps people less frownie, pledge your support like I did when I took the time to make this post and give them all flash objects so anyone of any o/s can enjoy so long as they can run flash objects in the first place. on the top left of each game there's a link that says NODE (node name) click that and you're back to where you... well, where I think you want to be..
Also there are PLENTY of flash objects that are already out there, they're live out there, on newgrounds or wherever. More on that on another setting and time.
_
Hey everyone... I made a silly remake of my old KotM game Cactus Block over the course of today and yesterday. A few people here liked the original game, so I figured I should post it...
You can download it here. Move and jump with WASD and left click to create a block or cactus.
I was supposed to make a feature but then like I thought this was my own personal rhymebook and I think I was going somewhere. not sure.. pressed ctrl a then del and included it in a text file instead.
PIRATE CARD OFFICIAL ENTRY NO. Are you ready for intense action?
There will be 16 playing cards, will be the creator who will?
Play to get! Enjoy the world! Make game for SMEDX Rainbow console of plays!