Development Diaries

Twine: apply CSS to passages with specific tags (Tag CSS)

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:

  1. 11/2/13 - Possibly fixed crash in situations where 'state' hadn't been initialised yet.
  2. 6/2/13 - Additional code to affect the <body> tag was added for both versions.
  3. 5/2/13 - Altered to use "data-tags" attribute rather than "tags".
  4. 4/2/13 - Split into two snippets for Twine 1.3.6 alpha and Twine stable versions.
  5. 26/1/13 - Altered to affect the Start passage.
  6. 25/1/13 - Initial.

Twine: HTML file to Twee source code converter

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.

HTML to Twee Converter

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.

Twine: horizontal hacked Jonah format, "Journal"

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.

Twine: Sugarcane passage transition: dissolve

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==

A breakdown of the CSS in my Twine game Capri Toot

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.

Twine: preloading images

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>

...but of course, that requires you to manually list every image yourself. Here is my recommendation: use this JavaScript that will do it automatically, when the story starts. Just put this in a passage tagged with "script".

(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:

  1. 17/2/13 - Now works for image files specified in HTML src="..." attributes.
  2. 13/2/13 - CSS preloading now only loads JPEG, JPG, PNG, APNG, GIF and BMP files (that is to say, not font files).
  3. 12/2/13 - Now preloads images specified by CSS URL values too.
  4. 19/1/13 - Initial.
+b+

A couple flash objects for you to reenjoy.

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.

DELIICOUS by nano:

This was probably the first game here I enjoyed. Actually it was glorious redemption but this game was in there as kind of a dvd extra, a minigame if you will, but it holds its own.. There's a brutal boss level but that's part of the charm. A powerful message is put in this one and really makes you feel an emotion not prehistorically felt.

Scramble the Eggs by mno

Yeah well I'd have to say this is one of my favorites on the whole site. It's so suave you don't know what to do with it. When first running it you don't know what to expect, but you just kind of jump in.. If you haven't played this one, now's your chance. Scramble 50 eggs and keep trying until you get it right. It's worth playing through this one, full of so many surprises in so little frames. You may want to click THE NODE FIRST so you have a sense of the documentation since I didn't really go so far as to put it in the html file of the flash objects, but he wanted you to know this and that you know.

A Man, a tree. by Zecks

you are out for a walk in the park...
but whats your goal?

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.

POLICEMN by oligophagy

This one's nice, very short.. just the name alone is cryptic, wants to draw you in.. and the klipart.. what beautiful use... yeah, this one's a keeper.

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.

_

Cactus Block 2013

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.

You guys gals others and whatnots happy new yer

cclemon.png

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.

Smedis2's picture

SMEDX RAINBOW FUN GAME COLLABORATIONAL

SMEDXRAINBOW.PNG

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!

Syndicate content
pensive-mosquitoes