Initial import.
authorJoe Wreschnig <joe.wreschnig@gmail.com>
Wed, 3 Sep 2014 23:07:23 +0000 (01:07 +0200)
committerJoe Wreschnig <joe.wreschnig@gmail.com>
Wed, 3 Sep 2014 23:07:23 +0000 (01:07 +0200)
35 files changed:
.gitignore [new file with mode: 0644]
css/FiraMono-Bold.woff [new file with mode: 0644]
css/FiraMono-Regular.woff [new file with mode: 0644]
css/FiraSans-Bold.woff [new file with mode: 0644]
css/FiraSans-BoldItalic.woff [new file with mode: 0644]
css/FiraSans-Light.woff [new file with mode: 0644]
css/FiraSans-LightItalic.woff [new file with mode: 0644]
css/FiraSans-Medium.woff [new file with mode: 0644]
css/FiraSans-MediumItalic.woff [new file with mode: 0644]
css/FiraSans-Regular.woff [new file with mode: 0644]
css/FiraSans-RegularItalic.woff [new file with mode: 0644]
css/main.css [new file with mode: 0644]
favicon.ico [new file with mode: 0644]
google44dc8921b920c50f.html [new file with mode: 0644]
index.html [new file with mode: 0644]
logotype.png [new file with mode: 0644]
logotype_horizontal_1.png [new file with mode: 0644]
logotype_horizontal_2.png [new file with mode: 0644]
logotype_medium.png [new file with mode: 0644]
logotype_small.png [new file with mode: 0644]
string-lerp/index.html [new file with mode: 0644]
string-lerp/string-lerp-1.0.0.tar.gz [new file with mode: 0644]
string-lerp/string-lerp-1.0.0.zip [new file with mode: 0644]
string-lerp/string-lerp.js [new file with mode: 0644]
thumbnails/123456789.png [new file with mode: 0644]
thumbnails/bulletml.png [new file with mode: 0644]
thumbnails/enjoyable.png [new file with mode: 0644]
thumbnails/featherfall.png [new file with mode: 0644]
thumbnails/lagomorph.png [new file with mode: 0644]
thumbnails/matrixcreatrix.png [new file with mode: 0644]
thumbnails/psvzipper.png [new file with mode: 0644]
thumbnails/pwl6.png [new file with mode: 0644]
thumbnails/rogue1980.png [new file with mode: 0644]
thumbnails/string-lerp.png [new file with mode: 0644]
thumbnails/webcart1000.png [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..e43b0f9
--- /dev/null
@@ -0,0 +1 @@
+.DS_Store
diff --git a/css/FiraMono-Bold.woff b/css/FiraMono-Bold.woff
new file mode 100644 (file)
index 0000000..e81f4ae
Binary files /dev/null and b/css/FiraMono-Bold.woff differ
diff --git a/css/FiraMono-Regular.woff b/css/FiraMono-Regular.woff
new file mode 100644 (file)
index 0000000..0a04a4f
Binary files /dev/null and b/css/FiraMono-Regular.woff differ
diff --git a/css/FiraSans-Bold.woff b/css/FiraSans-Bold.woff
new file mode 100644 (file)
index 0000000..415071c
Binary files /dev/null and b/css/FiraSans-Bold.woff differ
diff --git a/css/FiraSans-BoldItalic.woff b/css/FiraSans-BoldItalic.woff
new file mode 100644 (file)
index 0000000..a4129c6
Binary files /dev/null and b/css/FiraSans-BoldItalic.woff differ
diff --git a/css/FiraSans-Light.woff b/css/FiraSans-Light.woff
new file mode 100644 (file)
index 0000000..f05e73a
Binary files /dev/null and b/css/FiraSans-Light.woff differ
diff --git a/css/FiraSans-LightItalic.woff b/css/FiraSans-LightItalic.woff
new file mode 100644 (file)
index 0000000..43a73e8
Binary files /dev/null and b/css/FiraSans-LightItalic.woff differ
diff --git a/css/FiraSans-Medium.woff b/css/FiraSans-Medium.woff
new file mode 100644 (file)
index 0000000..5627227
Binary files /dev/null and b/css/FiraSans-Medium.woff differ
diff --git a/css/FiraSans-MediumItalic.woff b/css/FiraSans-MediumItalic.woff
new file mode 100644 (file)
index 0000000..f381487
Binary files /dev/null and b/css/FiraSans-MediumItalic.woff differ
diff --git a/css/FiraSans-Regular.woff b/css/FiraSans-Regular.woff
new file mode 100644 (file)
index 0000000..9ff4044
Binary files /dev/null and b/css/FiraSans-Regular.woff differ
diff --git a/css/FiraSans-RegularItalic.woff b/css/FiraSans-RegularItalic.woff
new file mode 100644 (file)
index 0000000..074c220
Binary files /dev/null and b/css/FiraSans-RegularItalic.woff differ
diff --git a/css/main.css b/css/main.css
new file mode 100644 (file)
index 0000000..70a6fe9
--- /dev/null
@@ -0,0 +1,442 @@
+@font-face {
+    font-family: 'Fira Sans';
+    font-style: normal;
+    font-weight: 300;
+    src: local('Fira Sans OT Light'), local('Fira Sans Light'), url(FiraSans-Light.woff) format('woff');
+}
+
+@font-face {
+    font-family: 'Fira Sans';
+    font-style: italic;
+    font-weight: 300;
+    src: local('Fira Sans OT Light Italic'), local('Fira Sans Light Italic'), url(FiraSans-LightItalic.woff) format('woff');
+}
+
+@font-face {
+    font-family: 'Fira Sans';
+    font-style: normal;
+    font-weight: 400;
+    src: local('Fira Sans OT'), local('Fira Sans'), url(FiraSans-Regular.woff) format('woff');
+}
+
+@font-face {
+    font-family: 'Fira Sans';
+    font-style: normal;
+    font-weight: 700;
+    src: local('Fira Sans OT Bold'), local('Fira Sans Bold'), url(FiraSans-Bold.woff) format('woff');
+}
+
+@font-face {
+    font-family: 'Fira Sans';
+    font-style: italic;
+    font-weight: 400;
+    src: local('Fira Sans OT Italic'), local('Fira Sans Italic'), url(FiraSans-RegularItalic.woff) format('woff');
+}
+
+@font-face {
+    font-family: 'Fira Sans';
+    font-style: italic;
+    font-weight: 700;
+    src: local('Fira Sans OT Bold Italic'), local('Fira Sans Bold Italic'), url(FiraSans-BoldItalic.woff) format('woff');
+}
+
+@font-face {
+    font-family: 'Fira Mono';
+    font-style: normal;
+    font-weight: 400;
+    src: local('Fira Mono OT'), local('Fira Mono'), url(FiraMono-Regular.woff) format('woff');
+}
+
+@font-face {
+    font-family: 'Fira Mono';
+    font-style: normal;
+    font-weight: 700;
+    src: local('Fira Mono OT Bold'), local('Fira Mono Bold'), url(FiraMono-Bold.woff) format('woff');
+}
+
+* {
+    list-style-type: none;
+    padding: 0;
+    margin: 0;
+    font-weight: normal;
+    text-decoration: none;
+}
+
+a:link, [onclick] {
+    text-decoration: underline;
+    cursor: pointer;
+}
+
+html {
+    font-family: "Fira Sans", sans-serif;
+    font-size: 16px;
+    background-color: rgb(226, 192, 242);
+    padding: 0 1em;
+}
+
+body {
+    margin: 0 auto;
+    color: black;
+    background-color: white;
+    max-width: 56em;
+    padding: 0 1em;
+}
+
+header {
+    border-top: solid rgb(206, 132, 242) 0.5em;
+    border-bottom: solid rgb(244, 126, 126) 0.5em;
+    border-radius: 2.5em;
+    height: 6em;
+    transition: border-color 0.5s;
+    white-space: nowrap;
+    text-align: right;
+    margin: 0 auto;
+}
+
+header img {
+    float: left;
+    height: 100%;
+    width: auto;
+}
+
+header h1 {
+    font-size: 3em;
+    font-weight: normal;
+    margin-right: 0.25em;
+    display: inline-block;
+    height: 100%;
+    line-height: 2em;
+}
+
+header:hover {
+    border-top-color: rgb(244, 126, 126);
+    border-bottom-color: rgb(206, 132, 242);
+}
+
+img.logo {
+    -webkit-transition: -webkit-transform 1.5s;
+    transition: transform 1.5s;
+    -webkit-transition-delay: 0.5s;
+    transition-delay: 0.5s;
+    -webkit-transition-timing-function: cubic-bezier(0.4, 0.2, 0.5, 1.3);
+    transition-timing-function: cubic-bezier(0.4, 0.2, 0.5, 1.3);
+}
+
+img.logo:hover {
+    -webkit-transform: rotate(360deg);
+    transform: rotate(360deg);
+}
+
+h2 {
+    border-top: solid rgb(206, 132, 242) 0.0625em;
+    border-left: solid rgb(206, 132, 242) 0.0625em;
+    border-radius: 1em 0 0 1em;
+    font-size: 1.25em;
+    font-weight: 300;
+    margin-left: -0.67em;
+    margin-right: -0.67em;
+    margin-top: 2em;
+    margin-bottom: 0.5em;
+    padding-left: 0.5em;
+    padding-top: 0.125em;
+}
+
+h3 {
+    border-top: solid rgb(206, 132, 242) 1px;
+    border-left: solid rgb(206, 132, 242) 1px;
+    border-radius: 1.5em;
+    display: inline-block;
+    font-size: 1.125em;
+    font-weight: 300;
+    margin-bottom: 0;
+    margin-left: -0.89em;
+    padding-left: 0.67em;
+    padding-right: 0.67em;
+    white-space: nowrap;
+}
+
+a:link, [onclick] {
+    color: rgb(206, 132, 242);
+    transition: color 0.3s;
+}
+
+a:visited {
+    color: rgb(206, 132, 242);
+}
+
+a:hover, [onclick]:hover {
+    color: rgb(244, 126, 126);
+}
+
+main {
+    display: block;
+    padding: 1em;
+    max-width: 50em;
+    margin: auto;
+}
+
+main > p {
+    margin: 1em 0.5em;
+}
+
+hr {
+    margin-top: 0;
+    margin-bottom: 1em;
+    border-bottom: solid rgb(206, 132, 242) 1px;
+    height: 2em;
+}
+
+.highlight {
+    border-bottom: solid rgb(206, 132, 242) 0.125em;
+    border-top: solid rgb(206, 132, 242) 0.125em;
+    border-radius: 1em;
+    font-weight: 300;
+    padding: 1em 3em;
+    transition: border-radius 0.3s;
+    box-sizing: border-box;
+}
+
+.highlight:hover {
+    border-radius: 3em;
+}
+
+.game-preview {
+    padding: 0;
+    text-align: center;
+    width: 100%;
+    max-width: 37em;
+    margin: auto;
+}
+
+.game-preview > li {
+    position: relative;
+    border: solid rgb(206, 132, 242) 1px;
+    margin-bottom: 1.5em;
+    margin-top: 1em;
+    margin-left: 2.5em;
+    border-left-width: 0;
+    height: 8em;
+    transition: border-radius 0.3s, border-color 0.3s;
+    padding-left: 4em;
+    box-sizing: border-box;
+    border-radius: 0 4em 4em 0;
+}
+
+.game-preview > li:nth-child(even) {
+    padding-left: 0;
+    padding-right: 4em;
+    margin-right: 2.5em;
+    margin-left: 0;
+    border-left-width: 1px;
+    border-right-width: 0;
+    border-radius: 4em 0 0 4em;
+}
+
+.game-preview > li:hover {
+    border-radius: 0 0.25em 0.25em 0;
+    border-color: rgb(244, 126, 126);
+}
+
+.game-preview > li img {
+    border: solid rgb(206, 132, 242) 1px;
+    position: absolute;
+    border-radius: 50%;
+    top: -1px;
+    left: -4em;
+    height: 8em;
+    width: 8em;
+    opacity: 0.75;
+    transition: border-radius 0.3s, border-color 0.3s, opacity 0.3s;
+    box-sizing: border-box;
+}
+
+.game-preview > li:nth-child(even) img {
+    left: auto;
+    right: -4em;
+}
+
+.game-preview > li:hover img {
+    border-radius: 0;
+    border-color: rgb(244, 126, 126);
+    opacity: 1.0;
+}
+
+.game-preview .info {
+    position: relative;
+    height: 100%;
+}
+
+.game-preview .info h4 {
+    color: inherit;
+    font-style: italic;
+    padding-left: 0.125em;
+    padding-right: 0.125em;
+    text-decoration: none;
+    text-align: center;
+    box-sizing: border-box;
+    padding-top: 0.25em;
+}
+
+.game-preview li:nth-child(odd) .info h4,
+.game-preview li:nth-child(odd) .info ul {
+    margin-right: 6.5rem;
+}
+
+.game-preview li:nth-child(even) .info h4,
+.game-preview li:nth-child(even) .info ul {
+    margin-right: 0em;
+    margin-left: 6.5rem;
+}
+
+h4 a:link {
+    text-decoration: none;
+}
+
+.game-preview .info p {
+    padding: 0.25em;
+    text-align: center;
+    position: absolute;
+    left: 0;
+    right: 0;
+    top: 50%;
+    transform: translateY(-50%);
+    -webkit-transform: translateY(-50%);
+    margin-top: 0.125em;
+}
+
+.game-preview .info ul {
+    bottom: 0.25em;
+    font-size: 0.75em;
+    position: absolute;
+    right: 0.125em;
+    left: 0.125em;
+    text-align: center;
+}
+
+.game-preview .info li:before {
+    content: ' ~ ';
+}
+
+.game-preview .info li:first-child:before {
+    content: '';
+}
+
+.game-preview .info li {
+    display: inline;
+    font-weight: 300;
+}
+
+ul.download {
+    border-radius: 1em;
+    border: solid rgb(206, 132, 242) 0.125em;
+    font-weight: 300;
+    padding: 0.5em;
+    margin: 1em auto;
+    transition: border-radius 0.3s, border-color 0.3s;
+    white-space: nowrap;
+    display: table;
+}
+
+ul.download:hover {
+    border-radius: 4px;
+    border-color: rgb(244, 126, 126);
+}
+
+ul.download li {
+    list-style-type: none;
+    font-size: 1.25em;
+    margin-bottom: 0.8em;
+    text-align: center;
+}
+
+ul.download li a {
+    text-decoration: none;
+}
+
+ul.download li.sh {
+    margin-bottom: 0;
+    font-size: 0.75em;
+    font-family: "Fira Mono", monospace;
+    text-align: left;
+}
+
+ul.download li:last-child {
+    margin-bottom: 0;
+}
+
+.sh:before {
+    content: "$ ";
+}
+
+input {
+    font-family: inherit;
+    font-size: 1em;
+}
+
+.copyright {
+    margin: auto;
+    text-align: justify;
+    width: 75%;
+    font-size: 0.875em;
+    font-weight: 400;
+}
+
+.copyright > p {
+    font-size: 0.875em;
+    font-weight: 300;
+}
+
+.copyright:before {
+    content: "Copyright ©";
+}
+
+pre {
+    border-left: solid rgba(206, 132, 242, 0.5) 8px;
+    border-radius: 8px;
+    font-family: "Fira Mono", monospace;
+    margin-left: 1em;
+    overflow: auto;
+    padding-left: 2em;
+    padding: 0.5em;
+    transition: background-color 0.3s, border-color 0.3s, border-radius 0.3s;
+}
+
+pre:hover {
+    background-color: rgba(206, 132, 242, 0.125);
+    border-color: rgb(206, 132, 242);
+    border-radius: 16px;
+}
+
+code {
+    font-family: "Fira Mono", monospace;
+    transition: background-color 0.3s;
+}
+
+code:hover {
+    background-color: rgba(206, 132, 242, 0.125);
+}
+
+pre code:hover {
+    background-color: transparent;
+}
+
+@media (max-width: 599px) {
+    html { font-size: 13px; }
+
+    .optional {
+        display: none;
+    }
+
+    ul.download li.sh:before {
+        content: "";
+    }
+
+    pre {
+        font-size: 0.875em;
+    }
+}
+
+@media (max-width: 479px) {
+    html { font-size: 10px; }
+}
+
diff --git a/favicon.ico b/favicon.ico
new file mode 100644 (file)
index 0000000..1555e77
Binary files /dev/null and b/favicon.ico differ
diff --git a/google44dc8921b920c50f.html b/google44dc8921b920c50f.html
new file mode 100644 (file)
index 0000000..c3f4c69
--- /dev/null
@@ -0,0 +1 @@
+google-site-verification: google44dc8921b920c50f.html
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644 (file)
index 0000000..053e87f
--- /dev/null
@@ -0,0 +1,283 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta name=viewport content="width=device-width, initial-scale=1">
+    <link rel="stylesheet" href="css/main.css" type="text/css">
+    <title>Yukkuri Games</title>
+    <style>
+      body {
+          border-top: solid rgb(206, 132, 242) 0.75em;
+          border-bottom: solid rgb(244, 126, 126) 0.75em;
+          border-radius: 2em;
+      }
+
+      /* Reset usual header CSS */
+      header {
+          border: none;
+          height: 13em;
+          text-align: center;
+      }
+
+      header img {
+          float: none;
+      }
+
+    </style>
+  </head>
+
+  <body>
+    <header>
+      <img src="logotype.png" class=logo alt="Yukkuri Games">
+    </header>
+    <main>
+      <h2>Games</h2>
+      <ul class=game-preview>
+        <li>
+          <img src="thumbnails/pwl6.png" alt=Icon>
+          <div class=info>
+            <h4>Pixel Witch Lesson&nbsp;#6</h4>
+            <ul>
+              <li>Coming Summer 2014</li>
+              <li>Browser (WebGL), PC, Android</li>
+            </ul>
+            <p>
+              A puzzle game for witches in training.
+            </p>
+          </div>
+        </li>
+      </ul>
+      <h2>For Games</h2>
+      <ul class=game-preview>
+        <li>
+          <a href="/heroik/heroik.html">
+            <img src="/heroik/favicon_256.png" alt=Icon>
+          </a>
+          <div class=info>
+            <h4><a href="/heroik/heroik.html">Hero: Immortal King Scenario Generator</a></h4>
+            <p>
+              Random scenarios and
+              <a href="/heroik/variants.html">variant rules</a> for
+              Emmanuel Beltrando's dungeon-crawling card game
+              <em>Hero: Immortal King</em>.
+            </p>
+            <ul>
+              <li>2014</li>
+              <li>(Mobile) Browser</li>
+            </ul>
+          </div>
+        </li>
+
+        <li>
+          <a href="/mlpccg/mlpccg.html">
+            <img src="/mlpccg/favicon_256.png" alt=Icon>
+          </a>
+          <div class=info>
+            <h4><a href="/mlpccg/mlpccg.html">MLPCCG Helper</a></h4>
+            <p>
+              Play the <em>My Little Pony</em> <a href="http://enter-play.com/products/mlpccg.html">collectible card game</a>
+              even if, like us, you can't remember three numbers at
+              the same time.
+            </p>
+            <ul>
+              <li>2014</li>
+              <li>(Mobile) Browser</li>
+            </ul>
+          </div>
+        </li>
+
+        <li>
+          <a href="/labelle/">
+            <img src="/labelle/icon_128x128.png" alt=Icon>
+          </a>
+          <div class=info>
+            <h4><a href="/labelle/">Labelle Litanizer</a></h4>
+            <p>
+              Investigate the non-human with outfit-oriented ontology.
+            </p>
+            <ul>
+              <li>2013</li>
+              <li>(Mobile) Browser</li>
+            </ul>
+          </div>
+        </li>
+
+        <li>
+          <a href="http://psvzipper.appspot.com/">
+            <img src="thumbnails/psvzipper.png" alt=Icon>
+          </a>
+          <div class=info>
+            <h4><a href="http://psvzipper.appspot.com/">Vita Background Generator</a></h4>
+            <p>
+              Tetsuya Nomura Simulator, if his job was drawing
+              backgrounds for your PlayStation Vita.
+            </p>
+            <ul>
+              <li>2012</li>
+              <li>Browser</li>
+            </ul>
+          </div>
+        </li>
+        <li>
+          <a href="/enjoyable/">
+            <img src="thumbnails/enjoyable.png" alt=Icon>
+          </a>
+          <div class=info>
+            <h4><a href="/enjoyable/">Enjoyable</a></h4>
+            <p>
+              Map controller inputs to mouse and keyboard events. Many
+              of your games will become more fun.
+            </p>
+            <ul>
+              <li>2013</li>
+              <li>Mac OS X 10.7+</li>
+            </ul>
+          </div>
+        </li>
+      </ul>
+
+      <h2>Not Games (Yet?)</h2>
+      <ul class=game-preview>
+        <li>
+          <a href="/string-lerp/">
+            <img src="thumbnails/string-lerp.png" alt=Icon>
+          </a>
+          <div class=info>
+            <h4><a href="/string-lerp/">String Lerp</a></h4>
+            <p>
+              Animate one string progressively changing into another.
+            </p>
+            <ul>
+              <li>2014</li>
+              <li>JavaScript Module (Browser, Node)</li>
+            </ul>
+          </div>
+        </li>
+        <li>
+          <a href="/webcart1000/">
+            <img src="thumbnails/webcart1000.png" alt=Icon>
+          </a>
+          <div class=info>
+            <h4><a href="/webcart1000/">WEBCART1000</a></h4>
+            <p>
+              Share save files between multiple browser-based games.
+            </p>
+            <ul>
+              <li>2013</li>
+              <li>JavaScript Module (Browser)</li>
+            </ul>
+          </div>
+        </li>
+        <li>
+          <a href="https://code.google.com/p/python-bulletml">
+            <img src='thumbnails/bulletml.png' alt=Icon>
+          </a>
+          <div class=info>
+            <h4>
+              <a href="https://code.google.com/p/python-bulletml">
+                python-bulletml
+              </a>
+            </h4>
+            <p>
+              Parse and run BulletML scripts in Python.
+            </p>
+            <ul>
+              <li>2010</li>
+              <li>Python Module (2.6+, 3.x)</li>
+            </ul>
+          </div>
+        </li>
+      </ul>
+      <h2>Game Jams</h2>
+      <ul class=game-preview>
+        <li>
+          <a href="/123456789/">
+            <img src="/thumbnails/123456789.png" alt=Icon>
+          </a>
+          <div class=info>
+            <h4><a href="/123456789/">123456789</a></h4>
+            <p>
+              A puzzle-<wbr>paean
+              from <a href="http://www.gamesetwatch.com/2007/03/column_beyond_tetris_nemesis_f_1.php">one
+              forgotten input chimera</a> to another near extinction.
+            </p>
+            <ul>
+              <li>2013</li>
+              <li>LD26, "minimalism"</li>
+              <li>Browser</li>
+            </ul>
+          </div>
+        </li>
+        <li>
+          <a href="/pphs/">
+            <img src="/thumbnails/rogue1980.png" alt=Icon>
+          </a>
+          <div class=info>
+            <h4><a href="/pphs/">Rogue (1980)</a></h4>
+            <p>
+              Speculative digital archaeology. Also, a poorly-balanced
+              dungeon-crawler-<em>cum</em>-flirting-minigame.
+            </p>
+            <ul>
+              <li>2013</li>
+              <li><a href="http://www.electricopolis.net/2013/03/29/pphs-jam/">♥♡♥PPHS♥♡♥</a></li>
+              <li>Version 7 Unix, 4.2BSD, IBM PC</li>
+            </ul>
+          </div>
+        </li>
+
+        <li>
+          <a href="/matrixcreatrix/">
+            <img src="/thumbnails/matrixcreatrix.png" alt=Icon>
+          </a>
+          <div class=info>
+            <h4><a href="/matrixcreatrix/">Matrix Creatrix</a></h4>
+            <p>
+              Whatever the opposite of color-matching games are, while
+              still being a color-matching game.
+            </p>
+            <ul>
+              <li>2012</li>
+              <li>LD23, "tiny world"</li>
+              <li>Browser (Perlenspiel)</li>
+            </ul>
+          </div>
+        </li>
+
+        <li> 
+          <a href="http://pyweek.org/e/kuri/">
+            <img src="/thumbnails/featherfall.png" alt=Icon>
+          </a>
+          <div class=info>
+            <h4><a href="http://pyweek.org/e/kuri/">Feather Fall</a></h4>
+            <p>
+              High-flying fast-falling arcade action.
+            </p>
+            <ul>
+              <li>2009</li>
+              <li>PyWeek #9, "feather"</li>
+              <li>GNU/Linux, Windows</li>
+            </ul>
+          </div>
+        </li>
+        <li>
+          <a href="http://pyweek.org/e/Yukkuri/">
+            <img src="/thumbnails/lagomorph.png" alt=Icon>
+          </a>
+          <div class=info>
+            <h4><a href="http://pyweek.org/e/Yukkuri/">I Am Lagomorph</a></h4>
+            <p>
+              Tend a farm threatened by undead bunnies and
+              poop. Unfinished and unstable.
+            </p>
+            <ul>
+              <li>2009</li>
+              <li>PyWeek #8, "get off my lawn"</li>
+              <li>? (Python, OpenGL)</li>
+            </ul>
+          </div>
+        </li>
+      </ul>
+    </main>
+  </body>
+</html>
diff --git a/logotype.png b/logotype.png
new file mode 100644 (file)
index 0000000..3f3d63a
Binary files /dev/null and b/logotype.png differ
diff --git a/logotype_horizontal_1.png b/logotype_horizontal_1.png
new file mode 100644 (file)
index 0000000..a845d24
Binary files /dev/null and b/logotype_horizontal_1.png differ
diff --git a/logotype_horizontal_2.png b/logotype_horizontal_2.png
new file mode 100644 (file)
index 0000000..7ae1d09
Binary files /dev/null and b/logotype_horizontal_2.png differ
diff --git a/logotype_medium.png b/logotype_medium.png
new file mode 100644 (file)
index 0000000..603f77c
Binary files /dev/null and b/logotype_medium.png differ
diff --git a/logotype_small.png b/logotype_small.png
new file mode 100644 (file)
index 0000000..3d5893b
Binary files /dev/null and b/logotype_small.png differ
diff --git a/string-lerp/index.html b/string-lerp/index.html
new file mode 100644 (file)
index 0000000..b6b1fc3
--- /dev/null
@@ -0,0 +1,133 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <meta name=viewport content="width=device-width, initial-scale=1">
+    <link rel="stylesheet" href="/css/main.css" type="text/css">
+    <title>String Lerp - Yukkuri Games</title>
+    <style>
+      input[type=text] {
+      margin: 0.125em 1em;
+      width: 40%;
+      text-align: center;
+      }
+    </style>
+    <script type="text/javascript" src="string-lerp.js"></script>
+    <script>
+      var DEMOS = [
+          ["explore", "implode"],
+          ["Do you like green eggs and ham?", "I do not like them, Sam-I-am."],
+          ["apple core", "core dump"],
+          ["rgb(255, 0, 0)", "rgb(0, 128, 255)"],
+          ["chicken wing", "buffalo wing"],
+          ["1.5 + 1.5 ≈ 3", "3.0 + 7.0 ≈ 10"],
+          ["<(o.o<)    v(._.)v", "(>o.o)>    ^(*_*)^"],
+          ["ZALGO̸", "ZA̢LG͜O"],
+          ["", "Typing, one letter at a time."],
+          ["( ノ゚▽゚)ノ", "( ╯︵╰)"]
+      ];
+      var i = Math.floor(Math.random() * DEMOS.length);
+
+      function set () {
+          var a = document.getElementById("a");
+          var b = document.getElementById("b");
+          var d = DEMOS[i++ % DEMOS.length];
+          a.value = d[0];
+          b.value = d[1];
+          update();
+      }
+
+      function escape (s) {
+          return s.replace(/&/g, "&amp;")
+                  .replace(/</g, "&lt;")
+                  .replace(/>/g, "&gt;")
+                  .replace(/ /g, "&nbsp;");
+                  
+      }
+      
+      function update () {
+          var p = +document.getElementById("slider").value;
+          var a = document.getElementById("a");
+          var b = document.getElementById("b");
+          var e = document.getElementById("text");
+          e.innerHTML = escape(stringLerp.lerp(a.value, b.value, p));
+      }
+    </script>
+  </head>
+  <body onload="set()">
+    <header>
+      <a href="/">
+        <img src="/logotype_horizontal_1.png" class=logo alt="(◕ ヮ ◕)">
+        <img src="/logotype_horizontal_2.png" class=optional
+             alt="Yukkuri Games">
+      </a>
+      <h1>String Lerp</h1>
+    </header>
+    <main>
+      <p>
+        String Lerp is a JavaScript module to interpolate (lerp,
+        blend, tween) between two string values, that is,
+        progressively turn one string into another.  It
+        uses <a href="http://en.wikipedia.org/wiki/Levenshtein_distance">Levenshtein
+        distance</a> measurements along with other heuristics to try
+        to blend between two strings as naturally as possible.
+      </p>
+      <ul class=download>
+        <li><a href="string-lerp-1.0.0.tar.gz">string-lerp-1.0.0.tar.gz</a> (16KB)
+        <li class=sh>npm install <a href="https://www.npmjs.org/package/string-lerp">string-lerp</a>
+        <li class=sh><span data-optional>git clone
+          </span><a href="http://git.yukkurigames.com/string-lerp.git">http://git.yukkurigames.com/string-lerp.git</a>
+      </ul>
+      <p style="text-align: center">
+        Not really sure what that means? Try it out.
+      </p>
+      <div class=highlight>
+        <div style="width: 100%; text-align: center">
+          <input type="text" id="a" value="Do you like green eggs and ham?"
+                 oninput="update();">
+          <input type="text" id="b" value="I do not like them, Sam-I-am."
+                 oninput="update();">
+        </div>
+        <input id=slider type=range value=0.5 max=1.00 step=0.00390625
+               oninput="update();"
+               style="width: 80%; margin: 1em auto; display: block;">
+        <div id=text style="font-size: 1.5em; text-align: center; min-height: 1.5em;">
+        </div>
+        <div style="text-align: center">
+          <a onclick="set();">Try a different string pair</a>
+        </div>
+      </div>
+      <h2>API</h2>
+      <p>In a browser, use</p>
+      <pre><code>&lt;script type="text/javascript" src="string-lerp.js"&gt;&lt;/script&gt;</code></pre>
+      <p>In Node.js and other non-browser environments,</p>
+      <pre><code>var stringLerp = require("./string-lerp")</code></pre>
+
+      <p>Then,</p>
+      <pre><code>var result = stringLerp.lerp(source, target, amount);
+    // `source' is the string to start with
+    // `target' is the string to finish with
+    // `amount' is an amount to edit the strings, between 0 and 1,
+    //          e.g. 0.23 = 23% from source to target</code></pre>
+      <p>
+        The internal <code>diff</code> and <code>patch</code> routines
+        are also exposed, as <code>diffLerp</code> is too slow for
+        very long strings unless you compute and store the diff list
+        ahead of time.
+      </p>
+      <h2>License</h2>
+      <div class=copyright>
+        2014 Joe Wreschnig 
+        <p>
+          String Lerp is free software. You can redistribute it and/or
+          modify it under the terms of the GNU General Public License
+          as published by the Free Software Foundation;
+          either <a href="http://www.gnu.org/licenses/gpl-2.0.html">version
+          2 of the License</a>, or (at your
+          option) <a href="http://www.gnu.org/licenses/gpl.html">any
+          later version</a>.
+        </p>
+      </div>
+    </main>
+  </body>
+</html>
diff --git a/string-lerp/string-lerp-1.0.0.tar.gz b/string-lerp/string-lerp-1.0.0.tar.gz
new file mode 100644 (file)
index 0000000..9ff0779
Binary files /dev/null and b/string-lerp/string-lerp-1.0.0.tar.gz differ
diff --git a/string-lerp/string-lerp-1.0.0.zip b/string-lerp/string-lerp-1.0.0.zip
new file mode 100644 (file)
index 0000000..fff9cae
Binary files /dev/null and b/string-lerp/string-lerp-1.0.0.zip differ
diff --git a/string-lerp/string-lerp.js b/string-lerp/string-lerp.js
new file mode 100644 (file)
index 0000000..5473199
--- /dev/null
@@ -0,0 +1,307 @@
+/* string-lerp - progressively turn one string into another
+   Copyright 2014 Joe Wreschnig
+   Licensed under the terms of the GNU GPL v2 or later
+   @license http://www.gnu.org/licenses/gpl-2.0.html
+   @source: http://yukkurigames.com/string-lerp/
+*//*
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   As additional permission, you may distribute the program or works
+   based on it without the copy of the GNU GPL normally required,
+   provided you include this license notice and a URL through which
+   recipients can access the corresponding source code.
+*/
+
+/*globals exports, Uint32Array */
+
+(function (exports) {
+    "use strict";
+
+    var MAX_MATRIX_SIZE = 256 * 256;
+
+    function costMatrix(source, target, ins, del, sub) {
+        /** Calculate the Levenshtein cost matrix for source and target
+
+            If source and target are strings, they cannot contain any
+            astral or combining codepoints. Such data must be passed
+            as arrays of strings with one element per glyph.
+
+            ins, del, and sub are the costs for insertion, deletion,
+            and substition respectively. Their default value is 1. If
+            only ins is passed, del and sub are set to the same cost.
+            If ins and del are passed, sub is set to the more
+            expensive of the two.
+
+            The matrix is returned as a flat typed array.
+
+            Following http://en.wikipedia.org/wiki/Levenshtein_distance
+        */
+        ins = ins === undefined ? 1 : (ins | 0);
+        del = (del | 0) || ins;
+        sub = (sub | 0) || Math.max(ins, del);
+        var m = source.length + 1;
+        var n = target.length + 1;
+        var d = new Uint32Array(m * n);
+        var i, j;
+        for (i = 1; i < m; ++i)
+            d[n * i] = i;
+        for (j = 1; j < n; ++j)
+            d[j] = j;
+        for (j = 1; j < n; ++j)
+            for (i = 1; i < m; ++i)
+                if (source[i - 1] === target[j - 1])
+                    d[n * i + j] = d[n * (i - 1) + j - 1];
+                else
+                    d[n * i + j] = Math.min(del + d[n * (i - 1) + j    ],
+                                            ins + d[n *    i    + j - 1],
+                                            sub + d[n * (i - 1) + j - 1]);
+        return d;
+    }
+
+    // First, note that deletion is just substition with nothing, so
+    // any DEL operation can be replaced by a SUB. Second, the
+    // operation code *is* the necessary slice offset for applying the
+    // diff.
+    var INS = 0, SUB = 1;
+
+    function editPath(costs, target) {
+        /** Given a cost matrix and a target, create an edit list */
+        var path = [];
+        var j = target.length;
+        var n = j + 1;
+        var i = costs.length / n - 1;
+        while (i || j) {
+            var sub = (i && j) ? costs[n * (i - 1) + j - 1] : Infinity;
+            var del = i ? costs[n * (i - 1) + j] : Infinity;
+            var ins = j ? costs[n * i + j - 1] : Infinity;
+            if (sub <= ins && sub <= del) {
+                if (costs[n * i + j] !== costs[n * (i - 1) + j - 1])
+                    path.push([SUB, i - 1, target[j - 1]]);
+                --i; --j;
+            } else if (ins <= del) {
+                path.push([INS, i, target[j - 1]]);
+                --j;
+            } else {
+                path.push([SUB, i - 1, ""]);
+                --i;
+            }
+        }
+        return path;
+    }
+
+    function diff(source, target, ins, del, sub) {
+        /** Create a list of edits to turn source into target
+
+            ins, del, and sub are as passed to costMatrix.
+        */
+        return editPath(costMatrix(source, target, ins, del, sub), target);
+    }
+
+    function patchArray(diff, source) {
+        for (var i = 0; i < diff.length; ++i) {
+            var edit = diff[i];
+            source.splice(edit[1], edit[0], edit[2]);
+        }
+        return source;
+    }
+
+    function patchString(diff, source) {
+        for (var i = 0; i < diff.length; ++i) {
+            var edit = diff[i];
+            var head = source.slice(0, edit[1]);
+            var tail = source.slice(edit[1] + edit[0]);
+            source = head + edit[2] + tail;
+        }
+        return source;
+    }
+
+    function patch(diff, source) {
+        /** Apply a list of edits to source */
+        var patcher = Array.isArray(source) ? patchArray : patchString;
+        return patcher(diff, source);
+    }
+
+    // Matches if a string contains combining characters or astral
+    // codepoints (technically, the first half surrogate of an astral
+    // codepoint).
+    var MULTI = /[\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uD800-\uDBFF\uFE20-\uFE2F]/;
+
+    // Match an entire (potentially astral) codepoint and any
+    // combining characters following it.
+    var GLYPH = /[\0-\u02FF\u0370-\u1DBF\u1E00-\u20CF\u2100-\uD7FF\uD800-\uFE1F\uFE30-\uFFFF][\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uDC00-\uDFFF\uFE20-\uFE2F]*/g;
+
+    function diffLerpAstral(source, target, amount) {
+        // This split is not perfect for all languages, but at least
+        // it won't create invalid surrogate pairs or orphaned
+        // combining characters.
+        var sourceGlyphs = source.match(GLYPH) || [];
+        var targetGlyphs = target.match(GLYPH) || [];
+        var edits = diff(targetGlyphs, sourceGlyphs, 2, 2, 3);
+        // The edit path works from the string end, forwards, because
+        // that's how Levenshtein edits work. To match LTR reading
+        // direction (and the behavior of fastLerp), swap the strings
+        // and invert the parameter when editing.
+        var partial = edits.slice(0, Math.round((1 - amount) * edits.length));
+        return patchArray(partial, targetGlyphs).join("");
+    }
+
+    function diffLerpBasic(source, target, amount) {
+        var edits = diff(target, source, 2, 2, 3);
+        // The edit path works from the string end, forwards, because
+        // that's how Levenshtein edits work. To match LTR reading
+        // direction (and the behavior of fastLerp), swap the strings
+        // and invert the parameter when editing.
+        var partial = edits.slice(0, Math.round((1 - amount) * edits.length));
+        return patchString(partial, target);
+    }
+
+    function diffLerp(source, target, amount) {
+        /** Interpolate between two strings using edit operations
+
+            This interpolation algorithm applys a partial edit of one
+            string into the other. This produces nice looking results,
+            but can take a significant amount of time and memory to
+            compute the edits. It is not recommended for strings
+            longer than a few hundred characters.
+        */
+
+        if (source.match(MULTI) || target.match(MULTI))
+            return diffLerpAstral(source, target, amount);
+        else
+            return diffLerpBasic(source, target, amount);
+    }
+
+    var NUMBERS = /(-?\d{1,20}(?:\.\d{1,20})?)/g;
+
+    function areNumericTwins(source, target) {
+        /** Check if a and b differ only in numerals */
+        return source.replace(NUMBERS, "0") === target.replace(NUMBERS, "0");
+    }
+
+    function nlerp(source, target, amount) {
+        return source + (target - source) * amount;
+    }
+
+    function numericLerp(source, target, amount) {
+        /** Interpolate numerically between strings containing numbers
+
+            Numbers may have a leading "-" and a single "." to mark
+            the decimal point, but something must be after the ".".
+            No other floating point syntax (e.g. 1e6) is supported.
+            They are treated as fixed-point values, with the point's
+            position itself interpolating.
+
+            For example, numericLerp("0.0", "100".0, 0.123) === "12.3"
+            because the "." in "0.0" is interpreted as a decimal
+            point. But numericLerp("0.", "100.", 0.123) === "12."
+            because the strings are interpreted as integers followed
+            by a full stop.
+
+            Calling this functions on strings that differ in more than
+            numerals gives undefined results.
+        */
+
+        var targetParts = target.split(NUMBERS);
+        var match;
+        var i = 1;
+        while ((match = NUMBERS.exec(source))) {
+            var sourcePart = match[0];
+            var targetPart = targetParts[i];
+            var part = nlerp(+sourcePart, +targetPart, amount);
+            var sourcePoint = sourcePart.indexOf(".");
+            var targetPoint = targetPart.indexOf(".");
+            var point = Math.round(nlerp(
+                sourcePoint >= 0 ? (sourcePart.length - 1) - sourcePoint : 0,
+                targetPoint >= 0 ? (targetPart.length - 1) - targetPoint : 0,
+                amount));
+            targetParts[i] = part.toFixed(point);
+            i += 2;
+        }
+        return targetParts.join("");
+    }
+
+    function fastLerpAstral(source, target, amount) {
+        var sourceGlyphs = source.match(GLYPH) || [];
+        var targetGlyphs = target.match(GLYPH) || [];
+        var sourceLength = Math.round(sourceGlyphs.length * amount);
+        var targetLength = Math.round(targetGlyphs.length * amount);
+        var head = targetGlyphs.slice(0, targetLength);
+        var tail = sourceGlyphs.slice(sourceLength, sourceGlyphs.length);
+        head.push.apply(head, tail);
+        return head.join("");
+    }
+
+    function fastLerpBasic(source, target, amount) {
+        var sourceLength = Math.round(source.length * amount);
+        var targetLength = Math.round(target.length * amount);
+        var head = target.substring(0, targetLength);
+        var tail = source.substring(sourceLength, source.length);
+        return head + tail;
+    }
+
+    function fastLerp(source, target, amount) {
+        /** Interpolate between two strings based on length
+
+            This interpolation algorithm progressively replaces the
+            front of one string with another. This approach is fast
+            but does not look good when the strings are similar.
+        */
+
+        // TODO: Consider fast-pathing this even more for very large
+        // strings, e.g. in the megabyte range. These are large enough
+        // that it should be fine to just pick a codepoint and search
+        // for the nearest glyph start.
+        if (source.match(MULTI) || target.match(MULTI))
+            return fastLerpAstral(source, target, amount);
+        else
+            return fastLerpBasic(source, target, amount);
+    }
+
+    function lerp(source, target, amount) {
+        /** Interpolate between two strings as best as possible
+
+            If the strings are identical aside from numbers in them,
+            they are passed through numericLerp.
+
+            If the strings are not numbers and short, they are passed
+            through diffLerp.
+
+            Otherwise, they are passed through fastLerp.
+        */
+        source = source.toString();
+        target = target.toString();
+
+        // Fast path for boundary cases.
+        if (amount === 0) return source;
+        if (amount === 1) return target;
+
+        if (areNumericTwins(source, target))
+            return numericLerp(source, target, amount);
+
+        // Numeric lerps should over- and under-shoot when fed numbers
+        // outside 0 to 1, but other types cannot.
+        if (amount < 0) return source;
+        if (amount > 1) return target;
+
+        var n = source.length * target.length;
+        var appropriate = (n && n < MAX_MATRIX_SIZE) ? diffLerp : fastLerp;
+        return appropriate(source, target, amount);
+    }
+
+    exports.costMatrix = costMatrix;
+    exports.patch = patch;
+    exports.diff = diff;
+    exports.fastLerp = fastLerp;
+    exports.diffLerp = diffLerp;
+    exports.numericLerp = numericLerp;
+    exports.lerp = lerp;
+
+})(typeof exports === "undefined" ? (this.stringLerp = {}) : exports);
diff --git a/thumbnails/123456789.png b/thumbnails/123456789.png
new file mode 100644 (file)
index 0000000..693bcd7
Binary files /dev/null and b/thumbnails/123456789.png differ
diff --git a/thumbnails/bulletml.png b/thumbnails/bulletml.png
new file mode 100644 (file)
index 0000000..fa76325
Binary files /dev/null and b/thumbnails/bulletml.png differ
diff --git a/thumbnails/enjoyable.png b/thumbnails/enjoyable.png
new file mode 100644 (file)
index 0000000..d51c46f
Binary files /dev/null and b/thumbnails/enjoyable.png differ
diff --git a/thumbnails/featherfall.png b/thumbnails/featherfall.png
new file mode 100644 (file)
index 0000000..ba14859
Binary files /dev/null and b/thumbnails/featherfall.png differ
diff --git a/thumbnails/lagomorph.png b/thumbnails/lagomorph.png
new file mode 100644 (file)
index 0000000..cbf3397
Binary files /dev/null and b/thumbnails/lagomorph.png differ
diff --git a/thumbnails/matrixcreatrix.png b/thumbnails/matrixcreatrix.png
new file mode 100644 (file)
index 0000000..a71cd42
Binary files /dev/null and b/thumbnails/matrixcreatrix.png differ
diff --git a/thumbnails/psvzipper.png b/thumbnails/psvzipper.png
new file mode 100644 (file)
index 0000000..80a5e3f
Binary files /dev/null and b/thumbnails/psvzipper.png differ
diff --git a/thumbnails/pwl6.png b/thumbnails/pwl6.png
new file mode 100644 (file)
index 0000000..9372fd5
Binary files /dev/null and b/thumbnails/pwl6.png differ
diff --git a/thumbnails/rogue1980.png b/thumbnails/rogue1980.png
new file mode 100644 (file)
index 0000000..156e680
Binary files /dev/null and b/thumbnails/rogue1980.png differ
diff --git a/thumbnails/string-lerp.png b/thumbnails/string-lerp.png
new file mode 100644 (file)
index 0000000..bd2fa9b
Binary files /dev/null and b/thumbnails/string-lerp.png differ
diff --git a/thumbnails/webcart1000.png b/thumbnails/webcart1000.png
new file mode 100644 (file)
index 0000000..3ad09a3
Binary files /dev/null and b/thumbnails/webcart1000.png differ