Начало игры
This commit is contained in:
parent
d9dc8ea5ef
commit
2515a5ff91
|
@ -43,9 +43,6 @@ gulp.task('sass', () ->
|
|||
|
||||
gulp.task('concatCoffee', () ->
|
||||
gulp.src([
|
||||
## additional functions
|
||||
'./game/dialogue.coffee',
|
||||
'./game/phrase.coffee',
|
||||
## the actual game
|
||||
'./game/begin.coffee',
|
||||
'./game/story.coffee',
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
salet.game_id = "your-game-id-here"
|
||||
salet.game_version = "1.6"
|
||||
salet.game_id = "2156049f-ca32-4460-a363-feb1caaa2a39"
|
||||
salet.game_version = "1.0"
|
||||
$(document).ready(() ->
|
||||
window.addEventListener('popstate', (event) ->
|
||||
salet.goBack()
|
||||
|
@ -28,46 +28,9 @@ $(document).ready(() ->
|
|||
salet.beginGame()
|
||||
)
|
||||
|
||||
###
|
||||
Element helpers. There is no real need to build monsters like a().id("hello")
|
||||
because you won't use them as is. It does not make sense in context, the
|
||||
author has Markdown and all utilities to *forget* about the markup.
|
||||
###
|
||||
way_to = (content, ref) ->
|
||||
return "<a href='#{ref}' class='way'>#{content}</a>"
|
||||
textlink = (content, ref) ->
|
||||
return "<a href='./_writer_#{ref}' class='once'>#{content}</a>"
|
||||
actlink = (content, ref) ->
|
||||
return "<a href='./#{ref}' class='once'>#{content}</a>"
|
||||
|
||||
# The first room of the game.
|
||||
# For accessibility reasons the text is provided in HTML, not here.
|
||||
room "start",
|
||||
enter: () ->
|
||||
salet.character.bought_lamp = false
|
||||
dsc: """
|
||||
""",
|
||||
choices: "#start"
|
||||
|
||||
# This is a special inventory room.
|
||||
# The inventory button is a regular link to this room.
|
||||
# You may alter these as much as you like or scrap it along with the button.
|
||||
room "inventory",
|
||||
canSave: false # saving the game here is forbidden. Aautosaving too.
|
||||
enter: () ->
|
||||
$("#inventory").hide()
|
||||
exit: () ->
|
||||
$("#inventory").show()
|
||||
dsc: () ->
|
||||
if salet.character.inventory.length == 0
|
||||
text = "You are carrying nothing."
|
||||
else
|
||||
text = "You are carrying:\n\n"
|
||||
for thing in salet.character.inventory
|
||||
text += "* #{salet.character.listinv(thing.name)}\n"
|
||||
return text+"\n\n"+"""
|
||||
<div class="center"><a href="./exit"><button class="btn btn-lg btn-outline-primary">Go back</button></a></div>
|
||||
"""
|
||||
actions:
|
||||
exit: () ->
|
||||
return salet.goBack()
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
###
|
||||
A dialogue shortcut.
|
||||
Usage:
|
||||
|
||||
dialogue "Point out a thing in her purse (mildly)", "start", "mild", """
|
||||
Point out a thing in her purse (mildly)
|
||||
""", "character.mild = true"
|
||||
###
|
||||
dialogue = (title, startTag, endTag, text, effect) ->
|
||||
retval = room("dialogue_"+Object.keys(salet.rooms).length, {
|
||||
optionText: title
|
||||
dsc: text
|
||||
clear: false # backlog is useful in dialogues
|
||||
choices: "#"+endTag
|
||||
})
|
||||
if typeof(startTag) == "string"
|
||||
retval.tags = [startTag]
|
||||
else if typeof(startTag) == "object"
|
||||
retval.tags = startTag
|
||||
if effect?
|
||||
retval.before = (character, system) ->
|
||||
eval(effect)
|
||||
return retval
|
|
@ -1,26 +0,0 @@
|
|||
###
|
||||
A phrase shortcut.
|
||||
Usage:
|
||||
|
||||
phrase "Point out a thing in her purse (mildly)", "start", """
|
||||
Point out a thing in her purse (mildly)
|
||||
""", "character.sandbox.mild = true"
|
||||
|
||||
@param title phrase Phrase (question)
|
||||
@param salet Salet core
|
||||
@param string tag tag marking viewing condition
|
||||
@param string text Response
|
||||
@param string effect an optional parameter, eval'd code
|
||||
###
|
||||
phrase = (title, tag, text, effect) ->
|
||||
retval = room("phrase_"+salet.rooms.length, {
|
||||
optionText: title
|
||||
dsc: text
|
||||
clear: false # backlog is useful in dialogues
|
||||
choices: "#"+tag
|
||||
tags: [tag]
|
||||
})
|
||||
if effect?
|
||||
retval.before = (character, system) ->
|
||||
eval(effect)
|
||||
return retval
|
|
@ -1,126 +1,63 @@
|
|||
room "world",
|
||||
tags: ["start"],
|
||||
optionText: "Enter the world",
|
||||
ways: ["plaza"]
|
||||
dsc: """
|
||||
### Rhinestone Room
|
||||
croom = (name, spec) ->
|
||||
spec.clear = false
|
||||
if spec.onexit
|
||||
spec.exit = () ->
|
||||
salet.view.write('<span class="shake">'+@onexit+'</span>')
|
||||
return true
|
||||
return room(name, spec)
|
||||
|
||||
You're in a large room carved inside a giant milky rock mountain.
|
||||
The floor and walls are littered with signs and signatures of the previous visitors.
|
||||
croom "start",
|
||||
dsc: """
|
||||
Вы спокойно работаете в уютном кабинете #{way_to('без мебели и окон.', 'line2')}
|
||||
"""
|
||||
units: [
|
||||
unit "well",
|
||||
dsc: "A steep narrow {{well}} proceeds upward."
|
||||
act: "There is only one passage out. See the „Other rooms“ block popped up? Click it."
|
||||
]
|
||||
onexit: "шурх-шурх-шурх"
|
||||
|
||||
room "plaza",
|
||||
title: (from) ->
|
||||
if from == "world"
|
||||
return "Upwards"
|
||||
else
|
||||
return "Town plaza"
|
||||
cycle: ["quirky", "distinct", "kooky", "crazy", "quaint"]
|
||||
ways: ["shop"]
|
||||
before: (from) ->
|
||||
if from == 'world'
|
||||
"""
|
||||
You climb up the well and come out to a central plaza of a #{salet.view.cycleLink("quaint")} little town.
|
||||
A plaque nearby says it's the town of *Innsmouth,* wherever that is.
|
||||
"""
|
||||
else
|
||||
"You quickly find the central plaza."
|
||||
units: [
|
||||
unit "policeman",
|
||||
dsc: "There is a policeman nearby. You could ask him {{for directions.}}"
|
||||
act: () ->
|
||||
if salet.character.has_mark?
|
||||
return "You already talked to him, no need to bug the man twice."
|
||||
salet.character.has_mark ?= true
|
||||
salet.getRoom("lair").destination()
|
||||
"""
|
||||
“Here, let me mark it on your map.”
|
||||
"""
|
||||
unit "people",
|
||||
dsc: "There are {{people shouting}} nearby."
|
||||
act: 'Just some weirdos shouting "Viva la Cthulhu!". Typical.'
|
||||
]
|
||||
|
||||
room "shop",
|
||||
title: "The Shop"
|
||||
#pic: "http://loremflickr.com/640/300/room,shop"
|
||||
ways: ["plaza", "shop-inside", "lair"]
|
||||
croom "line2",
|
||||
dsc: """
|
||||
Being the only shop in town, this trendy establishment did not need a name.
|
||||
It's an open question why it had one, especially because its name was "Hung Crossing".
|
||||
Вы перемалываете листья платкодрева.
|
||||
Это возможно только голыми руками, #{way_to('в полной темноте.', 'line3')}
|
||||
"""
|
||||
onexit: "шурх-шурх-шурх"
|
||||
|
||||
You are standing in front of a picturesque sign. It's cold here.
|
||||
croom "line3",
|
||||
dsc: """
|
||||
Плотные кожистые лист падают с потолка.
|
||||
Вы слышите, как он застывает в углу комнаты.
|
||||
|
||||
Длинный влажный хобот касается ноги.
|
||||
Кромюл ищет перемолотые листья и всасывает их.
|
||||
Вам не нужно вставать.
|
||||
|
||||
#{way_to('Продолжайте перемалывать.', 'dream1')}
|
||||
"""
|
||||
onexit: "шурх-шурх-шурх"
|
||||
|
||||
croom "dream1",
|
||||
dsc: """
|
||||
Из воды чёрного от грязи моря выходит разбойник.
|
||||
На нём намного больше волос, чем одежды.
|
||||
Его лодка разбилась на камнях, его друзья в лучшем мире.
|
||||
"""
|
||||
options: ["dream2a", "dream2b"]
|
||||
|
||||
croom "dream2a",
|
||||
optionText: "Он направляется по берегу."
|
||||
dsc: """
|
||||
"""
|
||||
|
||||
room "lair",
|
||||
title: "The Lair"
|
||||
before: "Finding The Lair is easy. Leaving it is impossible. Your game ends here."
|
||||
croom "dream2b",
|
||||
optionText: "Он направляется вглубь земли."
|
||||
dsc: """
|
||||
The Lair of Yog-Sothoth is a very *n'gai* cave, full of *buggs-shoggogs* and *n'ghaa ng'aa*.
|
||||
"""
|
||||
ways: ["shop"]
|
||||
units: [
|
||||
unit "bugg",
|
||||
dsc: "You see a particularly beautiful slimy {{bugg.}}"
|
||||
takeable: false
|
||||
display: "bugg"
|
||||
act: () =>
|
||||
salet.rooms[salet.current].drop("bugg")
|
||||
return "You eat the bugg mass. Delicious and raw. Perhaps it's a good lair to live in."
|
||||
]
|
||||
|
||||
phrase "Yes", "merchant", """
|
||||
Yes.
|
||||
"""
|
||||
dialogue "No", "merchant", "merchant", """
|
||||
No.
|
||||
"""
|
||||
room "sell-lamp",
|
||||
ways: ["shop"]
|
||||
tags: ["merchant"]
|
||||
choices: ["#merchant"]
|
||||
optionText: "May I buy this lamp?"
|
||||
title: "Talking with merchant"
|
||||
canView: () ->
|
||||
return salet.character.has("lamp") and salet.character.bought_lamp == false
|
||||
enter: () ->
|
||||
salet.character.bought_lamp = true
|
||||
dsc: """
|
||||
"That'll be 30 pieces of your time."
|
||||
|
||||
You quickly pay the price and take the lamp as a rightful owner.
|
||||
"""
|
||||
|
||||
room "shop-inside",
|
||||
ways: ["shop"]
|
||||
tags: ["merchant"]
|
||||
optionText: "End the conversation"
|
||||
title: "Inside the Shop"
|
||||
croom "line4",
|
||||
dsc: """
|
||||
The insides are painted pastel white, honouring The Great Milk Spill of 1985.
|
||||
"""
|
||||
units: [
|
||||
unit "merchant",
|
||||
dsc: "A {{merchant}} eyes you warily."
|
||||
takeable: false
|
||||
act: () =>
|
||||
salet.processClick("merchdialogue")
|
||||
return ""
|
||||
]
|
||||
Пары платкодрева вызывают галлюцинации.
|
||||
Но кромюлы не волнуются.
|
||||
Что с того, что человек видит сны наяву?
|
||||
|
||||
lamp = unit "lamp",
|
||||
display: "lamp"
|
||||
takeable: true
|
||||
lamp.put("shop-inside")
|
||||
А ещё эти пары ядовиты.
|
||||
Кромюлы не волнуются.
|
||||
|
||||
# The dialogue entry point has to be a room, in order to have an ID to go to.
|
||||
room "merchdialogue",
|
||||
choices: "#merchant",
|
||||
dsc: """
|
||||
Nice day, isn't it?
|
||||
А вам зачем беспокоиться?
|
||||
"""
|
||||
|
|
|
@ -1,64 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Salet showcase</title>
|
||||
<title>Чистильщик</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href='https://fonts.googleapis.com/css?family=PT+Sans:400,400italic|PT+Sans+Caption' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="css/main.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="page">
|
||||
<div class="fixed container">
|
||||
<div id="tools_wrapper" class="row">
|
||||
<div class='ways'>
|
||||
<small class="text-muted" id="ways_hint">Click these links to explore other rooms</small>
|
||||
<ul class="nav nav-pills" id="ways">
|
||||
</ul>
|
||||
</div>
|
||||
<div class='ways'></div>
|
||||
<div class="buttons">
|
||||
<a href="inventory"><button id="inventory" class="btn btn-outline-primary">Inventory</button></a>
|
||||
<button id="night" class="btn btn-outline-primary">Night mode</button>
|
||||
<button id="erase" class="btn btn-outline-danger">Restart</button>
|
||||
<button id="night" class="btn btn-outline-primary">Ночной режим</button>
|
||||
<button id="erase" class="btn btn-outline-danger">Заново</button>
|
||||
</div>
|
||||
</div> <!-- End of div.tools_wrapper -->
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div id="title" class="title">
|
||||
<div class="label">
|
||||
<h1>Salet</h1>
|
||||
<h2>A general cybertext IF engine</h2>
|
||||
<noscript>
|
||||
<p class="noscript_message">This game requires Javascript.</p>
|
||||
</noscript>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="content_wrapper" class="row">
|
||||
<div id="intro" class="content">
|
||||
<section>
|
||||
<!-- For the accessibility reasons, you really should begin your game here.
|
||||
Write a short intro the player will read while the Javascript is loading and executing.
|
||||
It has to be HTML but that shouldn't be a BIG problem if you're reading this.
|
||||
On the other hand this means the first intro passages will be non-interactive. -->
|
||||
<p><em>Salet</em> is an offspring of Undum and Raconteur.</p>
|
||||
<p>The project is still a work-in-progress. This "game" will show you some of the new features.</p>
|
||||
<p>It's supposed to be relatively painless for the author without sacrificing the reader's experience.
|
||||
For example, the game still loads while you're reading this.</p>
|
||||
<p><em>Salet</em> is <em>not</em> a library or a framework you can slap something on.
|
||||
It's more a game you can hack into your game. (Like Undum, yeah.)</p>
|
||||
<p>There are no either cool editor or clear instructions.
|
||||
You'll have to copy the source code and edit the CoffeeScript files in the <code>game</code> folder.
|
||||
Then <em>compile</em> them.</p>
|
||||
<p>This is neither a technical documentation nor UI tutorial, this is a <em>game.</em>
|
||||
You're supposed to note all the cool and curious features yourself.
|
||||
If you want some technical info, there are the <a href="http://git.oreolek.ru/oreolek/salet">source code</a> and a <a href="https://salet.su">wiki.</a></p>
|
||||
<p>I'm just here to point out that you are playing this in the web browser, online.
|
||||
And you don't need to learn <em>The Complete Javascript, Volumes I-III</em> to write in this style.</p>
|
||||
<p>So let me show you... The World.</p>
|
||||
|
||||
<noscript>You need to turn on Javascript to play this game.</noscript>
|
||||
</section>
|
||||
</div>
|
||||
|
@ -66,17 +29,6 @@
|
|||
</div>
|
||||
<a name="end_of_content"></a>
|
||||
</div>
|
||||
<div id="legal" class="row">
|
||||
<div id="footleft">
|
||||
<p>
|
||||
If you want to know how this game was made, check out <a
|
||||
href="https://git.oreolek.ru/oreolek/salet" target="_blank">the
|
||||
source code.</a>
|
||||
</p>
|
||||
</div>
|
||||
<div id="footright">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- End of div.page -->
|
||||
|
||||
|
|
|
@ -1,46 +1,7 @@
|
|||
@import "variables";
|
||||
@import "../node_modules/bootstrap/scss/bootstrap.scss";
|
||||
@import "shake";
|
||||
|
||||
// The title block
|
||||
.title {
|
||||
margin-top: 3.5em;
|
||||
@extend .col-xs-12;
|
||||
.label {
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 1em;
|
||||
@extend .col-md-8;
|
||||
@extend .offset-md-2;
|
||||
@extend .col-xs-12;
|
||||
text-align: center;
|
||||
}
|
||||
.subtitle {
|
||||
font-size: smaller;
|
||||
color: #aaa;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
.warnings {
|
||||
font-size: small;
|
||||
font-style: italic;
|
||||
p {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
}
|
||||
.noscript_message {
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
font-size: 0.9em;
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
color: #943;
|
||||
}
|
||||
}
|
||||
#choices {
|
||||
@extend .col-xs-12;
|
||||
}
|
||||
.fixed {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
|
@ -103,27 +64,6 @@
|
|||
text-align: center;
|
||||
}
|
||||
}
|
||||
#legal {
|
||||
margin-top: 1em;
|
||||
color: darken($body-color, 10%);
|
||||
font-size: smaller;
|
||||
#footleft {
|
||||
@extend .col-md-5;
|
||||
@extend .offset-md-2;
|
||||
@extend .col-xs-12;
|
||||
}
|
||||
#footright {
|
||||
text-align: right;
|
||||
@extend .col-md-2;
|
||||
@extend .offset-md-2;
|
||||
@extend .col-xs-12;
|
||||
}
|
||||
}
|
||||
|
||||
.way {
|
||||
color: $waycolor;
|
||||
margin-right: 1em;
|
||||
}
|
||||
.cycle {
|
||||
color: darkgreen;
|
||||
border-bottom: darkgreen dashed 1px;
|
||||
|
@ -156,3 +96,9 @@ hr {
|
|||
border: none;
|
||||
border-color: transparent;
|
||||
}
|
||||
.shake {
|
||||
color: grey;
|
||||
font-size: smaller;
|
||||
margin-left: 3em;
|
||||
@include do-shake('shake-crazy', 5, 5, 20, 150ms, .1, $opacity: false, $q: 5);
|
||||
}
|
||||
|
|
103
sass/shake.scss
Normal file
103
sass/shake.scss
Normal file
|
@ -0,0 +1,103 @@
|
|||
// Variables
|
||||
$prefix: 'shake' !default;
|
||||
$trigger: 'shake-trigger' !default;
|
||||
|
||||
// Placeholders
|
||||
%shake {
|
||||
display: inline-block;
|
||||
transform-origin: center center;
|
||||
}
|
||||
|
||||
%paused { animation-play-state: paused; }
|
||||
%running { animation-play-state: running; }
|
||||
|
||||
@function apply-random($input) {
|
||||
@return if($input != 0, random($input) - $input/2, 0);
|
||||
}
|
||||
|
||||
/// Do The Shake
|
||||
/// @param {String} $name ['shake'] - Name for the keyframes animation
|
||||
/// @param {Number} $h [5px] - Max number for random to assign in x axis
|
||||
/// @param {Number} $v [5px] - Max number for random to assign in y axis
|
||||
/// @param {Number} $r [3deg] - Max number for random rotation
|
||||
/// @param {Number} $dur [100ms] - animation-duration; valid time value
|
||||
/// @param {Number} $precision [.1] - Precision of the keyframes animation (i.e 2 > 2%, 4%, 6%...)
|
||||
/// @param {Boolean} $opacity [false] - To apply random animation also in the opacity property
|
||||
/// @param {String} $q [infinite] - animation-iteration-count; valid value
|
||||
/// @param {String} $t [ease-in-out] - animation-timing-function; valid value
|
||||
/// @param {Number} $delay [null] - animation-delay; valid time value
|
||||
/// @param {Number} $chunk [100%] - Part of 100% where apply the animation
|
||||
@mixin do-shake(
|
||||
$name: 'shake',
|
||||
$h: 5px,
|
||||
$v: 5px,
|
||||
$r: 3deg,
|
||||
$dur: 100ms,
|
||||
$precision: .02,
|
||||
$opacity: false,
|
||||
$q: infinite,
|
||||
$t: ease-in-out,
|
||||
$delay: null,
|
||||
$chunk: 100%
|
||||
) {
|
||||
|
||||
$rotate: 0;
|
||||
$move-x: 0;
|
||||
$move-y: 0;
|
||||
|
||||
$h: if(unitless($h) and $h != 0, $h * 1px, $h);
|
||||
$v: if(unitless($v) and $v != 0, $v * 1px, $v);
|
||||
$r: if(unitless($r) and $r != 0, $r * 1deg, $r);
|
||||
|
||||
// Keyframes
|
||||
@at-root {
|
||||
@keyframes #{$name} {
|
||||
$interval: if($precision > 0 and $precision < 1, 100 * $precision, 10);
|
||||
$step: $interval * 1%;
|
||||
|
||||
@while $step < $chunk {
|
||||
$rotate: apply-random($r);
|
||||
$move-x: apply-random($h);
|
||||
$move-y: apply-random($v);
|
||||
|
||||
#{$step} {
|
||||
transform: translate($move-x, $move-y) rotate($rotate);
|
||||
@if $opacity { opacity: random(100) / 100; }
|
||||
}
|
||||
|
||||
$step: $step + $interval;
|
||||
}
|
||||
|
||||
#{ if($chunk < 100%, (0%, $chunk, 100%), (0%, 100%)) } {
|
||||
transform: translate(0, 0) rotate(0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@extend %shake;
|
||||
|
||||
&:hover,
|
||||
.#{$trigger}:hover &,
|
||||
&.#{$prefix}-freeze,
|
||||
&.#{$prefix}-constant {
|
||||
@if $delay { animation-delay: $delay; }
|
||||
animation-name: #{$name};
|
||||
animation-duration: $dur;
|
||||
animation-timing-function: $t;
|
||||
animation-iteration-count: $q;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
.#{$trigger}:hover & { @extend %running; }
|
||||
|
||||
}
|
||||
|
||||
.#{$prefix}-freeze,
|
||||
.#{$prefix}-constant.#{$prefix}-constant--hover:hover,
|
||||
.#{$trigger}:hover .#{$prefix}-constant.#{$prefix}-constant--hover {
|
||||
@extend %paused;
|
||||
}
|
||||
|
||||
.#{$prefix}-freeze:hover,
|
||||
.#{$trigger}:hover .#{$prefix}-freeze { @extend %running; }
|
Loading…
Reference in a new issue