Добрый день! Хочу представить Вашему вниманию проект-игру «Слова из Слова». Относительно недавно я стал изучать web-программирование и, так как лучший учитель — это практика, решил написать свой вариант довольно-таки известной игры «Слова из Слова». Основная цель — использование чистого Javascript без подключения дополнительных библиотек.
Вид игрового поля
Описание игры
Задача игрока – из букв представленного на экране слова составлять другие. Составленное слово должно быть нарицательным именем существительным в единственном числе, уменьшительно-ласкательные формы, а также сокращения не принимаются. Минимальная длина – 3 буквы. За каждое отгаданное слово начисляются очки в зависимости от его длины (базовая ставка за каждую букву, умножаемая на коэффициент). Базовая ставка равняется десяти очкам. Коэффициент рассчитывается следующим образом:
- три буквы – 1;
- от четырех до пяти букв – 1.25;
- от шести до семи букв – 1.5;
- от восьми до девяти букв – 1.75;
- более девяти букв – 2.
На каждом уровне игрок может заработать дополнительные очки, выполняя определенные условия:
- отгадать 40 проц. возможных слов на уровне (1 000 очков);
- отгадать три слова, начинающихся на ту же букву, что и слово уровня (500 очков);
- отгадать все возможные слова на уровне (50 000 очков).
Отгаданные игроком слова отображаются на игровом поле в алфавитном порядки, сгруппированные по количеству букв в слове. Игрок может посмотреть значение каждого, нажав на него. Результаты охраняются каждый раз после верно отгаданного слова.
Использованные техники и приемы
В ходе работы над приложением использовались элементы подхода MVC (model, view, controller). В отдельные компоненты также вынесено управление звуком, обработка результатов игры и общие методы для всего приложения.
GAME = {
"utils":{}, // общие инструменты
"sounds":{}, // обработка звуков
"view":{}, // представление
"controller":{}, // обработка поведения
"model":{}, // основные данные
"results":{} // обработка результатов
}
GAME.init(place) // инициализация приложения
GAME.namespace(ns_string) // создание пространств имен
В процессе разработки ощутил все преимущества использования замыканий и немедленно вызываемых функций. Так, их использование избавило от постоянного поиска элементов на странице посредством getElementById и т.п.
controller.play = (function () {
// блокировка множественного нажатия
var cancelClick = false;
return function (letter) {
if (cancelClick) return;
cancelClick = true;
setTimeout(function () {
cancelClick = false;
}, 200)
//код функции
})()
Этапы выполнения приложения
В процессе инициализации приложения создаются все необходимые html-элементы, формируются объекты-списки для упрощения доступа к ним.
<body>
<div id="gamefield"></div>
<div id="help">
<h2>Правила</h2>
<div class='textGuide'>
<p>Необходимо составлять слова из показанного на экране слова. Слово должно быть нарицательным именем существительным в единственном числе. Уменьшительно-ласкательные формы, а также сокращения не принимаются. Минимальная длина слова - 3 буквы.</p>
</div>
<h2>Управление</h2>
<div class='textGuide'>
<p>Чтобы выбрать букву, кликните мышкой. Повторный клик по последней выбранной букве снимает выделение.</p>
<p>Клавиша Esc отменяет ввод всего слова.</p>
<p>Клавиша Backspace (←) отменяет ввод последней буквы.</p>
</div>
<h2>Игровые бонусы</h2>
<div class="textGuide">
<p>Первая звезда - отгадать 40% возможных слов на уровне. Бонус: 1 000 очков.</p>
<p>Вторая звезда - отгадать три слова, начинающихся на ту же букву, что и слово уровня. Бонус: 500 очков.</p>
<p>Третья звезда - отгадать все возможные слова на уровне. Бонус: 50 000 очков.</p>
</div>
<h2>Подсказки</h2>
<div>
<img src="images/icons/tips/definition.png">
<p>Показать определение неотгаданного слова. Стоимость подсказки: 100 очков</p>
</div>
<div>
<img src="images/icons/tips/word.png">
<p>Показать неотгаданное слово. Стоимость подсказки: 500 очков.</p>
</div>
<h2>Элементы интерфейса</h2>
<div>
<img src="images/icons/buttons_small/soundON.png">
<p>Управление звуком.</p>
</div>
<div>
<img src="images/icons/buttons_small/menuButton.png">
<p>Вызов игрового меню.</p>
</div>
<div>
<progress max="10" value="3"></progress>
<p>Прогресс на уровне.</p>
</div>
</div>
</body>
<body>
<div id="gamefield" style="position: relative;">
<div>
<div class="gameInfo">
<!-- Область информации о текущей сессии игры -->
<h1>Слова из слова</h1>
<div class="userName">Игрок: <span>123</span></div>
<div class="currentLevel">Уровень: <span>1</span></div>
<div class="menuLevel">
<!-- Переходы по уровням-->
<div class="menuLabel">Карта уровней ⇩</div>
<div class="levelMap" style="display: none;">
<a class="reached levelButton">1</a>
<a class="levelButton">2</a>
<a class="levelButton">3</a>
<a class="levelButton">4</a>
</div>
</div>
<div class="score">Очки: <span>0</span></div>
<progress max="31" value="0" title="Отгадано 0 из 31 слов"></progress>
<div class="tips">
<h2>Подсказки:</h2>
<img id="wordDefinition" title="Показать определение неотгаданного слова." alt="Показать определение неотгаданного слова." src="images/icons/tips/definition_gray.png">
<img id="holeWord" title="Показать неотгаданное слово целиком." alt="Показать неотгаданное слово целиком." src="images/icons/tips/word_gray.png"></div>
</div>
<!-- Игровая область-->
<div class="gameField">
<div class="missions">
<img src="images/icons/missions/incomplete.png" alt="Первая звезда" title="Отгадайте больше 40% слов">
<img src="images/icons/missions/incomplete.png" alt="Вторая звезда" title="Отгадайте 3 слова на букву "р"">
<img src="images/icons/missions/incomplete.png" alt="Третья звезда" title="Отгадайте 100% слов">
</div>
<div class="buttonGroup">
<img src="images/icons/buttons_small/soundON.png" alt="Выключить звук" title="Выключить звук">
<img src="images/icons/buttons_small/menuButton.png" alt="Меню" title="Игровое меню">
<img src="images/icons/buttons_small/help.png" title="Помощь" alt="Помощь">
</div>
<!-- Отображение вводимого игроком слова -->
<div class="userWord"></div>
<div class="levelWord">
<!-- Буквы основного слова -->
<div class="letter" data-order="0">р</div>
<div class="letter" data-order="0">о</div>
<div class="letter" data-order="0">д</div>
<div class="letter" data-order="0">и</div>
<div class="letter" data-order="0">н</div>
<div class="letter" data-order="0">а</div></div>
<!-- контейнер для найденных слов -->
<div class="foundWords"></div>
</div>
</div>
</div>
</body>
Все информация о прохождении игроком уровня сохраняется в объекте GAME.model.level
level = {
"1":{
"wordForLevel":"родина",
"foundWords":["род","анод","аир"],
"missions": {
"progress":3,
"firstStar":true,
"secondStar":true,
"thirdStar":true
}
}
}
Для того, чтобы как-то сохранять прогресс и не задействовать при этом серверные скрипты и базы данных, был выбран способ сохранения в localStorage браузера. Кроме того, реализовал «таблицу рекордов» для игроков, которые используют это приложение в одном и том же браузере
/**
* Сохранение результатов.
* @method GAME.controller.storeResults
* @param {string} name
* Имя игрока.
*/
controller.storeResults = function (name) {
var results = {
level: GAME.utils.createClone(model.level),
score: model.score
}
results = JSON.stringify(results);
window.localStorage.setItem(name, results);
}
Таким образом, представляю Вам на обсуждения мой проект. Буду рад выслушать конструктивную критику и предложения как в комментариях, так и в личном общении. Если интересуют подробности, с удовольствием расскажу о процессе написания подробнее.
Автор: Ghivan