mirror of
https://github.com/Oreolek/raconteur.git
synced 2024-05-17 08:18:17 +03:00
Porting
This commit is contained in:
parent
9473cbfa6e
commit
fb170cf4d0
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
|||
node_modules/**
|
||||
devel/node_modules/**
|
||||
devel/build/**
|
||||
game/**
|
||||
*.sublime-workspace
|
74
devel/Gulpfile.js
Normal file
74
devel/Gulpfile.js
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
This Gulpfile is used to build a development version of the library and
|
||||
example game all together from the main sources, for development use.
|
||||
*/
|
||||
|
||||
var gulp = require('gulp'),
|
||||
browserify = require('browserify'),
|
||||
babelify = require('babelify'),
|
||||
source = require('vinyl-source-stream'),
|
||||
less = require ('gulp-less'),
|
||||
browserSync = require('browser-sync');
|
||||
|
||||
var reload = browserSync.reload;
|
||||
|
||||
gulp.task('lib', function () {
|
||||
return gulp.src('../undum/lib/*.js')
|
||||
.pipe(gulp.dest('./build/lib/'));
|
||||
});
|
||||
|
||||
gulp.task('undularity', function () {
|
||||
return gulp.src('../undularity/undularity.js')
|
||||
.pipe(gulp.dest('./build/lib/'));
|
||||
});
|
||||
|
||||
gulp.task('js-template', function () {
|
||||
return gulp.src('../template/js/*.js')
|
||||
.pipe(gulp.dest('./build/game/'));
|
||||
});
|
||||
|
||||
gulp.task('browserify', ['lib', 'undularity', 'js-template'], function () {
|
||||
return browserify('./build/game/main.js')
|
||||
.transform(babelify)
|
||||
.bundle()
|
||||
.on("error", function (err) { console.log ("Error: " + err.message)})
|
||||
.pipe(source('undum.js'))
|
||||
.pipe(gulp.dest('./build/game/'))
|
||||
.pipe(reload({stream: true}));
|
||||
|
||||
});
|
||||
|
||||
gulp.task('less', function () {
|
||||
return gulp.src('../template/less/undum.less')
|
||||
.pipe(less())
|
||||
.pipe(gulp.dest('./build/css/'))
|
||||
.pipe(reload({stream: true}));
|
||||
});
|
||||
|
||||
gulp.task('html', function () {
|
||||
return gulp.src('../template/html/index.html')
|
||||
.pipe(gulp.dest('./build/'))
|
||||
.pipe(reload({stream: true}));
|
||||
|
||||
});
|
||||
|
||||
gulp.task('default', function () {
|
||||
gulp.start('browserify');
|
||||
gulp.start('less');
|
||||
gulp.start('html');
|
||||
});
|
||||
|
||||
gulp.task('serve', ['default'], function () {
|
||||
browserSync({
|
||||
notify: false,
|
||||
port: 9000,
|
||||
server: './build'
|
||||
});
|
||||
|
||||
gulp.watch('../template/less/*.less', ['less']);
|
||||
gulp.watch('../template/html/*.html', ['html']);
|
||||
gulp.watch('../undum/lib/*.js', ['browserify']);
|
||||
gulp.watch('../undularity/undularity.js', ['browserify']);
|
||||
gulp.watch('../template/js/*.js', ['browserify']);
|
||||
|
||||
});
|
|
@ -2,11 +2,67 @@ var situation = require('../lib/undularity.js'),
|
|||
$ = require('jquery'),
|
||||
undum = require('../lib/undum.js');
|
||||
|
||||
var a = situation.a;
|
||||
|
||||
undum.game.id = "my_game_id";
|
||||
undum.game.version = "1.0";
|
||||
|
||||
situation('start', {
|
||||
content: `This is a -- "testing" situation.`
|
||||
content:
|
||||
`This is a testing situation for Undularity, a better development system for Undum.
|
||||
|
||||
Choose one of the options below to see the relevant content and test it.`,
|
||||
choices: ['#testing-option']
|
||||
});
|
||||
|
||||
situation('functions-as-properties', {
|
||||
content: (character, system, from) =>
|
||||
`This property of this situation is outputted by a function, which allows
|
||||
us to incorporate variables such as the name of the situation we came
|
||||
from; in this case, "${from}."
|
||||
|
||||
Undularity allows most properties that are text to be defined as
|
||||
functions; the notable exception is optionText. Those functions are
|
||||
passed the character and system objects, in that order, and a third
|
||||
object that is usually either the current situation, or the situation
|
||||
we just came from.`,
|
||||
tags: ['testing-option'],
|
||||
optionText: 'Functions as properties'
|
||||
});
|
||||
|
||||
situation('markdown-features', {
|
||||
content: `
|
||||
# Markdown Support
|
||||
|
||||
Undularity uses Markdown for formatting the content of individual
|
||||
situations. Supported features include **strong** and *emphasis*,
|
||||
headers (as above), [external links](http://github.com), and even
|
||||
preformatted blocks of text:
|
||||
|
||||
situation('start', {
|
||||
content: "This is an example."
|
||||
});
|
||||
|
||||
Additionally, we also support "smart quotes" and -- dashes.`,
|
||||
tags: ['testing-option'],
|
||||
optionText: 'Markdown support'
|
||||
});
|
||||
|
||||
situation('special-links', {
|
||||
content: `
|
||||
# Special Links
|
||||
|
||||
Undularity supports various special types of links, starting with
|
||||
${a().content('writer').once.writer('writerlink')} links.
|
||||
|
||||
Also notable are ${a().id('replacer-link').content('replacer').replacer('replacer-link')}
|
||||
links, which replace the content of a given id.
|
||||
`,
|
||||
writers: {
|
||||
writerlink: "Writer links can only be clicked once.",
|
||||
'replacer-link': "switching"
|
||||
},
|
||||
tags: ['testing-option']
|
||||
});
|
||||
|
||||
$(function(){undum.begin()});
|
|
@ -1,12 +1,14 @@
|
|||
@import "undum-mobile";
|
||||
|
||||
@body_bg: tan;
|
||||
@content_bg: white;
|
||||
@title_bg: steelblue;
|
||||
@text-color: black;
|
||||
|
||||
body {
|
||||
background: #170804 url("../img/page_bg.jpg") repeat-x left top;
|
||||
font-family: Palatino, Times, "Times New Roman", serif;
|
||||
background: @body_bg;
|
||||
color: @text-color;
|
||||
font-size: 18px;
|
||||
line-height: 1.6em;
|
||||
background-attachment: fixed;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
/* Basic structure */
|
||||
|
@ -14,91 +16,85 @@ body {
|
|||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#mid_panel {
|
||||
margin: 0 10.5em;
|
||||
}
|
||||
|
||||
/* The title block */
|
||||
#title, #title .label, #content, .tools {
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
#title {
|
||||
max-width: 28em;
|
||||
background: #e6e6c6 url("../img/title_bg.jpg") repeat -1.1em -1.1em;
|
||||
margin: 2.2em auto 1.1em auto;
|
||||
background: @title_bg;
|
||||
padding: 1.7em;
|
||||
border: 1.1em solid rgba(0,0,0,0.25);
|
||||
border: 1px solid black;
|
||||
cursor: pointer; /* Until we click to start. */
|
||||
}
|
||||
#title .label {
|
||||
overflow: hidden;
|
||||
background: #e6e6c6 url("../img/text_bg.jpg") repeat left top;
|
||||
padding: 2.0em;
|
||||
margin: auto;
|
||||
max-width: 18em;
|
||||
-webkit-box-shadow: 0 0 4px rgba(0,0,0,0.4);
|
||||
box-shadow: 0 0 4px rgba(0,0,0,0.4);
|
||||
position: relative;
|
||||
}
|
||||
#title h1 {
|
||||
font-size: 1.6em;
|
||||
line-height: 1.4em;
|
||||
letter-spacing: 0.2em;
|
||||
font-weight: normal;
|
||||
padding-bottom: 1.1em;
|
||||
border-bottom: 1px solid #321;
|
||||
}
|
||||
#title h2 {
|
||||
font-size: 1.2em;
|
||||
font-weight: normal;
|
||||
text-align: center;
|
||||
margin: 1.1em 0 0 0;
|
||||
}
|
||||
#title h3 {
|
||||
font-size: 1.0em;
|
||||
font-weight: normal;
|
||||
text-align: center;
|
||||
margin: 1.1em 0 0 0;
|
||||
}
|
||||
#title h1, #title h2, #title h3 {
|
||||
color: rgba(33,17,0,0.9);
|
||||
text-shadow: rgba(255,255,255,0.5) 2px 2px 2px,
|
||||
rgba(0,0,0,0.1) -1px -1px 2px;
|
||||
}
|
||||
#title h1 span.fancy {
|
||||
font-size: 2.5em;
|
||||
line-height: 0;
|
||||
font-family: Tangerine, Palatino, Times, "Times New Roman", serif;
|
||||
font-style: italic;
|
||||
margin: 0 -0.2em;
|
||||
}
|
||||
#title .click_message {
|
||||
display: none;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
font-size: 0.9em;
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
color: #987;
|
||||
}
|
||||
#title .noscript_message {
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
font-size: 0.9em;
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
color: #943;
|
||||
|
||||
|
||||
.label {
|
||||
overflow: hidden;
|
||||
padding: 2.0em;
|
||||
margin: auto;
|
||||
max-width: 18em;
|
||||
position: relative;
|
||||
border: 1px dashed black;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.6em;
|
||||
line-height: 1.4em;
|
||||
letter-spacing: 0.2em;
|
||||
font-weight: normal;
|
||||
padding-bottom: 1.1em;
|
||||
border-bottom: 1px solid #321;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.2em;
|
||||
font-weight: normal;
|
||||
text-align: center;
|
||||
margin: 1.1em 0 0 0;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.0em;
|
||||
font-weight: normal;
|
||||
text-align: center;
|
||||
margin: 1.1em 0 0 0;
|
||||
}
|
||||
|
||||
|
||||
.click_message {
|
||||
display: none;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
font-size: 0.9em;
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
color: #987;
|
||||
}
|
||||
|
||||
.noscript_message {
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
font-size: 0.9em;
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
color: #943;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Main content */
|
||||
#content_wrapper {
|
||||
max-width: 28em;
|
||||
position: relative;
|
||||
background: #e6e6c6 url("../img/text_bg.jpg") repeat left top;
|
||||
background: @content_bg;
|
||||
margin: 0.6em auto 1.1em auto;
|
||||
padding: 2.8em;
|
||||
display: none; /* Shown by Javascript */
|
||||
|
@ -107,11 +103,13 @@ body {
|
|||
span.drop + p {
|
||||
text-indent: -0.4em;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
-webkit-transition: text-indent 0.25s ease;
|
||||
transition: text-indent 0.25s ease;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
background-color: rgba(0,0,0,0.25);
|
||||
|
@ -119,29 +117,16 @@ hr {
|
|||
width: 1.1em;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
p + p, p + img + p, p + hr + p {
|
||||
text-indent: 1.6em;
|
||||
}
|
||||
#content h1 + p:first-line,
|
||||
#content h1 + img + p:first-line {
|
||||
font-weight: bold;
|
||||
color: rgba(0,0,0,0.85);
|
||||
}
|
||||
#content h1 + p:first-letter,
|
||||
#content h1 + img + p:first-letter {
|
||||
position: relative;
|
||||
padding-top: 0.1em;
|
||||
display: block;
|
||||
float: left;
|
||||
font-weight: normal;
|
||||
font-size: 3.2em;
|
||||
line-height: 0.8em;
|
||||
color: #210;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0 0 0 1em;
|
||||
}
|
||||
|
||||
ul.options {
|
||||
border: 2px solid #876;
|
||||
padding: 0;
|
||||
|
@ -150,14 +135,17 @@ ul.options {
|
|||
list-style-type: none;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
ul.options li {
|
||||
border-bottom: 1px solid #876;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
ul.options li:hover {
|
||||
background-color: rgba(153,136,119,0.2);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
ul.options li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
@ -170,9 +158,11 @@ h1 {
|
|||
color: #210;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #900;
|
||||
text-decoration: none;
|
||||
|
@ -180,7 +170,6 @@ a {
|
|||
}
|
||||
a.raw {
|
||||
padding-right: 14px;
|
||||
background: transparent url("../img/external_link.png") no-repeat right 4px;
|
||||
}
|
||||
a:hover {
|
||||
border-bottom: 1px dotted #900;
|
||||
|
@ -212,7 +201,7 @@ img.float_left {
|
|||
.tools {
|
||||
padding: 0.6em;
|
||||
width: 8.9em;
|
||||
background: #cec3ae url("../img/tools_bg.jpg") repeat left top;
|
||||
background: #cec3ae;
|
||||
position: absolute;
|
||||
}
|
||||
.tools p {
|
||||
|
@ -357,3 +346,26 @@ img.float_left {
|
|||
#menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@keyframes fade_in{
|
||||
from {
|
||||
color: rgba(0,0,0,0);
|
||||
}
|
||||
to {
|
||||
color: rgba(0,0,0,1);
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes fade_in{
|
||||
from {
|
||||
color: rgba(0,0,0,0);
|
||||
}
|
||||
to {
|
||||
color: rgba(0,0,0,1);
|
||||
}
|
||||
}
|
||||
|
||||
.fade {
|
||||
animation: fade_in 500ms ease-in-out;
|
||||
-webkit-animation: fade_in 500ms ease-in-out;
|
||||
}
|
|
@ -1,10 +1,53 @@
|
|||
var undum = require('./undum.js'),
|
||||
marked = require('marked'),
|
||||
md = require('markdown-it'),
|
||||
$ = require('jquery');
|
||||
|
||||
var markdown = function (content) {
|
||||
return marked(content, {smartypants: true});
|
||||
}
|
||||
/*
|
||||
Helper functions
|
||||
*/
|
||||
|
||||
/*
|
||||
Normalises the whitespace on a string. So the indentation level of the
|
||||
first line will become 0.
|
||||
*/
|
||||
|
||||
String.prototype.normaliseTabs = function () {
|
||||
let lines = this.split('\n');
|
||||
let indent = lines[0].match(/^\s+/) || lines[1].match(/^\s/);
|
||||
if (!indent) return this;
|
||||
return lines.map( s => s.replace('^' + indent[0], '')).join('\n');
|
||||
};
|
||||
|
||||
/* Agnostic Call */
|
||||
|
||||
Function.prototype.fcall = Function.prototype.call;
|
||||
|
||||
String.prototype.fcall = function () {return this;};
|
||||
|
||||
/*
|
||||
Markdown renderer.
|
||||
*/
|
||||
|
||||
var markdown = new md({
|
||||
typographer: true,
|
||||
html: true
|
||||
});
|
||||
|
||||
/*
|
||||
Ensures a string is a HTML string, by wrapping span tags.
|
||||
*/
|
||||
|
||||
String.prototype.spanWrap = function () {
|
||||
return `<span>${this}</span>`;
|
||||
};
|
||||
|
||||
/*
|
||||
Adds the "fade" class to some html.
|
||||
*/
|
||||
|
||||
String.prototype.fade = function () {
|
||||
return $(this).addClass('fade');
|
||||
};
|
||||
|
||||
var UndularitySituation = function (spec) {
|
||||
undum.Situation.call(this, spec);
|
||||
|
@ -12,20 +55,113 @@ var UndularitySituation = function (spec) {
|
|||
// API properties
|
||||
|
||||
this.content = spec.content;
|
||||
this.choices = (spec.choices === undefined) ? [] : spec.choices;
|
||||
this.writers = (spec.writers === undefined) ? {} : spec.writers;
|
||||
|
||||
this.visited = false;
|
||||
|
||||
};
|
||||
|
||||
UndularitySituation.prototype.enter = function (character, system, from) {
|
||||
console.log("got here");
|
||||
console.log(this);
|
||||
UndularitySituation.inherits(undum.Situation);
|
||||
|
||||
UndularitySituation.prototype.enter = function (character, system, f) {
|
||||
if (this.content) {
|
||||
system.write(this.content);
|
||||
system.write(markdown.render(this.content.fcall(this, character, system, f).normaliseTabs()));
|
||||
}
|
||||
|
||||
if (this.choices) {
|
||||
let choices = system.getSituationIdChoices(this.choices,
|
||||
this.minChoices, this.maxChoices);
|
||||
system.writeChoices(choices);
|
||||
}
|
||||
};
|
||||
|
||||
UndularitySituation.prototype.act = function (character, system, action) {
|
||||
var actionClass,
|
||||
self = this;
|
||||
|
||||
var responses = {
|
||||
writer: function (ref) {
|
||||
system.write(
|
||||
markdown.render(
|
||||
self.writers[ref].fcall(this, character, system, action)
|
||||
).fade());
|
||||
},
|
||||
replacer: function (ref) {
|
||||
console.log('Replacer called ', ref);
|
||||
system.replaceWith(
|
||||
markdown.renderInline(
|
||||
self.writers[ref].fcall(this, character, system, action)
|
||||
).spanWrap().fade(), `#${ref}`);
|
||||
}
|
||||
};
|
||||
|
||||
if (actionClass = action.match(/^_(\w+)_(.+)$/)) {
|
||||
responses[actionClass[1]](actionClass[2]);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/* Element Helpers */
|
||||
/*
|
||||
While you can write HTML elements by hand, those helpers make it easier to
|
||||
place anchors (especially with special purpose) and spans.
|
||||
|
||||
They define a monadic interface:
|
||||
|
||||
a().id('my-link').content('link').writer('my-ref')
|
||||
-> <a id="my-link" href="./_writer_my-ref">link</a>
|
||||
|
||||
span().here -> <span></span>
|
||||
*/
|
||||
|
||||
/* Anchor element */
|
||||
/* Transforms:
|
||||
content: The inner content of the link, as inline Markdown.
|
||||
id: A space-separated list of element ids.
|
||||
once: The 'once' special link class. A getter.
|
||||
*/
|
||||
|
||||
|
||||
var a = function () {
|
||||
var once = "",
|
||||
id = "",
|
||||
content = "";
|
||||
var monad = {
|
||||
writer: (ref) => `<a ${id} class="${once} writer" href="./_writer_${ref}">${markdown.renderInline(content)}</a>`,
|
||||
replacer: (ref) => `<a ${id} class="${once} replacer" href="./_replacer_${ref}">${markdown.renderInline(content)}</a>`,
|
||||
content: function (s) { content = s; return monad; },
|
||||
id: function (s) {id = `id="${s}"`; return monad; },
|
||||
get once () { once = "once"; return monad; }
|
||||
};
|
||||
return monad;
|
||||
};
|
||||
|
||||
var span = function (content) {
|
||||
var elementClass = "",
|
||||
id = "",
|
||||
content = "";
|
||||
var monad = {
|
||||
get here () { return `<span ${id} ${elementClass}>${content}</span>`; },
|
||||
id: function (s) {
|
||||
id = `id="${s}"`;
|
||||
return monad;
|
||||
},
|
||||
content: function (s) {
|
||||
content = s;
|
||||
return monad;
|
||||
},
|
||||
class: function (s) {
|
||||
elementClass = `class="${s}"`;
|
||||
return monad;
|
||||
}
|
||||
};
|
||||
return monad;
|
||||
}
|
||||
|
||||
module.exports = function (name, spec) {
|
||||
spec.name = name;
|
||||
spec.content = markdown(spec.content);
|
||||
undum.game.situations[name] = new UndularitySituation(spec);
|
||||
};
|
||||
|
||||
module.exports.a = a;
|
Loading…
Reference in a new issue