1
0
Fork 0
mirror of https://github.com/Oreolek/shooter.git synced 2024-05-26 04:38:10 +03:00

Version 0.5 - the minimal playable version.

This commit is contained in:
Alexander Yakovlev 2015-12-01 16:43:51 +07:00
parent 9df72b5ae3
commit 0c32acd500
6 changed files with 247 additions and 27 deletions

View file

@ -26,7 +26,7 @@ var reload = browserSync.reload;
function html (target) { function html (target) {
return function () { return function () {
return gulp.src('html/index.html') return gulp.src(['html/index.html','html/en.html'])
.pipe(gulp.dest(target)); .pipe(gulp.dest(target));
}; };
} }
@ -158,4 +158,4 @@ gulp.task('zip', ['dist'], function () {
return gulp.src('dist/**') return gulp.src('dist/**')
.pipe(zip('dist.zip')) .pipe(zip('dist.zip'))
.pipe(gulp.dest('.')); .pipe(gulp.dest('.'));
}); });

View file

@ -1,5 +1,6 @@
# copyright (c) Alexander Yakovlev 2015. # copyright (c) Alexander Yakovlev 2015.
# Distributed under the MIT license. See LICENSE for information. # This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
# To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0
situation = require('raconteur') situation = require('raconteur')
undum = require('undum-commonjs') undum = require('undum-commonjs')
@ -13,13 +14,15 @@ markdown = new md({
typographer: true, typographer: true,
html: true html: true
}) })
undumloc = require("./ru.coffee").language
undum.language["ru"] = undumloc
a = elements.a a = elements.a
span = elements.span span = elements.span
img = elements.img img = elements.img
undum.game.id = "7a1aba32-f0fd-4e3b-ba5a-59e3fa9e6012" undum.game.id = "7a1aba32-f0fd-4e3b-ba5a-59e3fa9e6012"
undum.game.version = "0.1" undum.game.version = "0.5"
way_to = (content, ref) -> a(content).class('way').ref(ref) way_to = (content, ref) -> a(content).class('way').ref(ref)
textlink = (content, ref) -> a(content).once().writer(ref) textlink = (content, ref) -> a(content).once().writer(ref)
@ -31,6 +34,11 @@ writemd = (system, text) ->
link_colour = "#B68000" link_colour = "#B68000"
# This is an easy game.
# I'm thinking if you want more harder approach, you can:
# a) remove bullet counter (you don't know how many bullets left in a clip)
# b) remove canChoose restriction (you can shoot any time you want, but if you have no bullets - nothing comes out and you've lost a turn)
spend_bullet = (character, system) -> spend_bullet = (character, system) ->
bullets = character.sandbox.clips[character.sandbox.current_clip] bullets = character.sandbox.clips[character.sandbox.current_clip]
if bullets >= 1 if bullets >= 1
@ -38,21 +46,25 @@ spend_bullet = (character, system) ->
system.setQuality("bullets", bullets - 1) system.setQuality("bullets", bullets - 1)
spend_clip = (character, system) -> spend_clip = (character, system) ->
clips = character.sandbox.clips.length
bullets = character.sandbox.clips[character.sandbox.current_clip] bullets = character.sandbox.clips[character.sandbox.current_clip]
if clips == 0 clips = character.sandbox.clips.length
if clips < 2
return return
if bullets == 0 if bullets == 0
character.sandbox.clips.splice(character.sandbox.current_clip, 1) character.sandbox.clips.splice(character.sandbox.current_clip, 1)
system.setQuality("bullets", character.sandbox.clips[character.sandbox.current_clip]) clips = character.sandbox.clips.length
system.setQuality("clips", clips - 1)
writemd(system, "Я выбрасываю пустой картридж.") writemd(system, "Я выбрасываю пустой картридж.")
system.setQuality("clips", clips)
if character.sandbox.current_clip < clips - 1
character.sandbox.current_clip++
else else
if character.sandbox.current_clip < clips - 1 character.sandbox.current_clip = 0
character.sandbox.current_clip++ system.setQuality("bullets", character.sandbox.clips[character.sandbox.current_clip])
else
character.sandbox.current_clip == 0 check_distance = (character, system) ->
system.setQuality("bullets", character.sandbox.clips[character.sandbox.current_clip]) if character.sandbox.distance == 0
system.setQuality("health", character.qualities.health - 1)
system.writemd("Один из андроидов доходит до меня и кусает!")
situation 'start', situation 'start',
content: """ content: """
@ -60,6 +72,9 @@ situation 'start',
Узкий коридор, я и непрекращающаяся очередь сверкающих белоснежной кожей андроидов. Узкий коридор, я и непрекращающаяся очередь сверкающих белоснежной кожей андроидов.
Я уверен, что я представлял этот Новый Год совершенно не так. Я уверен, что я представлял этот Новый Год совершенно не так.
Один ящик андроидов содержит тридцать пять машин.
Это будет длинная битва.
""", """,
choices: ["#shoot"], choices: ["#shoot"],
@ -72,8 +87,11 @@ situation "hit",
return response() return response()
choices: ["#shoot"] choices: ["#shoot"]
before: (character, system, from) -> before: (character, system, from) ->
system.setQuality("enemies", character.qualities.enemies - 1)
character.sandbox.nicked = 0 character.sandbox.nicked = 0
if character.qualities.enemies > 1
system.setQuality("enemies", character.qualities.enemies - 1)
if character.qualities.enemies == 0
system.doLink("finale")
choices: ["#shoot"] choices: ["#shoot"]
situation "nicked", situation "nicked",
@ -108,25 +126,41 @@ situation "miss",
situation "shoot", situation "shoot",
tags: ["shoot"], tags: ["shoot"],
optionText: (character, system, from) -> optionText: (character, system, from) ->
response = oneOf( return oneOf(
"Выстрел", "Выстрел",
"Бдыщь!",
"Выстрелить",
"Нажать на курок",
"Атака",
"Стрельба",
"СТРЕЛЯТЬ!", "СТРЕЛЯТЬ!",
"УБИТЬ ИХ ИЗ ПИСТОЛЕТА", "УБИТЬ ИХ ИЗ ПИСТОЛЕТА",
"НЕНАВИЖУ АНДРОИДОВ" "НЕНАВИЖУ АНДРОИДОВ",
).stopping(system) "АННИГИЛЯЦИЯ МЕХАНОИДОВ",
return response() "Уничтожить механоидов",
"Отправить пулю в андроида",
"Послать пулю взрывом",
"Нажать на курок во имя ЧЕЛОВЕЧЕСТВА",
"Прыгнуть к стене и выстрелить из пистолета в полёте",
"Присесть и выстрелить с колена",
"Взять пистолет в обе руки и нажать на курок",
"Не спеша прицелиться и выстрелить"
).randomly(system)
canChoose: (character, system) -> canChoose: (character, system) ->
return character.qualities.bullets > 0 return character.qualities.bullets > 0
before: (character, system, from) -> before: (character, system, from) ->
spend_bullet(character, system) spend_bullet(character, system)
character.sandbox.distance = 3
system.clearContent() system.clearContent()
after: (character, system, from) -> after: (character, system, from) ->
# d20 roll roll = system.rnd.dice(1,20) # d20 roll
# 1-14 - hit, 15-18 - nicked, 19-20 = miss hit_threshold = 15
roll = system.rnd.randomInt(1,20) miss_threshold = 18
if character.qualities.health < 2
hit_threshold = 18
switch switch
when roll < 15 then system.doLink("hit") when roll < hit_threshold then system.doLink("hit")
when roll > 18 then system.doLink("miss") when roll > miss_threshold then system.doLink("miss")
else system.doLink("nicked") else system.doLink("nicked")
situation "reload", situation "reload",
@ -134,18 +168,79 @@ situation "reload",
choices: ["#shoot"], choices: ["#shoot"],
optionText: "Перезарядить пистолет", optionText: "Перезарядить пистолет",
canView: (character, system) -> canView: (character, system) ->
return character.qualities.bullets < 6 return character.sandbox.seen_reload || character.qualities.bullets < 6
canChoose: (character, system) ->
return character.qualities.bullets < 6 and character.sandbox.clips.length > 1
before: (character, system) -> before: (character, system) ->
character.sandbox.seen_reload = 1
system.clearContent() system.clearContent()
character.sandbox.distance--
after: (character, system) -> after: (character, system) ->
spend_clip(character, system) spend_clip(character, system)
writemd(system, "Я вставляю другой картридж в пистолет. Надеюсь, в нём есть патроны.") writemd(system, "Я вставляю другой картридж в пистолет. Надеюсь, в нём есть патроны.")
return true return true
# А теперь plot twist: у пистолета есть шанс осечки и промаха. Ты теряешь патрон. Всего патронов у тебя 36, а врагов 35. situation "search",
tags: ["shoot"],
optionText: "Искать чужие картриджи",
canView: (character, system) ->
return character.sandbox.seen_search || character.qualities.clips < 5
canChoose: (character, system) ->
return character.qualities.clips < 5
before: (character, system) ->
system.clearContent()
character.sandbox.seen_search = 1
character.sandbox.distance--
after: (character, system) ->
response = oneOf(
"Я в спешке шарю по полу, пытаясь найти хотя бы один целый картридж.",
"Я быстро оглядываюсь в поисках картриджей на полу."
).randomly(system)
writemd(system, response())
roll = system.rnd.dice(1,20) # d20 roll
find_threshold = 10
if character.qualities.health < 2
find_threshold += 2
if character.sandbox.distance < 2
find_threshold += 2
if roll < find_threshold
system.doLink("found")
else
system.doLink("not_found")
situation "found",
choices: ["#shoot"],
before: (character, system, from) ->
bullets = system.rnd.randomInt(2,4)
character.sandbox.clips[character.sandbox.clips.length] = bullets
system.setQuality("clips", character.sandbox.clips.length)
content: (character, system, from) ->
response = oneOf(
"Ага! Есть один. Надеюсь, в нём есть патроны.",
"А, вот какой-то. На вес тяжёлый -- надеюсь, в нём есть патроны."
).randomly(system)
return response()
situation "not_found",
choices: ["#shoot"],
content: (character, system, from) ->
response = oneOf(
"Нет, ничего нет.",
"Ну хотя бы один! Нет, не нашёл."
).randomly(system)
return response()
situation "finale", situation "finale",
content: """ content: """
Ба-бах!
Последний андроид внезапно взрывается, как будто нашпигованный взрывчаткой.
А, впрочем, с этими машинами никогда не знаешь наверняка.
Я отворачиваюсь и ухожу прочь, не обращая внимания на взрыв.
Моя работа сделана.
<center><h3>КОНЕЦ</h3></center>
""", """,
qualities qualities
@ -153,13 +248,18 @@ qualities
bullets: qualities.integer('Патронов в картридже'), bullets: qualities.integer('Патронов в картридже'),
clips: qualities.integer('Картриджей с патронами'), clips: qualities.integer('Картриджей с патронами'),
enemies: qualities.integer('Врагов впереди'), enemies: qualities.integer('Врагов впереди'),
health: qualities.fudgeAdjectives('Здоровье'),
undum.game.init = (character, system) -> undum.game.init = (character, system) ->
system.setQuality("bullets", 6) system.setQuality("bullets", 6)
system.setQuality("clips", 6) system.setQuality("clips", 6)
system.setQuality("enemies", 35) system.setQuality("enemies", 35)
character.sandbox.clips = [6,6,6,6] system.setQuality("health", 3)
character.sandbox.clips = [5,5]#[6,6,6,6,6,6]
character.sandbox.current_clip = 0 character.sandbox.current_clip = 0
character.sandbox.nicked = 0 character.sandbox.nicked = 0
character.sandbox.distance = 3
character.sandbox.seen_reload = 0
character.sandbox.seen_search = 0
window.onload = undum.begin window.onload = undum.begin

21
game/ru.coffee Normal file
View file

@ -0,0 +1,21 @@
module.exports.language =
terrible: "ужасно",
poor: "бедно",
mediocre: "средне",
fair: "нормально"
good: "хорошо"
great: "прекрасно"
superb: "идеально"
yes: "да"
no: "нет"
no_group_definition: "Невозможно найти определение группы {id}."
link_not_valid: "Ссылка '{link}' не выглядит правильной."
link_no_action: "Ссылка с ситуацией '.' должна иметь действие."
unknown_situation: "Вы не можете переместиться в неизвестную ситуацию {id}."
erase_message: "Это навсегда удалит вашего персонажа и немедленно вернёт вас к началу игры. Вы уверены?"
no_current_situation: "Я не могу отобразить, потому что у нас нет текущей ситуации."
no_local_storage: "Локальное хранилище недоступно."
random_seed_error: "Вы должны задать верное случайное зерно."
random_error: "Проинициализируйте Random с непустым зерном перед использованием."
dice_string_error: "не могу интерпретировать вашу cтроку кубиков: '{string}'."
erase_message: "Это навсегда удалит вашего персонажа и немедленно вернёт вас на старт игры. Вы уверены?"

95
html/en.html Normal file
View file

@ -0,0 +1,95 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Thirty five shots</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div id="toolbar">
<h1>Thirty five shots</h1>
<div class="nav">
<a href="#" class="button" id="menu-button">Menu</a>
</div>
</div>
<ul id="menu">
<li><a href="#title, #content_wrapper">Story</a></li>
<li><a href="#character_panel">Character</a></li>
</ul>
<div id="page">
<div id="tools_wrapper">
<div id="character_panel" class="tools right">
<div id="character">
<div id="character_text">
<div id="character_text_content"></div>
</div>
<div id="qualities"></div>
</div>
<div class='buttons'>
<button id="save">Save</button><button id="erase">Erase</button>
</div>
</div>
</div> <!-- End of div.tools_wrapper -->
<div id="mid_panel">
<div id="title">
<div class="label">
<h1>Thirty five shots</h1>
<noscript>
<p class="noscript_message">This game requires Javascript.</p>
</noscript>
<p class="click_message">click to play</p>
</div>
</div>
<div id="content_wrapper">
<div id="content">
</div>
<a name="end_of_content"></a>
</div>
<div id="legal">
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/" class="footright"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a>
<p>Approximate play time: five minites.</p>
<p>Made using <a href="http://undum.com">Undum</a> and <a href="http://sequitur.github.io/raconteur/">Raconteur</a>.</p>
</div>
</div>
</div> <!-- End of div.page -->
<div id="ui_library">
<div id="quality" class="quality">
<span class="name" data-attr="name"></span>
<span class="value" data-attr="value"></span>
</div>
<div id="quality_group" class="quality_group">
<h2 data-attr="title"></h2>
<div class="qualities_in_group">
</div>
</div>
<div id="progress_bar" class="progress_bar">
<span class="name" data-attr="name"></span>
<span class="value" data-attr="value"></span>
<div class="progress_bar_track">
<div class="progress_bar_color" data-attr="width">
</div>
</div>
<span class="left_label" data-attr="left_label"></span>
<span class="right_label" data-attr="right_label"></span>
</div>
<hr id="turn_separator">
</div>
<div id="content_library"></div>
<script type="text/javascript" src="game/undum.js"></script>
<script type="text/javascript" src="game/bundle.js"></script>
</body>
</html>

View file

@ -55,7 +55,8 @@
</div> </div>
<div id="legal"> <div id="legal">
<p>Приблизительное время прохождения игры: пятнадцать минут. Но вы схватите идею за пять.</p> <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/" class="footright"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a>
<p>Приблизительное время прохождения игры: пять минут.</p>
<p>Написано при помощи <a href="http://undum.com">Undum</a> и <a href="http://sequitur.github.io/raconteur/">Raconteur</a>.</p> <p>Написано при помощи <a href="http://undum.com">Undum</a> и <a href="http://sequitur.github.io/raconteur/">Raconteur</a>.</p>
</div> </div>
</div> </div>

View file

@ -458,3 +458,6 @@ img.left {
.center-block { .center-block {
margin: 0 auto; margin: 0 auto;
} }
.footright {
float: right;
}