- Тетрис на JavaScript
- В чём идея
- Код не мой
- Неожиданная сложность
- Подготовка страницы
- Заводим переменные и константы
- Генерируем выпадающие фигуры
- Движение, вращение и установка фигуры на место
- Что будет, когда мы проиграем
- Обрабатываем нажатия на клавиши
- Запускаем движения и анимацию
- Что дальше
- Русские Блоги
- Реализация игры Тетрис на Java (простая версия)
- Как я делал Brick Game на Unity3D для Android и получил блокировку от Google
- Предыстория. «Тетрисы» без тетриса
- Разработка. Выбор инструмента
- Разработка. Графическое представление
- Разработка. Звук
- Разработка. Логика
- Раскрутка
- Монетизация
- Блокировка и разблокировка
Тетрис на JavaScript
Стильный и цветной.
Отменяйте все дела, переносите встречи. Сегодня мы делаем тетрис, в который можно играть в браузере и на который можно потратить весь день.
В чём идея
Правила игры все знают: сверху в двумерный игровой стакан падают фигуры разной формы, составленные из модульных блоков. Внизу блоки соединяются. Если собрать целую горизонтальную линию из блоков, она исчезает, все остальные блоки сдвигаются на ряд ниже.
Наша задача — как можно дольше продержаться, чтобы экран не заполнился и было место, куда падать новым фигурам.
Если вдруг не знаете, как это работает, вот фрагмент с чемпионата мира по тетрису:
Код не мой
Код, который мы разбираем в этом проекте, написал американский разработчик Стивен Ламберт:
В этой статье мы объясним, как этот код работает.
Неожиданная сложность
Самое главное при программировании такой игры — это как-то хранить содержимое игрового экрана и учитывать движение фигур.
Если бы мы писали эту игру на Unreal Engine или Unity, первым интуитивным решением было бы сделать для блоков какую-то сущность типа объекта. У него были бы свойства — например, конфигурация. Может быть, мы бы захотели потом сделать взрывающиеся объекты или объекты с заморозкой, объекты с повышенной скоростью, отравленные объекты или что-то ещё в таком духе.
Но есть нюанс: смысл объекта в том, что он неделимый. А в «Тетрисе» все объекты запросто делятся, когда мы «закрываем линию». У какой-нибудь Т-образной фигуры может запросто пропасть хвостик, а у Z-образной фигуры — нижняя перекладина.
Получается, что фигура в тетрисе выглядит как объект, иногда ведёт себя как объект, но не обладает свойствами объекта. Поэтому объектный подход нам здесь не подходит.
Решение — представить игровое поле в виде двумерного массива нулей и единиц. Ноль означает, что клетка свободна, а единица — что занята какой-то частью фигуры. Хранить и обрабатывать двумерный массив довольно просто, поэтому решение кажется логичным.
Сами фигуры тоже представим в виде двумерного массива из нолей и единиц, но особым образом — в виде квадрата, где единицы отвечают за части фигуры, а ноли — за пустое место:
Если вместо квадрата просто взять фактические размеры фигуры и загнать их в массив, то при вращении они не влезут в исходный массив. А внутри квадрата их можно вращать как угодно — размер массива от этого не изменится:
Получается, что если мы добавим в общий массив с игровым цветом параметр, который отвечает за цвет, то можем рисовать каждую фигуру своим цветом. Так и сделаем.
Подготовка страницы
Игра будет работать на HTML-странице с помощью элемента Canvas — это холст, на котором мы можем рисовать произвольные фигуры через JavaScript.
Возьмём пустую страницу и сразу нарисуем на ней игровое поле. Сразу сделаем чёрный фон, игровое поле поставим по центру, а его рамки сделаем белыми:
Всё остальное сделаем скриптом. Добавим тэг сразу после того, как нарисовали холст, и начнём писать содержимое скрипта.
Заводим переменные и константы
Пока что всё просто:
- делаем массив для игрового поля и заполняем его;
- делаем массивы, которые хранят наши фигуры и их цвета;
- в отдельном массиве будем хранить новые фигуры, которые появятся следующими;
- делаем флаг остановки игры. Пока он не сработает — можно играть.
Генерируем выпадающие фигуры
Первое, что нам понадобится для этого, — функция, которая выдаёт случайное число в заданном диапазоне. По этому числу мы будем выбирать фигуры.
Теперь мы можем создать последовательность из выпадающих фигур. Логика будет такая:
- Задаём обычную последовательность доступных фигур.
- Случайным образом забираем оттуда фигуру и помещаем в игровую последовательность.
- Так делаем до тех пор, пока от обычной последовательности ничего не останется.
- У нас получилась случайная игровая последовательность фигур, с которыми мы будем работать дальше.
Последний этап в этом блоке — получить из игровой последовательности, которую мы только что сделали, следующую фигуру, которая у нас появится. Мы должны знать, что это за фигура; как она рисуется; откуда она начинает движение. Обратите внимание: на выходе мы получаем не только двумерный массив с фигурой, а ещё и название и её координаты. Название нам нужно для того, чтобы знать, каким цветом рисовать фигуру.
Движение, вращение и установка фигуры на место
В тетрисе мы можем вращать каждую фигуру на 90 градусов по часовой стрелке сколько угодно раз. А так как у нас фигура — это двумерный массив из чисел, то быстро найдём в интернете готовый код для поворота числовой матрицы:
После каждого поворота и при каждой смене позиции нам нужно проверить, а может ли в принципе фигура так двигаться? Если движению или вращению мешают стенки поля или другие фигуры, то нужно сообщить программе, что такое движение делать нельзя. Дальше мы будем делать эту проверку перед тем, как что-то отрисовывать на экране.
Если проверка не прошла, то мы не делаем последнее движение, и фигура просто продолжает падать вниз. Если ей некуда падать и она упёрлась в другие, то нам нужно зафиксировать это в игровом поле. Это значит, что мы записываем в массив, который отвечает за поле, нашу матрицу фигуры, пропуская ноли и записывая только единицы.
Как только фигура встала, нам нужно проверить, получился целый ряд или нет. Если получился — сдвигаем на один ряд вниз всё, что сверху. Такую проверку делаем каждый раз при установке фигуры и начинаем с нижнего ряда, поднимаясь наверх.
Что будет, когда мы проиграем
Когда фигура при окончательной установке вылезает за границы игрового поля, это значит, что мы проиграли. За это у нас отвечает флаг gameOver, и его задача — остановить анимацию игры.
Чтобы было понятно, что игра закончена, выведем надпись GAME OVER! прямо поверх игрового поля:
Обрабатываем нажатия на клавиши
Всё как в обычном тетрисе: стрелки влево и вправо двигают фигуру, стрелка вверх поворачивает её на 90 градусов, а стрелка вниз ускоряет падение.
Единственное, о чём нужно не забыть — после каждого нажатия вызвать проверку, можно ли так двигать фигуру или нет.
Запускаем движения и анимацию
Смысл главного цикла игры такой:
- на каждом кадре мы очищаем игровое поле и отрисовываем его заново с учётом упавших фигур;
- рисуем текущую фигуру в том месте, где она находится в данный момент.
Так как кадры меняются быстро, мы не заметим постоянного очищения и отрисовки. Нам будет казаться, что фигура просто движется вниз и реагирует на наши действия.
Последнее, что нам осталось сделать, — запустить игру:
// старт игры
rAF = requestAnimationFrame(loop);
Готовый результат можно посмотреть на странице с игрой.
Что дальше
У нас есть игра, но нет важных элементов:
- подсчёта очков и статистики;
- записи имён, чтобы понять, кто набрал больше очков;
- звуковых эффектов;
- ускорения падения после каждых, например, 10 собранных рядов.
Сделаем это в другой версии игры, а пока отменяйте планы, сегодня мы играем в бесконечный тетрис.
Источник
Русские Блоги
Реализация игры Тетрис на Java (простая версия)
Эффекты страницы игры следующие:
Логика самой игры Тетрис:
Логика игры в тетрис относительно проста. Он похож на сложенный дом, формы квадратов разные. Однако интерфейс игры Тетрис поровну разделен на несколько строк и несколько столбцов, поэтому суть куба заключается в том, сколько единиц он занимает.
Давайте сначала рассмотрим вопрос о данных. Для интерфейса необходим двумерный массив типа int, который содержит те места, которые должны быть раскрашены, а какие нет; тогда сами квадраты, хотя их формы неоднородны, они могут быть окружены квадратом масштаба 4X4. Следовательно, 16 байтов могут сохранить информацию о блоке,
Примечание. Фактически, данные квадрата также могут быть представлены массивом int, но когда дело доходит до эффективности, побитовые операции выполняются быстрее, чем обычные арифметические операции.
Затем подумайте о следующих конкретных действиях:
(1) Рождение куба. Его рождение требует принципа случайности.Кроме того, как он инициализируется для размещения в верхней части игрового интерфейса?
(2) Квадрат должен падать автоматически.В процессе падения он должен оценить, конфликтует ли он с окружающей средой и может ли он продолжать падать.
(3) Сам блок также может быть деформирован, и деформированный блок имеет другие данные, и метод оценки будет другим. (4) Когда пользователь продолжает нажимать клавишу s, квадрат должен продолжать падать.
Затем идет процесс. Игроки в основном действуют в следующих аспектах:
(1) Работа влево и вправо. Вам нужно прослушать KeyEvent и позволить квадрату перемещаться влево и вправо, пока не достигнет границы.
(2) Деформационная операция. Также послушайте KeyEvent, чтобы блок автоматически деформировался.
(3) Операция опускания. Также послушайте KeyEvent, чтобы ящик упал быстро.
Что касается конца игры, то здесь только одна ситуация, то есть рождение куба, который конфликтует с другими кубиками.
Исходный код выглядит следующим образом:Детали аннотации
Источник
Как я делал Brick Game на Unity3D для Android и получил блокировку от Google
Википедия: Brick Game («Игра с кирпичами»; также его называют «Тетрис») — игровое устройство, работающее на гальванических элементах, снабжённое несколькими предустановленными играми и чёрно-белым (монохромным) экраном. На таких устройствах практически всегда присутствует игра, аналогичная «Тетрису», хотя вместе с ней часто имеются и другие игры. Существуют разные виды устройств с разным количеством игр.
Я расскажу о том, как (и почему) создавал симулятор Brick Game на Unity3D для Android с тетрисом, змейкой, гонками, танчиками и прочими играми, об эксперименте с монетизацией, а также о том за что Google Play может заблокировать подобное приложение и как его потом разблокировать.
Предыстория. «Тетрисы» без тетриса
Однажды захотел поиграть в Тетрис (сперва именно в игру Тетрис, а не в то устройство, что у нас в детстве называли «тетрисом»). Порылся в Google Play, нашел только две официальные версии от EA games. Поразился количеству бесполезных (по моему мнению) модных фишечек и наличию внутриигровых платежей. В Тетрисе! В целом ощущения были «не те».
И тут я вспомнил о такой штуковине как Brick Game и как на нём здорово было играть в Тетрис. Подумал, что в Google Play наверняка должен быть симулятор, и не ошибся. Таких симуляторов нашлось множество. Я поставил самый популярный и… не нашел тетриса среди игр. Кроме того посреди экранчика из квадратиков красовалось меню из кнопок с современными сглаженными шрифтами, с помощью которого нужно было стартовать игру, переключать звук и так далее. Не реалистично. Странно, миллион скачиваний и такие недоработки. Проверил остальные симуляторы — ещё плачевней да и тетриса нет почти нигде, а там где он есть — реализован кривовато, играть неудобно. Не говоря уже о реалистичности графического воплощения.
В общем решил я заполнить пробел и создать свой симулятор, с хорошим тетрисом и реалистичным экраном, для себя и для всех.
Из Википедии (а позже и на своём опыте, об этом читайте ниже) узнал, почему нет игры Тетрис во многих популярных симуляторах.
В 1996 году предполагаемый автор Тетриса (кстати, выходец из СССР), вместе с неким Хенком Роджерсом (англ. Henk Rogers) создал за рубежом компании The Tetris Company LLC и Blue Planet Software, пытаясь получить прибыль от бренда Tetris. The Tetris Company LLC (TTC) зарегистрировала слово Tetris как торговую марку. С тех пор несколько компаний купили у TTC лицензию на торговую марку. По американским законам, игру нельзя защитить авторским правом (только запатентовать), поэтому основным имуществом компании является торговая марка Tetris. Несмотря на это, TTC преследует клоны игры под именами, непохожими на Tetris. В мае 2010 года юрист TTC послал письмо в Google с требованием убрать с рынка Android Market все 35 клонов данной игры, хотя их имена не схожи с именем «Tetris».
Разработка. Выбор инструмента
Вначале предстояло выбрать между 1) Unity3D и 2) Android + какая-нибудь библиотека либо на голом Android API.
У меня ранее были эксперименты и с Unity3D и C# и с Java + Android, поэтому и рассматривал эти варианты.
1) Плюсы:
+ много готовых функций которые пригодятся для такого симулятора
+ возможность моментально проверить работу приложения в редакторе прямо на ПК
Минусы:
– большой вес *.apk файла — от 20 Мб
– дольше запускается
– прожорливость (батарея садится быстрее, больше греется)
2) Плюсы:
+ маленький вес («платишь» в основном за вес графических файлов)
+ высокая скорость запуска и экономия батареи
Минусы:
– придется писать больше кода (точнее, абстракций, либо утонуть в процедурном коде)
– медленный процесс тестирования на эмуляторе/устройстве
Наверняка не все согласятся с моими оценками, это дело личных умений и вкуса. Я пожертвовал размером и прожорливостью в пользу быстроты разработки и избрал Unity3D.
Разработка. Графическое представление
Начал с рисования скина с кнопками и экраном. Рисовал в векторном графическом редакторе, прорисовал все детали вплоть до каждого кубика на экране и палочки в циферных LCD блоках. Полного фотореализма достигнуть не удалось, особенно с кнопками, но в целом вышло неплохо. Экспортировал в PNG и закинул в Unity, на Quad, в качестве текстуры.

Позже добавил еще два скина — с большим экраном и повёрнутый.
Скин с большим экраном (может быть удобен на устройствах с небольшой диагональю дисплея):

Не долго думая, экран решил оживлять с помощью маленьких квадратиков с неактивными пикселями. То есть подложка у меня вся состоит из активных пикселей, а сверху объекты с неактивными пикселями, которым я переключаю видимость, а именно флаг enable. Класс дисплея содержит самый обычный модифицируемый массив из 200 элементов (10х20) (по ячейке на каждый квадратик), работать с ним удобно.

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


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

Разработка. Звук
Пока работал над приложением нашел на городском рынке самый настоящий Brick Game, принес домой, и записал звуки нажатия и отпускания реальных кнопок. Многих игроков, кстати, эти звуки раздражали, я выпустил обновление, которое отключает эти звуки в режиме Mute, но даже сквозь пиликанье самого устройства пробивался звук нажатия кнопок и люди просили сделать эти звуки тише. А мне так нравились эти звуки, что не хотелось их приглушать.
Пиликанье сгенерировал заранее простейшим синтезатором (смешал несколько типов волн).
Разработка. Логика
Первой игрой которую я добавил в свой симулятор был, конечно же, Тетрис. Здесь я постарался: симметричная система поворотов, отскоки от стен и пола при повороте, проворачивание на 180 градусов в узком колодце, справедливый генератор выбора фигурки, скольжение после мягкого падения, управление (хорошая отзывчивость в целом, резкое падение двойным нажатием вниз, поворот в обратную сторону кнопкой вверх) и даже знаменитый T-spin вроде бы удалось сделать. В итоге мне было удобнее и приятнее играть в эту игру на своём симуляторе в смартфоне, чем на реальном Brick Game. Не говоря уже об официальном Тетрисе для Android который больше похож на цирковое представление, чем на тетрис (ИМХО).

В Unity3D можно использовать C# и все прелести ООП, что я и сделал. Написал базовый класс для всех игр (с банальным названием Game) и добавлял их по одной, наследуясь от этого класса.
Добавил змейку, гонки, еще несколько видов тетриса (например с фигурками из 5 блоков), понг, позже танчики, арканоид… Впихнул туда также парочку несвойственных этому устройству игр: Digger и Bomber. Digger получился сверхсложным и непонятным, но решил его оставить в качестве изюминки.
Сделал стандартную анимацию заливки экрана при проигрыше (с представлением дисплея в коде в виде массива это было элементарно), анимацию взрыва для гонок и пары других игр. К классам прибавились Sprite, AnimatedSprite. Например, каждая фигурка тетриса у меня это Sprite, и после сдвига этого спрайта можно проверять столкновения с игровым полем и реагировать соответственно.
В общем, разработка логики шла как по маслу и спустя месяц с начала разработки я выложил свой симулятор в Google Play. Первая иконка была скриншотом из игры, со временем нарисовал стилизованную иконку покрасивей (пока рисовал, помечтал о приложении с точно таким вот дизайном, уменьшенным экраном и тремя кнопками которых в принципе должно быть достаточно для тетриса и змейки):

Раскрутка
Из 39 тысяч, лишь пара сотен человек пришли по ссылкам из интернета, которые я оставлял на разных сайтах, посвященных Android-играм. Все остальные — самостоятельно нашли приложение в поиске Google Play.
Монетизация
Мне стало интересно, сколько можно заработать на такой игре, ведь все симуляторы были полны рекламой до безобразия, рекламой всевозможных видов и казалось, что в этом был какой-то смысл. Я подключил Google AdMob и по-моим подсчетам вышло, что если залепить всё приложение рекламой, то можно получить как минимум $5 за каждую тысячу скачиваний. Меньше рекламы — меньше денег. Сделать рекламу в 5 раз реже, будет грубо говоря $1 за 1000 скачиваний. Миллион скачиваний = $1000. Или $5000, если удастся скормить пользователям рекламу с небольшими вкраплениями собственно игры. Это касается только AdMob, говорят, есть и более щедрые партнёрки, а ещё у меня большинство траффика было из стран СНГ и Бразилии (почему-то), ставки на клики из этих стран низкие, это тоже влияет.
Вас, должно быть, смутило, что я у себя считаю только скачивания. Как показала моя статистика от постоянных пользователей притока мало, в основном играют новоскачавшие, половина скачавших вообще удаляет приложение сразу или на следующий день, а те, кто оставил — играют настолько редко, что слабо влияет на статистику.
Через месяц я решил выключить рекламу, чтобы не портить приложение. Отмечу, что после отключения рекламы средняя оценка выросла и популярность приложения тоже пошла вверх, пользователи стали отмечать отсутствие рекламы как одно из исключительных преимуществ моего симулятора.
Блокировка и разблокировка


4 Октября игру заблокировали и Google Play Support прислали мне письмо о том, что моё приложение “has been removed from Google Play because it violates our metadata policy. This app won’t be available to users until you submit a compliant update.”, что значит — что-то не так с описанием или названием. Никаких подробностей, что именно их не устроило они не сообщили. Мол, читай правила, догадывайся сам, исправляй либо подавай аппеляцию.
Я сразу предположил, что виной всему наличие в симуляторе игры в тетрис и упоминание об этом в описании. Но это же симулятор устройства, в котором всегда был тетрис (в первых Brick Game вообще кроме тетриса ничего не было)! И так уж сложилось, что устройство Brick Game у нас называли «тетрисом» хоть это и неверно, но прижилось, стало нарицательным.
Но всё же достоверно причину я не знал, поэтому ничего не меняя подал апелляцию.
Через 2 дня пришел ответ:

Перевод: Мы не допускаем приложений с метаданными, которые обманчивы, не имеют отношения к приложению, избыточны или неприемлемы. Метаданные включают описание приложения, иконки, скриншоты и промо-изображения.
К примеру, описание вашего приложения имеет отсылки к Тетрису.
Пожалуйста, уберите посторонние ключевые слова…
Вот такой вот маразм, нельзя писать, что у тебя в игре есть тетрис, даже если он там есть, а лучше вообще его убрать, наверное, чтобы в дальнейшем не было проблем. Можно было бы сэкономить время если бы они сразу написали, что дело в слове tetris в описании.
Подверг описание цензуре:
Приложение после этого разблокировали. Не исключаю, что в будущем могут влепить блокировку за то, что там есть тетрис на скриншоте или что он есть в самом симуляторе.
Источник