Random posts

Techokami's picture

Kangaroo Dollars

kangaroo.png
Game File: 

As per a request, you must fight the kangaroos to get dollars! You can then use those dollars to upgrade your guns. Try to get a lot of dollars, and all the upgrades, before you get killed!

Made For: 
An event

Twine: Custom CSS passage transitions

I've modified my previous Sugarcane passage transition code to allow you to define your own transitions with CSS.

Update: the Javascript that was on this page is now installed in Twine 1.4.

What this does is remove the default JavaScript transition from Sugarcane, and cause the outgoing passage to gain a "transition-out" class, and the incoming passage to instantly gain and lose a "transition-in" class. This enables you to define new passage transitions by styling these 3 classes using CSS.

CSS Examples

In order for there to be a transition, you must specify the transition property for your passage elements. A very basic example is as follows:

.passage {
	transition: 0.25s linear;
	-webkit-transition: 0.25s linear;
}
The transition property causes elements to transition between styles when they gain and lose them, in a specific way. In this case, it's a quarter-second, purely linear transition. (Other options than "linear" are listed here.) The maximum duration time before the departing passage is removed is 1 second.

The current versions of Opera, Firefox and IE support the plain transition property, but you need to also include the -webkit variant in order to work in Chrome and Safari (you can also include -khtml-transition for Konqueror users, few though they may be).

Now that you've defined the transition itself, you can define the styles that the passages can transition from and to.

A very basic example:

.transition-in {
	position:absolute;
	opacity:0;
}
When a new passage arrives, its style will transition from the "transition-in" style to the normal passage style. In this case, it starts invisible ("opacity:0") and fades in to visibility. Note the "position:absolute" - both "transition-in" and "transition-out" should have either position:absolute or position:fixed if you want them to neatly appear above or below each other.
.transition-out {
	position:absolute;
	opacity:0;
}

Putting identical styles for "transition-out" means that departing passages will fade out of visibility as well. With all 3 of these CSS snippets, you've replicated the "dissolve" transition linked above.

A broad number of CSS attributes can be used with this technique. Experiment!

Combining with tag-based CSS

If you use my tag-based passage CSS code, you can tie transitions to passages tagged with a particular tag. For instance, to bind the "dissolve" transition to passages tagged with "t8n-dissolve":

body[data-tags~=t8n-dissolve] .transition-in {
	position:absolute;
	opacity:0;
}
body[data-tags~=t8n-dissolve] .passage {
	transition:1s;
	-webkit-transition: 1s;
}
body[data-tags~=t8n-dissolve] .transition-out {
	position:absolute;
	opacity:0;
}
I recommend prefixing all transition-based tags with something identical, like "t8n" (a numeronym of "transition"). This way, you can then define a default transition to be used only when no "t8n" tags are present:
body:not([data-tags*=t8n]) .transition-in {
	opacity:0;
	transform: translate(0,3rem);
	-webkit-transform: translate(0,3rem);
	position:absolute;
}
body:not([data-tags*=t8n]) .passage {
	transition: 2s;
	-webkit-transition: 2s;
}
body:not([data-tags*=t8n]) .transition-out {
	opacity:0;
	transform: translate(0,-3rem);
	-webkit-transform: translate(0,-3rem);
	position:absolute;
}

(Remember that [data-tags*=t8n] selects elements whose tags contain "t8n", and :not() selects elements that do not fulfill the requirement in the brackets.)

It's important that if you use multiple transitions, the default transition should be guarded using body:not([data-tags*=t8n]), so that its code doesn't interfere with the other transitions' code.

To see an example where the first four passages are tagged "t8n-dissolve" and the rest are not, see here.

Live examples
All examples are "The Sky in the Room" by Porpentine.

Fade in (the default transition)

.transition-in {
	opacity:0;
	position:absolute;
}
.passage:not(.transition-out) {
	transition: 1s;
	-webkit-transition: 1s;
}
.transition-out {
	opacity:0;
	position:absolute;
}

Specifying :not(.transition-out) means that the transition is applied only for the incoming passage - the departing one instantly gets opacity:0. Note that specifying passage.transition-in would not do anything, since it is by removing the transition-in class that the transition is initiated.

Dissolve

.transition-in {
	position:absolute;
	opacity:0;
}
.passage {
	transition: 1s;
	-webkit-transition: 1s;
}
.transition-out {
	position:absolute;
	opacity:0;
}

Retro 8-bit four-step fade in

.transition-in {
	opacity:0;
	position:absolute;
}
.passage:not(.transition-out) {
	transition: 0.8s steps(3);
	-webkit-transition: 0.8s steps(3);
}
.transition-out {
	opacity:0;
	position:absolute;
}

Fade out

.transition-in {
	opacity:0;
	position:absolute;
}
.passage:not(.transition-out) {
	transition: 0s 1s;
	-webkit-transition: 0s 1s;
}
.transition-out {
	transition: 1s;
	-webkit-transition: 1s;
	opacity:0;
	position:absolute;
}

Vertical wipe
Sadly, this currently only works if you give the passage div a fixed width and height.
If you use this, replace all instances of "1200px" and "800px" with dimensions appropriate for your story.

.transition-in {
	clip: rect(0px, 1200px, 0px, 0px) !important;
}
.passage {
	clip: rect(0px, 1200px, 800px, 0px);
	width: 1200px;
	height: 800px;
	position: absolute;
	transition: 1s linear;
	-webkit-transition: 1s linear;
}
.transition-out {
	clip: rect(800px, 1200px, 800px, 0px);
}

Zoom In

.transition-in {
	opacity:0;
	transform: scale(0.8,0.8);
	-webkit-transform: scale(0.8,0.8);
	position:absolute;
}
.passage {
	width: calc(100% - 12em); // Necessary to keep the zoom origin point consistent.
	width: -webkit-calc(100% - 12em);
	transition: 0.5s ease-out;
	-webkit-transition: 0.5s ease-out;
}
.transition-out {
	opacity:0;
	transform: scale(2,2);
	-webkit-transform: scale(2,2);
	position:absolute;
}

Fast scroll up
Ideally you would use "vh" (viewport height) units instead of "rem" (root em) units, but not enough browsers support it yet. ;_;
You can also make it a slow fading scroll if you change the lengths to something short (like 3rem).

.transition-in {
	opacity:0;
	transform: translate(0,-100rem);
	-webkit-transform: translate(0,-100rem);
	position:absolute;
}
.passage {
	transition: 1s;
	-webkit-transition: 1s;
}
.transition-out {
	opacity:0;
	transform: translate(0,100rem);
	-webkit-transform: translate(0,100rem);
	position:absolute;
}

Garage door
This would work well with a story whose passage divs have a fixed width and height, but unlike the vertical wipe it isn't strictly necessary.

.transition-in {
	opacity:0;
	position:absolute;
}
.passage {
	background-color: #000;
	transition: 1s ease-in;
	-webkit-transition: 1s ease-in;
}
.transition-out {
	position:absolute;
	z-index:3;
	transform: translate(0,-200%);
	-webkit-transform: translate(0,-200%);
}

Focus

.transition-in {
	color:transparent;
	text-shadow: #fff 0 0 1em;
	position:absolute;
}
.passage:not(.transition-out) {
	transition: 1s;
	-webkit-transition: 1s;
}
.transition-out {
	opacity:0;
	position:absolute;
}

"Blur Merge"

.transition-in {
	color:transparent;
	text-shadow: #fff -4em 0 1em, #fff 4em 0 1em;
	position:absolute;
}
.passage:not(.transition-out) {
	transition: 1s;
	-webkit-transition: 1s;
}
.transition-out {
	opacity:0;
	position:absolute;
}

Feel free to report any bugs to @webbedspace.

AttachmentSize
tsitr_fadein.html92.69 KB
tsitr_fadeout.html92.74 KB
tsitr_scrollup.html92.82 KB
tsitr_focus.html92.76 KB
tsitr_sillyrotate.html92.92 KB
tsitr_retrofadein.html92.71 KB
tsitr_spin5seconds.html92.98 KB
tsitr_blur_merge.html92.74 KB
tsitr_garagedoor.html92.78 KB
tsitr_zoomin2.html92.92 KB
tsitr_verticalwipe.html92.87 KB
tsitr_t8ntest.html93.84 KB
everythingstaken's picture

Happy New Year's Eve Rylie James Thomas: 2015, Heaven versus Hell.

ScreenShot.png

"HPY NYE RJT: 2015, HvH" for short.

This is for Rylie James Thomas.

All of the stuff on your list is in there somewhere cuz you've been a nice this year.

The biggest suggestion's influence was the "not being at computer", so I made it so you can sort of leave the game on and stuff can still happen. The big thing I made was a system so the car can turn corners automatically and it can take you wherever you want.

I also took another hint from Rylie's philosophy about having music in games. There's only one song and SPOILER: It's in the Circle K.

Edit:
Wow, I just realized because of how scaling works in MMF2, if the screen is scaled differently then the dialogue boxes do not work. I will sometime later make a version of this game where there aren't dialogue boxes, but something else like clickable word art or something. :( So, basically that means this game has to be played in 1280 x 1024 and up.

New Edit:
I edited a few things so some narrative parts are more clear. :)

Made For: 
An event

The Terrible Terrible Turret

TerribleTurret.png
Game File: 

Dodge the falling grenades that your malfunctioning war turret is shooting!

Made For: 
Pirate Kart 2

In The Well

inthewell.png
Game File: 

I pondered several story ideas for this, but didn't really like any of them. So, just enjoy this wordless implementation.

Arrows to move; Z, Space or Up to jump.

Event Created For: 
Made For: 
An event

Assault on Crater Bulb

craterbulb.png
Game File: 

This game is inspired primarily by ZiGGURAT, Outpost Nexus and SpaceInvader! The news ticker is inspired by Super Mario Sunshine. The tractors are inspired by Team Fortress 2. The environment is loosely inspired by Return of the Invaders.

Defend the lone frontier town, Crater Bulb, from these brightly coloured invading ships! Bounce shots off the floor of the crater to attack airborne and ground foes alike. Charge up to fire one of three different shots, each with unique abilities and purposes. Beware: if even one enemy trooper reaches the city, they will immediately surrender! Undoubtedly, heroic sacrifice isn't the Crater Bulb citizen's top priority.

Event Created For: 
Made For: 
An event

Twine code shortcuts minutia

This is an optional appendix to my Twine code shortcuts article. Most of the things here are entirely valid, but aren't as intuitive, and don't really save that much in the way of typing or expression. Nonetheless, they do reveal some underlying concepts to JavaScript that may be enlightening.

Reducing strings and numbers to true and false

In JavaScript, using strings or numbers in place of true, false, or conditional statements such as "x > y" means that the computer will try and convert the strings or numbers into either true or false. The rule for those two types of values is: the number 0 and a string with zero characters in it, "", are converted to false - everything else is converted to true. (0 and "" are called "falsy" values because they're equivalent to false - other values are "truthy").

(If you're familiar with Game Maker, you of course know that Game Maker considers all negative numbers to be falsy as well - but not so in JavaScript!)

This is not really that useful, except for explaining the behaviour of later examples, but it does mean that you could shorten certain <<if>> comparisons:

<<if $hp neq 0>>

can be shortened to

<<if $hp>>

You can also use Not to express the opposite.

<<if $hp eq 0>>

can be validly rewritten as

<<if not $hp>>

false is equivalent to 0, true is equivalent to 1

With regards to numbers, the process of true/false coercion also works symmetrically - the value false, when used in arithmetic, is converted to 0. <<set $red = 3 + false>> is valid, but useless. Nevertheless, this understanding is necessary for the next part.

As a corollary, the raw value true, when used in arithmetic, is converted to 1. This means that <<set $dead += (not $hp)>> will add 1 to $dead if $hp is 0.

And and Or

The way And and Or is implemented in JavaScript is interesting: "x and y" means "if x is false, the value of this statement is x (i.e false), otherwise the value of this statement is y". And, as discussed previously, since such statements are usually used for true/false comparisons, then y is reduced to its true/false value - as one expects.

However, what if you used it in a situation where a plain value was expected? Essentially, it can be used in a manner similar to the ternary operator:

<<set $liveammo = ($gun and $bullets)>>

This line, given the rule above, sets $liveammo to equal $bullets, but only if $gun is true - if not, it's set to false, i.e. 0 (or whatever falsy value $gun has). It may look counterintuitive, especially since it relies on the aforementioned understanding of true/false reduction, but it's equivalent to <<set $liveammo = ($gun ? 0 : $bullets)>>

Or is implemented in JavaScript this way: "x or y" means "if x is true, the value of this statement is x (i.e true), otherwise the value of this statement is y". This means you could use it like this:

<<set $samusenergy = ($energytank or $reservetank)>>

That line only sets $samusenergy to be $reservetank if the $energytank variable is 0. It's equivalent to <<set $samusenergy = ($energytank ? $energytank : $reservetank)>>

It can also be used, in a way, to specify a "default" value if the first value is 0 or an empty string:

<<set $name = ($name or prompt(“What’s your name?”))>>

This line of code will only prompt the player if $name isn't an empty string (i.e. a name was already given).

The Last Hanukkah

lasthanukkah.jpg

It's the last Hanukkah! Don't worry about messing up the prayer or getting the order of the candles wrong. We're all friends here.

Created By: 
AttachmentSize
lsthnkkh.zip87.31 KB
Zecks's picture

Zecks

i am zesck

i mak gamse

this site hass some of my bestest jokework ever, but youre probs gonna recognise me as a really kickass "serious developer" sometime in the future hopefully.

bio_picture: 
magests.jpg
Made For: 
Pirate Kart 2
Syndicate content
pensive-mosquitoes