Однажды на досуге я придумал карточную игру и, недолго думая, создал ее электронную версию. А потом добавил еще четыре игры, включая покер Техасский Холдем. А чтобы было еще интереснее, я встроил некое подобие прогресса: выигрываешь в одной игре – открывается новая. Запланировал я разместить свою игру в двух социальных сетях и в магазине Windows Store как html5-js приложение. А также, возможно, создать еще сборки под Android и iOs. Можно играть чрез сервер с другими людьми, а можно – офф-лайн с ИИ.

Для работы я, как всегда, не использовал никакие сторонние движки и библиотеки, даже jQuery мне не понадобилось. Только функции ванильного JavaScript, включая средства работы с холстом (canvas). Холст в игре – основа для вывода всей игровой графики. В WebGL, на этот раз, не было необходимости, поэтому зоопарк поддерживаемых браузеров расширился. Средой программирования, как обычно, стал продвинутый блокнот. Игра получилась объемом 3,8 Мб, из которых 3 Мб — это семь карт спрайтов в формате png. Запускается игра по html-файлу. Сервер на PHP. В случае выбора однопользовательской игры (то есть, с ИИ), запросы к серверу не отправляются и все расчеты ведутся на клиенте. Диздок не писал – он не нужен хипстерам.


Далее – занимательная геометрия и программирование, а во второй части будет рассказ о размещении игры в социальных сетях и в магазине.

GUI


Написание кода графической части не отняло у меня слишком много времени, так как для своих предыдущих игр я уже разработал движок меню на JavaScript на теге canvas с подгрузкой спрайтов из форматов jpg и png, или, иначе говоря, GUI. Достаточно было лишь взять тот код и определить в качестве экранных кнопок при помощи ассоциативного массива все активные области, то есть, карты и кнопки меню. Ну и еще набросать сами спрайты, то есть, создать дизайн. Основное время ушло, собственно, на описание игровой логики всех пяти игр. И чуть позже – на создание многопользовательской версии под две социальные сети и магазин Windows.

Впрочем, я немного слукавил насчет того, что мое canvas-меню так уж прямо полностью готово. Его нельзя просто так взять и… В общем, оно (говнокод) далеко от совершенства и весьма ограничено в своих возможностях. Но главное, мне захотелось, чтобы карты не лежали скучной прямой линией, а выкладывались бы веселым веером, независимо от их количества. Однако, мое меню не поддерживало поворот «кнопок». Поэтому настало время запрограммировать это безобразие раз и навсегда. Для начала.

Добро пожаловать в Вегас


Я решил, что изгиб будет задаваться неким параметром d, который обозначает, насколько центр линии карт выдвигается вверх.


Итак, дано: количество карт (n), ширина прямоугольника (w), ограниченного центрами крайних, скучных, «неизогнутых» карт, и смещение середины линейки карт вверх (d), придающее им веселья. Требуется найти точки центров и углы поворота каждой карты так, чтобы получился веер, как на картинке. Сложно сказать, насколько хорош мой метод, но это то, что мне удалось вспомнить из геометрии. Писать будем на JavaScript.

var L=0, h=0, dx=0, hx=0, hy=0;
//Находим неизвестные стороны треугольника (1..3..n), вокруг которого будет описана окружность
//Обозначим переменной a равные стороны 1..3 и 3..n
var a = Math.sqrt ( d*d+(w*w/4) );
//Найдем радиус R описанной окружности по формуле
var p = 0.5*(a+w+a);
var R = a*w*a / ( 4*Math.sqrt( p*(p-a)*(p-w)*(p-a) ) );
//Угол L0 для отклонения первой и последней карт от горизонтальной оси будет равен
var L0 = Math.asin( 1 - (d/R) );
//Угол dL, на который будут отступать карты друг от друга по окружности
var dL = ( Math.PI-(2*L0) ) / (n-1);
//Переберем в цикле все карты
for (var i=0; i<n; i++) {
    //Найдем общий угол отклонения для карты от горизонтальной оси координат
    L = L0 + (dL*i) + rot;
    //Здесь rot – еще один входной параметр, который задает общий угол наклона всего веера, если нам захочется, чтобы линия w располагалась под углом
    //Найдем отступы по вертикальной и горизонтальной осям для каждой карты, из которых и можно вывести координаты центров каждой карты
    hx = -R*Math.cos(L) - R*Math.sin(rot);
    hy = d + R*Math.sin(L) - R*Math.cos(rot);
    //Запоминая эти параметры в массиве, получим все координаты и углы
};

Вегас уже где-то близко.

Код для отображения всех спрайтов на холсте по сформированному массиву точек и углов тривиален и использует только стандартные функции работы с canvas. Схема простая: нужно сохранить состояние canvas, переместиться туда, где будет находиться центр спрайта, повернуть canvas на требуемый угол, отобразить спрайт, а затем восстановить состояние canvas. Кстати, половинную ширину (w2) и высоту (h2) спрайта не обязательно вычислять каждый раз, их можно предопределить. В общем, примерно так:

var w2 = Math.floor(spriteW/2), h2 = Math.floor(spriteH/2);
var x = spriteX+w2, y = spriteY+h2;
ctx.save();
ctx.translate(x, y);
ctx.rotate(spriteL - Math.PI/2);
ctx.drawImage(spriteMapImage,   spriteMapX, spriteMapY, spriteW, spriteH,   -w2, -h2, spriteW, spriteH);
ctx.restore();


Ура! Теперь карты вкладываются веером, ну прямо, как в Вегасе – в кино видел. Недостаток или, точнее, недоработка пока заключается в том, что, хотя спрайты карт-кнопок теперь и располагаются под углом, но кликабельные области все равно остаются не повернутыми, пусть даже при этом правильно смещенными. То есть, у них cо спрайтами совпадают только центры. Однако, для данной игры этого вполне достаточно. Угол отклонения карт будет довольно мал, и вряд ли случайно кликнешь по соседней карте. Здесь, если и будут подобные круги из карт, как на этой картинке, то не кликабельные, а просто для эффекта. Для карт игроков будут изгибы гораздо меньше.

Всегда есть, к чему стремиться. Можно в обработчике указателя мыши для проверки вхождения в область клика считать синусы и косинусы, чтобы точнее позиционироваться по наклоненной кнопке. Либо можно поворачивать canvas при движении мыши. Но все это будет, как мне показалось, сильно и необоснованно нагружать процессор. Ведь, нужно будет при каждом движении мыши перебирать синусы-косинусы всех «экранных кнопок», чтобы определять вхождение указателя в какую-либо область клика. Можно, конечно, отрабатывать углы только при событии клика, но тогда не будет такого красивого изменения вида указателя при вхождении и выходе из кликабельной области. Я еще подумаю над тем, как можно решить данную задачу. А пока двигаемся дальше.

AI


Прочитав данный подзаголовок, можно было подумать, что вот он, наконец-то, изобретен искусственный интеллект. Свершилось то, к чему так долго стремились все светлые умы цивилизации. Однако, разочарую. В данном случае под пафосной аббревиатурой AI скрывается обычный генератор случайных чисел. Ладно, шучу, не совсем обычный. Минимальная логика у нашего игрового ИИ (Иван Иваныча) все же есть. Иван Иваныч – серьезный мужик. Логика будет еще дополняться, но даже сейчас Иван Иваныч частенько обыгрывает меня, например, в мою же игру, наглец. В покер так я вообще почти всегда проигрываю. Но, возможно, я не умею в него играть. А вы говорите, искусственного интеллекта не существует. Нет, он явно что-то замышляет… Я опасаюсь, как бы случайно не создать Sky-Net.


Анимация карт


Сделаем из игры конфетку. Без анимации карт все работает как-то резко и некрасиво. Добавим еще один графический слой (читай – прозрачный холст, canvas) поверх основного и будем на нем устраивать «заезды» карт между колодой и столом, столом и игроками, колодой и игроками. С вращением, песнями и плясками. Карта, которую требуется анимировать, будет просто выноситься на внешний холст и там уже беспрепятственно двигаться, не опасаясь оказаться слоном в посудной лавке, чтобы случайно не стереть собой соседей и фон. А в конце пути она будет падать обратно на нижний холст и далее вести себя прилично. Анимацию можно и отключить через игровое меню, если она не нужна. Обработчики кликов, кстати, повесим сразу на внешний холст.

Движение карты по холсту будем задавать следующими входными параметрами: скоростью V и точками, начальной (X0;Y0) и конечной (X,Y). При движении будем отрисовывать спрайт в позиции, в которой он должен оказаться по истечении времени ti, прошедшего с момента начала движения. И предварительно, конечно же, стирать спрайт со старой позиции. Вызывать следующую отрисовку будем сразу после того, как завершится предыдущая. Таким образом, обеспечим настолько плавное движение, насколько это позволит устройство, на котором будет выполняться код. А привязка ко времени сделает движение в целом равномерным, независимо от возможных кратковременных тормозов браузера. Принцип расчета такой:

В начале функции вызова движения определим некоторые параметры для движения

//Запомним начальное время
var t0 = Date.now() / 100;
//Полные перемещения по горизонтальной и вертикальной осям
var Sx = X - X0;
var Sy = Y - Y0;
//Общее расстояние находим по формуле
var S = Math.sqrt (Sx*Sx + Sy*Sy);
//Время, прошедшее с момента начала движения (ti), относится к общему времени движения (t), как относятся соответствующие расстояния по оси, например, x, то есть, ti / t = dxi / Sx. Из этого следует, что приращение координаты для горизонтальной оси dxi = Sx * ti / t, или dxi = Sx * ti * V / S. Скорость задается как параметр движения, а расстояния мы уже вычислили. Аналогично – для вертикальной оси.
//Выведем для этой анимации некие константы-коэффициенты, которые следуют из формулы выше и которые будут использоваться для расчета горизонтальной и вертикальной координат в цикле, чтобы не вычислять эти значения при каждой итерации. То есть, пока возьмем без времени ti
var constX = V * Sx / S;
var constY = V * Sy / S;

А в цикле движения будем каждый раз рассчитывать координаты уже по времени

//Время, прошедшее с начала движения, равно
var ti = Date.now()/100 - t0;
//Текущие координаты (Xi;Yi) в зависимости от этого времени
var Xi = constX * ti + X0;
var Yi = constY * ti + Y0;

И, наконец, эти координаты будем проверять на принадлежность к отрезку движения. То есть, Xi должно лежать между X0 и X, а Yi – между Y0 и Y. Пока выполняется данное условие, отрисовываем спрайт в (Xi;Yi) и зацикливаем функцию движения. Далее код, думаю, понятен, и нет смысла его подробно расписывать. Весь принцип я объяснил.

Теперь касательно угла поворота спрайта (ai). Если заданные в качестве входных параметров начальный угол (a0) и конечный угол (a) различаются, то в функции движения вычисляем текущий угол ai следующим образом. Приращение угла, то есть, (ai) относится к приращению пути, например, по горизонтальной оси ( которое у нас равно (Xi — X0) ), как общий угол поворота (a — a0) относится к общему пути по горизонтальной оси (Sx), то есть:
ai / (Xi — X0) = (a-a0) / Sx

//И туда, где мы рассчитываем текущие координаты спрайта в цикле, добавим также расчет также текущего угла поворота, не забывая прибавить начальный угол (a).
var ai = (a-a0) * Math.abs (Xi - X0) / Math.abs(Sx) + a;
//Можно вынести за скобки цикла постоянную величину (a-a0) / Math.abs(Sx);

Отрисовываем спрайт стандартным drawImage с предварительным поворотом холста при помощи стандартных же функций JS translate и rotate, здесь, думаю, все понятно.

Да, этот алгоритм не учитывает некоторые частные случаи. Когда, например, расстояние равно 0, то возникает ошибка деления на 0. Но мы не будем задавать картам нулевое движение, зачем бы нам это? Поэтому и делать проверку на такие крайности в данном случае излишне.

Игры


Игры в комплекте следующие. «Три мешка» — моя авторская игра. «Подкидной дурак», «Покер Техасский Холдем». Это те, что открыты изначально. Теперь закрытые: «Чешский дурак» и «Три палки». Открываются они, если выиграть достаточное количество монет: для открытия первой закрытой игры у игрока должно быть 700 монет, второй – 900 монет. Изначально игроку дается 650 монет. Если же проигрывать, то игры, наоборот, будут закрываться вплоть до самой первой. Монеты можно выиграть у других игроков в открытых играх или приобрести. В однопользовательской версии монеты убраны совсем, а доступны только три игры из пяти.

Отдельно про покер


Я раньше никогда не играл в покер, но слышал, что это популярная игра и по ней даже проводят мировые турниры. Я посмотрел один такой, а также пару фильмов про карточных шулеров. Как когда я делал «Морской бой», я смотрел сериал про пиратов. Новичку сложно запомнить все покерные комбинации, а тем более, по ходу игры сразу представлять все возможные варианты. Поэтому я добавил экран, который можно вызвать во время своего хода и посмотреть все возможные на данный момент для себя комбинации. И уже в зависимости от этого сделать тот или иной ход. Этот алгоритм использует и Иван Иваныч (Искусственный Интеллект) для оценки своих шансов, поэтому писать данную функцию в любом случае пришлось бы. Вот, как в итоге это выглядит. Яркие карты – это те, которые есть на столе и на руках. Затемненные – это те, которых пока нет, но они еще могут прийти из колоды. А, если все 5 карт перевернуты, то данная комбинация уже невозможна ни при каких условиях. Зеленой точкой помечаются собранные комбинации: чем ближе к номеру один, тем, соответственно, лучше.


Для покера я просто, ради прикола, также предусмотрел такой вариант, когда в игре участвует только ИИ, без людей. Получилось что-то вроде экранной заставки, где компьютер сам с собой бесконечно играет в покер.


Дизайн


Дизайн – это не моя стихия. В процессе создания игры он, как обычно, много раз переделывался и корректировался. В итоге, к моменту релиза игры я остановился на внезапно пришедшем мне в голову кабацком черно-красном варианте с расположением главного меню на мастях. Я долго думал, какой из двух видов оставить, а потом решил, что пусть будут оба с переключением между ними.


Английский язык


Опыт локализации предыдущих игр подсказывал мне, насколько муторно потом выдергивать из скриптов все кириллические строки и заменять их ссылками. Поэтому я добавлял их в языковой файл прямо по ходу, а в скрипты основной программы вставлял сразу ссылки (с комментариями). Cначала я заполнял только русскоязычный файл, а затем сделал копию и перевел его на английский. Языковой файл подключается динамически, в зависимости от выбранного языка, и представляет собой массив строк с определенным именем. Как обычно, простой скрипт:

var el=document.createElement("script"); el.type="text/javascript";
el.src="lng/lng_"+lng+".js"; el.async=true;
document.getElementsByTagName("head")[0].appendChild(el);

Здесь переменная lng ранее читается из параметров командной строки. Функция применения языка запускается по готовности html-документа. А во всех функциях, где присутствуют текстовые строки, уже заданы ссылки на элементы массива языкового файла с фразами. В верстке самой html-страницы никаких фраз нет, ведь, по сути, документ представляет собой просто два канваса (canvas), наложенные один на другой, да пустой блочный элемент для вывода правил игры. Правила также располагаются в «языковом» файле.

Те фразы, которые были «захардкорены» в изображениях – например, подписи на кнопках, вынесены в отдельные изображения в формате png, соответственно, для русского и английского языков. А фоны – например, сам игровой стол, подложи для меню и прочие спрайты без надписей, располагаются в общем файле.

Вот пример русскоязычной локализации и общего для русского и английского языков фона (в уменьшенном виде):


«Русскоязычная» карта спрайтов


Общая карта спрайтов (фонов) для всех языков

Подложки для главного меню слишком большие, поэтому они располагаются еще в одном, дополнительном файле. Они также общие для всех языков, а «кнопки» для них уже включены в обе «языковые» карты.

Звуки


Звуки для игры были частично сгенерированы при помощи программы-синтезатора, частично взяты из бесплатных ассетов и подключены тегом audio. Здесь рассказывать особо не о чем. Был только один неприятный момент, связанный с тем, что если не закончилось воспроизведение текущего звука, то новый звук пропускается и не воспроизводится совсем. Поэтому пришлось сокращать звуки, чтобы они не «перекрывали» друг друга в некоторых ситуациях.

Промежуточный итог


В следующей статье расскажу об опыте размещения универсального Windows-приложения в магазине Windows Store, о создании классического (десктопного) приложения под Windows из html-js файлов, а также о многопользовательской версии для социальных сетей ВКонтакте и Фейсбук. На данный момент игра доступна пока только в Windows Store в виде однопользовательского UWP-приложения x86 и x64 под Windows 8.1 – 10. Планирую также сделать сборки под Android и iOs. А также, возможно, выложить просто zip-архив для запуска однопользовательской версии игры по index.html для всех операционных систем.

Вообще, архив с html-js файлами мне кажется самым оптимальным вариантом для распространения подобных приложений, так как нет необходимости что-то собирать при помощи «тяжелых» средств разработки, нет необходимости создавать инсталлятор, нет необходимости включать в сборку какие-либо библиотеки, html можно открыть в любой ОС при помощи любого бразузера на выбор и использовать тот, в каком приложение будет работать лучше всего. Жаль, что магазины приложений не позволяют распространять приложения таким способом, а операционные системы не устанавливают и не создают ярлыки для html, как, например, это делают с исполняемыми файлами. Разве что, Windows 8.1 – 10 как-то движется в этом направлении, собранный пакет для магазина Windows Store занимает всего 4,4 Мб. Производители браузеров могли бы тоже повернуться лицом к html-js приложениям и предусмотреть какой-нибудь режим запуска без показа интерфейса браузера, как это делается, например, в node-webkit, когда используется браузерный движок. Тогда бы не пришлось, например, в сборку «классического» приложения включать движок и «тащить» этот движок с каждым таким приложением. Ведь, потенциал у веб-приложений есть: доступна 3D графика WebGL, байт-код и скоро, возможно, браузерный код еще больше приблизится по скорости к нативному. Но обо всем этом – в следующей части. А пока я пишу сервер.
Поделиться с друзьями
-->

Комментарии (45)


  1. Kanumowa
    21.01.2017 18:08

    Молодец, разрабатывать игры для фана всегда весело, не понял откуда берутся начальные х у, но я в своих играх всегда их беру 100 100 разрабатывать просто и потом неважно какой вью: канвас или что-то другое. Говорят пхпшники любят vue.js, может перепишешь?


    1. Kempston
      21.01.2017 18:17

      Начальные координаты карт — это входные параметры функции движения. Они сохраняются в массив в функции раскладке карт веером.
      Фреймворки использовать не хочется, не люблю их вообще.


  1. Areso
    21.01.2017 20:10

    Всякие инсталляторы умеют делать ярлычки на любой вид файлов — включая html.


    1. Kempston
      21.01.2017 20:28

      Да, я уже сделал sfx-архив 7z. Но, опять же, после запуска виден интерфейс браузера.


      1. Areso
        21.01.2017 20:32

        http://www.it-devices.com/2015/03/how-to-open-internet-explorer-in-full_26.html с другими браузерам тоже можно сделать также (запускать в т.н. kiosk-mode).


        1. Kempston
          21.01.2017 20:42

          Я так понимаю, что kiosk-mode не включается программно. Есть еще FullScreen, вот его я включал через JavaScript, но в нем не работает клавиатура, работают только некоторые клавиши типа стрелок.


          1. Areso
            21.01.2017 20:52

            У меня работает клавиатура нормально — Chromium/FF в Debian/Ubuntu, мне кажется это какой-то баг.


            1. Kempston
              21.01.2017 20:57

              У меня Windows. Там дело в том, что полноэкранный режим, вызываемый по F11 — это не то, что полноэкранный режим FullScreen api, вызываемый через JavaScript. Вот в последнем не работает клавиатура. А вот как в Ubuntu — этого я не знаю, может быть, и не так.


              1. Areso
                21.01.2017 21:41

                Можете ссылку дать на сниппет со скриптом? Сразу бы и проверили.


                1. Kempston
                  21.01.2017 22:55

                  В этой игре этой возможности нет, но есть другая моя игра в Фейсбук и ВКонтакте, где можно разворачивать на полный экран кнопкой в верхнем правом углу: FB, VK


                  1. Areso
                    22.01.2017 06:43

                    В 51 Хромиуме на Debian'е вообще не запустилось: Ошибка. Отсутствует поддержка WebGL


                    1. Kempston
                      22.01.2017 11:59

                      Тут уж ничем не могу помочь, только полазить в настройках… Например, в Win XP тоже не во всех браузерах работает WebGL. Работает, как ни странно, в старом Хроме примерно 2013 года, а также в новых Firefox. Больше нигде. В Win 7-… и далее в любых новых версиях браузеров. То есть, поддержка WebGL еще не повсеместна.


                  1. Areso
                    22.01.2017 12:07

                    По крайней мере горячие клавиши игры W A S D F работают нормально в FF 50 и Chromium 53 в Ubuntu в полноэкранном режиме вызванным на нажатие нарисованной кнопки в игре


                    1. Kempston
                      22.01.2017 12:35

                      Протестировал на планшете Win 8.1 с подключенной клавиатурой. Да, WASD работают во всех браузерах. На десктопе в XP работают в новом FF, а вот в старом Chrome — нет, только стрелки. То есть, скорее правы вы, а не я. Получается, что проблема в старом браузере. Однако, в XP у меня старый Хром работает с WebGL заметно быстрее, чем новый FF, поэтому в XP пользоваться первым все же предпочтительнее.


                    1. Kempston
                      22.01.2017 12:36

                      Да и спасибо, буду знать, что в Ubuntu тоже работает WebGL. А вы что-то делали с настройками? Или просто обновили браузер?


                      1. Areso
                        22.01.2017 13:16

                        У меня разные ОС на разных железках, браузеры немного отличаются версиями.
                        На Дебиане возможно тоже есть поддержка WebGL, просто там железка специфичная и не факт, что драйвер видеоадаптера умеет в OpenGL/WebGL нужной версии.


                    1. Kempston
                      23.01.2017 11:03

                      Кстати, есть еще такой момент. Full Screen api по спецификации работает только по нажатию кнопки. Запустить эту функцию автоматически после загрузки страницы невозможно.


  1. alexeymorozovv
    21.01.2017 20:28

    А можно где-то посмотреть результат, а может даже и код? :)


    1. Kempston
      21.01.2017 20:29

      Windows Store — пока только выложена версия под Windows 8.1 — 10.


  1. Kempston
    21.01.2017 22:57

    Я случайно отклонил комментарий с вопросом о том, как реализован сервер. На PHP с периодическими запросами раз в 5 секунд. Я уже делал так в двух других играх.


  1. Sergiy
    22.01.2017 01:28

    А не пробовали спрайты в png-8 сконвертировать? Вроде размер меньше должен получиться.


    1. Kempston
      22.01.2017 01:56

      Однозначно — меньше, однако, и качество ниже. Пусть лучше будет 32 бита на канал. Не так уж и много места они занимают.


      1. Kempston
        22.01.2017 12:42

        32 бита на пиксель, то есть.


  1. babylon
    22.01.2017 01:48
    -1

    @Kempston, здравствуйте. Сколько Вам лет?


    1. Kempston
      22.01.2017 01:57

      Здравствуйте. Не думаю, что хотел бы разглашать здесь персональные данные, включая возраст.


      1. Areso
        22.01.2017 06:41
        +1

        В таком случае, я бы из соцсетей удалился бы совсем — они выдают возраст, в количестве полных лет, всем интересующимся. Ну или возраст в профиле поменял)


        1. sens_boston
          22.01.2017 09:15

          Вот как-то вопрос про возраст — ну, не понял совсем… Что ставится в упрек? То, что автор слишком молод, или слишком стар? Но даже пусть автор и будет слишком молод (или одной ногой стоит в могиле) — ну, разве это повод, чтобы оценивать его приложение и статью?!

          Много чего видел на хабре, но такое — впервые :( Даже не знаю, что и сказать :(


          1. Areso
            22.01.2017 09:47

            Возможно, вопрос был задан просто из интереса. Мол, такой молодой, а приложения такие качественные/интересные, это бывает с учащимися. Не могу назвать себя стариком, но когда я узнал возраст одного из моих любимых авторов-экспертов, сильно удивился. С другой стороны, если человек не прожигал время в играх (совсем) и занимался развитием, то почему бы и нет. Возможно, кто-то ищет для себя пример, мол, хватит фигней страдать, пора начать заниматься.
            Бывало ли такое уже на Хабре? Бывало. Увы, пальцем ткнуть в нужный комментарий не смогу, но бывало.


            1. sens_boston
              22.01.2017 10:00

              Все равно не понимаю, каким образом «возраст в профиле» может поменять мнение о статье или программе.


              1. Areso
                22.01.2017 10:28

                Считаю, все же, что спросить можно. Главное потом — суметь принять ответ «вас не касается», или вариации на тему, как ответил автор. К примеру, меня часто спрашивают собеседующие о моем возрасте (не указан в резюме, но указаны годы учебы), семейном положении и о том, где и с кем я живу. Мне кажется, мой ответ «не ваше собачье дело» был бы несколько грубоват, но даже ответ в мягкой форме устраивает далеко не всех)


                1. sens_boston
                  22.01.2017 10:32

                  Я бы сказал, что вопрос был достаточно неожиданно хамский. Если было бы действительно «интересно» — то это в «личку». Публично же, в озвученной форме — очень режет ухо и глаз, ей Богу!

                  Ответ же камрада Kempston был весьма мягким, не по вопросу…


            1. Kempston
              22.01.2017 12:09

              > Мол, такой молодой, а приложения такие качественные/интересные

              А оно не такое уж и качественное. Если смотреть с точки зрения стандартной веб-разработки. Никаких вам ангуляров и гитхабов. И даже велосипедов с классами на JavaScript…


  1. sens_boston
    22.01.2017 09:37

    Хочу посоветовать Вам следующие вещи (заранее прося извинения за непрошеные советы! :) )

    • допилить игру и до многострадальных Windows Phones (в рамках UWP будет достаточно просто)
    • пропиариться на тематических ресурсах: 4pda, xda-dev, windowcentral etc.
    • сделать приложение платным, но с unlimited trial — много не даст, но раз в месяц принесет небольшую «копеечку», «мелочь, а приятно!»
    • переработать Texas Hold'em к нормальному виду; ну, или добавить больше опций, включая all in ;)


    1. Kempston
      22.01.2017 11:49

      Нет, мнение другого человека всегда интересно, особенно, если принять во внимание то, что я не большой спец в области исследования юзабилити.
      1. У меня нет самого устройства WP. Хотя, а почему бы не попробовать… С другой стороны доля пользователей WP, да и Windows 10, невелика. Это далеко не самые популярные системы. Я просто хотел получить опыт сборки под них. Ну еще мне нравится подход MS к html5-js приложениям, то есть, сама эта концепция. Надеюсь, MS не забросит это дело…
      2. Да, это планирую.
      3. По-моему, триал приносит меньше дохода, чем внутриигровые покупки. В онлайн версии я планировал реализовать последние.
      4. Это была первая, пробная версия… Покер доработаю. Вот только сам его изучу получше. :) А то я в него учился играть параллельно с написанием игры. А что имеется в виду под «all in»?


      1. sens_boston
        22.01.2017 12:05

        1) Эмулятор вполне OK; только обратите внимание на usability через жесты (что для десктопной версии не сильно актуально). Ну, еще, возможно с версткой нужно будет поработать. WP хоть не очень популярны, но в России присутствуют в определенных количествах (и не только в России).
        3) Не рассчитывайте на особый доход: карточных игр на любой платформе… «как грязи» :) Притом, есть чрезвычайно удачные реализации, с которыми вам будет трудно (или почти невозможно) конкурировать. Поэтому, я бы порекомендовал «easy come, easy go mode» — типа, «не заработал, так и хрен с ним, лишь бы процесс мне нравился!» ;) Но на 6 pack хорошего пива, а то и поболе есть шанс подработать.
        4) Ну, «олл ин» (all in), это ставка «ва-банк», неотъемлемая часть Texas Hold'em. Да и в реализации ставок у вас небольшая путаница, очень странный алгоритм. Вообще-то, вариантов этих «Тексас Холдемов» — как грязи, но есть более-менее общепринятые. Я бы порекомендовал вам взять, что-ли, «вегасский» вариант.


        1. Kempston
          22.01.2017 12:17

          1. Ok, посмотрю в эмуляторе. Изначально даже мысли такой не было — собирать под WP. :) А с жестами там вроде бы и так все нормально. У меня планшет на Windows 8.1, все работает.
          3. Да, карточных игр много. Это я ощутил, когда в магазине Windows моя игра провалилась в изобилие таковых) Насчет удачных реализаций, с которыми мне не тягаться… Ну, не скажите. Постепенно можно допилить игру и до их уровня. Хоть 3D туда добавить…
          4. Понял. Добавлю. У меня ставки — фиксировано +5 к предыдущей ставке. И пока все не уравняют. То есть один ставит +5, следующий еще +5, значит, третий, если хочет просто уравнять, то ставит уже +10, а если повысить, то +15 (10+5). Мне казалось, что это довольно просто.


  1. PlatinumThinker
    22.01.2017 09:56

    Kempston почитайте про криптографию в разрезе ваших задач (Ментальный покер)
    Суть в том что вы можете написать алгоритм который будет мухлевать и скажем раскрывать ваши карты аппонентам или AI а это не так честно =)


    1. Kempston
      22.01.2017 11:37

      В онлайн версии, которую я сейчас пишу, колода будет храниться исключительно на сервере, а карты, которые появляются на столе, будут приходить непосредственно перед своим появлением. Колода полностью — никому не приходит. Карты оппонентов вообще не видны. Все расчеты — на сервере. AI в онлайн версии будет полностью на сервере, то есть, карты AI не будут никому приходить на клиент.
      Да, теоретически сервер может мухлевать. Но кто будет лезть в код и проверять, действительно ли там используется шифрование? А если бы программа была не на JS, а в машинном коде? Или, например, сервер втихаря будет все равно использовать свою колоду, независимо от того, что было на клиенте…


      1. PlatinumThinker
        22.01.2017 14:11

        Суть в том что пользователи не смогут доверять тебе =)
        А насчёт проверок, как только появится игра за наличные точно найдутся кто сможет это сделать и не важно на чём написан клиент


        1. Kempston
          22.01.2017 15:40

          Сервер они не обманут. По сути, игра идет на сервере, а игрокам только демонстрируется результат. То есть, если, например, игрок берет из колоды карту, то она берется на сервере из заранее перетасованного массива, никому неизвестного и ни в каком виде не приходящего на клиент. Приходит только очередная карта, причем, только тому, кто ее берет.
          Но вот сам сервер теоретически, конечно, может мухлевать. Однако, я не вижу способа продемонстрировать игрокам абсолютное доказательство неподдельности шифрования.


          1. andrew911
            22.01.2017 19:26

            Выкладывать заранее запароленные архивы с раздачами, т.е. заранее готовить колоду под каждый матч.
            После дается пароль и все могут сверить раздачу в соответствии с номером игры.


            1. Kempston
              22.01.2017 19:30

              В покере, кстати, можно «зарядить» колоду, то есть, распределить карты так, чтобы всегда выигрывать, так что независимый архив все равно особо ничего не гарантирует. Да и технически это как-то сложновато реализовать, в отличии от простой базы данных на сервере.
              Думаю, игрокам все же придется смириться и доверять серверу. :)


  1. Aler
    22.01.2017 11:45

    можно собрать приложение c electron.atom.io


    1. Kempston
      22.01.2017 11:51

      Я собирал с nw-js. Наверно получится примерно то же самое?


      1. Aler
        22.01.2017 14:15

        вроде того, но приятнее