Начало
This commit is contained in:
commit
a209caa42d
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
index.html
|
4
Makefile
Normal file
4
Makefile
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
all:
|
||||||
|
tweego src -o index.html
|
||||||
|
test:
|
||||||
|
tweego -t src -o index.html
|
93
src/game.css
Normal file
93
src/game.css
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
html {
|
||||||
|
/* Vertical colour gradient */
|
||||||
|
background-image: linear-gradient(to bottom, gainsboro, silver);
|
||||||
|
background-image: -webkit-linear-gradient(top, gainsboro, silver);
|
||||||
|
background-attachment: fixed;
|
||||||
|
width: 100%;
|
||||||
|
/* Fallback colour */
|
||||||
|
background-color: papayawhip;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
background-color: transparent;
|
||||||
|
margin: 10% 0 0 0;
|
||||||
|
font-size: 100%;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
hr {
|
||||||
|
border-top: 1px solid #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#passages {
|
||||||
|
/* Box background (white with 70% opacity) */
|
||||||
|
background-color: rgba(255, 255, 255, 0.7);
|
||||||
|
|
||||||
|
/* Border */
|
||||||
|
border: 2px solid white;
|
||||||
|
|
||||||
|
/* Rounded corners */
|
||||||
|
border-radius: 1em;
|
||||||
|
|
||||||
|
/* Centered box */
|
||||||
|
display: inline-block;
|
||||||
|
width: 60%;
|
||||||
|
min-height: 40%;
|
||||||
|
margin:auto;
|
||||||
|
margin-bottom: 5%;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.passage {
|
||||||
|
margin: 0px;
|
||||||
|
padding: 2em;
|
||||||
|
|
||||||
|
/* Text formatting */
|
||||||
|
color: black;
|
||||||
|
font-size: 100%;
|
||||||
|
text-align:justify;
|
||||||
|
}
|
||||||
|
|
||||||
|
.red,
|
||||||
|
.green {,
|
||||||
|
transition: all .7s;
|
||||||
|
-webkit-transition: all .7s;
|
||||||
|
}
|
||||||
|
.red {
|
||||||
|
color: #420000;
|
||||||
|
}
|
||||||
|
.red:hover {
|
||||||
|
color: #DD0000;
|
||||||
|
}
|
||||||
|
.green {
|
||||||
|
color: #004200;
|
||||||
|
}
|
||||||
|
.green:hover {
|
||||||
|
color: #00DD00;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Links */
|
||||||
|
a.internalLink,
|
||||||
|
a.externalLink {
|
||||||
|
color: royalblue;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
a.internalLink:hover,
|
||||||
|
a.externalLink:hover {
|
||||||
|
color: deepskyblue;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
a.gamepadSelected {
|
||||||
|
border: 2px dotted blue;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shrink the page when viewed on devices with a low screen width */
|
||||||
|
@media screen and (max-width: 960px) {
|
||||||
|
#passages { width: 75%; }
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 840px) {
|
||||||
|
#passages { width: 85%; }
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 720px) {
|
||||||
|
#passages { width: 95%; }
|
||||||
|
}
|
111
src/game.tw
Normal file
111
src/game.tw
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
::StoryTitle
|
||||||
|
Космические Волны
|
||||||
|
::StorySettings
|
||||||
|
ifid:dcd7d6b9-0f25-4ce1-bff1-e603c67066d5
|
||||||
|
::StoryConfig [script]
|
||||||
|
Config.debug = true;
|
||||||
|
Config.ui.stowBarInitially = true;
|
||||||
|
Config.passages.nobr = true;
|
||||||
|
::Start
|
||||||
|
|
||||||
|
<!-- «Четвёртое измерение», «Дворцовые интриги» и «Городской житель случайно попадает в глухую деревню» -->
|
||||||
|
|
||||||
|
<center>
|
||||||
|
<h1 class="red">Космические Волны</h1>
|
||||||
|
<small>Oreolek</small>
|
||||||
|
</center>
|
||||||
|
|
||||||
|
<p>Сегодня вечером группа «Космические Волны» выступает с единственным концертом на Луне. Вам <b>необходимо</b> попасть на ракету Москва-кратер Аль-Баттани C. Сумка уже собрана, но можно что-то повесить на себя. Что же взять с собой в дорогу?</p>
|
||||||
|
|
||||||
|
<ul class="choices">
|
||||||
|
<li>[[Гитару, чтобы получить на ней автограф|guitar]]</li>
|
||||||
|
<li>[[Вязаную шапку, чтобы не замёрзли уши|hat]]</li>
|
||||||
|
<li>[[Бутылочку домашней настойки|bottle]]</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
::guitar
|
||||||
|
<<set $inventory to 'guitar' >>
|
||||||
|
<p>Вряд ли получится протолкнуться в зону автографов, но вы очень надеетесь на свою уникальную удачу. Без гитары — никуда.</p>
|
||||||
|
|
||||||
|
<<include flight>>
|
||||||
|
|
||||||
|
::hat
|
||||||
|
<<set $inventory to 'hat' >>
|
||||||
|
<p>На этой шапке тоже нарисованы уши. Говорят, что сначала лунный холод отмораживает их, а потом уже принимается за ваши собственные.</p>
|
||||||
|
|
||||||
|
<<include flight>>
|
||||||
|
|
||||||
|
::bottle
|
||||||
|
<<set $inventory to 'bottle' >>
|
||||||
|
<p>Чёрная смородина, мёд, шишки и немного веселья для полного отрыва на концерте.
|
||||||
|
Будет незабываемо.</p>
|
||||||
|
|
||||||
|
<<include flight>>
|
||||||
|
|
||||||
|
::flight
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>В ракете вас пристёгивают к жёсткому креслу. <<if $inventory is 'guitar'>> Вы отвоевали право не расставаться с гитарой, но вот сумку пришлось отдать стюардессе на хранение. <<else>> Сумку пришлось отдать на хранение стюардессе. <</if>></p>
|
||||||
|
|
||||||
|
<p>На подлёте к Луне вы слышите громкое <span class="red">хлоп.</span> Затем мимо вас проплывает пилот в пухлом скафандре, отталкиваясь руками от кресел.</p>
|
||||||
|
|
||||||
|
<ul class="choices">
|
||||||
|
<li>[[Попробовать освободиться|escape]]</li>
|
||||||
|
<li>[[Ждать|wait]]</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
::escape
|
||||||
|
|
||||||
|
<<set $escape to true >>
|
||||||
|
|
||||||
|
<p>Вы отстёгиваете один из ремней. Теперь вы можете поворачивать туловище.</p>
|
||||||
|
|
||||||
|
<<include escape2>>
|
||||||
|
|
||||||
|
::wait
|
||||||
|
|
||||||
|
<<include escape2>>
|
||||||
|
|
||||||
|
::escape2
|
||||||
|
|
||||||
|
<p><span class="red">хлоп.</span></p>
|
||||||
|
|
||||||
|
<p>Внезапно ракета вокруг просто… перестаёт быть. С тихим <span class="red">пуф</span> вы падаете спиной назад на что-то тёплое.
|
||||||
|
Над головой светит красное небо.
|
||||||
|
<<if $escape is true>>
|
||||||
|
<<if $inventory is 'guitar'>>
|
||||||
|
И гитары в руках тоже больше нет.
|
||||||
|
<<elseif $inventory is 'hat'>>
|
||||||
|
И шапки на голове тоже больше нет.
|
||||||
|
<<else>>
|
||||||
|
И бутылки в кармане тоже больше нет.
|
||||||
|
<</if>>
|
||||||
|
<<set $inventory to ''>>
|
||||||
|
<</if>>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><span class="green">— Паис! Паис!</span> — кричит женский голос.</p>
|
||||||
|
|
||||||
|
<p>К вам подбегает <<link "чумазая девушка">><<replace "#look" t8n>>
|
||||||
|
Русоволосая девушка лет двадцати в рабочем комбинезоне и резиновых сапогах.
|
||||||
|
<</replace>><</link>> и помогает встать. Вы оглядываетесь: под вами без чувств лежит какой-то мужчина.</p>
|
||||||
|
|
||||||
|
<p><span class="green">— Паис! Вставай!</span></p>
|
||||||
|
|
||||||
|
<p>Вы оглядываетесь. Кроваво-красное небо, жёлтые колосья пшеницы в чёрном песке, какие-то дома вдалеке.
|
||||||
|
Вы не знаете, где очутились.</p>
|
||||||
|
|
||||||
|
<span id="look"></span>
|
||||||
|
|
||||||
|
<ul class="choices">
|
||||||
|
<li>[[Разбудить мужчину|man]]</li>
|
||||||
|
<li>[[Тихо уйти|away]]</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
::away
|
||||||
|
|
||||||
|
<p>Вы отходите на несколько шагов и наступаете на незаметную яму.
|
||||||
|
Нога вязнет в чёрном песке, за ней застревает и вторая.</p>
|
||||||
|
|
||||||
|
<p>Девушка расталкивает мужчину; тот встаёт
|
23
src/gamepad.min.js
vendored
Normal file
23
src/gamepad.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
181
src/twine_gamepad.js
Normal file
181
src/twine_gamepad.js
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
/* @license
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 mildmojo
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function(exports) {
|
||||||
|
var Gamepad = window.Gamepad;
|
||||||
|
|
||||||
|
// Removed until it's tested with node-webkit.
|
||||||
|
// if ((typeof(module) !== 'undefined') && module.exports) {
|
||||||
|
// Gamepad = require('gamepad');
|
||||||
|
// } else {
|
||||||
|
// Gamepad = window.Gamepad;
|
||||||
|
// }
|
||||||
|
|
||||||
|
var gamepad = new Gamepad();
|
||||||
|
var axes = { LEFT_STICK_X: 0, LEFT_STICK_Y: 0 };
|
||||||
|
var DEADZONE = 0.5;
|
||||||
|
|
||||||
|
gamepad.bind(Gamepad.Event.CONNECTED, function(_device) {
|
||||||
|
console.log('Gamepad connected.');
|
||||||
|
});
|
||||||
|
|
||||||
|
gamepad.bind(Gamepad.Event.DISCONNECTED, function(_device) {
|
||||||
|
console.log('Gamepad disconnected.');
|
||||||
|
});
|
||||||
|
|
||||||
|
gamepad.bind(Gamepad.Event.BUTTON_DOWN, function(e) {
|
||||||
|
switch(e.control) {
|
||||||
|
case 'DPAD_DOWN':
|
||||||
|
case 'DPAD_RIGHT':
|
||||||
|
nextLink();
|
||||||
|
break;
|
||||||
|
case 'DPAD_UP':
|
||||||
|
case 'DPAD_LEFT':
|
||||||
|
prevLink();
|
||||||
|
break;
|
||||||
|
case 'FACE_1':
|
||||||
|
case 'FACE_2':
|
||||||
|
case 'FACE_3':
|
||||||
|
case 'FACE_4':
|
||||||
|
var selected = document.querySelector('.gamepadSelected');
|
||||||
|
if (selected) {
|
||||||
|
removeClass(selected, 'gamepadSelected');
|
||||||
|
selected.dispatchEvent(new MouseEvent('click'));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Treat axes as buttons; register presses and releases.
|
||||||
|
gamepad.bind(Gamepad.Event.AXIS_CHANGED, function(data) {
|
||||||
|
var newValue = 0;
|
||||||
|
if (Math.abs(data.value) > DEADZONE) {
|
||||||
|
newValue = data.value < 0 ? -1 : 1;
|
||||||
|
if (axes[data.axis] !== newValue) {
|
||||||
|
if (data.axis === 'LEFT_STICK_X') {
|
||||||
|
if (newValue === -1) {
|
||||||
|
gamepad._fire(Gamepad.Event.BUTTON_DOWN, {control: 'DPAD_LEFT'});
|
||||||
|
} else {
|
||||||
|
gamepad._fire(Gamepad.Event.BUTTON_DOWN, {control: 'DPAD_RIGHT'});
|
||||||
|
}
|
||||||
|
} else if (data.axis === 'LEFT_STICK_Y') {
|
||||||
|
if (newValue === 1) {
|
||||||
|
gamepad._fire(Gamepad.Event.BUTTON_DOWN, {control: 'DPAD_DOWN'});
|
||||||
|
} else {
|
||||||
|
gamepad._fire(Gamepad.Event.BUTTON_DOWN, {control: 'DPAD_UP'});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
axes[data.axis] = newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
gamepad.init();
|
||||||
|
|
||||||
|
function nextLink() {
|
||||||
|
var links = getTwineLinks();
|
||||||
|
if (links === null) return;
|
||||||
|
var selectedIndex = findSelectedIndex(links);
|
||||||
|
var newIndex = 0;
|
||||||
|
if (selectedIndex !== null) {
|
||||||
|
removeClass(links[selectedIndex], 'gamepadSelected');
|
||||||
|
newIndex = (selectedIndex + 1) % links.length
|
||||||
|
}
|
||||||
|
addClass(links[newIndex], 'gamepadSelected');
|
||||||
|
showLink();
|
||||||
|
}
|
||||||
|
|
||||||
|
function prevLink() {
|
||||||
|
var links = getTwineLinks();
|
||||||
|
if (links === null) return;
|
||||||
|
var selectedIndex = findSelectedIndex(links);
|
||||||
|
var newIndex = 0;
|
||||||
|
if (selectedIndex !== null) {
|
||||||
|
removeClass(links[selectedIndex], 'gamepadSelected');
|
||||||
|
newIndex = selectedIndex > 0 ? selectedIndex - 1 : links.length - 1;
|
||||||
|
}
|
||||||
|
addClass(links[newIndex], 'gamepadSelected');
|
||||||
|
showLink();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showLink() {
|
||||||
|
var selected = document.querySelector('.gamepadSelected');
|
||||||
|
if (selected && !isVisible(selected)) {
|
||||||
|
var position = isAboveViewport(selected)
|
||||||
|
selected.scrollIntoView(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTwineLinks() {
|
||||||
|
return document.querySelectorAll('a.internalLink, a.externalLink');
|
||||||
|
}
|
||||||
|
|
||||||
|
function findSelectedIndex(links) {
|
||||||
|
for (var i = 0; i < links.length; i++) {
|
||||||
|
if (hasClass(links[i], 'gamepadSelected')) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isVisible(el) {
|
||||||
|
var offset = el.getBoundingClientRect();
|
||||||
|
if (offset.left < 0 || offset.top < 0){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (offset.left > window.innerWidth || offset.top > window.innerHeight){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isAboveViewport(el) {
|
||||||
|
return el.getBoundingClientRect().top < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// From youmightnotneedjquery.com
|
||||||
|
function hasClass(el, className) {
|
||||||
|
if (el.classList)
|
||||||
|
return el.classList.contains(className);
|
||||||
|
else
|
||||||
|
return new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className);
|
||||||
|
}
|
||||||
|
|
||||||
|
// From youmightnotneedjquery.com
|
||||||
|
function removeClass(el, className) {
|
||||||
|
if (el.classList)
|
||||||
|
el.classList.remove(className);
|
||||||
|
else
|
||||||
|
el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
// From youmightnotneedjquery.com
|
||||||
|
function addClass(el, className) {
|
||||||
|
if (el.classList)
|
||||||
|
el.classList.add(className);
|
||||||
|
else
|
||||||
|
el.className += ' ' + className;
|
||||||
|
}
|
||||||
|
|
||||||
|
})(((typeof(module) !== 'undefined') && module.exports) || window);
|
Loading…
Reference in a new issue